@dudousxd/nestjs-agent-dashboard 0.17.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +28 -132
  2. package/dist/client/agent-client.d.ts +47 -1
  3. package/dist/client/agent-client.d.ts.map +1 -1
  4. package/dist/client/agent-client.js +0 -4
  5. package/dist/client/agent-client.js.map +1 -1
  6. package/dist/server/index.cjs +286 -1373
  7. package/dist/server/index.cjs.map +1 -1
  8. package/dist/server/index.d.cts +37 -287
  9. package/dist/server/index.d.ts +37 -287
  10. package/dist/server/index.js +239 -1323
  11. package/dist/server/index.js.map +1 -1
  12. package/dist/spa/assets/index-B1znMy6W.css +1 -0
  13. package/dist/spa/assets/{index-DKPuTuEx.js → index-DzukxAmy.js} +1 -1
  14. package/dist/spa/assets/index-eW1zMwDF.js +25 -0
  15. package/dist/spa/assets/{preview-BgeSHiwH.js → preview-Ch59R-LE.js} +1 -1
  16. package/dist/spa/index.html +3 -3
  17. package/dist/spa/preview.html +3 -3
  18. package/package.json +6 -20
  19. package/dist/client/console-session.d.ts +0 -63
  20. package/dist/client/console-session.d.ts.map +0 -1
  21. package/dist/client/console-session.js +0 -107
  22. package/dist/client/console-session.js.map +0 -1
  23. package/dist/react/index.d.ts +0 -4
  24. package/dist/react/index.d.ts.map +0 -1
  25. package/dist/react/index.js +0 -14
  26. package/dist/react/index.js.map +0 -1
  27. package/dist/react/open-console-button.d.ts +0 -26
  28. package/dist/react/open-console-button.d.ts.map +0 -1
  29. package/dist/react/open-console-button.js +0 -29
  30. package/dist/react/open-console-button.js.map +0 -1
  31. package/dist/react/use-open-console.d.ts +0 -34
  32. package/dist/react/use-open-console.d.ts.map +0 -1
  33. package/dist/react/use-open-console.js +0 -70
  34. package/dist/react/use-open-console.js.map +0 -1
  35. package/dist/spa/assets/index-B2rAzTPe.js +0 -25
  36. package/dist/spa/assets/index-P6B28Wyx.css +0 -1
