feat(phase-4): WS2 + WS3 — Developer Portal (Next.js 14) and CLI tool (sentryagent)

WS2: Developer Portal (portal/)
- Standalone Next.js 14 + Tailwind CSS app — independent deployment
- Home page: hero, feature grid, CTA to /get-started
- /pricing: free tier limits table (10 agents, 1k calls/day) + paid tier CTA
- /sdks: all 4 SDKs (Node.js, Python, Go, Java) with install + code examples
- /api-explorer: Swagger UI from NEXT_PUBLIC_API_URL/openapi.json, persistAuthorization
- /get-started: 4-step wizard (setup → register agent → credentials → SDK snippet)
- Shared Nav component with active-link highlighting
- Build: 8/8 static pages, zero TypeScript errors

WS3: CLI Tool (cli/ — npm package: sentryagent)
- configure, register-agent, list-agents, issue-token, rotate-credentials, tail-audit-log
- Auto OAuth2 token fetch + 30s-buffer cache via client_credentials flow
- chalk-formatted table output, confirmation prompts, bounded audit log dedup
- bash + zsh shell completion scripts
- README with installation, all commands, and completion setup
- Build: tsc clean, node dist/index.js --help verified

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
SentryAgent.ai Developer
2026-04-02 04:29:50 +00:00
parent 1b682c22b2
commit d1e6af25aa
147 changed files with 8079 additions and 29 deletions

View File