@@ -1 +1 @@
1
- import{x as C,n as O,r as M,e as A,M as _,A as R,d as m,c as N,a as v,f as j,G as c,P as k,t as P,S as g,b as U,C as E,B as h,D as L,R as K,T as q}from"./index-B2rAzTPe.js";import{j as e,r as w}from"./base-ui-Bm0nR785.js";import"./recharts-CURTGZ5d.js";const G=[{modelId:"gpt-4o",requests:4200,inputTokens:84e5,outputTokens:21e5,costUsd:84.2},{modelId:"claude-3-5-sonnet",requests:2600,inputTokens:52e5,outputTokens:13e5,costUsd:41.6},{modelId:"gpt-4o-mini",requests:9800,inputTokens:12e6,outputTokens:3e6,costUsd:9.4},{modelId:"llama-3-70b",requests:1200,inputTokens:21e5,outputTokens:64e4,costUsd:0}],H=[{actorRef:"tenant:acme",requests:8200,totalTokens:184e5,costUsd:78.1,actorLabel:"Acme Corp"},{actorRef:"user:davi@goflip.ai",requests:3100,totalTokens:69e5,costUsd:34.2,actorLabel:"Davi de Carvalho"},{actorRef:"tenant:globex",requests:4400,totalTokens:92e5,costUsd:21.8,actorLabel:null},{actorRef:"user:ops-bot",requests:2100,totalTokens:394e4,costUsd:1.1,actorLabel:null}],B={"tenant:acme":2e7,"user:davi@goflip.ai":5e6,"tenant:globex":12e6};function F(){const a=[];for(let t=29;t>=0;t-=1){const r=new Date(Date.now()-t*864e5).toISOString().slice(0,10),s=Math.sin(t/3)*.5+1;a.push({day:r,totalTokens:Math.round(7e5*s+t*4e3),costUsd:Number((4.2*s+t*.05).toFixed(2))})}return a}function z(){const a=[];for(let t=29;t>=0;t-=1){const r=new Date(Date.now()-t*864e5).toISOString().slice(0,10),s=Math.sin(t/3)*.5+1,l=Math.round(18*s+t*.3);a.push({day:r,runs:l,failed:Math.max(0,Math.round(l*.06))})}return a}const u={byModel:G,byActor:H,trend:F()},W={metrics:{runs:482,completed:461,failed:21,successRate:461/482,retries:34,durationP50Ms:640,durationP95Ms:2400,ttftP50Ms:310,ttftP95Ms:1150},byAgent:[{agentName:"analyst",runs:210,failed:8,retries:14},{agentName:"billing-agent",runs:150,failed:9,retries:12},{agentName:"(default)",runs:122,failed:4,retries:8}],errors:[{errorCode:"TIMEOUT",count:9},{errorCode:"TOOL_ERROR",count:6},{errorCode:"RATE_LIMIT",count:4},{errorCode:"UNKNOWN",count:2}],trend:z()},x={runId:"r-7c31",threadId:"th2",actorRef:"user:ops-bot",agentName:"billing-agent",status:"failed",durationMs:4200,ttftMs:null,costUsd:.0031,modelId:"gpt-4o",errorCode:"TIMEOUT",errorMessage:"upstream model request timed out after 3 attempts",retries:2,startedAt:new Date(Date.now()-21e4).toISOString(),promptHash:"ffeeddccbbaa99887766554433221100ffeeddccbbaa99887766554433221",parentRunId:null},D=[{runId:"r-9f2a",threadId:"th1",actorRef:"tenant:acme",agentName:"analyst",status:"completed",durationMs:820,ttftMs:290,costUsd:.0042,modelId:"gpt-4o-mini",errorCode:null,errorMessage:null,retries:0,startedAt:new Date(Date.now()-4e4).toISOString(),promptHash:"a1b2c3d4e5f60718293a4b5c6d7e8f9012345678901234567890abcdef01234",parentRunId:null},x,{runId:"r-a114",threadId:"th3",actorRef:"user:davi@goflip.ai",agentName:null,status:"completed",durationMs:1150,ttftMs:410,costUsd:.0117,modelId:"claude-sonnet-4-5",errorCode:null,errorMessage:null,retries:1,startedAt:new Date(Date.now()-54e4).toISOString(),promptHash:null,parentRunId:null},{runId:"r-b902",threadId:"th1",actorRef:"tenant:acme",agentName:"analyst",status:"failed",durationMs:980,ttftMs:null,costUsd:null,modelId:null,errorCode:"TOOL_ERROR",errorMessage:"search_records returned a 500",retries:0,startedAt:new Date(Date.now()-132e4).toISOString(),promptHash:"a1b2c3d4e5f60718293a4b5c6d7e8f9012345678901234567890abcdef01234",parentRunId:null},{runId:"r-c447",threadId:"th2",actorRef:"user:ops-bot",agentName:"billing-agent",status:"running",durationMs:null,ttftMs:null,costUsd:null,modelId:null,errorCode:null,errorMessage:null,retries:0,startedAt:new Date(Date.now()-8e3).toISOString(),promptHash:"ffeeddccbbaa99887766554433221100ffeeddccbbaa99887766554433221",parentRunId:"r-7c31"}],Q=[{toolCallId:"tc-approve-1",runId:"r-c447",toolName:"delete_asset",input:{assetId:"asset-42",reason:"stale"},threadId:"th2",threadTitle:"Incident triage",actorRef:"user:ops-bot",agentName:"billing-agent",requestedAt:new Date(Date.now()-3e5).toISOString()},{toolCallId:"tc-approve-2",runId:"r-9f2a",toolName:"send_email",input:{to:"finance@acme.example",subject:"Q3 invoice adjustment"},threadId:"th1",threadTitle:"Q3 procurement review",actorRef:"tenant:acme",agentName:"analyst",requestedAt:new Date(Date.now()-9e5).toISOString()}],V=[{toolName:"search_records",toolType:"read",calls:420,failed:6,rejected:0,p50ExecutionMs:42,p95ExecutionMs:180},{toolName:"delete_asset",toolType:"action",calls:34,failed:1,rejected:4,p50ExecutionMs:310,p95ExecutionMs:620},{toolName:"send_email",toolType:"action",calls:58,failed:2,rejected:2,p50ExecutionMs:96,p95ExecutionMs:410},{toolName:"fetch_pricing",toolType:"read",calls:210,failed:0,rejected:0,p50ExecutionMs:88,p95ExecutionMs:95}],Y=B,p=[{toolCallId:"tc1",runId:"r-9f2a",toolName:"search_records",toolType:"read",status:"ok",threadId:"th1",createdAt:new Date(Date.now()-12e3).toISOString()},{toolCallId:"tc2",runId:"r-7c31",toolName:"delete_asset",toolType:"action",status:"forbidden",threadId:"th2",createdAt:new Date(Date.now()-9e4).toISOString()},{toolCallId:"tc3",runId:"r-9f2a",toolName:"fetch_pricing",toolType:"read",status:"ok",threadId:"th1",createdAt:new Date(Date.now()-24e4).toISOString()},{toolCallId:"tc4",runId:"r-a114",toolName:"send_email",toolType:"action",status:"failed",threadId:"th3",createdAt:new Date(Date.now()-62e4).toISOString()},{toolCallId:"tc5",runId:null,toolName:"summarize_thread",toolType:"read",status:"ok",threadId:"th2",createdAt:new Date(Date.now()-12e5).toISOString()}],y={threadId:"th2",title:"Incident triage",actorRef:"user:ops-bot",messageCount:11,totalTokens:62e3,lastActivityAt:new Date(Date.now()-4e5).toISOString(),actorLabel:null},J=[{threadId:"th1",title:"Q3 procurement review",actorRef:"tenant:acme",messageCount:24,totalTokens:184e3,lastActivityAt:new Date(Date.now()-3e4).toISOString(),actorLabel:"Acme Corp"},y,{threadId:"th3",title:"Contract summary",actorRef:"user:davi@goflip.ai",messageCount:6,totalTokens:28400,lastActivityAt:new Date(Date.now()-18e5).toISOString(),actorLabel:"Davi de Carvalho"}],X=[{threadId:"th1",title:"Q3 procurement review",actorRef:"tenant:acme",requests:24,totalTokens:184e3,costUsd:18.4,actorLabel:"Acme Corp"},{threadId:"th2",title:"Incident triage",actorRef:"user:ops-bot",requests:11,totalTokens:62e3,costUsd:6.2,actorLabel:null},{threadId:"th3",title:"Contract summary",actorRef:"user:davi@goflip.ai",requests:6,totalTokens:28400,costUsd:2.8,actorLabel:"Davi de Carvalho"}],f={rows:p,total:137,page:1,pageSize:25},I={rows:J,total:46,page:1,pageSize:25},Z={rows:D,total:482,page:1,pageSize:25},$={rows:Q,total:7,page:1,pageSize:25},T={run:x,thread:{threadId:"th2",title:"Incident triage",actorRef:"user:ops-bot",deleted:!1,actorLabel:null},toolCalls:[{toolCallId:"tc2",toolName:"delete_asset",toolType:"action",status:"forbidden",executionMs:null,executedByRef:"user:davi@goflip.ai",error:null,createdAt:new Date(Date.now()-215e3).toISOString()},{toolCallId:"tc9",toolName:"fetch_pricing",toolType:"read",status:"ok",executionMs:96,executedByRef:null,error:null,createdAt:new Date(Date.now()-213e3).toISOString()},{toolCallId:"tc10",toolName:"search_records",toolType:"read",status:"failed",executionMs:3980,executedByRef:null,error:"upstream returned 500 after 3 attempts",createdAt:new Date(Date.now()-212e3).toISOString()}]},S={thread:y,deleted:!1,usage:{requests:11,inputTokens:48e3,outputTokens:14e3,totalTokens:62e3,costUsd:6.2},runs:D.filter(a=>a.threadId==="th2"),runTotal:34,messages:[{messageId:"m1",role:"user",content:"The billing sync failed again overnight — can you find out which asset broke it?",truncated:!1,agentName:null,toolCallCount:0,createdAt:new Date(Date.now()-4e5).toISOString()},{messageId:"m2",role:"assistant",content:"I found 3 assets with a null billing code. Asset-42 is the only one touched by last night’s sync, so I want to delete it — that needs your approval.",truncated:!1,agentName:"billing-agent",toolCallCount:2,createdAt:new Date(Date.now()-38e4).toISOString()},{messageId:"m3",role:"assistant",content:"Here is the full audit trail for asset-42 across the last 90 days, starting with the ingest that first assigned it a billing code and continuing through every subsequent",truncated:!0,agentName:"billing-agent",toolCallCount:1,createdAt:new Date(Date.now()-36e4).toISOString()}]},ee=[{modelId:"gpt-4o",inputPricePer1m:2.5,outputPricePer1m:10,cacheReadPricePer1m:1.25,effectiveFrom:new Date(Date.now()-5*864e5).toISOString()},{modelId:"claude-3-5-sonnet",inputPricePer1m:3,outputPricePer1m:15,cacheWritePricePer1m:3.75,cacheReadPricePer1m:.3,effectiveFrom:new Date(Date.now()-12*864e5).toISOString()},{modelId:"gpt-4o-mini",inputPricePer1m:.15,outputPricePer1m:.6,effectiveFrom:new Date(Date.now()-2*864e5).toISOString()}],te=[{id:"e1",event:"run.started",ts:Date.now()-2e3,payload:{runId:"r-9f2",agentName:"analyst"}},{id:"e2",event:"tool-call",ts:Date.now()-5e3,payload:{toolName:"search_records",toolType:"read",status:"ok"}},{id:"e3",event:"quota.exceeded",ts:Date.now()-9e3,payload:{actorId:"tenant:globex",usedTokens:124e5,limitTokens:12e6}},{id:"e4",event:"tool-call",ts:Date.now()-14e3,payload:{toolName:"delete_asset",toolType:"action",status:"forbidden"}},{id:"e5",event:"delegated",ts:Date.now()-2e4,payload:{fromAgent:"router",toAgent:"billing-agent"}},{id:"e6",event:"run.finished",ts:Date.now()-26e3,payload:{runId:"r-8a1",steps:7,inputTokens:4200,outputTokens:1100}}];function ae(){const a=[];for(let t=29;t>=0;t-=1){const r=new Date(Date.now()-t*864e5).toISOString().slice(0,10),s=Math.sin(t/4)*.4+1,l=Math.round(26*s+(29-t)*.6),i=Math.round(l*1.28);a.push({day:r,calls:i,turns:l,inputTokens:i*3400,outputTokens:i*1150,costUsd:Number((i*.0123).toFixed(4)),firstTryRate:Number((.82+Math.cos(t/5)*.06).toFixed(3))})}return a}const n=ae(),oe={totals:{calls:n.reduce((a,t)=>a+t.calls,0),turns:n.reduce((a,t)=>a+t.turns,0),firstAttempts:1014,firstTrySuccesses:842,firstTryRate:842/1014,retried:131,failed:207,inputTokens:n.reduce((a,t)=>a+t.inputTokens,0),outputTokens:n.reduce((a,t)=>a+t.outputTokens,0),costUsd:n.reduce((a,t)=>a+(t.costUsd??0),0)},byToolModel:[{toolName:"ui__render",modelId:"arn:aws:bedrock:us-east-1:123456789012:inference-profile/us.anthropic.claude-sonnet-4-5",mode:"tree",calls:612,firstAttempts:498,firstTrySuccesses:461,firstTryRate:461/498,retried:41,failed:58,costUsd:6.84},{toolName:"ui__sandbox",modelId:"arn:aws:bedrock:us-east-1:123456789012:inference-profile/us.anthropic.claude-sonnet-4-5",mode:"sandbox",calls:284,firstAttempts:201,firstTrySuccesses:139,firstTryRate:139/201,retried:52,failed:93,costUsd:5.12},{toolName:"ui__show_order_card",modelId:"gpt-4o-mini",mode:"per-component",calls:241,firstAttempts:232,firstTrySuccesses:221,firstTryRate:221/232,retried:7,failed:13,costUsd:.41},{toolName:"ui__show",modelId:"gpt-4o-mini",mode:"show",calls:108,firstAttempts:83,firstTrySuccesses:21,firstTryRate:21/83,retried:31,failed:43,costUsd:null}],errors:[{category:"syntax",message:"invalid Sandbox code: jsx line 14:22: Unexpected token — check that every JSX tag is closed in order",toolName:"ui__sandbox",count:48,lastAt:new Date(Date.now()-12*6e4).toISOString()},{category:"shape",message:'invalid UI tree: children[2].props.columns: Expected array, received "…"',toolName:"ui__render",count:37,lastAt:new Date(Date.now()-40*6e4).toISOString()},{category:"unknown-component",message:"invalid UI tree code: children[0] jsx line 3:22: `<Slider>` is not a kit component — use one of `Button`, `Card`, or a plain element",toolName:"ui__render",count:21,lastAt:new Date(Date.now()-3*36e5).toISOString()},{category:"missing-app",message:"invalid Sandbox code: jsx: no `App` — rename `function Calculator` to `function App`; App is what gets drawn",toolName:"ui__sandbox",count:19,lastAt:new Date(Date.now()-5*36e5).toISOString()},{category:"unavailable",message:'component "…" is not available here',toolName:"ui__show",count:14,lastAt:new Date(Date.now()-26*36e5).toISOString()},{category:"bridge",message:"invalid Sandbox code: html line 1:18: `flippy.send` — the bridge is `agent.send(payload)`",toolName:"ui__sandbox",count:9,lastAt:new Date(Date.now()-2*864e5).toISOString()},{category:"other",message:"Request timed out after 30000ms",toolName:"ui__show",count:3,lastAt:new Date(Date.now()-4*864e5).toISOString()}],byDay:n,costPerTurn:{turns:n.reduce((a,t)=>a+t.turns,0),avgUsd:.0157,p50Usd:.0112,p95Usd:.0441},latency:{firstFrame:{samples:1002,p50Ms:740,p95Ms:2310},complete:{samples:931,p50Ms:3480,p95Ms:9120}}},ne={totals:{calls:0,turns:0,firstAttempts:0,firstTrySuccesses:0,firstTryRate:null,retried:0,failed:0,inputTokens:0,outputTokens:0,costUsd:null},byToolModel:[],errors:[],byDay:[],costPerTurn:{turns:0,avgUsd:null,p50Usd:null,p95Usd:null},latency:{firstFrame:{samples:0,p50Ms:null,p95Ms:null},complete:{samples:0,p50Ms:null,p95Ms:null}}};function d(a){return{page:a,error:null,retry:()=>{}}}function se(a,t){return{page:a,error:t,retry:()=>{}}}function re(){const[a,t]=w.useState(null);return e.jsx(O,{delay:400,closeDelay:0,timeout:300,children:e.jsxs("div",{className:"relative min-h-full",children:[e.jsx("div",{className:"app-bg"}),e.jsxs("div",{className:"relative z-10 mx-auto max-w-[1180px] space-y-6 px-5 py-6",children:[e.jsxs("header",{className:"flex items-center gap-2.5",children:[e.jsx("div",{className:"grid h-8 w-8 place-items-center rounded-lg border border-brand/40 bg-brand/10",children:e.jsx(M,{className:"h-4 w-4 text-brand"})}),e.jsxs("div",{className:"leading-none",children:[e.jsx("div",{className:"text-sm font-semibold tracking-tight",children:"AI gateway — preview"}),e.jsx("div",{className:"mono text-[10px] uppercase tracking-[0.2em] text-muted-foreground",children:"mock data · no backend"})]})]}),e.jsx(o,{label:"Spend & usage",children:e.jsx(A,{overview:u,topThreads:X,onOpenThread:()=>t("thread")})}),e.jsx(o,{label:"Models",children:e.jsx(_,{rows:u.byModel})}),e.jsx(o,{label:"Actors & budgets",children:e.jsx(R,{rows:u.byActor,budgets:Y})}),e.jsx(o,{label:"Runs & tools",children:e.jsx(m,{toolCalls:p,toolCallsTable:d(f),toolCallsWhere:{},onToolCallsToolNameChange:()=>{},onToolCallsStatusChange:()=>{},onToolCallsPageChange:()=>{},threadsTable:d(I),threadsWhere:{},onThreadsTitleChange:()=>{},onThreadsPageChange:()=>{},onOpenRun:()=>t("run"),onOpenThread:()=>t("thread")})}),e.jsx(o,{label:"Reliability",children:e.jsx(N,{overview:W,runsTable:d(Z),runsWhere:{threadId:"th2"},onRunsStatusChange:()=>{},onRunsAgentNameChange:()=>{},onRunsThreadIdClear:()=>{},onRunsPageChange:()=>{},onOpenRun:()=>t("run")})}),e.jsx(o,{label:"Approvals",children:e.jsx(v,{table:d($),onPageChange:()=>{},onDecide:async()=>{},onOpenRun:()=>t("run")})}),e.jsx(o,{label:"Tools",children:e.jsx(j,{rows:V})}),e.jsx(o,{label:"Generative UI",children:e.jsx(c,{stats:oe})}),e.jsx(o,{label:"Pricing",children:e.jsx(k,{prices:ee,loading:!1,unavailable:!1,onUpsert:async()=>{},saving:!1})}),e.jsx(o,{label:"Live",children:e.jsx(P,{events:te,connected:!0})}),e.jsx(o,{label:"Failure & loading states",children:e.jsxs("div",{className:"space-y-4",children:[e.jsx(g,{label:"Spend & usage",error:new Error("503 Service Unavailable"),onRetry:()=>{}}),e.jsx(g,{label:"Pricing",error:new Error("401 Unauthorized"),onRetry:()=>{}}),e.jsx(U,{label:"Reliability"}),e.jsx(c,{stats:null,unavailable:!0}),e.jsx(c,{stats:ne}),e.jsx(m,{toolCalls:p,toolCallsTable:se(f,new Error("500 Internal Server Error")),toolCallsWhere:{},onToolCallsToolNameChange:()=>{},onToolCallsStatusChange:()=>{},onToolCallsPageChange:()=>{},threadsTable:d(I),threadsWhere:{},onThreadsTitleChange:()=>{},onThreadsPageChange:()=>{}})]})}),e.jsx(o,{label:"Drill-downs",children:e.jsxs(E,{className:"flex flex-wrap gap-2 p-4 text-xs",children:[e.jsx(h,{size:"md",className:"rounded-lg",onClick:()=>t("run"),children:"Open a run"}),e.jsx(h,{size:"md",className:"rounded-lg",onClick:()=>t("thread"),children:"Open a thread"})]})})]}),a!==null&&e.jsx(L,{title:a==="run"?"Run":"Thread",subtitle:a==="run"?T.run.runId:S.thread.threadId,onClose:()=>t(null),...a==="run"?{onBack:()=>t("thread")}:{},children:a==="run"?e.jsx(K,{detail:T,onOpenThread:()=>t("thread")}):e.jsx(q,{detail:S,onOpenRun:()=>t("run"),runsHref:"#/reliability?threadId=th2"})})]})})}function o({label:a,children:t}){return e.jsxs("div",{className:"space-y-2",children:[e.jsx("h2",{className:"mono text-[11px] uppercase tracking-[0.2em] text-muted-foreground",children:a}),t]})}const b=document.getElementById("root");b&&C.createRoot(b).render(e.jsx(w.StrictMode,{children:e.jsx(re,{})}));
1
+ import{x as C,n as O,r as M,e as A,M as _,A as R,d as m,c as N,a as v,f as j,G as c,P as k,t as P,S as g,b as U,C as E,B as h,D as L,R as K,T as q}from"./index-eW1zMwDF.js";import{j as e,r as w}from"./base-ui-Bm0nR785.js";import"./recharts-CURTGZ5d.js";const G=[{modelId:"gpt-4o",requests:4200,inputTokens:84e5,outputTokens:21e5,costUsd:84.2},{modelId:"claude-3-5-sonnet",requests:2600,inputTokens:52e5,outputTokens:13e5,costUsd:41.6},{modelId:"gpt-4o-mini",requests:9800,inputTokens:12e6,outputTokens:3e6,costUsd:9.4},{modelId:"llama-3-70b",requests:1200,inputTokens:21e5,outputTokens:64e4,costUsd:0}],H=[{actorRef:"tenant:acme",requests:8200,totalTokens:184e5,costUsd:78.1,actorLabel:"Acme Corp"},{actorRef:"user:davi@goflip.ai",requests:3100,totalTokens:69e5,costUsd:34.2,actorLabel:"Davi de Carvalho"},{actorRef:"tenant:globex",requests:4400,totalTokens:92e5,costUsd:21.8,actorLabel:null},{actorRef:"user:ops-bot",requests:2100,totalTokens:394e4,costUsd:1.1,actorLabel:null}],B={"tenant:acme":2e7,"user:davi@goflip.ai":5e6,"tenant:globex":12e6};function F(){const a=[];for(let t=29;t>=0;t-=1){const r=new Date(Date.now()-t*864e5).toISOString().slice(0,10),s=Math.sin(t/3)*.5+1;a.push({day:r,totalTokens:Math.round(7e5*s+t*4e3),costUsd:Number((4.2*s+t*.05).toFixed(2))})}return a}function z(){const a=[];for(let t=29;t>=0;t-=1){const r=new Date(Date.now()-t*864e5).toISOString().slice(0,10),s=Math.sin(t/3)*.5+1,l=Math.round(18*s+t*.3);a.push({day:r,runs:l,failed:Math.max(0,Math.round(l*.06))})}return a}const u={byModel:G,byActor:H,trend:F()},W={metrics:{runs:482,completed:461,failed:21,successRate:461/482,retries:34,durationP50Ms:640,durationP95Ms:2400,ttftP50Ms:310,ttftP95Ms:1150},byAgent:[{agentName:"analyst",runs:210,failed:8,retries:14},{agentName:"billing-agent",runs:150,failed:9,retries:12},{agentName:"(default)",runs:122,failed:4,retries:8}],errors:[{errorCode:"TIMEOUT",count:9},{errorCode:"TOOL_ERROR",count:6},{errorCode:"RATE_LIMIT",count:4},{errorCode:"UNKNOWN",count:2}],trend:z()},x={runId:"r-7c31",threadId:"th2",actorRef:"user:ops-bot",agentName:"billing-agent",status:"failed",durationMs:4200,ttftMs:null,costUsd:.0031,modelId:"gpt-4o",errorCode:"TIMEOUT",errorMessage:"upstream model request timed out after 3 attempts",retries:2,startedAt:new Date(Date.now()-21e4).toISOString(),promptHash:"ffeeddccbbaa99887766554433221100ffeeddccbbaa99887766554433221",parentRunId:null},D=[{runId:"r-9f2a",threadId:"th1",actorRef:"tenant:acme",agentName:"analyst",status:"completed",durationMs:820,ttftMs:290,costUsd:.0042,modelId:"gpt-4o-mini",errorCode:null,errorMessage:null,retries:0,startedAt:new Date(Date.now()-4e4).toISOString(),promptHash:"a1b2c3d4e5f60718293a4b5c6d7e8f9012345678901234567890abcdef01234",parentRunId:null},x,{runId:"r-a114",threadId:"th3",actorRef:"user:davi@goflip.ai",agentName:null,status:"completed",durationMs:1150,ttftMs:410,costUsd:.0117,modelId:"claude-sonnet-4-5",errorCode:null,errorMessage:null,retries:1,startedAt:new Date(Date.now()-54e4).toISOString(),promptHash:null,parentRunId:null},{runId:"r-b902",threadId:"th1",actorRef:"tenant:acme",agentName:"analyst",status:"failed",durationMs:980,ttftMs:null,costUsd:null,modelId:null,errorCode:"TOOL_ERROR",errorMessage:"search_records returned a 500",retries:0,startedAt:new Date(Date.now()-132e4).toISOString(),promptHash:"a1b2c3d4e5f60718293a4b5c6d7e8f9012345678901234567890abcdef01234",parentRunId:null},{runId:"r-c447",threadId:"th2",actorRef:"user:ops-bot",agentName:"billing-agent",status:"running",durationMs:null,ttftMs:null,costUsd:null,modelId:null,errorCode:null,errorMessage:null,retries:0,startedAt:new Date(Date.now()-8e3).toISOString(),promptHash:"ffeeddccbbaa99887766554433221100ffeeddccbbaa99887766554433221",parentRunId:"r-7c31"}],Q=[{toolCallId:"tc-approve-1",runId:"r-c447",toolName:"delete_asset",input:{assetId:"asset-42",reason:"stale"},threadId:"th2",threadTitle:"Incident triage",actorRef:"user:ops-bot",agentName:"billing-agent",requestedAt:new Date(Date.now()-3e5).toISOString()},{toolCallId:"tc-approve-2",runId:"r-9f2a",toolName:"send_email",input:{to:"finance@acme.example",subject:"Q3 invoice adjustment"},threadId:"th1",threadTitle:"Q3 procurement review",actorRef:"tenant:acme",agentName:"analyst",requestedAt:new Date(Date.now()-9e5).toISOString()}],V=[{toolName:"search_records",toolType:"read",calls:420,failed:6,rejected:0,p50ExecutionMs:42,p95ExecutionMs:180},{toolName:"delete_asset",toolType:"action",calls:34,failed:1,rejected:4,p50ExecutionMs:310,p95ExecutionMs:620},{toolName:"send_email",toolType:"action",calls:58,failed:2,rejected:2,p50ExecutionMs:96,p95ExecutionMs:410},{toolName:"fetch_pricing",toolType:"read",calls:210,failed:0,rejected:0,p50ExecutionMs:88,p95ExecutionMs:95}],Y=B,p=[{toolCallId:"tc1",runId:"r-9f2a",toolName:"search_records",toolType:"read",status:"ok",threadId:"th1",createdAt:new Date(Date.now()-12e3).toISOString()},{toolCallId:"tc2",runId:"r-7c31",toolName:"delete_asset",toolType:"action",status:"forbidden",threadId:"th2",createdAt:new Date(Date.now()-9e4).toISOString()},{toolCallId:"tc3",runId:"r-9f2a",toolName:"fetch_pricing",toolType:"read",status:"ok",threadId:"th1",createdAt:new Date(Date.now()-24e4).toISOString()},{toolCallId:"tc4",runId:"r-a114",toolName:"send_email",toolType:"action",status:"failed",threadId:"th3",createdAt:new Date(Date.now()-62e4).toISOString()},{toolCallId:"tc5",runId:null,toolName:"summarize_thread",toolType:"read",status:"ok",threadId:"th2",createdAt:new Date(Date.now()-12e5).toISOString()}],y={threadId:"th2",title:"Incident triage",actorRef:"user:ops-bot",messageCount:11,totalTokens:62e3,lastActivityAt:new Date(Date.now()-4e5).toISOString(),actorLabel:null},J=[{threadId:"th1",title:"Q3 procurement review",actorRef:"tenant:acme",messageCount:24,totalTokens:184e3,lastActivityAt:new Date(Date.now()-3e4).toISOString(),actorLabel:"Acme Corp"},y,{threadId:"th3",title:"Contract summary",actorRef:"user:davi@goflip.ai",messageCount:6,totalTokens:28400,lastActivityAt:new Date(Date.now()-18e5).toISOString(),actorLabel:"Davi de Carvalho"}],X=[{threadId:"th1",title:"Q3 procurement review",actorRef:"tenant:acme",requests:24,totalTokens:184e3,costUsd:18.4,actorLabel:"Acme Corp"},{threadId:"th2",title:"Incident triage",actorRef:"user:ops-bot",requests:11,totalTokens:62e3,costUsd:6.2,actorLabel:null},{threadId:"th3",title:"Contract summary",actorRef:"user:davi@goflip.ai",requests:6,totalTokens:28400,costUsd:2.8,actorLabel:"Davi de Carvalho"}],f={rows:p,total:137,page:1,pageSize:25},I={rows:J,total:46,page:1,pageSize:25},Z={rows:D,total:482,page:1,pageSize:25},$={rows:Q,total:7,page:1,pageSize:25},T={run:x,thread:{threadId:"th2",title:"Incident triage",actorRef:"user:ops-bot",deleted:!1,actorLabel:null},toolCalls:[{toolCallId:"tc2",toolName:"delete_asset",toolType:"action",status:"forbidden",executionMs:null,executedByRef:"user:davi@goflip.ai",error:null,createdAt:new Date(Date.now()-215e3).toISOString()},{toolCallId:"tc9",toolName:"fetch_pricing",toolType:"read",status:"ok",executionMs:96,executedByRef:null,error:null,createdAt:new Date(Date.now()-213e3).toISOString()},{toolCallId:"tc10",toolName:"search_records",toolType:"read",status:"failed",executionMs:3980,executedByRef:null,error:"upstream returned 500 after 3 attempts",createdAt:new Date(Date.now()-212e3).toISOString()}]},S={thread:y,deleted:!1,usage:{requests:11,inputTokens:48e3,outputTokens:14e3,totalTokens:62e3,costUsd:6.2},runs:D.filter(a=>a.threadId==="th2"),runTotal:34,messages:[{messageId:"m1",role:"user",content:"The billing sync failed again overnight — can you find out which asset broke it?",truncated:!1,agentName:null,toolCallCount:0,createdAt:new Date(Date.now()-4e5).toISOString()},{messageId:"m2",role:"assistant",content:"I found 3 assets with a null billing code. Asset-42 is the only one touched by last night’s sync, so I want to delete it — that needs your approval.",truncated:!1,agentName:"billing-agent",toolCallCount:2,createdAt:new Date(Date.now()-38e4).toISOString()},{messageId:"m3",role:"assistant",content:"Here is the full audit trail for asset-42 across the last 90 days, starting with the ingest that first assigned it a billing code and continuing through every subsequent",truncated:!0,agentName:"billing-agent",toolCallCount:1,createdAt:new Date(Date.now()-36e4).toISOString()}]},ee=[{modelId:"gpt-4o",inputPricePer1m:2.5,outputPricePer1m:10,cacheReadPricePer1m:1.25,effectiveFrom:new Date(Date.now()-5*864e5).toISOString()},{modelId:"claude-3-5-sonnet",inputPricePer1m:3,outputPricePer1m:15,cacheWritePricePer1m:3.75,cacheReadPricePer1m:.3,effectiveFrom:new Date(Date.now()-12*864e5).toISOString()},{modelId:"gpt-4o-mini",inputPricePer1m:.15,outputPricePer1m:.6,effectiveFrom:new Date(Date.now()-2*864e5).toISOString()}],te=[{id:"e1",event:"run.started",ts:Date.now()-2e3,payload:{runId:"r-9f2",agentName:"analyst"}},{id:"e2",event:"tool-call",ts:Date.now()-5e3,payload:{toolName:"search_records",toolType:"read",status:"ok"}},{id:"e3",event:"quota.exceeded",ts:Date.now()-9e3,payload:{actorId:"tenant:globex",usedTokens:124e5,limitTokens:12e6}},{id:"e4",event:"tool-call",ts:Date.now()-14e3,payload:{toolName:"delete_asset",toolType:"action",status:"forbidden"}},{id:"e5",event:"delegated",ts:Date.now()-2e4,payload:{fromAgent:"router",toAgent:"billing-agent"}},{id:"e6",event:"run.finished",ts:Date.now()-26e3,payload:{runId:"r-8a1",steps:7,inputTokens:4200,outputTokens:1100}}];function ae(){const a=[];for(let t=29;t>=0;t-=1){const r=new Date(Date.now()-t*864e5).toISOString().slice(0,10),s=Math.sin(t/4)*.4+1,l=Math.round(26*s+(29-t)*.6),i=Math.round(l*1.28);a.push({day:r,calls:i,turns:l,inputTokens:i*3400,outputTokens:i*1150,costUsd:Number((i*.0123).toFixed(4)),firstTryRate:Number((.82+Math.cos(t/5)*.06).toFixed(3))})}return a}const n=ae(),oe={totals:{calls:n.reduce((a,t)=>a+t.calls,0),turns:n.reduce((a,t)=>a+t.turns,0),firstAttempts:1014,firstTrySuccesses:842,firstTryRate:842/1014,retried:131,failed:207,inputTokens:n.reduce((a,t)=>a+t.inputTokens,0),outputTokens:n.reduce((a,t)=>a+t.outputTokens,0),costUsd:n.reduce((a,t)=>a+(t.costUsd??0),0)},byToolModel:[{toolName:"ui__render",modelId:"arn:aws:bedrock:us-east-1:123456789012:inference-profile/us.anthropic.claude-sonnet-4-5",mode:"tree",calls:612,firstAttempts:498,firstTrySuccesses:461,firstTryRate:461/498,retried:41,failed:58,costUsd:6.84},{toolName:"ui__sandbox",modelId:"arn:aws:bedrock:us-east-1:123456789012:inference-profile/us.anthropic.claude-sonnet-4-5",mode:"sandbox",calls:284,firstAttempts:201,firstTrySuccesses:139,firstTryRate:139/201,retried:52,failed:93,costUsd:5.12},{toolName:"ui__show_order_card",modelId:"gpt-4o-mini",mode:"per-component",calls:241,firstAttempts:232,firstTrySuccesses:221,firstTryRate:221/232,retried:7,failed:13,costUsd:.41},{toolName:"ui__show",modelId:"gpt-4o-mini",mode:"show",calls:108,firstAttempts:83,firstTrySuccesses:21,firstTryRate:21/83,retried:31,failed:43,costUsd:null}],errors:[{category:"syntax",message:"invalid Sandbox code: jsx line 14:22: Unexpected token — check that every JSX tag is closed in order",toolName:"ui__sandbox",count:48,lastAt:new Date(Date.now()-12*6e4).toISOString()},{category:"shape",message:'invalid UI tree: children[2].props.columns: Expected array, received "…"',toolName:"ui__render",count:37,lastAt:new Date(Date.now()-40*6e4).toISOString()},{category:"unknown-component",message:"invalid UI tree code: children[0] jsx line 3:22: `<Slider>` is not a kit component — use one of `Button`, `Card`, or a plain element",toolName:"ui__render",count:21,lastAt:new Date(Date.now()-3*36e5).toISOString()},{category:"missing-app",message:"invalid Sandbox code: jsx: no `App` — rename `function Calculator` to `function App`; App is what gets drawn",toolName:"ui__sandbox",count:19,lastAt:new Date(Date.now()-5*36e5).toISOString()},{category:"unavailable",message:'component "…" is not available here',toolName:"ui__show",count:14,lastAt:new Date(Date.now()-26*36e5).toISOString()},{category:"bridge",message:"invalid Sandbox code: html line 1:18: `flippy.send` — the bridge is `agent.send(payload)`",toolName:"ui__sandbox",count:9,lastAt:new Date(Date.now()-2*864e5).toISOString()},{category:"other",message:"Request timed out after 30000ms",toolName:"ui__show",count:3,lastAt:new Date(Date.now()-4*864e5).toISOString()}],byDay:n,costPerTurn:{turns:n.reduce((a,t)=>a+t.turns,0),avgUsd:.0157,p50Usd:.0112,p95Usd:.0441},latency:{firstFrame:{samples:1002,p50Ms:740,p95Ms:2310},complete:{samples:931,p50Ms:3480,p95Ms:9120}}},ne={totals:{calls:0,turns:0,firstAttempts:0,firstTrySuccesses:0,firstTryRate:null,retried:0,failed:0,inputTokens:0,outputTokens:0,costUsd:null},byToolModel:[],errors:[],byDay:[],costPerTurn:{turns:0,avgUsd:null,p50Usd:null,p95Usd:null},latency:{firstFrame:{samples:0,p50Ms:null,p95Ms:null},complete:{samples:0,p50Ms:null,p95Ms:null}}};function d(a){return{page:a,error:null,retry:()=>{}}}function se(a,t){return{page:a,error:t,retry:()=>{}}}function re(){const[a,t]=w.useState(null);return e.jsx(O,{delay:400,closeDelay:0,timeout:300,children:e.jsxs("div",{className:"relative min-h-full",children:[e.jsx("div",{className:"app-bg"}),e.jsxs("div",{className:"relative z-10 mx-auto max-w-[1180px] space-y-6 px-5 py-6",children:[e.jsxs("header",{className:"flex items-center gap-2.5",children:[e.jsx("div",{className:"grid h-8 w-8 place-items-center rounded-lg border border-brand/40 bg-brand/10",children:e.jsx(M,{className:"h-4 w-4 text-brand"})}),e.jsxs("div",{className:"leading-none",children:[e.jsx("div",{className:"text-sm font-semibold tracking-tight",children:"AI gateway — preview"}),e.jsx("div",{className:"mono text-[10px] uppercase tracking-[0.2em] text-muted-foreground",children:"mock data · no backend"})]})]}),e.jsx(o,{label:"Spend & usage",children:e.jsx(A,{overview:u,topThreads:X,onOpenThread:()=>t("thread")})}),e.jsx(o,{label:"Models",children:e.jsx(_,{rows:u.byModel})}),e.jsx(o,{label:"Actors & budgets",children:e.jsx(R,{rows:u.byActor,budgets:Y})}),e.jsx(o,{label:"Runs & tools",children:e.jsx(m,{toolCalls:p,toolCallsTable:d(f),toolCallsWhere:{},onToolCallsToolNameChange:()=>{},onToolCallsStatusChange:()=>{},onToolCallsPageChange:()=>{},threadsTable:d(I),threadsWhere:{},onThreadsTitleChange:()=>{},onThreadsPageChange:()=>{},onOpenRun:()=>t("run"),onOpenThread:()=>t("thread")})}),e.jsx(o,{label:"Reliability",children:e.jsx(N,{overview:W,runsTable:d(Z),runsWhere:{threadId:"th2"},onRunsStatusChange:()=>{},onRunsAgentNameChange:()=>{},onRunsThreadIdClear:()=>{},onRunsPageChange:()=>{},onOpenRun:()=>t("run")})}),e.jsx(o,{label:"Approvals",children:e.jsx(v,{table:d($),onPageChange:()=>{},onDecide:async()=>{},onOpenRun:()=>t("run")})}),e.jsx(o,{label:"Tools",children:e.jsx(j,{rows:V})}),e.jsx(o,{label:"Generative UI",children:e.jsx(c,{stats:oe})}),e.jsx(o,{label:"Pricing",children:e.jsx(k,{prices:ee,loading:!1,unavailable:!1,onUpsert:async()=>{},saving:!1})}),e.jsx(o,{label:"Live",children:e.jsx(P,{events:te,connected:!0})}),e.jsx(o,{label:"Failure & loading states",children:e.jsxs("div",{className:"space-y-4",children:[e.jsx(g,{label:"Spend & usage",error:new Error("503 Service Unavailable"),onRetry:()=>{}}),e.jsx(g,{label:"Pricing",error:new Error("401 Unauthorized"),onRetry:()=>{}}),e.jsx(U,{label:"Reliability"}),e.jsx(c,{stats:null,unavailable:!0}),e.jsx(c,{stats:ne}),e.jsx(m,{toolCalls:p,toolCallsTable:se(f,new Error("500 Internal Server Error")),toolCallsWhere:{},onToolCallsToolNameChange:()=>{},onToolCallsStatusChange:()=>{},onToolCallsPageChange:()=>{},threadsTable:d(I),threadsWhere:{},onThreadsTitleChange:()=>{},onThreadsPageChange:()=>{}})]})}),e.jsx(o,{label:"Drill-downs",children:e.jsxs(E,{className:"flex flex-wrap gap-2 p-4 text-xs",children:[e.jsx(h,{size:"md",className:"rounded-lg",onClick:()=>t("run"),children:"Open a run"}),e.jsx(h,{size:"md",className:"rounded-lg",onClick:()=>t("thread"),children:"Open a thread"})]})})]}),a!==null&&e.jsx(L,{title:a==="run"?"Run":"Thread",subtitle:a==="run"?T.run.runId:S.thread.threadId,onClose:()=>t(null),...a==="run"?{onBack:()=>t("thread")}:{},children:a==="run"?e.jsx(K,{detail:T,onOpenThread:()=>t("thread")}):e.jsx(q,{detail:S,onOpenRun:()=>t("run"),runsHref:"#/reliability?threadId=th2"})})]})})}function o({label:a,children:t}){return e.jsxs("div",{className:"space-y-2",children:[e.jsx("h2",{className:"mono text-[11px] uppercase tracking-[0.2em] text-muted-foreground",children:a}),t]})}const b=document.getElementById("root");b&&C.createRoot(b).render(e.jsx(w.StrictMode,{children:e.jsx(re,{})}));
@@ -10,11 +10,11 @@
10
10
  rel="stylesheet"
11
11
  />
12
12
  <title>ai gateway · governance console</title>
13
- <script type="module" crossorigin src="/ai-gateway/assets/index-DKPuTuEx.js"></script>
13
+ <script type="module" crossorigin src="/ai-gateway/assets/index-DzukxAmy.js"></script>
14
14
  <link rel="modulepreload" crossorigin href="/ai-gateway/assets/base-ui-Bm0nR785.js">
15
15
  <link rel="modulepreload" crossorigin href="/ai-gateway/assets/recharts-CURTGZ5d.js">
16
- <link rel="modulepreload" crossorigin href="/ai-gateway/assets/index-B2rAzTPe.js">
17
- <link rel="stylesheet" crossorigin href="/ai-gateway/assets/index-P6B28Wyx.css">
16
+ <link rel="modulepreload" crossorigin href="/ai-gateway/assets/index-eW1zMwDF.js">
17
+ <link rel="stylesheet" crossorigin href="/ai-gateway/assets/index-B1znMy6W.css">
18
18
  </head>
19
19
  <body>
20
20
  <div id="root"></div>
@@ -10,11 +10,11 @@
10
10
  rel="stylesheet"
11
11
  />
12
12
  <title>ai gateway · preview</title>
13
- <script type="module" crossorigin src="/ai-gateway/assets/preview-BgeSHiwH.js"></script>
13
+ <script type="module" crossorigin src="/ai-gateway/assets/preview-Ch59R-LE.js"></script>
14
14
  <link rel="modulepreload" crossorigin href="/ai-gateway/assets/base-ui-Bm0nR785.js">