@@ -0,0 +1,86 @@
(()=>{var e={};e.id=146,e.ids=[146],e.modules={7849:e=>{"use strict";e.exports=require("next/dist/client/components/action-async-storage.external")},2934:e=>{"use strict";e.exports=require("next/dist/client/components/action-async-storage.external.js")},5403:e=>{"use strict";e.exports=require("next/dist/client/components/request-async-storage.external")},4580:e=>{"use strict";e.exports=require("next/dist/client/components/request-async-storage.external.js")},4749:e=>{"use strict";e.exports=require("next/dist/client/components/static-generation-async-storage.external")},5869:e=>{"use strict";e.exports=require("next/dist/client/components/static-generation-async-storage.external.js")},399:e=>{"use strict";e.exports=require("next/dist/compiled/next-server/app-page.runtime.prod.js")},2250:(e,t,n)=>{"use strict";n.r(t),n.d(t,{GlobalError:()=>i.a,__next_app__:()=>p,originalPathname:()=>g,pages:()=>c,routeModule:()=>m,tree:()=>d}),n(9495),n(7341),n(5866);var s=n(3191),a=n(8716),r=n(7922),i=n.n(r),o=n(5231),l={};for(let e in o)0>["default","tree","pages","GlobalError","originalPathname","__next_app__","routeModule"].indexOf(e)&&(l[e]=()=>o[e]);n.d(t,l);let d=["",{children:["sdks",{children:["__PAGE__",{},{page:[()=>Promise.resolve().then(n.bind(n,9495)),"/home/ubuntu/vj_ai_agents_dev/sentryagent-idp/portal/app/sdks/page.tsx"]}]},{}]},{layout:[()=>Promise.resolve().then(n.bind(n,7341)),"/home/ubuntu/vj_ai_agents_dev/sentryagent-idp/portal/app/layout.tsx"],"not-found":[()=>Promise.resolve().then(n.t.bind(n,5866,23)),"next/dist/client/components/not-found-error"]}],c=["/home/ubuntu/vj_ai_agents_dev/sentryagent-idp/portal/app/sdks/page.tsx"],g="/sdks/page",p={require:n,loadChunk:()=>Promise.resolve()},m=new s.AppPageRouteModule({definition:{kind:a.x.APP_PAGE,page:"/sdks/page",pathname:"/sdks",bundlePath:"",filename:"",appPaths:[]},userland:{loaderTree:d}})},5642:(e,t,n)=>{Promise.resolve().then(n.bind(n,4174))},6643:(e,t,n)=>{Promise.resolve().then(n.t.bind(n,2994,23)),Promise.resolve().then(n.t.bind(n,6114,23)),Promise.resolve().then(n.t.bind(n,9727,23)),Promise.resolve().then(n.t.bind(n,9671,23)),Promise.resolve().then(n.t.bind(n,1868,23)),Promise.resolve().then(n.t.bind(n,4759,23))},5303:()=>{},4174:(e,t,n)=>{"use strict";n.d(t,{Nav:()=>o});var s=n(326);n(7577);var a=n(434),r=n(5047);let i=[{href:"/",label:"Home"},{href:"/api-explorer",label:"API Explorer"},{href:"/get-started",label:"Get Started"},{href:"/sdks",label:"SDKs"},{href:"/pricing",label:"Pricing"}];function o(){let e=(0,r.usePathname)();return s.jsx("header",{className:"sticky top-0 z-50 border-b border-slate-200 bg-white/90 backdrop-blur",children:(0,s.jsxs)("nav",{className:"mx-auto flex max-w-7xl items-center justify-between px-6 py-4",children:[(0,s.jsxs)(a.default,{href:"/",className:"flex items-center gap-2",children:[s.jsx("span",{className:"text-xl font-bold text-brand-600",children:"SentryAgent"}),s.jsx("span",{className:"rounded bg-brand-100 px-1.5 py-0.5 text-xs font-semibold text-brand-700",children:"AgentIdP"})]}),s.jsx("ul",{className:"flex items-center gap-1",children:i.map(({href:t,label:n})=>{let r="/"===t?"/"===e:e.startsWith(t);return s.jsx("li",{children:s.jsx(a.default,{href:t,className:["rounded-md px-3 py-2 text-sm font-medium transition-colors",r?"bg-brand-100 text-brand-700":"text-slate-600 hover:bg-slate-100 hover:text-slate-900"].join(" "),children:n})},t)})}),s.jsx(a.default,{href:"/get-started",className:"rounded-lg bg-brand-600 px-4 py-2 text-sm font-semibold text-white shadow-sm transition-colors hover:bg-brand-700",children:"Get Started Free"})]})})}},7341:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>c,metadata:()=>d});var s=n(9510);n(7272);var a=n(8570);let r=(0,a.createProxy)(String.raw`/home/ubuntu/vj_ai_agents_dev/sentryagent-idp/portal/components/Nav.tsx`),{__esModule:i,$$typeof:o}=r;r.default;let l=(0,a.createProxy)(String.raw`/home/ubuntu/vj_ai_agents_dev/sentryagent-idp/portal/components/Nav.tsx#Nav`),d={title:"SentryAgent.ai Developer Portal",description:"Identity and access management for AI agents. Register, authenticate, and secure your agents with SentryAgent AgentIdP."};function c({children:e}){return s.jsx("html",{lang:"en",children:(0,s.jsxs)("body",{className:"min-h-screen bg-slate-50 text-slate-900 antialiased",children:[s.jsx(l,{}),s.jsx("main",{children:e}),s.jsx("footer",{className:"border-t border-slate-200 py-8 text-center text-sm text-slate-500",children:(0,s.jsxs)("p",{children:["\xa9 ",new Date().getFullYear()," SentryAgent.ai — All rights reserved."]})})]})})}},9495:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>r});var s=n(9510);let a=[{name:"Node.js SDK",language:"typescript",badge:"TypeScript",installCmd:"npm install @sentryagent/idp-sdk",codeExample:`import { AgentIdPClient } from '@sentryagent/idp-sdk';
const client = new AgentIdPClient({
apiUrl: process.env.AGENTIDP_URL!,
clientId: process.env.AGENTIDP_CLIENT_ID!,
clientSecret: process.env.AGENTIDP_CLIENT_SECRET!,
});
// Register a new agent
const agent = await client.agents.register({
name: 'my-ai-agent',
description: 'Production summarisation agent',
});
console.log('Agent ID:', agent.agentId);
// Issue an access token
const { accessToken } = await client.tokens.issue(agent.agentId);
console.log('Token:', accessToken);`,repoUrl:"https://github.com/sentryagent/sdk-node"},{name:"Python SDK",language:"python",badge:"Python",installCmd:"pip install sentryagent-idp",codeExample:`from sentryagent_idp import AgentIdPClient
client = AgentIdPClient(
api_url=os.environ["AGENTIDP_URL"],
client_id=os.environ["AGENTIDP_CLIENT_ID"],
client_secret=os.environ["AGENTIDP_CLIENT_SECRET"],
)
# Register a new agent
agent = client.agents.register(
name="my-ai-agent",
description="Production summarisation agent",
)
print("Agent ID:", agent.agent_id)
# Issue an access token
token_response = client.tokens.issue(agent.agent_id)
print("Token:", token_response.access_token)`,repoUrl:"https://github.com/sentryagent/sdk-python"},{name:"Go SDK",language:"go",badge:"Go",installCmd:"go get github.com/sentryagent/idp-sdk-go",codeExample:`import (
"fmt"
"os"
idp "github.com/sentryagent/idp-sdk-go"
)
client := idp.NewClient(idp.Config{
APIURL: os.Getenv("AGENTIDP_URL"),
ClientID: os.Getenv("AGENTIDP_CLIENT_ID"),
ClientSecret: os.Getenv("AGENTIDP_CLIENT_SECRET"),
})
// Register a new agent
agent, err := client.Agents.Register(ctx, &idp.RegisterAgentInput{
Name: "my-ai-agent",
Description: "Production summarisation agent",
})
if err != nil {
panic(err)
}
fmt.Println("Agent ID:", agent.AgentID)
// Issue an access token
token, err := client.Tokens.Issue(ctx, agent.AgentID)
fmt.Println("Token:", token.AccessToken)`,repoUrl:"https://github.com/sentryagent/sdk-go"},{name:"Java SDK",language:"java",badge:"Java",installCmd:`<dependency>
<groupId>ai.sentryagent</groupId>
<artifactId>idp-sdk</artifactId>
<version>1.0.0</version>
</dependency>`,codeExample:`import ai.sentryagent.idp.AgentIdPClient;
import ai.sentryagent.idp.model.Agent;
import ai.sentryagent.idp.model.TokenResponse;
AgentIdPClient client = AgentIdPClient.builder()
.apiUrl(System.getenv("AGENTIDP_URL"))
.clientId(System.getenv("AGENTIDP_CLIENT_ID"))
.clientSecret(System.getenv("AGENTIDP_CLIENT_SECRET"))
.build();
// Register a new agent
Agent agent = client.agents().register(
RegisterAgentRequest.builder()
.name("my-ai-agent")
.description("Production summarisation agent")
.build()
);
System.out.println("Agent ID: " + agent.getAgentId());
// Issue an access token
TokenResponse token = client.tokens().issue(agent.getAgentId());
System.out.println("Token: " + token.getAccessToken());`,repoUrl:"https://github.com/sentryagent/sdk-java"}];function r(){return s.jsx("div",{className:"px-6 py-20",children:(0,s.jsxs)("div",{className:"mx-auto max-w-5xl",children:[(0,s.jsxs)("div",{className:"mb-12 text-center",children:[s.jsx("h1",{className:"mb-4 text-4xl font-extrabold text-slate-900",children:"Official SDKs"}),s.jsx("p",{className:"text-xl text-slate-600",children:"Native libraries for your language of choice. Every SDK is type-safe, fully tested, and maintained by the SentryAgent team."})]}),s.jsx("div",{className:"space-y-10",children:a.map(e=>(0,s.jsxs)("div",{className:"rounded-2xl border border-slate-200 bg-white p-8 shadow-sm",children:[(0,s.jsxs)("div",{className:"mb-6 flex items-center justify-between",children:[(0,s.jsxs)("div",{className:"flex items-center gap-3",children:[s.jsx("h2",{className:"text-2xl font-bold text-slate-900",children:e.name}),s.jsx("span",{className:"rounded-full bg-brand-100 px-3 py-0.5 text-sm font-semibold text-brand-700",children:e.badge})]}),s.jsx("a",{href:e.repoUrl,target:"_blank",rel:"noopener noreferrer",className:"text-sm font-medium text-brand-600 hover:underline",children:"View on GitHub →"})]}),(0,s.jsxs)("div",{className:"mb-6",children:[s.jsx("p",{className:"mb-2 text-sm font-semibold uppercase tracking-wider text-slate-500",children:"Installation"}),s.jsx("pre",{className:"overflow-x-auto rounded-lg bg-slate-900 px-4 py-3 text-sm text-slate-100",children:s.jsx("code",{children:e.installCmd})})]}),(0,s.jsxs)("div",{children:[s.jsx("p",{className:"mb-2 text-sm font-semibold uppercase tracking-wider text-slate-500",children:"Quick Start"}),s.jsx("pre",{className:"overflow-x-auto rounded-lg bg-slate-900 px-4 py-4 text-sm leading-relaxed text-slate-100",children:s.jsx("code",{children:e.codeExample})})]})]},e.name))})]})})}},7272:()=>{}};var t=require("../../webpack-runtime.js");t.C(e);var n=e=>t(t.s=e),s=t.X(0,[24],()=>n(2250));module.exports=s})();