15
15
  <link rel="modulepreload" crossorigin href="/ai-gateway/assets/recharts-CURTGZ5d.js">
16
- <link rel="modulepreload" crossorigin href="/ai-gateway/assets/index-B2rAzTPe.js">
17
- <link rel="stylesheet" crossorigin href="/ai-gateway/assets/index-P6B28Wyx.css">
16
+ <link rel="modulepreload" crossorigin href="/ai-gateway/assets/index-eW1zMwDF.js">
17
+ <link rel="stylesheet" crossorigin href="/ai-gateway/assets/index-B1znMy6W.css">
18
18
  </head>
19
19
  <body>
20
20
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dudousxd/nestjs-agent-dashboard",
3
- "version": "0.17.0",
3
+ "version": "0.19.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/DavideCarvalho/nestjs-agent.git",
@@ -37,11 +37,6 @@
37
37
  "types": "./dist/client/agent-client.d.ts",
38
38
  "import": "./dist/client/agent-client.js",
39
39
  "default": "./dist/client/agent-client.js"
40
- },
41
- "./react": {
42
- "types": "./dist/react/index.d.ts",
43
- "import": "./dist/react/index.js",
44
- "default": "./dist/react/index.js"
45
40
  }
46
41
  },
47
42
  "files": [
@@ -51,19 +46,9 @@
51
46
  "@dudousxd/nestjs-agent-core": ">=0.1.0 <1.0.0",
52
47
  "@nestjs/common": "^10.0.0 || ^11.0.0 || ^12.0.0",
53
48
  "@nestjs/core": "^10.0.0 || ^11.0.0 || ^12.0.0",
54
- "react": ">=18.0.0",
55
- "react-dom": ">=18.0.0",
56
49
  "reflect-metadata": "^0.2.0",
57
50
  "rxjs": "^7.0.0"
58
51
  },
59
- "peerDependenciesMeta": {
60
- "react": {
61
- "optional": true
62
- },
63
- "react-dom": {
64
- "optional": true
65
- }
66
- },
67
52
  "dependencies": {
68
53
  "@dudousxd/nestjs-diagnostics": "0.7.2",
69
54
  "react-is": "19.3.0",
@@ -71,6 +56,7 @@
71
56
  },
72
57
  "devDependencies": {
73
58
  "@base-ui/react": "1.8.0",
59
+ "@nestjs/authorization": "0.1.3",
74
60
  "@nestjs/common": "12.0.4",
75
61
  "@nestjs/core": "12.0.4",
76
62
  "@nestjs/platform-express": "12.0.4",
@@ -99,11 +85,11 @@
99
85
  "typescript": "5.9.3",
100
86
  "vite": "5.4.21",
101
87
  "vitest": "2.1.9",
102
- "@dudousxd/nestjs-agent-core": "0.58.0"
88
+ "@dudousxd/nestjs-agent-core": "0.62.0"
103
89
  },
104
90
  "scripts": {
105
- "build": "vite build && tsup && tsc -p tsconfig.client.json && tsc -p tsconfig.react.json",
106
- "typecheck": "tsc -p tsconfig.server.json --noEmit && tsc -p tsconfig.server.spec.json --noEmit && tsc -p tsconfig.app.json --noEmit && tsc -p tsconfig.react.spec.json --noEmit",
107
- "typecheck:specs": "tsc -p tsconfig.server.spec.json --noEmit && tsc -p tsconfig.app.json --noEmit && tsc -p tsconfig.react.spec.json --noEmit"
91
+ "build": "vite build && tsup && tsc -p tsconfig.client.json",
92
+ "typecheck": "tsc -p tsconfig.server.json --noEmit && tsc -p tsconfig.server.spec.json --noEmit && tsc -p tsconfig.app.json --noEmit",
93
+ "typecheck:specs": "tsc -p tsconfig.server.spec.json --noEmit && tsc -p tsconfig.app.json --noEmit"
108
94
  }
109
95
  }
@@ -1,63 +0,0 @@
1
- /**
2
- * Headless client for opening the console from YOUR app.
3
- *
4
- * The console SPA is served at a literal path and knows nothing about your app's auth, so a plain
5
- * browser navigation to it carries no identity. Mode A closes that gap: an XHR from inside your app
6
- * — which DOES carry your auth — posts to the console's session endpoint, the `session` hook
7
- * decides, and the library answers with its own signed cookie. The navigation that follows rides it.
8
- *
9
- * No UI here on purpose: you own the button, the page and the copy. This module owns the two things
10
- * a host would otherwise have to rediscover — where the session endpoint actually lives, and how to
11
- * call it without the failure mode below.
12
- */
13
- /**
14
- * Where `POST` mints the console session cookie.
15
- *
16
- * Derived from `basePath` rather than hardcoded by the caller: this package owns the route (the
17
- * auth controller is mounted relative to `basePath` by `RouterModule`), so a host that hardcodes it
18
- * is guessing at something that can change under a version bump — with no compile error when it
19
- * does, because the break only shows up as a 404 at runtime.
20
- */
21
- export declare function agentConsoleSessionUrl(basePath?: string): string;
22
- /** Where the console SPA itself is served. */
23
- export declare function agentConsoleUrl(basePath?: string): string;
24
- export interface OpenConsoleOptions {
25
- /** Where the console is mounted. MUST match `AgentDashboardModule.forRoot({ basePath })`. */
26
- basePath?: string;
27
- /**
28
- * Headers for the mint request — in practice your app's `Authorization` header. A function (sync
29
- * or async) is accepted so a token can be read at call time rather than captured at wiring time,
30
- * which is what a refreshing token needs.
31
- */
32
- headers?: HeadersInit | (() => HeadersInit | Promise<HeadersInit>);
33
- /** Injected for tests and non-browser callers. Defaults to the global `fetch`. */
34
- fetch?: typeof globalThis.fetch;
35
- signal?: AbortSignal;
36
- /**
37
- * Performs the navigation after a successful mint. Defaults to `location.assign`. Override to
38
- * route through your own router, or to open in a new tab.
39
- */
40
- navigate?: (url: string) => void;
41
- }
42
- /** Thrown when the session could not be minted. Never thrown after a successful mint. */
43
- export declare class ConsoleSessionError extends Error {
44
- readonly url: string;
45
- /** The HTTP status, or `undefined` when the request never produced one (network error). */
46
- readonly status?: number | undefined;
47
- constructor(message: string, url: string,
48
- /** The HTTP status, or `undefined` when the request never produced one (network error). */
49
- status?: number | undefined);
50
- }
51
- /**
52
- * Mint the console session cookie. Resolves on success; throws {@link ConsoleSessionError} on
53
- * refusal. Use this directly when you want to mint without navigating (a pre-flight check, or a
54
- * link the user opens later).
55
- */
56
- export declare function mintAgentConsoleSession(options?: OpenConsoleOptions): Promise<void>;
57
- /**
58
- * Mint the session, then navigate to the console. Throws without navigating when the mint is
59
- * refused, so a denied user gets a real error instead of landing on the console's
60
- * "no session" page — which reads as a bug rather than a permission decision.
61
- */
62
- export declare function openAgentConsole(options?: OpenConsoleOptions): Promise<void>;
63
- //# sourceMappingURL=console-session.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"console-session.d.ts","sourceRoot":"","sources":["../../src/client/console-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAWH;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,GAAE,MAA0B,GAAG,MAAM,CAEnF;AAED,8CAA8C;AAC9C,wBAAgB,eAAe,CAAC,QAAQ,GAAE,MAA0B,GAAG,MAAM,CAE5E;AAED,MAAM,WAAW,kBAAkB;IACjC,6FAA6F;IAC7F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,OAAO,CAAC,EAAE,WAAW,GAAG,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;IACnE,kFAAkF;IAClF,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAChC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED,yFAAyF;AACzF,qBAAa,mBAAoB,SAAQ,KAAK;IAG1C,QAAQ,CAAC,GAAG,EAAE,MAAM;IACpB,2FAA2F;IAC3F,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM;gBAHxB,OAAO,EAAE,MAAM,EACN,GAAG,EAAE,MAAM;IACpB,2FAA2F;IAClF,MAAM,CAAC,EAAE,MAAM,YAAA;CAK3B;AAOD;;;;GAIG;AACH,wBAAsB,uBAAuB,CAAC,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkD7F;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAKtF"}
@@ -1,107 +0,0 @@
1
- /**
2
- * Headless client for opening the console from YOUR app.
3
- *
4
- * The console SPA is served at a literal path and knows nothing about your app's auth, so a plain
5
- * browser navigation to it carries no identity. Mode A closes that gap: an XHR from inside your app
6
- * — which DOES carry your auth — posts to the console's session endpoint, the `session` hook
7
- * decides, and the library answers with its own signed cookie. The navigation that follows rides it.
8
- *
9
- * No UI here on purpose: you own the button, the page and the copy. This module owns the two things
10
- * a host would otherwise have to rediscover — where the session endpoint actually lives, and how to
11
- * call it without the failure mode below.
12
- */
13
- /** The mount default; matches `AgentDashboardModule.forRoot()`'s own default. */
14
- const DEFAULT_BASE_PATH = '/ai-gateway';
15
- function normalizeBasePath(basePath) {
16
- const trimmed = basePath.trim().replace(/\/+$/, '');
17
- if (trimmed === '')
18
- return '';
19
- return trimmed.startsWith('/') ? trimmed : `/${trimmed}`;
20
- }
21
- /**
22
- * Where `POST` mints the console session cookie.
23
- *
24
- * Derived from `basePath` rather than hardcoded by the caller: this package owns the route (the
25
- * auth controller is mounted relative to `basePath` by `RouterModule`), so a host that hardcodes it
26
- * is guessing at something that can change under a version bump — with no compile error when it
27
- * does, because the break only shows up as a 404 at runtime.
28
- */
29
- export function agentConsoleSessionUrl(basePath = DEFAULT_BASE_PATH) {
30
- return `${normalizeBasePath(basePath)}/auth/session`;
31
- }
32
- /** Where the console SPA itself is served. */
33
- export function agentConsoleUrl(basePath = DEFAULT_BASE_PATH) {
34
- return normalizeBasePath(basePath) || '/';
35
- }
36
- /** Thrown when the session could not be minted. Never thrown after a successful mint. */
37
- export class ConsoleSessionError extends Error {
38
- url;
39
- status;
40
- constructor(message, url,
41
- /** The HTTP status, or `undefined` when the request never produced one (network error). */
42
- status) {
43
- super(message);
44
- this.url = url;
45
- this.status = status;
46
- this.name = 'ConsoleSessionError';
47
- }
48
- }
49
- async function resolveHeaders(headers) {
50
- if (headers === undefined)
51
- return {};
52
- return typeof headers === 'function' ? await headers() : headers;
53
- }
54
- /**
55
- * Mint the console session cookie. Resolves on success; throws {@link ConsoleSessionError} on
56
- * refusal. Use this directly when you want to mint without navigating (a pre-flight check, or a
57
- * link the user opens later).
58
- */
59
- export async function mintAgentConsoleSession(options = {}) {
60
- const url = agentConsoleSessionUrl(options.basePath);
61
- const doFetch = options.fetch ?? globalThis.fetch;
62
- if (typeof doFetch !== 'function') {
63
- throw new ConsoleSessionError('No `fetch` available; pass one via `options.fetch`.', url);
64
- }
65
- let response;
66
- try {
67
- response = await doFetch(url, {
68
- method: 'POST',
69
- // The whole point: the response's Set-Cookie must stick, and the cookie must ride the
70
- // navigation that follows.
71
- credentials: 'include',
72
- headers: await resolveHeaders(options.headers),
73
- // Load-bearing, and the reason this helper exists rather than three lines at the call site.
74
- // `fetch` FOLLOWS redirects by default, so an app whose auth layer rewrites a 401 into a
75
- // "go to /signin" redirect makes this request resolve 200 against the sign-in HTML —
76
- // `response.ok` reads true, the caller navigates, and the user lands in a console with no
77
- // session, which looks exactly like a permissions bug. Handling the redirect explicitly turns
78
- // that into a clear error instead of a silent false success.
79
- redirect: 'manual',
80
- ...(options.signal ? { signal: options.signal } : {}),
81
- });
82
- }
83
- catch (cause) {
84
- throw new ConsoleSessionError(`Could not reach the console session endpoint at ${url}: ${String(cause)}`, url);
85
- }
86
- // `redirect: 'manual'` surfaces differently per runtime: browsers give an opaque response
87
- // (`type: 'opaqueredirect'`, status 0), Node/undici gives the real 3xx. Both mean the same thing.
88
- const redirected = response.type === 'opaqueredirect' || (response.status >= 300 && response.status < 400);
89
- if (redirected) {
90
- throw new ConsoleSessionError(`The console session endpoint at ${url} answered with a redirect instead of minting a session. Something in front of it — usually an auth middleware or exception filter that rewrites 401s into a sign-in redirect — is intercepting the response. Exempt this path from that rewrite so the real status reaches this caller.`, url, response.status || undefined);
91
- }
92
- if (!response.ok) {
93
- throw new ConsoleSessionError(`The console refused to open (HTTP ${response.status}).`, url, response.status);
94
- }
95
- }
96
- /**
97
- * Mint the session, then navigate to the console. Throws without navigating when the mint is
98
- * refused, so a denied user gets a real error instead of landing on the console's
99
- * "no session" page — which reads as a bug rather than a permission decision.
100
- */
101
- export async function openAgentConsole(options = {}) {
102
- await mintAgentConsoleSession(options);
103
- const target = agentConsoleUrl(options.basePath);
104
- const navigate = options.navigate ?? ((url) => globalThis.location?.assign(url));
105
- navigate(target);
106
- }
107
- //# sourceMappingURL=console-session.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"console-session.js","sourceRoot":"","sources":["../../src/client/console-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,iFAAiF;AACjF,MAAM,iBAAiB,GAAG,aAAa,CAAC;AAExC,SAAS,iBAAiB,CAAC,QAAgB;IACzC,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACpD,IAAI,OAAO,KAAK,EAAE;QAAE,OAAO,EAAE,CAAC;IAC9B,OAAO,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC;AAC3D,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CAAC,WAAmB,iBAAiB;IACzE,OAAO,GAAG,iBAAiB,CAAC,QAAQ,CAAC,eAAe,CAAC;AACvD,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,eAAe,CAAC,WAAmB,iBAAiB;IAClE,OAAO,iBAAiB,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC;AAC5C,CAAC;AAqBD,yFAAyF;AACzF,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAGjC;IAEA;IAJX,YACE,OAAe,EACN,GAAW;IACpB,2FAA2F;IAClF,MAAe;QAExB,KAAK,CAAC,OAAO,CAAC,CAAC;QAJN,QAAG,GAAH,GAAG,CAAQ;QAEX,WAAM,GAAN,MAAM,CAAS;QAGxB,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED,KAAK,UAAU,cAAc,CAAC,OAAsC;IAClE,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACrC,OAAO,OAAO,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;AACnE,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,UAA8B,EAAE;IAC5E,MAAM,GAAG,GAAG,sBAAsB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC;IAClD,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;QAClC,MAAM,IAAI,mBAAmB,CAAC,qDAAqD,EAAE,GAAG,CAAC,CAAC;IAC5F,CAAC;IAED,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE;YAC5B,MAAM,EAAE,MAAM;YACd,sFAAsF;YACtF,2BAA2B;YAC3B,WAAW,EAAE,SAAS;YACtB,OAAO,EAAE,MAAM,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC;YAC9C,4FAA4F;YAC5F,yFAAyF;YACzF,qFAAqF;YACrF,0FAA0F;YAC1F,8FAA8F;YAC9F,6DAA6D;YAC7D,QAAQ,EAAE,QAAQ;YAClB,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACtD,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,mBAAmB,CAC3B,mDAAmD,GAAG,KAAK,MAAM,CAAC,KAAK,CAAC,EAAE,EAC1E,GAAG,CACJ,CAAC;IACJ,CAAC;IAED,0FAA0F;IAC1F,kGAAkG;IAClG,MAAM,UAAU,GACd,QAAQ,CAAC,IAAI,KAAK,gBAAgB,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;IAC1F,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,IAAI,mBAAmB,CAC3B,mCAAmC,GAAG,yRAAyR,EAC/T,GAAG,EACH,QAAQ,CAAC,MAAM,IAAI,SAAS,CAC7B,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,mBAAmB,CAC3B,qCAAqC,QAAQ,CAAC,MAAM,IAAI,EACxD,GAAG,EACH,QAAQ,CAAC,MAAM,CAChB,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,UAA8B,EAAE;IACrE,MAAM,uBAAuB,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACzF,QAAQ,CAAC,MAAM,CAAC,CAAC;AACnB,CAAC"}
@@ -1,4 +0,0 @@
1
- export * from './use-open-console.js';
2
- export * from './open-console-button.js';
3
- export * from '../client/console-session.js';
4
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AASA,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AAEzC,cAAc,8BAA8B,CAAC"}
@@ -1,14 +0,0 @@
1
- // The React tier of `@dudousxd/nestjs-agent-dashboard`, published at the `./react` subpath so a
2
- // host that only mounts the NestJS module never pulls React in. Three levels, pick one:
3
- //
4
- // openAgentConsole(...) — no React at all (`./client`), you own everything
5
- // useOpenAgentConsole(...) — state for a launcher UI, you own the markup
6
- // <OpenAgentConsoleButton /> — drop-in, unstyled, forwards every button prop
7
- //
8
- // `openAgentConsoleMutationOptions` wires the same call into TanStack Query without this package
9
- // depending on TanStack.
10
- export * from './use-open-console.js';
11
- export * from './open-console-button.js';
12
- // Re-exported so a React consumer needs one import path, not two.
13
- export * from '../client/console-session.js';
14
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,wFAAwF;AACxF,EAAE;AACF,oFAAoF;AACpF,+EAA+E;AAC/E,iFAAiF;AACjF,EAAE;AACF,iGAAiG;AACjG,yBAAyB;AACzB,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,kEAAkE;AAClE,cAAc,8BAA8B,CAAC"}
@@ -1,26 +0,0 @@
1
- import type { ButtonHTMLAttributes, ReactNode } from 'react';
2
- import type { OpenConsoleOptions } from '../client/console-session.js';
3
- export interface OpenAgentConsoleButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onClick' | 'children'>, OpenConsoleOptions {
4
- /** Button label. Defaults to "Open AI gateway". */
5
- children?: ReactNode;
6
- /** Shown while the session is being minted. Defaults to "Opening…". */
7
- pendingLabel?: ReactNode;
8
- /**
9
- * Render the refusal yourself. Omit and the button renders a plain `<p role="alert">` under
10
- * itself; pass `null` to render nothing and read the error from {@link useOpenAgentConsole}.
11
- */
12
- renderError?: ((error: Error) => ReactNode) | null;
13
- }
14
- /**
15
- * Drop-in launcher: the top tier, for a host that just wants a working button.
16
- *
17
- * Deliberately unstyled — it emits a bare `<button>` and forwards `className`/`style`/every other
18
- * button prop, so it inherits whatever design system the host already has instead of importing CSS
19
- * that would fight it. When it doesn't fit, drop to {@link useOpenAgentConsole} (same behaviour,
20
- * your markup) or to `openAgentConsole` (no React at all).
21
- *
22
- * The error is rendered by default rather than swallowed: a refused mint is the case a launcher most
23
- * needs to surface, and a button that silently does nothing reads as broken rather than forbidden.
24
- */
25
- export declare function OpenAgentConsoleButton({ children, pendingLabel, renderError, basePath, headers, fetch: fetchImpl, signal, navigate, disabled, ...buttonProps }: OpenAgentConsoleButtonProps): import("react").JSX.Element;
26
- //# sourceMappingURL=open-console-button.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"open-console-button.d.ts","sourceRoot":"","sources":["../../src/react/open-console-button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,MAAM,WAAW,2BACf,SAAQ,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC,EAC3E,kBAAkB;IACpB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,uEAAuE;IACvE,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,SAAS,CAAC,GAAG,IAAI,CAAC;CACpD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,OAAO,EACP,KAAK,EAAE,SAAS,EAChB,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,GAAG,WAAW,EACf,EAAE,2BAA2B,+BA4B7B"}
@@ -1,29 +0,0 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useOpenAgentConsole } from './use-open-console.js';
3
- /**
4
- * Drop-in launcher: the top tier, for a host that just wants a working button.
5
- *
6
- * Deliberately unstyled — it emits a bare `<button>` and forwards `className`/`style`/every other
7
- * button prop, so it inherits whatever design system the host already has instead of importing CSS
8
- * that would fight it. When it doesn't fit, drop to {@link useOpenAgentConsole} (same behaviour,
9
- * your markup) or to `openAgentConsole` (no React at all).
10
- *
11
- * The error is rendered by default rather than swallowed: a refused mint is the case a launcher most
12
- * needs to surface, and a button that silently does nothing reads as broken rather than forbidden.
13
- */
14
- export function OpenAgentConsoleButton({ children, pendingLabel, renderError, basePath, headers, fetch: fetchImpl, signal, navigate, disabled, ...buttonProps }) {
15
- const { open, isPending, error } = useOpenAgentConsole({
16
- // Spread-if-defined rather than passing the keys through: the package compiles with
17
- // `exactOptionalPropertyTypes`, under which an explicit `basePath: undefined` is not assignable
18
- // to `basePath?: string`.
19
- ...(basePath !== undefined ? { basePath } : {}),
20
- ...(headers !== undefined ? { headers } : {}),
21
- ...(fetchImpl !== undefined ? { fetch: fetchImpl } : {}),
22
- ...(signal !== undefined ? { signal } : {}),
23
- ...(navigate !== undefined ? { navigate } : {}),
24
- });
25
- return (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", ...buttonProps, onClick: open, disabled: disabled || isPending, "aria-busy": isPending || undefined, children: isPending ? (pendingLabel ?? 'Opening…') : (children ?? 'Open AI gateway') }), error &&
26
- renderError !== null &&
27
- (renderError?.(error) ?? _jsx("p", { role: "alert", children: error.message }))] }));
28
- }
29
- //# sourceMappingURL=open-console-button.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"open-console-button.js","sourceRoot":"","sources":["../../src/react/open-console-button.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAgB5D;;;;;;;;;;GAUG;AACH,MAAM,UAAU,sBAAsB,CAAC,EACrC,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,OAAO,EACP,KAAK,EAAE,SAAS,EAChB,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,GAAG,WAAW,EACc;IAC5B,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,mBAAmB,CAAC;QACrD,oFAAoF;QACpF,gGAAgG;QAChG,0BAA0B;QAC1B,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/C,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7C,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxD,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3C,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAChD,CAAC,CAAC;IAEH,OAAO,CACL,8BACE,iBACE,IAAI,EAAC,QAAQ,KACT,WAAW,EACf,OAAO,EAAE,IAAI,EACb,QAAQ,EAAE,QAAQ,IAAI,SAAS,eACpB,SAAS,IAAI,SAAS,YAEhC,SAAS,CAAC,CAAC,CAAC,CAAC,YAAY,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,iBAAiB,CAAC,GACpE,EACR,KAAK;gBACJ,WAAW,KAAK,IAAI;gBACpB,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,IAAI,YAAG,IAAI,EAAC,OAAO,YAAE,KAAK,CAAC,OAAO,GAAK,CAAC,IAC9D,CACJ,CAAC;AACJ,CAAC"}
@@ -1,34 +0,0 @@
1
- import { ConsoleSessionError, type OpenConsoleOptions } from '../client/console-session.js';
2
- /**
3
- * React layer over `openAgentConsole` — the middle tier between the bare function
4
- * (`../client/console-session.ts`) and the drop-in `<OpenAgentConsoleButton>`.
5
- *
6
- * You get the state a launcher UI actually needs (in-flight, error) and keep full control of the
7
- * markup. Nothing here is AI-gateway-specific beyond the endpoint: it is a mint-then-navigate call
8
- * with the two states that call can be in.
9
- */
10
- export interface UseOpenConsoleResult {
11
- /** Start the mint-then-navigate. Never rejects — read `error` instead. */
12
- open: () => void;
13
- /** True from the click until the navigation starts, or until it fails. */
14
- isPending: boolean;
15
- /** The last refusal, or `null`. Cleared when `open()` is called again. */
16
- error: ConsoleSessionError | null;
17
- /** Drop a stale error without retrying — e.g. when a dialog closes. */
18
- reset: () => void;
19
- }
20
- export declare function useOpenAgentConsole(options?: OpenConsoleOptions): UseOpenConsoleResult;
21
- /**
22
- * TanStack Query integration WITHOUT a TanStack dependency: the returned object is the shape
23
- * `useMutation` takes, so a host that already uses Query wires the launcher into its own cache,
24
- * devtools and error handling with no extra adapter — and a host that doesn't never pays for it.
25
- *
26
- * ```ts
27
- * const { mutate, isPending } = useMutation(openAgentConsoleMutationOptions({ headers }));
28
- * ```
29
- */
30
- export declare function openAgentConsoleMutationOptions(options?: OpenConsoleOptions): {
31
- mutationKey: readonly unknown[];
32
- mutationFn: () => Promise<void>;
33
- };
34
- //# sourceMappingURL=use-open-console.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-open-console.d.ts","sourceRoot":"","sources":["../../src/react/use-open-console.ts"],"names":[],"mappings":"AACA,OAAO,EACL,mBAAmB,EACnB,KAAK,kBAAkB,EAGxB,MAAM,8BAA8B,CAAC;AAEtC;;;;;;;GAOG;AACH,MAAM,WAAW,oBAAoB;IACnC,0EAA0E;IAC1E,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,0EAA0E;IAC1E,SAAS,EAAE,OAAO,CAAC;IACnB,0EAA0E;IAC1E,KAAK,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAClC,uEAAuE;IACvE,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,kBAAuB,GAAG,oBAAoB,CA2D1F;AAED;;;;;;;;GAQG;AACH,wBAAgB,+BAA+B,CAAC,OAAO,GAAE,kBAAuB,GAAG;IACjF,WAAW,EAAE,SAAS,OAAO,EAAE,CAAC;IAChC,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACjC,CAKA"}
@@ -1,70 +0,0 @@
1
- import { useCallback, useEffect, useRef, useState } from 'react';
2
- import { ConsoleSessionError, agentConsoleSessionUrl, openAgentConsole, } from '../client/console-session.js';
3
- export function useOpenAgentConsole(options = {}) {
4
- const [isPending, setIsPending] = useState(false);
5
- const [error, setError] = useState(null);
6
- // Kept in a ref so a caller passing an inline object literal (the common case) doesn't change the
7
- // identity of `open` on every render, which would defeat memoizing anything downstream.
8
- const optionsRef = useRef(options);
9
- optionsRef.current = options;
10
- const open = useCallback(() => {
11
- setIsPending(true);
12
- setError(null);
13
- void openAgentConsole(optionsRef.current)
14
- .then(() => {
15
- // Deliberately NOT clearing `isPending` on success: the navigation is already underway and
16
- // this component is about to be torn down. Flipping the button back to idle first produces
17
- // a visible flicker of "ready to click again" on a page that is leaving.
18
- //
19
- // "About to be torn down" is true only until the user presses Back — see the `pageshow`
20
- // effect below, which is the other half of this decision.
21
- })
22
- .catch((cause) => {
23
- setError(cause instanceof ConsoleSessionError
24
- ? cause
25
- : // Anything else got thrown before the client could classify it, so the endpoint is
26
- // the only context worth carrying — `ConsoleSessionError` takes the url, not a kind.
27
- new ConsoleSessionError(String(cause), agentConsoleSessionUrl(optionsRef.current.basePath)));
28
- setIsPending(false);
29
- });
30
- }, []);
31
- // The success path above leaves `isPending` stuck on purpose, which is only correct while the
32
- // page really is dying. It often isn't: `openAgentConsole` navigates with `location.assign`, and
33
- // a browser back/forward-cache hit FREEZES this page instead of destroying it — pressing Back
34
- // restores this component with the React state it fell asleep with, so the launcher wakes up
35
- // showing a spinner on a button that is disabled forever. Only a bfcache restore fires `pageshow`
36
- // with `persisted: true`, which makes it the one signal that distinguishes "you came back" from
37
- // "you loaded"; keying off anything looser (a plain `pageshow`, `visibilitychange`, `focus`)
38
- // would also fire while a mint is genuinely in flight and reintroduce the flicker the comment
39
- // above exists to prevent. So: clear it here, and ONLY here.
40
- useEffect(() => {
41
- // Guarded rather than assumed: this hook ships in a published package and hosts render it
42
- // through SSR, where `window` does not exist. (`window` is never touched at module scope.)
43
- if (typeof window === 'undefined')
44
- return;
45
- const onPageShow = (event) => {
46
- if (event.persisted)
47
- setIsPending(false);
48
- };
49
- window.addEventListener('pageshow', onPageShow);
50
- return () => window.removeEventListener('pageshow', onPageShow);
51
- }, []);
52
- const reset = useCallback(() => setError(null), []);
53
- return { open, isPending, error, reset };
54
- }
55
- /**
56
- * TanStack Query integration WITHOUT a TanStack dependency: the returned object is the shape
57
- * `useMutation` takes, so a host that already uses Query wires the launcher into its own cache,
58
- * devtools and error handling with no extra adapter — and a host that doesn't never pays for it.
59
- *
60
- * ```ts
61
- * const { mutate, isPending } = useMutation(openAgentConsoleMutationOptions({ headers }));
62
- * ```
63
- */
64
- export function openAgentConsoleMutationOptions(options = {}) {
65
- return {
66
- mutationKey: ['agent', 'console', 'open', options.basePath ?? null],
67
- mutationFn: () => openAgentConsole(options),
68
- };
69
- }
70
- //# sourceMappingURL=use-open-console.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-open-console.js","sourceRoot":"","sources":["../../src/react/use-open-console.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjE,OAAO,EACL,mBAAmB,EAEnB,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,8BAA8B,CAAC;AAqBtC,MAAM,UAAU,mBAAmB,CAAC,UAA8B,EAAE;IAClE,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAA6B,IAAI,CAAC,CAAC;IAErE,kGAAkG;IAClG,wFAAwF;IACxF,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IACnC,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;IAE7B,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE;QAC5B,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,KAAK,gBAAgB,CAAC,UAAU,CAAC,OAAO,CAAC;aACtC,IAAI,CAAC,GAAG,EAAE;YACT,2FAA2F;YAC3F,2FAA2F;YAC3F,yEAAyE;YACzE,EAAE;YACF,wFAAwF;YACxF,0DAA0D;QAC5D,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;YACxB,QAAQ,CACN,KAAK,YAAY,mBAAmB;gBAClC,CAAC,CAAC,KAAK;gBACP,CAAC,CAAC,mFAAmF;oBACnF,qFAAqF;oBACrF,IAAI,mBAAmB,CACrB,MAAM,CAAC,KAAK,CAAC,EACb,sBAAsB,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,CACpD,CACN,CAAC;YACF,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;IACP,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,8FAA8F;IAC9F,iGAAiG;IACjG,8FAA8F;IAC9F,6FAA6F;IAC7F,kGAAkG;IAClG,gGAAgG;IAChG,6FAA6F;IAC7F,8FAA8F;IAC9F,6DAA6D;IAC7D,SAAS,CAAC,GAAG,EAAE;QACb,0FAA0F;QAC1F,2FAA2F;QAC3F,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO;QAC1C,MAAM,UAAU,GAAG,CAAC,KAA0B,EAAE,EAAE;YAChD,IAAI,KAAK,CAAC,SAAS;gBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;QAC3C,CAAC,CAAC;QACF,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QAChD,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAClE,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;IAEpD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AAC3C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,+BAA+B,CAAC,UAA8B,EAAE;IAI9E,OAAO;QACL,WAAW,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAU;QAC5E,UAAU,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,OAAO,CAAC;KAC5C,CAAC;AACJ,CAAC"}