@specship/specship-win32-arm64 0.11.6 → 0.11.7

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 (38) hide show
  1. package/lib/dist/server/routes/chat.js +2 -3
  2. package/lib/dist/server/routes/claude.js +2 -3
  3. package/lib/dist/server/routes/events.js +2 -3
  4. package/lib/dist/server/routes/projects.js +2 -3
  5. package/lib/dist/server/routes/sse.js +23 -0
  6. package/lib/dist/server/routes/workflow.js +2 -3
  7. package/lib/dist/web/{chunk-H2TR6BKW.js → chunk-7KWBINA7.js} +1 -1
  8. package/lib/dist/web/{chunk-BZ5SMVXG.js → chunk-7MUNFW56.js} +1 -1
  9. package/lib/dist/web/{chunk-Z23KACD6.js → chunk-AZUUBUEJ.js} +1 -1
  10. package/lib/dist/web/{chunk-BDF4LLKR.js → chunk-CYXQILZI.js} +1 -1
  11. package/lib/dist/web/{chunk-PAO2624Y.js → chunk-DTWIJ3GJ.js} +1 -1
  12. package/lib/dist/web/{chunk-G2FTQVMJ.js → chunk-E27QAKAB.js} +1 -1
  13. package/lib/dist/web/{chunk-YPWBUJH7.js → chunk-EXBUKHH2.js} +1 -1
  14. package/lib/dist/web/{chunk-YVAUYHOB.js → chunk-F5TBUYDH.js} +1 -1
  15. package/lib/dist/web/{chunk-C6I5R6UZ.js → chunk-FC3R7YHR.js} +1 -1
  16. package/lib/dist/web/{chunk-IXQIWN6Z.js → chunk-G7RXFHYO.js} +1 -1
  17. package/lib/dist/web/{chunk-NY5CBIVU.js → chunk-HPKNOV45.js} +1 -1
  18. package/lib/dist/web/{chunk-PBRCKHEQ.js → chunk-JGDK6YKG.js} +1 -1
  19. package/lib/dist/web/{chunk-5CR7TMVN.js → chunk-JPSYO24K.js} +1 -1
  20. package/lib/dist/web/{chunk-FYXVIWM2.js → chunk-K7UD24Z4.js} +1 -1
  21. package/lib/dist/web/{chunk-QJSQ3ORB.js → chunk-LIFS4XH2.js} +1 -1
  22. package/lib/dist/web/{chunk-6FZTSHJS.js → chunk-MADMRWIK.js} +1 -1
  23. package/lib/dist/web/{chunk-7ALHQYYG.js → chunk-MNFTHCSJ.js} +1 -1
  24. package/lib/dist/web/{chunk-7ULUC3DC.js → chunk-N5WSFE4J.js} +1 -1
  25. package/lib/dist/web/{chunk-G2MHCJUR.js → chunk-PCW6R7OP.js} +1 -1
  26. package/lib/dist/web/{chunk-EAWW6PQJ.js → chunk-POCVU4VK.js} +1 -1
  27. package/lib/dist/web/chunk-TWVVIWKO.js +1 -0
  28. package/lib/dist/web/{chunk-HZYJAXHL.js → chunk-U67LRNER.js} +1 -1
  29. package/lib/dist/web/{chunk-KXMWAQNB.js → chunk-USVLLFVR.js} +1 -1
  30. package/lib/dist/web/{chunk-U6CWVOZO.js → chunk-UYOKO7C5.js} +1 -1
  31. package/lib/dist/web/{chunk-7V4MGZCG.js → chunk-XAUQEKZX.js} +1 -1
  32. package/lib/dist/web/{chunk-D7HQMX7C.js → chunk-YXYPTZ6E.js} +1 -1
  33. package/lib/dist/web/index.html +1 -1
  34. package/lib/dist/web/{main-A6QZ3DLK.js → main-5B4RR3BC.js} +1 -1
  35. package/lib/node_modules/.package-lock.json +1 -1
  36. package/lib/package.json +1 -1
  37. package/package.json +1 -1
  38. package/lib/dist/web/chunk-3H2EZLZN.js +0 -1
@@ -26,6 +26,7 @@
26
26
  * `done`. The chunking is presentation pacing only; a client disconnect ends
27
27
  * the stream cleanly without throwing (A4).
28
28
  */
29
+ import { writeSseHead } from './sse.js';
29
30
  import { answerForIntent, chunkAnswer } from './chat-answer.js';
30
31
  import { classifyIntent } from '../chat/classify.js';
31
32
  export async function registerChatRoutes(app) {
@@ -74,9 +75,7 @@ export async function registerChatRoutes(app) {
74
75
  const { found, answer, sources } = answerForIntent(cg, classified);
75
76
  const chunks = chunkAnswer(answer);
76
77
  const tool = toolForIntent(classified);
77
- reply.raw.setHeader('Content-Type', 'text/event-stream');
78
- reply.raw.setHeader('Cache-Control', 'no-cache');
79
- reply.raw.setHeader('Connection', 'keep-alive');
78
+ writeSseHead(req, reply);
80
79
  let closed = false;
81
80
  let timer;
82
81
  const write = (event, data) => {
@@ -16,6 +16,7 @@
16
16
  * GET /api/claude/specship-impact?range=&project= — SpecShip token-impact aggregation
17
17
  * POST /api/claude/ingest — force a one-shot ingest pass
18
18
  */
19
+ import { writeSseHead } from './sse.js';
19
20
  import { decodeProjectSlug } from '../ingest/index.js';
20
21
  import { computeSpecshipImpact } from '../ingest/impact-query.js';
21
22
  /**
@@ -204,9 +205,7 @@ export async function registerClaudeRoutes(app) {
204
205
  const row = db.prepare('SELECT MAX(ts) as m FROM claude_tool_calls WHERE session_id = ?').get(sessionId);
205
206
  lastToolTs = row?.m ?? 0;
206
207
  }
207
- reply.raw.setHeader('Content-Type', 'text/event-stream');
208
- reply.raw.setHeader('Cache-Control', 'no-cache');
209
- reply.raw.setHeader('Connection', 'keep-alive');
208
+ writeSseHead(req, reply);
210
209
  reply.raw.setHeader('X-Accel-Buffering', 'no'); // nginx-friendly
211
210
  reply.raw.flushHeaders();
212
211
  // Initial snapshot — gives the client a clean baseline (so it knows
@@ -14,6 +14,7 @@
14
14
  * desktop notifications, gated on permission + per-type toggles.
15
15
  */
16
16
  import os from 'node:os';
17
+ import { writeSseHead } from './sse.js';
17
18
  import path from 'node:path';
18
19
  import { enumerate } from './projects.js';
19
20
  const POLL_MS = 3000;
@@ -25,9 +26,7 @@ const SWEEP_MS = 24 * 60 * 60 * 1000;
25
26
  export async function registerEventsRoutes(app) {
26
27
  const claudeRoot = path.join(os.homedir(), '.claude', 'projects');
27
28
  app.get('/api/events', async (req, reply) => {
28
- reply.raw.setHeader('Content-Type', 'text/event-stream');
29
- reply.raw.setHeader('Cache-Control', 'no-cache');
30
- reply.raw.setHeader('Connection', 'keep-alive');
29
+ writeSseHead(req, reply);
31
30
  reply.raw.write(': connected\n\n');
32
31
  // Per-connection seen-state — emit only NEW transitions.
33
32
  const lastStatus = new Map(); // `${slug}:${runId}` -> status
@@ -12,6 +12,7 @@
12
12
  * user have at all?" — without coupling to the specship instance.
13
13
  */
14
14
  import { EventEmitter } from 'node:events';
15
+ import { writeSseHead } from './sse.js';
15
16
  import { promises as fs, watch } from 'node:fs';
16
17
  import os from 'node:os';
17
18
  import path from 'node:path';
@@ -144,9 +145,7 @@ export async function registerProjectsRoutes(app) {
144
145
  return { claudeRoot, projects: await enumerate(claudeRoot) };
145
146
  });
146
147
  app.get('/api/projects/events', async (req, reply) => {
147
- reply.raw.setHeader('Content-Type', 'text/event-stream');
148
- reply.raw.setHeader('Cache-Control', 'no-cache');
149
- reply.raw.setHeader('Connection', 'keep-alive');
148
+ writeSseHead(req, reply);
150
149
  reply.raw.flushHeaders();
151
150
  let closed = false;
152
151
  const onClose = () => {
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Set the standard SSE response headers on the raw socket AND reflect the
3
+ * request's `Origin` as `Access-Control-Allow-Origin`.
4
+ *
5
+ * SSE handlers write to `reply.raw` directly and flush immediately, which
6
+ * bypasses Fastify's response lifecycle — so `@fastify/cors` (registered with
7
+ * `origin: true`) never gets to add the CORS header. Without this, a
8
+ * cross-origin `EventSource` is blocked: e.g. the dashboard opened at
9
+ * `127.0.0.1:<port>` calling the API host `localhost` (different origins to the
10
+ * browser), or the Angular dev server on `:4200`. Echoing the request origin
11
+ * mirrors what `origin: true` does for the non-raw routes.
12
+ */
13
+ export function writeSseHead(req, reply) {
14
+ reply.raw.setHeader('Content-Type', 'text/event-stream');
15
+ reply.raw.setHeader('Cache-Control', 'no-cache');
16
+ reply.raw.setHeader('Connection', 'keep-alive');
17
+ const origin = req.headers.origin;
18
+ if (typeof origin === 'string' && origin.length > 0) {
19
+ reply.raw.setHeader('Access-Control-Allow-Origin', origin);
20
+ reply.raw.setHeader('Access-Control-Allow-Credentials', 'true');
21
+ reply.raw.setHeader('Vary', 'Origin');
22
+ }
23
+ }
@@ -14,6 +14,7 @@
14
14
  * faster + more reliable than wiring an in-process event bus across packages.
15
15
  */
16
16
  import path from 'node:path';
17
+ import { writeSseHead } from './sse.js';
17
18
  import { existsSync, readdirSync, readFileSync } from 'node:fs';
18
19
  import { fileURLToPath, pathToFileURL } from 'node:url';
19
20
  async function resolveCg(app, req, reply) {
@@ -169,9 +170,7 @@ export async function registerWorkflowRoutes(app) {
169
170
  const { sq } = executorFor(cg);
170
171
  const runId = req.params.id;
171
172
  let lastId = parseInt(req.query.since ?? '0', 10) || 0;
172
- reply.raw.setHeader('Content-Type', 'text/event-stream');
173
- reply.raw.setHeader('Cache-Control', 'no-cache');
174
- reply.raw.setHeader('Connection', 'keep-alive');
173
+ writeSseHead(req, reply);
175
174
  reply.raw.flushHeaders();
176
175
  let closed = false;
177
176
  req.raw.on('close', () => { closed = true; });
@@ -1 +1 @@
1
- import{a as q}from"./chunk-YWIRU745.js";import{a as Q}from"./chunk-JLOJCDIY.js";import{a as N}from"./chunk-5NTGUSXJ.js";import{a as $,b as j}from"./chunk-WBJ5VEB5.js";import{a as R}from"./chunk-SQPYSOV6.js";import{c as M}from"./chunk-DOKZOFKM.js";import{c as V}from"./chunk-PAO2624Y.js";import{a as L}from"./chunk-PBRCKHEQ.js";import{a as O}from"./chunk-3H2EZLZN.js";import{Aa as p,Ga as S,I as C,Ia as b,Ka as c,M as v,N as g,Ta as D,Ua as I,Va as l,W as y,Wa as u,Xa as x,ea as n,ka as z,lb as h,qa as P,ra as _,sa as f,ua as F,va as w,wa as k,xa as s,ya as r,za as o,zb as A}from"./chunk-SYGIPC2P.js";import{a as E,b as T}from"./chunk-Q7L6LLAK.js";var H=(i,t)=>t.id;function J(i,t){i&1&&p(0,"app-pick-project-empty",0)}function K(i,t){if(i&1){let e=S();r(0,"button",10),b("click",function(){let d=v(e).$implicit,m=c(2);return g(m.toggleFilter(d))}),r(1,"span",11),l(2),o(),r(3,"span",12),l(4),o()()}if(i&2){let e=t.$implicit,a=c(2);D("background",a.stateFilter()[e]?a.STATE[e].bg:"var(--bg-panel)")("color",a.stateFilter()[e]?a.STATE[e].color:"var(--text-muted)")("border-color",a.stateFilter()[e]?"transparent":"var(--border-subtle)"),n(2),u(e),n(2),u(a.counts()[e])}}function U(i,t){if(i&1&&(r(0,"span",13),l(1),o(),r(2,"button",14),p(3,"app-icon",15),l(4," Re-verify all "),o(),r(5,"button",14),p(6,"app-icon",16),l(7," Open all "),o()),i&2){let e=c(2);n(),x("",e.selectedCount()," selected"),n(2),s("size",12),n(3),s("size",12)}}function W(i,t){i&1&&p(0,"app-empty",8)}function X(i,t){if(i&1&&(r(0,"app-pill",28),l(1),o()),i&2){let e=c().$implicit;n(),u(e.driftAxis)}}function Y(i,t){i&1&&(r(0,"button",37),p(1,"app-icon",39),l(2," Fix "),o()),i&2&&(n(),s("size",12))}function Z(i,t){i&1&&(r(0,"button",37),p(1,"app-icon",15),l(2," Re-verify "),o()),i&2&&(n(),s("size",12))}function ee(i,t){i&1&&(r(0,"button",37),p(1,"app-icon",40),l(2," Re-attach "),o()),i&2&&(n(),s("size",12))}function te(i,t){if(i&1){let e=S();r(0,"div",32)(1,"div",33)(2,"div")(3,"div",34),l(4,"Spec"),o(),r(5,"div",35),l(6),o()(),r(7,"div")(8,"div",34),l(9,"Target"),o(),r(10,"div",35),l(11),o()(),r(12,"div")(13,"div",34),l(14,"Provenance"),o(),r(15,"div",35),l(16),o()(),r(17,"div")(18,"div",34),l(19,"Drift axis"),o(),r(20,"div",35),l(21),o()(),r(22,"div")(23,"div",34),l(24,"Age"),o(),r(25,"div",35),l(26),o()()(),r(27,"div",36),_(28,Y,3,1,"button",37),_(29,Z,3,1,"button",37),_(30,ee,3,1,"button",37),r(31,"button",38),b("click",function(){v(e);let d=c().$implicit,m=c(3);return g(m.openSpec(d.specId))}),l(32," Open spec "),o(),r(33,"button",38),b("click",function(){v(e);let d=c().$implicit,m=c(3);return g(m.showInGraph(d.specId))}),l(34," Show in graph "),o()()()}if(i&2){let e=c().$implicit,a=c(3);n(6),u(e.specId),n(5),u(e.targetQualifiedName),n(5),u(e.provenance),n(5),u(e.driftAxis??"\u2014"),n(5),u(a.ageOf(e)),n(2),f(e.state==="drifted"?28:-1),n(),f(e.state==="broken"?29:-1),n(),f(e.state==="orphaned"?30:-1)}}function ie(i,t){if(i&1){let e=S();r(0,"div",18)(1,"div",19)(2,"input",20),b("click",function(d){let m=v(e).$implicit,B=c(3);return g(B.toggleSelect(m.id,d))})("change",function(d){return d.stopPropagation()}),o(),r(3,"div",21),b("click",function(){let d=v(e).$implicit,m=c(3);return g(m.toggleExpand(d.id))}),r(4,"div",22),p(5,"app-state-pill",23),o(),r(6,"span",24),l(7),o(),r(8,"span",25),l(9),o(),p(10,"app-icon",26),r(11,"span",27),l(12),o(),_(13,X,2,1,"app-pill",28),r(14,"span",29),l(15),o(),r(16,"span",30),l(17),o(),p(18,"app-icon",31),o()(),_(19,te,35,8,"div",32),o()}if(i&2){let e=t.$implicit,a=c(3);D("border-bottom","1px solid var(--border-subtle)"),n(),I("selected",a.isSelected(e.id)),n(),s("checked",a.isSelected(e.id)),P("aria-label","Select "+e.specId),n(3),s("state",e.state),n(2),x(" ",e.specId," "),n(2),x(" ",e.specTitle??""," "),n(),s("size",13),n(2),x(" ",e.targetQualifiedName," "),n(),f(e.driftAxis?13:-1),n(2),x(" ",e.provenance," "),n(2),x(" ",a.ageOf(e)," "),n(),s("name",a.isExpanded(e.id)?"chevronDown":"chevronRight")("size",13),n(),f(a.isExpanded(e.id)?19:-1)}}function ne(i,t){if(i&1&&(r(0,"div",9),w(1,ie,20,17,"div",17,H),o()),i&2){let e=c(2);n(),k(e.visibleLinks())}}function re(i,t){if(i&1&&(r(0,"div",1)(1,"div",2),p(2,"app-page-head",3),o(),r(3,"div",4),p(4,"app-icon",5),w(5,K,5,8,"button",6,F),p(7,"div",7),_(8,U,8,3),o(),_(9,W,1,0,"app-empty",8)(10,ne,3,0,"div",9),o()),i&2){let e=c();n(2),s("sub",e.resource.state().loading?"loading\u2026":e.allLinks().length+" links need attention"),n(2),s("size",13),n(),k(e.states),n(3),f(e.selectedCount()>0?8:-1),n(),f(e.visibleLinks().length===0?9:10)}}var G=class i{api=C(O);projects=C(L);router=C(M);stateFilter=y({drifted:!0,broken:!0,orphaned:!0});resource=V(this.api,()=>`/api/drift?state=drifted,broken,orphaned${this.projects.projectQuery("&")}`);selected=y(new Set);expanded=y(new Set);allLinks=h(()=>this.resource.state().data?.links??[]);visibleLinks=h(()=>{let t=this.stateFilter();return this.allLinks().filter(e=>t[e.state])});counts=h(()=>{let t={drifted:0,broken:0,orphaned:0};for(let e of this.allLinks())e.state in t&&t[e.state]++;return t});selectedCount=h(()=>this.selected().size);states=["drifted","broken","orphaned"];STATE=$;toggleFilter(t){this.stateFilter.update(e=>T(E({},e),{[t]:!e[t]}))}toggleSelect(t,e){e.stopPropagation(),this.selected.update(a=>{let d=new Set(a);return d.has(t)?d.delete(t):d.add(t),d})}isSelected(t){return this.selected().has(t)}toggleExpand(t){this.expanded.update(e=>{let a=new Set(e);return a.has(t)?a.delete(t):a.add(t),a})}isExpanded(t){return this.expanded().has(t)}ageOf(t){if(!t.updatedAt)return"";let e=Date.now()-t.updatedAt;return e<6e4?"just now":e<36e5?Math.round(e/6e4)+"m":e<864e5?Math.round(e/36e5)+"h":Math.round(e/864e5)+"d"}openSpec(t){this.router.navigate(["/specs"],{queryParams:{sel:t}})}showInGraph(t){this.router.navigate(["/graph"],{queryParams:{focus:"spec:"+t}})}static \u0275fac=function(e){return new(e||i)};static \u0275cmp=z({type:i,selectors:[["app-drift"]],decls:2,vars:1,consts:[["surface","The drift queue"],[1,"page","col"],[2,"padding","16px 18px 0"],["icon","drift","title","Drift queue",3,"sub"],[1,"filter-bar","row","gap-8"],["name","filter",2,"color","var(--text-muted)",3,"size"],["type","button",1,"filter-chip","row","gap-6",3,"background","color","border-color"],[1,"grow"],["icon","check","title","All links in good standing \u2728","body","Nothing has drifted. Every spec link points at code that still matches."],[1,"scroll-y","list-frame"],["type","button",1,"filter-chip","row","gap-6",3,"click"],[2,"text-transform","capitalize"],[1,"tabular",2,"opacity","0.7"],[1,"secondary",2,"font-size","12px"],["type","button",1,"btn","btn-secondary","btn-sm"],["name","refresh",3,"size"],["name","reveal",3,"size"],[1,"drift-row-wrap",3,"border-bottom"],[1,"drift-row-wrap"],[1,"drift-row","row","gap-10"],["type","checkbox",1,"drift-checkbox",3,"click","change","checked"],[1,"row","gap-10","grow",2,"min-width","0","cursor","pointer",3,"click"],[2,"width","92px","flex-shrink","0"],[3,"state"],[1,"mono",2,"font-size","12px","color","var(--node-spec)","flex-shrink","0","width","130px","overflow","hidden","text-overflow","ellipsis","white-space","nowrap"],[1,"secondary",2,"font-size","12.5px","overflow","hidden","text-overflow","ellipsis","white-space","nowrap","flex","0 1 220px"],["name","arrowRight",2,"color","var(--text-muted)","flex-shrink","0",3,"size"],[1,"mono","grow",2,"font-size","11.5px","color","var(--text-secondary)","overflow","hidden","text-overflow","ellipsis","white-space","nowrap"],["color","var(--warn)","bg","var(--warn-soft)"],[1,"mono","muted",2,"font-size","11px","flex-shrink","0","width","48px","text-align","right"],[1,"mono","muted","tabular",2,"font-size","11px","flex-shrink","0","width","32px","text-align","right"],[2,"color","var(--text-muted)","flex-shrink","0",3,"name","size"],[1,"drift-detail"],[1,"row",2,"gap","22px","padding","10px 0","flex-wrap","wrap"],[1,"muted",2,"font-size","10.5px"],[1,"mono",2,"font-size","12.5px","margin-top","1px"],[1,"row","gap-8"],["type","button",1,"btn","btn-primary","btn-sm"],["type","button",1,"btn","btn-secondary","btn-sm",3,"click"],["name","wrench",3,"size"],["name","graph",3,"size"]],template:function(e,a){e&1&&_(0,J,1,0,"app-pick-project-empty",0)(1,re,11,4,"div",1),e&2&&f(a.resource.state().noProject?0:1)},dependencies:[R,A,N,q,j,Q],styles:["[_nghost-%COMP%]{display:contents}.page[_ngcontent-%COMP%]{flex:1;min-height:0}.filter-bar[_ngcontent-%COMP%]{padding:0 18px 12px;flex-wrap:wrap;align-items:center}.filter-chip[_ngcontent-%COMP%]{height:26px;padding:0 10px;border-radius:999px;border:1px solid var(--border-subtle);font-size:11.5px;font-weight:500;cursor:pointer;font-family:inherit;align-items:center;transition:background .12s,color .12s}.list-frame[_ngcontent-%COMP%]{flex:1;border-top:1px solid var(--border-subtle);margin:0}.drift-row[_ngcontent-%COMP%]{padding:10px 14px;cursor:default;align-items:center;transition:background 80ms;background:transparent}.drift-row[_ngcontent-%COMP%]:not(.selected):hover{background:var(--bg-hover)}.drift-row.selected[_ngcontent-%COMP%]{background:var(--accent-soft)}.drift-checkbox[_ngcontent-%COMP%]{accent-color:var(--accent);width:14px;height:14px;flex-shrink:0;cursor:pointer}.drift-detail[_ngcontent-%COMP%]{padding:0 14px 14px 50px;background:var(--bg-canvas)}"],changeDetection:0})};export{G as Drift};
1
+ import{a as q}from"./chunk-YWIRU745.js";import{a as Q}from"./chunk-JLOJCDIY.js";import{a as N}from"./chunk-5NTGUSXJ.js";import{a as $,b as j}from"./chunk-WBJ5VEB5.js";import{a as R}from"./chunk-SQPYSOV6.js";import{c as M}from"./chunk-DOKZOFKM.js";import{c as V}from"./chunk-DTWIJ3GJ.js";import{a as L}from"./chunk-JGDK6YKG.js";import{a as O}from"./chunk-TWVVIWKO.js";import{Aa as p,Ga as S,I as C,Ia as b,Ka as c,M as v,N as g,Ta as D,Ua as I,Va as l,W as y,Wa as u,Xa as x,ea as n,ka as z,lb as h,qa as P,ra as _,sa as f,ua as F,va as w,wa as k,xa as s,ya as r,za as o,zb as A}from"./chunk-SYGIPC2P.js";import{a as E,b as T}from"./chunk-Q7L6LLAK.js";var H=(i,t)=>t.id;function J(i,t){i&1&&p(0,"app-pick-project-empty",0)}function K(i,t){if(i&1){let e=S();r(0,"button",10),b("click",function(){let d=v(e).$implicit,m=c(2);return g(m.toggleFilter(d))}),r(1,"span",11),l(2),o(),r(3,"span",12),l(4),o()()}if(i&2){let e=t.$implicit,a=c(2);D("background",a.stateFilter()[e]?a.STATE[e].bg:"var(--bg-panel)")("color",a.stateFilter()[e]?a.STATE[e].color:"var(--text-muted)")("border-color",a.stateFilter()[e]?"transparent":"var(--border-subtle)"),n(2),u(e),n(2),u(a.counts()[e])}}function U(i,t){if(i&1&&(r(0,"span",13),l(1),o(),r(2,"button",14),p(3,"app-icon",15),l(4," Re-verify all "),o(),r(5,"button",14),p(6,"app-icon",16),l(7," Open all "),o()),i&2){let e=c(2);n(),x("",e.selectedCount()," selected"),n(2),s("size",12),n(3),s("size",12)}}function W(i,t){i&1&&p(0,"app-empty",8)}function X(i,t){if(i&1&&(r(0,"app-pill",28),l(1),o()),i&2){let e=c().$implicit;n(),u(e.driftAxis)}}function Y(i,t){i&1&&(r(0,"button",37),p(1,"app-icon",39),l(2," Fix "),o()),i&2&&(n(),s("size",12))}function Z(i,t){i&1&&(r(0,"button",37),p(1,"app-icon",15),l(2," Re-verify "),o()),i&2&&(n(),s("size",12))}function ee(i,t){i&1&&(r(0,"button",37),p(1,"app-icon",40),l(2," Re-attach "),o()),i&2&&(n(),s("size",12))}function te(i,t){if(i&1){let e=S();r(0,"div",32)(1,"div",33)(2,"div")(3,"div",34),l(4,"Spec"),o(),r(5,"div",35),l(6),o()(),r(7,"div")(8,"div",34),l(9,"Target"),o(),r(10,"div",35),l(11),o()(),r(12,"div")(13,"div",34),l(14,"Provenance"),o(),r(15,"div",35),l(16),o()(),r(17,"div")(18,"div",34),l(19,"Drift axis"),o(),r(20,"div",35),l(21),o()(),r(22,"div")(23,"div",34),l(24,"Age"),o(),r(25,"div",35),l(26),o()()(),r(27,"div",36),_(28,Y,3,1,"button",37),_(29,Z,3,1,"button",37),_(30,ee,3,1,"button",37),r(31,"button",38),b("click",function(){v(e);let d=c().$implicit,m=c(3);return g(m.openSpec(d.specId))}),l(32," Open spec "),o(),r(33,"button",38),b("click",function(){v(e);let d=c().$implicit,m=c(3);return g(m.showInGraph(d.specId))}),l(34," Show in graph "),o()()()}if(i&2){let e=c().$implicit,a=c(3);n(6),u(e.specId),n(5),u(e.targetQualifiedName),n(5),u(e.provenance),n(5),u(e.driftAxis??"\u2014"),n(5),u(a.ageOf(e)),n(2),f(e.state==="drifted"?28:-1),n(),f(e.state==="broken"?29:-1),n(),f(e.state==="orphaned"?30:-1)}}function ie(i,t){if(i&1){let e=S();r(0,"div",18)(1,"div",19)(2,"input",20),b("click",function(d){let m=v(e).$implicit,B=c(3);return g(B.toggleSelect(m.id,d))})("change",function(d){return d.stopPropagation()}),o(),r(3,"div",21),b("click",function(){let d=v(e).$implicit,m=c(3);return g(m.toggleExpand(d.id))}),r(4,"div",22),p(5,"app-state-pill",23),o(),r(6,"span",24),l(7),o(),r(8,"span",25),l(9),o(),p(10,"app-icon",26),r(11,"span",27),l(12),o(),_(13,X,2,1,"app-pill",28),r(14,"span",29),l(15),o(),r(16,"span",30),l(17),o(),p(18,"app-icon",31),o()(),_(19,te,35,8,"div",32),o()}if(i&2){let e=t.$implicit,a=c(3);D("border-bottom","1px solid var(--border-subtle)"),n(),I("selected",a.isSelected(e.id)),n(),s("checked",a.isSelected(e.id)),P("aria-label","Select "+e.specId),n(3),s("state",e.state),n(2),x(" ",e.specId," "),n(2),x(" ",e.specTitle??""," "),n(),s("size",13),n(2),x(" ",e.targetQualifiedName," "),n(),f(e.driftAxis?13:-1),n(2),x(" ",e.provenance," "),n(2),x(" ",a.ageOf(e)," "),n(),s("name",a.isExpanded(e.id)?"chevronDown":"chevronRight")("size",13),n(),f(a.isExpanded(e.id)?19:-1)}}function ne(i,t){if(i&1&&(r(0,"div",9),w(1,ie,20,17,"div",17,H),o()),i&2){let e=c(2);n(),k(e.visibleLinks())}}function re(i,t){if(i&1&&(r(0,"div",1)(1,"div",2),p(2,"app-page-head",3),o(),r(3,"div",4),p(4,"app-icon",5),w(5,K,5,8,"button",6,F),p(7,"div",7),_(8,U,8,3),o(),_(9,W,1,0,"app-empty",8)(10,ne,3,0,"div",9),o()),i&2){let e=c();n(2),s("sub",e.resource.state().loading?"loading\u2026":e.allLinks().length+" links need attention"),n(2),s("size",13),n(),k(e.states),n(3),f(e.selectedCount()>0?8:-1),n(),f(e.visibleLinks().length===0?9:10)}}var G=class i{api=C(O);projects=C(L);router=C(M);stateFilter=y({drifted:!0,broken:!0,orphaned:!0});resource=V(this.api,()=>`/api/drift?state=drifted,broken,orphaned${this.projects.projectQuery("&")}`);selected=y(new Set);expanded=y(new Set);allLinks=h(()=>this.resource.state().data?.links??[]);visibleLinks=h(()=>{let t=this.stateFilter();return this.allLinks().filter(e=>t[e.state])});counts=h(()=>{let t={drifted:0,broken:0,orphaned:0};for(let e of this.allLinks())e.state in t&&t[e.state]++;return t});selectedCount=h(()=>this.selected().size);states=["drifted","broken","orphaned"];STATE=$;toggleFilter(t){this.stateFilter.update(e=>T(E({},e),{[t]:!e[t]}))}toggleSelect(t,e){e.stopPropagation(),this.selected.update(a=>{let d=new Set(a);return d.has(t)?d.delete(t):d.add(t),d})}isSelected(t){return this.selected().has(t)}toggleExpand(t){this.expanded.update(e=>{let a=new Set(e);return a.has(t)?a.delete(t):a.add(t),a})}isExpanded(t){return this.expanded().has(t)}ageOf(t){if(!t.updatedAt)return"";let e=Date.now()-t.updatedAt;return e<6e4?"just now":e<36e5?Math.round(e/6e4)+"m":e<864e5?Math.round(e/36e5)+"h":Math.round(e/864e5)+"d"}openSpec(t){this.router.navigate(["/specs"],{queryParams:{sel:t}})}showInGraph(t){this.router.navigate(["/graph"],{queryParams:{focus:"spec:"+t}})}static \u0275fac=function(e){return new(e||i)};static \u0275cmp=z({type:i,selectors:[["app-drift"]],decls:2,vars:1,consts:[["surface","The drift queue"],[1,"page","col"],[2,"padding","16px 18px 0"],["icon","drift","title","Drift queue",3,"sub"],[1,"filter-bar","row","gap-8"],["name","filter",2,"color","var(--text-muted)",3,"size"],["type","button",1,"filter-chip","row","gap-6",3,"background","color","border-color"],[1,"grow"],["icon","check","title","All links in good standing \u2728","body","Nothing has drifted. Every spec link points at code that still matches."],[1,"scroll-y","list-frame"],["type","button",1,"filter-chip","row","gap-6",3,"click"],[2,"text-transform","capitalize"],[1,"tabular",2,"opacity","0.7"],[1,"secondary",2,"font-size","12px"],["type","button",1,"btn","btn-secondary","btn-sm"],["name","refresh",3,"size"],["name","reveal",3,"size"],[1,"drift-row-wrap",3,"border-bottom"],[1,"drift-row-wrap"],[1,"drift-row","row","gap-10"],["type","checkbox",1,"drift-checkbox",3,"click","change","checked"],[1,"row","gap-10","grow",2,"min-width","0","cursor","pointer",3,"click"],[2,"width","92px","flex-shrink","0"],[3,"state"],[1,"mono",2,"font-size","12px","color","var(--node-spec)","flex-shrink","0","width","130px","overflow","hidden","text-overflow","ellipsis","white-space","nowrap"],[1,"secondary",2,"font-size","12.5px","overflow","hidden","text-overflow","ellipsis","white-space","nowrap","flex","0 1 220px"],["name","arrowRight",2,"color","var(--text-muted)","flex-shrink","0",3,"size"],[1,"mono","grow",2,"font-size","11.5px","color","var(--text-secondary)","overflow","hidden","text-overflow","ellipsis","white-space","nowrap"],["color","var(--warn)","bg","var(--warn-soft)"],[1,"mono","muted",2,"font-size","11px","flex-shrink","0","width","48px","text-align","right"],[1,"mono","muted","tabular",2,"font-size","11px","flex-shrink","0","width","32px","text-align","right"],[2,"color","var(--text-muted)","flex-shrink","0",3,"name","size"],[1,"drift-detail"],[1,"row",2,"gap","22px","padding","10px 0","flex-wrap","wrap"],[1,"muted",2,"font-size","10.5px"],[1,"mono",2,"font-size","12.5px","margin-top","1px"],[1,"row","gap-8"],["type","button",1,"btn","btn-primary","btn-sm"],["type","button",1,"btn","btn-secondary","btn-sm",3,"click"],["name","wrench",3,"size"],["name","graph",3,"size"]],template:function(e,a){e&1&&_(0,J,1,0,"app-pick-project-empty",0)(1,re,11,4,"div",1),e&2&&f(a.resource.state().noProject?0:1)},dependencies:[R,A,N,q,j,Q],styles:["[_nghost-%COMP%]{display:contents}.page[_ngcontent-%COMP%]{flex:1;min-height:0}.filter-bar[_ngcontent-%COMP%]{padding:0 18px 12px;flex-wrap:wrap;align-items:center}.filter-chip[_ngcontent-%COMP%]{height:26px;padding:0 10px;border-radius:999px;border:1px solid var(--border-subtle);font-size:11.5px;font-weight:500;cursor:pointer;font-family:inherit;align-items:center;transition:background .12s,color .12s}.list-frame[_ngcontent-%COMP%]{flex:1;border-top:1px solid var(--border-subtle);margin:0}.drift-row[_ngcontent-%COMP%]{padding:10px 14px;cursor:default;align-items:center;transition:background 80ms;background:transparent}.drift-row[_ngcontent-%COMP%]:not(.selected):hover{background:var(--bg-hover)}.drift-row.selected[_ngcontent-%COMP%]{background:var(--accent-soft)}.drift-checkbox[_ngcontent-%COMP%]{accent-color:var(--accent);width:14px;height:14px;flex-shrink:0;cursor:pointer}.drift-detail[_ngcontent-%COMP%]{padding:0 14px 14px 50px;background:var(--bg-canvas)}"],changeDetection:0})};export{G as Drift};
@@ -1 +1 @@
1
- import{a as F,b as R,c as f}from"./chunk-BPCJLNBS.js";import{a as N}from"./chunk-JLOJCDIY.js";import{a as D}from"./chunk-5NTGUSXJ.js";import{d as z}from"./chunk-DOKZOFKM.js";import{c as T}from"./chunk-PAO2624Y.js";import"./chunk-PBRCKHEQ.js";import{a as k}from"./chunk-3H2EZLZN.js";import{Aa as l,I as h,Ia as S,Ka as m,Ta as g,Ua as b,Va as c,Wa as s,Xa as v,Ya as O,bb as w,cb as E,ea as n,ka as C,lb as d,qa as y,ra as u,sa as x,ua as P,va as M,wa as _,xa as p,ya as o,za as i,zb as I}from"./chunk-SYGIPC2P.js";import"./chunk-Q7L6LLAK.js";var $=()=>[0,1,2,3],j=a=>["/mcp",a],L=(a,t)=>t.key,B=(a,t)=>t.id;function G(a,t){if(a&1&&(o(0,"div",7),l(1,"app-icon",20),o(2,"span"),c(3),i()()),a&2){let e=m();n(),p("size",12),n(2),v(" ",e.errored()?"Couldn\u2019t reach the MCP endpoint \u2014 showing":"No live MCP data yet \u2014 showing"," seed servers (illustrative). ")}}function H(a,t){a&1&&l(0,"div",21)}function U(a,t){a&1&&(o(0,"div",18),M(1,H,1,0,"div",21,P),i()),a&2&&(n(),_(w(0,$)))}function q(a,t){if(a&1&&l(0,"span",43),a&2){let e=m().$implicit,r=m(3);g("background",r.stateMeta(e.state).color)}}function J(a,t){if(a&1&&(o(0,"a",28)(1,"span",29),l(2,"app-icon",24)(3,"span",30),i(),o(4,"span",31)(5,"span",32)(6,"span",33),c(7),i(),o(8,"app-pill",34),l(9,"app-icon",24),c(10),i()(),o(11,"span",35),c(12),i()(),o(13,"span",36)(14,"span",37)(15,"span",38),c(16),i(),o(17,"span",39),c(18),i()(),o(19,"span",40),u(20,q,1,2,"span",41),c(21),i(),l(22,"app-icon",42),i()()),a&2){let e=t.$implicit,r=m(3);p("routerLink",E(32,j,e.id)),y("aria-label",e.name+" \u2014 "+r.stateMeta(e.state).label+", "+r.scopeMeta(e.scope).label),n(),g("background",r.mix(e.color))("color",e.color),n(),p("name",e.icon)("size",18),n(),g("background",r.stateMeta(e.state).color),b("dot-glow",e.state==="running"),n(4),s(e.name),n(),p("color",r.scopeMeta(e.scope).color)("bg",r.mix(r.scopeMeta(e.scope).color)),n(),p("name",r.scopeMeta(e.scope).icon)("size",10),n(),v(" ",r.scopeMeta(e.scope).label," "),n(2),s(e.command),n(3),b("cold",e.tools.length===0),n(),s(e.tools.length),n(2),s(r.toolLabel(e.tools.length)),n(),g("color",r.stateMeta(e.state).color)("background",r.mix(r.stateMeta(e.state).color)),b("pulse",e.state==="running"),n(),x(r.stateMeta(e.state).dot?20:-1),n(),v(" ",r.stateMeta(e.state).label," "),n(),p("size",15)}}function K(a,t){if(a&1&&(o(0,"div",22)(1,"div",23),l(2,"app-icon",24),o(3,"span",12),c(4),i(),o(5,"span",25),c(6),i(),o(7,"span",26),c(8),i()(),o(9,"div",27),M(10,J,23,34,"a",28,B),i()()),a&2){let e=t.$implicit;n(2),g("color",e.meta.color),p("name",e.meta.icon)("size",13),n(2),s(e.meta.label),n(2),s(e.meta.hint),n(2),v("\xB7 ",e.servers.length),n(2),_(e.servers)}}function Q(a,t){if(a&1&&M(0,K,12,7,"div",22,L),a&2){let e=m();_(e.groups())}}var A=class a{api=h(k);resource=T(this.api,()=>"/api/mcp/servers");loading=d(()=>this.resource.state().loading);servers=d(()=>{let t=this.resource.state();if(t.loading)return[];let e=t.data?.servers;return e&&e.length?e:F.servers});isSeed=d(()=>{let t=this.resource.state();return!t.loading&&!t.data?.servers?.length});errored=d(()=>this.resource.state().error!==null);total=d(()=>this.servers().length);running=d(()=>this.servers().filter(t=>t.state==="running").length);totalTools=d(()=>this.servers().reduce((t,e)=>t+e.tools.length,0));needsAttention=d(()=>this.servers().filter(t=>t.state==="error").length);groups=d(()=>{let t=this.servers();return["global","project"].map(e=>({key:e,meta:f[e],servers:t.filter(r=>r.scope===e)})).filter(e=>e.servers.length>0)});scopeMeta(t){return f[t]}stateMeta(t){return R[t]}mix(t,e=14){return`color-mix(in srgb, ${t} ${e}%, transparent)`}toolLabel(t){return t===1?"tool":"tools"}onReload(){this.resource.refetch()}static \u0275fac=function(e){return new(e||a)};static \u0275cmp=C({type:a,selectors:[["app-mcp"]],decls:50,vars:13,consts:[[1,"scroll-y","mcp-list"],["icon","plug","title","MCP servers","sub","Model Context Protocol servers configured at the global and project level"],["actions","",1,"row","gap-6"],["type","button",1,"btn","btn-ghost","btn-sm",3,"click"],["name","refresh",3,"size"],["type","button",1,"btn","btn-secondary","btn-sm"],["name","plus",3,"size"],[1,"mcp-seed-note","row","gap-8"],[1,"mcp-tile-grid"],[1,"card","mcp-tile"],[1,"row","gap-6","tile-eyebrow"],["name","plug",2,"color","var(--accent)",3,"size"],[1,"eyebrow"],[1,"mono","tabular","tile-value"],[1,"mono","muted","tile-sub"],["name","circle",2,"color","var(--success)",3,"size"],["name","wrench",2,"color","var(--node-code)",3,"size"],["name","drift",2,"color","var(--error)",3,"size"],[1,"col","gap-8","mcp-group"],[2,"height","20px"],["name","circle",3,"size"],[1,"skel",2,"height","62px","border-radius","10px"],[1,"mcp-group"],[1,"row","gap-8","group-head"],[3,"name","size"],[1,"mono","muted","group-hint"],[1,"muted","group-count"],[1,"col","gap-8"],[1,"card","server-row",3,"routerLink"],[1,"server-avatar"],[1,"server-dot"],[1,"grow","server-main"],[1,"row","gap-8","server-name-row"],[1,"mono","server-name"],[3,"color","bg"],[1,"mono","muted","server-command"],[1,"row","gap-16","server-meta"],[1,"server-toolcount"],[1,"mono","tabular","count-n"],[1,"muted","count-label"],[1,"pill","state-pill"],[1,"pill-dot",3,"background"],["name","chevronRight",2,"color","var(--text-muted)",3,"size"],[1,"pill-dot"]],template:function(e,r){e&1&&(o(0,"div",0)(1,"app-page-head",1)(2,"div",2)(3,"button",3),S("click",function(){return r.onReload()}),l(4,"app-icon",4),c(5," Reload "),i(),o(6,"button",5),l(7,"app-icon",6),c(8," Add server "),i()()(),u(9,G,4,2,"div",7),o(10,"div",8)(11,"div",9)(12,"div",10),l(13,"app-icon",11),o(14,"span",12),c(15,"Servers"),i()(),o(16,"div",13),c(17),i(),o(18,"div",14),c(19,"global + project"),i()(),o(20,"div",9)(21,"div",10),l(22,"app-icon",15),o(23,"span",12),c(24,"Running"),i()(),o(25,"div",13),c(26),i(),o(27,"div",14),c(28,"connected now"),i()(),o(29,"div",9)(30,"div",10),l(31,"app-icon",16),o(32,"span",12),c(33,"Tools"),i()(),o(34,"div",13),c(35),i(),o(36,"div",14),c(37,"exposed to agents"),i()(),o(38,"div",9)(39,"div",10),l(40,"app-icon",17),o(41,"span",12),c(42,"Needs attention"),i()(),o(43,"div",13),c(44),i(),o(45,"div",14),c(46,"auth / connection"),i()()(),u(47,U,3,1,"div",18)(48,Q,2,0),l(49,"div",19),i()),e&2&&(n(4),p("size",13),n(3),p("size",13),n(2),x(r.isSeed()?9:-1),n(4),p("size",12),n(4),s(r.total()),n(5),p("size",12),n(4),O("",r.running()," / ",r.total()),n(5),p("size",12),n(4),s(r.totalTools()),n(5),p("size",12),n(4),s(r.needsAttention()),n(3),x(r.loading()?47:48))},dependencies:[z,D,N,I],styles:['@charset "UTF-8";[_nghost-%COMP%]{display:flex;flex-direction:column;min-height:0;flex:1}.mcp-list[_ngcontent-%COMP%]{flex:1;min-height:0;padding:18px}.mcp-seed-note[_ngcontent-%COMP%]{margin:-6px 0 16px;padding:8px 11px;border-radius:8px;font-size:11.5px;color:var(--text-secondary);background:var(--bg-panel-2);border:1px solid var(--border-subtle)}.mcp-seed-note[_ngcontent-%COMP%] app-icon[_ngcontent-%COMP%]{color:var(--text-muted)}.mcp-tile-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;margin-bottom:18px}.mcp-tile[_ngcontent-%COMP%]{padding:11px 13px;display:flex;flex-direction:column;gap:3px}.mcp-tile[_ngcontent-%COMP%] .tile-eyebrow[_ngcontent-%COMP%]{color:var(--text-muted)}.mcp-tile[_ngcontent-%COMP%] .eyebrow[_ngcontent-%COMP%]{letter-spacing:.03em}.mcp-tile[_ngcontent-%COMP%] .tile-value[_ngcontent-%COMP%]{font-size:19px;font-weight:650;letter-spacing:-.01em}.mcp-tile[_ngcontent-%COMP%] .tile-sub[_ngcontent-%COMP%]{font-size:10px}.mcp-group[_ngcontent-%COMP%]{margin-bottom:18px}.group-head[_ngcontent-%COMP%]{margin-bottom:9px}.group-head[_ngcontent-%COMP%] .group-hint[_ngcontent-%COMP%], .group-head[_ngcontent-%COMP%] .group-count[_ngcontent-%COMP%]{font-size:11px}.server-row[_ngcontent-%COMP%]{padding:12px 14px;display:flex;align-items:center;gap:12px;cursor:pointer;text-decoration:none;color:inherit;transition:background .1s,border-color .1s}.server-row[_ngcontent-%COMP%]:hover{background:var(--bg-panel-2);border-color:var(--border-strong)}.server-row[_ngcontent-%COMP%]:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.server-avatar[_ngcontent-%COMP%]{position:relative;width:36px;height:36px;border-radius:9px;display:grid;place-items:center;flex-shrink:0}.server-dot[_ngcontent-%COMP%]{position:absolute;right:-2px;bottom:-2px;width:11px;height:11px;border-radius:50%;border:2px solid var(--bg-panel)}.server-dot.dot-glow[_ngcontent-%COMP%]{box-shadow:0 0 6px var(--success)}.server-main[_ngcontent-%COMP%]{min-width:0;display:flex;flex-direction:column}.server-name-row[_ngcontent-%COMP%]{display:flex;align-items:center}.server-name[_ngcontent-%COMP%]{font-size:13.5px;font-weight:600}.server-command[_ngcontent-%COMP%]{font-size:11px;margin-top:3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.server-meta[_ngcontent-%COMP%]{flex-shrink:0}.server-toolcount[_ngcontent-%COMP%]{display:flex;flex-direction:column;align-items:flex-end;width:56px}.server-toolcount[_ngcontent-%COMP%] .count-n[_ngcontent-%COMP%]{font-size:14px;font-weight:600}.server-toolcount[_ngcontent-%COMP%] .count-n.cold[_ngcontent-%COMP%]{color:var(--text-muted)}.server-toolcount[_ngcontent-%COMP%] .count-label[_ngcontent-%COMP%]{font-size:10px}.state-pill[_ngcontent-%COMP%]{width:92px;justify-content:center}.state-pill.pulse[_ngcontent-%COMP%] .pill-dot[_ngcontent-%COMP%]{animation:_ngcontent-%COMP%_mcpPulse 1.6s ease-out infinite}@keyframes _ngcontent-%COMP%_mcpPulse{0%{box-shadow:0 0 color-mix(in srgb,var(--success) 60%,transparent)}70%{box-shadow:0 0 0 5px transparent}to{box-shadow:0 0 0 0 transparent}}'],changeDetection:0})};export{A as Mcp};
1
+ import{a as F,b as R,c as f}from"./chunk-BPCJLNBS.js";import{a as N}from"./chunk-JLOJCDIY.js";import{a as D}from"./chunk-5NTGUSXJ.js";import{d as z}from"./chunk-DOKZOFKM.js";import{c as T}from"./chunk-DTWIJ3GJ.js";import"./chunk-JGDK6YKG.js";import{a as k}from"./chunk-TWVVIWKO.js";import{Aa as l,I as h,Ia as S,Ka as m,Ta as g,Ua as b,Va as c,Wa as s,Xa as v,Ya as O,bb as w,cb as E,ea as n,ka as C,lb as d,qa as y,ra as u,sa as x,ua as P,va as M,wa as _,xa as p,ya as o,za as i,zb as I}from"./chunk-SYGIPC2P.js";import"./chunk-Q7L6LLAK.js";var $=()=>[0,1,2,3],j=a=>["/mcp",a],L=(a,t)=>t.key,B=(a,t)=>t.id;function G(a,t){if(a&1&&(o(0,"div",7),l(1,"app-icon",20),o(2,"span"),c(3),i()()),a&2){let e=m();n(),p("size",12),n(2),v(" ",e.errored()?"Couldn\u2019t reach the MCP endpoint \u2014 showing":"No live MCP data yet \u2014 showing"," seed servers (illustrative). ")}}function H(a,t){a&1&&l(0,"div",21)}function U(a,t){a&1&&(o(0,"div",18),M(1,H,1,0,"div",21,P),i()),a&2&&(n(),_(w(0,$)))}function q(a,t){if(a&1&&l(0,"span",43),a&2){let e=m().$implicit,r=m(3);g("background",r.stateMeta(e.state).color)}}function J(a,t){if(a&1&&(o(0,"a",28)(1,"span",29),l(2,"app-icon",24)(3,"span",30),i(),o(4,"span",31)(5,"span",32)(6,"span",33),c(7),i(),o(8,"app-pill",34),l(9,"app-icon",24),c(10),i()(),o(11,"span",35),c(12),i()(),o(13,"span",36)(14,"span",37)(15,"span",38),c(16),i(),o(17,"span",39),c(18),i()(),o(19,"span",40),u(20,q,1,2,"span",41),c(21),i(),l(22,"app-icon",42),i()()),a&2){let e=t.$implicit,r=m(3);p("routerLink",E(32,j,e.id)),y("aria-label",e.name+" \u2014 "+r.stateMeta(e.state).label+", "+r.scopeMeta(e.scope).label),n(),g("background",r.mix(e.color))("color",e.color),n(),p("name",e.icon)("size",18),n(),g("background",r.stateMeta(e.state).color),b("dot-glow",e.state==="running"),n(4),s(e.name),n(),p("color",r.scopeMeta(e.scope).color)("bg",r.mix(r.scopeMeta(e.scope).color)),n(),p("name",r.scopeMeta(e.scope).icon)("size",10),n(),v(" ",r.scopeMeta(e.scope).label," "),n(2),s(e.command),n(3),b("cold",e.tools.length===0),n(),s(e.tools.length),n(2),s(r.toolLabel(e.tools.length)),n(),g("color",r.stateMeta(e.state).color)("background",r.mix(r.stateMeta(e.state).color)),b("pulse",e.state==="running"),n(),x(r.stateMeta(e.state).dot?20:-1),n(),v(" ",r.stateMeta(e.state).label," "),n(),p("size",15)}}function K(a,t){if(a&1&&(o(0,"div",22)(1,"div",23),l(2,"app-icon",24),o(3,"span",12),c(4),i(),o(5,"span",25),c(6),i(),o(7,"span",26),c(8),i()(),o(9,"div",27),M(10,J,23,34,"a",28,B),i()()),a&2){let e=t.$implicit;n(2),g("color",e.meta.color),p("name",e.meta.icon)("size",13),n(2),s(e.meta.label),n(2),s(e.meta.hint),n(2),v("\xB7 ",e.servers.length),n(2),_(e.servers)}}function Q(a,t){if(a&1&&M(0,K,12,7,"div",22,L),a&2){let e=m();_(e.groups())}}var A=class a{api=h(k);resource=T(this.api,()=>"/api/mcp/servers");loading=d(()=>this.resource.state().loading);servers=d(()=>{let t=this.resource.state();if(t.loading)return[];let e=t.data?.servers;return e&&e.length?e:F.servers});isSeed=d(()=>{let t=this.resource.state();return!t.loading&&!t.data?.servers?.length});errored=d(()=>this.resource.state().error!==null);total=d(()=>this.servers().length);running=d(()=>this.servers().filter(t=>t.state==="running").length);totalTools=d(()=>this.servers().reduce((t,e)=>t+e.tools.length,0));needsAttention=d(()=>this.servers().filter(t=>t.state==="error").length);groups=d(()=>{let t=this.servers();return["global","project"].map(e=>({key:e,meta:f[e],servers:t.filter(r=>r.scope===e)})).filter(e=>e.servers.length>0)});scopeMeta(t){return f[t]}stateMeta(t){return R[t]}mix(t,e=14){return`color-mix(in srgb, ${t} ${e}%, transparent)`}toolLabel(t){return t===1?"tool":"tools"}onReload(){this.resource.refetch()}static \u0275fac=function(e){return new(e||a)};static \u0275cmp=C({type:a,selectors:[["app-mcp"]],decls:50,vars:13,consts:[[1,"scroll-y","mcp-list"],["icon","plug","title","MCP servers","sub","Model Context Protocol servers configured at the global and project level"],["actions","",1,"row","gap-6"],["type","button",1,"btn","btn-ghost","btn-sm",3,"click"],["name","refresh",3,"size"],["type","button",1,"btn","btn-secondary","btn-sm"],["name","plus",3,"size"],[1,"mcp-seed-note","row","gap-8"],[1,"mcp-tile-grid"],[1,"card","mcp-tile"],[1,"row","gap-6","tile-eyebrow"],["name","plug",2,"color","var(--accent)",3,"size"],[1,"eyebrow"],[1,"mono","tabular","tile-value"],[1,"mono","muted","tile-sub"],["name","circle",2,"color","var(--success)",3,"size"],["name","wrench",2,"color","var(--node-code)",3,"size"],["name","drift",2,"color","var(--error)",3,"size"],[1,"col","gap-8","mcp-group"],[2,"height","20px"],["name","circle",3,"size"],[1,"skel",2,"height","62px","border-radius","10px"],[1,"mcp-group"],[1,"row","gap-8","group-head"],[3,"name","size"],[1,"mono","muted","group-hint"],[1,"muted","group-count"],[1,"col","gap-8"],[1,"card","server-row",3,"routerLink"],[1,"server-avatar"],[1,"server-dot"],[1,"grow","server-main"],[1,"row","gap-8","server-name-row"],[1,"mono","server-name"],[3,"color","bg"],[1,"mono","muted","server-command"],[1,"row","gap-16","server-meta"],[1,"server-toolcount"],[1,"mono","tabular","count-n"],[1,"muted","count-label"],[1,"pill","state-pill"],[1,"pill-dot",3,"background"],["name","chevronRight",2,"color","var(--text-muted)",3,"size"],[1,"pill-dot"]],template:function(e,r){e&1&&(o(0,"div",0)(1,"app-page-head",1)(2,"div",2)(3,"button",3),S("click",function(){return r.onReload()}),l(4,"app-icon",4),c(5," Reload "),i(),o(6,"button",5),l(7,"app-icon",6),c(8," Add server "),i()()(),u(9,G,4,2,"div",7),o(10,"div",8)(11,"div",9)(12,"div",10),l(13,"app-icon",11),o(14,"span",12),c(15,"Servers"),i()(),o(16,"div",13),c(17),i(),o(18,"div",14),c(19,"global + project"),i()(),o(20,"div",9)(21,"div",10),l(22,"app-icon",15),o(23,"span",12),c(24,"Running"),i()(),o(25,"div",13),c(26),i(),o(27,"div",14),c(28,"connected now"),i()(),o(29,"div",9)(30,"div",10),l(31,"app-icon",16),o(32,"span",12),c(33,"Tools"),i()(),o(34,"div",13),c(35),i(),o(36,"div",14),c(37,"exposed to agents"),i()(),o(38,"div",9)(39,"div",10),l(40,"app-icon",17),o(41,"span",12),c(42,"Needs attention"),i()(),o(43,"div",13),c(44),i(),o(45,"div",14),c(46,"auth / connection"),i()()(),u(47,U,3,1,"div",18)(48,Q,2,0),l(49,"div",19),i()),e&2&&(n(4),p("size",13),n(3),p("size",13),n(2),x(r.isSeed()?9:-1),n(4),p("size",12),n(4),s(r.total()),n(5),p("size",12),n(4),O("",r.running()," / ",r.total()),n(5),p("size",12),n(4),s(r.totalTools()),n(5),p("size",12),n(4),s(r.needsAttention()),n(3),x(r.loading()?47:48))},dependencies:[z,D,N,I],styles:['@charset "UTF-8";[_nghost-%COMP%]{display:flex;flex-direction:column;min-height:0;flex:1}.mcp-list[_ngcontent-%COMP%]{flex:1;min-height:0;padding:18px}.mcp-seed-note[_ngcontent-%COMP%]{margin:-6px 0 16px;padding:8px 11px;border-radius:8px;font-size:11.5px;color:var(--text-secondary);background:var(--bg-panel-2);border:1px solid var(--border-subtle)}.mcp-seed-note[_ngcontent-%COMP%] app-icon[_ngcontent-%COMP%]{color:var(--text-muted)}.mcp-tile-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;margin-bottom:18px}.mcp-tile[_ngcontent-%COMP%]{padding:11px 13px;display:flex;flex-direction:column;gap:3px}.mcp-tile[_ngcontent-%COMP%] .tile-eyebrow[_ngcontent-%COMP%]{color:var(--text-muted)}.mcp-tile[_ngcontent-%COMP%] .eyebrow[_ngcontent-%COMP%]{letter-spacing:.03em}.mcp-tile[_ngcontent-%COMP%] .tile-value[_ngcontent-%COMP%]{font-size:19px;font-weight:650;letter-spacing:-.01em}.mcp-tile[_ngcontent-%COMP%] .tile-sub[_ngcontent-%COMP%]{font-size:10px}.mcp-group[_ngcontent-%COMP%]{margin-bottom:18px}.group-head[_ngcontent-%COMP%]{margin-bottom:9px}.group-head[_ngcontent-%COMP%] .group-hint[_ngcontent-%COMP%], .group-head[_ngcontent-%COMP%] .group-count[_ngcontent-%COMP%]{font-size:11px}.server-row[_ngcontent-%COMP%]{padding:12px 14px;display:flex;align-items:center;gap:12px;cursor:pointer;text-decoration:none;color:inherit;transition:background .1s,border-color .1s}.server-row[_ngcontent-%COMP%]:hover{background:var(--bg-panel-2);border-color:var(--border-strong)}.server-row[_ngcontent-%COMP%]:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.server-avatar[_ngcontent-%COMP%]{position:relative;width:36px;height:36px;border-radius:9px;display:grid;place-items:center;flex-shrink:0}.server-dot[_ngcontent-%COMP%]{position:absolute;right:-2px;bottom:-2px;width:11px;height:11px;border-radius:50%;border:2px solid var(--bg-panel)}.server-dot.dot-glow[_ngcontent-%COMP%]{box-shadow:0 0 6px var(--success)}.server-main[_ngcontent-%COMP%]{min-width:0;display:flex;flex-direction:column}.server-name-row[_ngcontent-%COMP%]{display:flex;align-items:center}.server-name[_ngcontent-%COMP%]{font-size:13.5px;font-weight:600}.server-command[_ngcontent-%COMP%]{font-size:11px;margin-top:3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.server-meta[_ngcontent-%COMP%]{flex-shrink:0}.server-toolcount[_ngcontent-%COMP%]{display:flex;flex-direction:column;align-items:flex-end;width:56px}.server-toolcount[_ngcontent-%COMP%] .count-n[_ngcontent-%COMP%]{font-size:14px;font-weight:600}.server-toolcount[_ngcontent-%COMP%] .count-n.cold[_ngcontent-%COMP%]{color:var(--text-muted)}.server-toolcount[_ngcontent-%COMP%] .count-label[_ngcontent-%COMP%]{font-size:10px}.state-pill[_ngcontent-%COMP%]{width:92px;justify-content:center}.state-pill.pulse[_ngcontent-%COMP%] .pill-dot[_ngcontent-%COMP%]{animation:_ngcontent-%COMP%_mcpPulse 1.6s ease-out infinite}@keyframes _ngcontent-%COMP%_mcpPulse{0%{box-shadow:0 0 color-mix(in srgb,var(--success) 60%,transparent)}70%{box-shadow:0 0 0 5px transparent}to{box-shadow:0 0 0 0 transparent}}'],changeDetection:0})};export{A as Mcp};
@@ -1 +1 @@
1
- import{a as A,b as U,c as K,d as L}from"./chunk-BPCJLNBS.js";import{a as B}from"./chunk-NKPK3BR3.js";import{a as $}from"./chunk-YWIRU745.js";import{a as R}from"./chunk-JLOJCDIY.js";import{a as V}from"./chunk-PZSU53SS.js";import{a as z,c as D}from"./chunk-DOKZOFKM.js";import{c as F}from"./chunk-PAO2624Y.js";import"./chunk-PBRCKHEQ.js";import{a as I}from"./chunk-3H2EZLZN.js";import{Aa as c,Ga as M,I as y,Ia as f,Ka as s,M as C,N as b,Ta as v,Ua as u,Va as a,W as S,Wa as p,Xa as h,Ya as k,ea as i,ka as E,lb as g,qa as T,ra as m,sa as _,va as P,wa as O,xa as d,ya as t,za as n,zb as N}from"./chunk-SYGIPC2P.js";import"./chunk-Q7L6LLAK.js";var w=(r,o)=>o.name;function j(r,o){r&1&&(t(0,"div",1),c(1,"div",3)(2,"div",4)(3,"div",5),n())}function G(r,o){if(r&1){let e=M();t(0,"app-empty",2)(1,"button",6),f("click",function(){C(e);let x=s();return b(x.back())}),c(2,"app-icon",7),a(3," Back to MCP servers "),n()()}if(r&2){let e=s();d("body","No MCP server with id \u201C"+e.serverId()+"\u201D is configured."),i(2),d("size",13)}}function J(r,o){if(r&1&&(t(0,"div",30),c(1,"app-icon",59),t(2,"span",60),a(3),n(),t(4,"button",61),a(5,"Re-authenticate"),n()()),r&2){let e=s();i(),d("size",14),i(2),p(e.error)}}function Q(r,o){r&1&&(t(0,"div",31)(1,"button",62),c(2,"app-icon",63),a(3," Enable server"),n(),t(4,"span",64),a(5,"Tools below are declared but not currently exposed."),n()()),r&2&&(i(2),d("size",12))}function W(r,o){r&1&&(t(0,"span",45),a(1,"click a tool for its schema"),n())}function X(r,o){r&1&&(t(0,"app-pill",88),a(1,"required"),n())}function Y(r,o){r&1&&(t(0,"span",89),a(1,"optional"),n())}function Z(r,o){if(r&1&&(t(0,"span",90),a(1),n()),r&2){let e=s().$implicit;i(),h("\xB7 ",e.hint)}}function ee(r,o){if(r&1&&(t(0,"div",85)(1,"span",86),a(2),n(),t(3,"span",87),a(4),n(),m(5,X,2,0,"app-pill",88)(6,Y,2,0,"span",89),m(7,Z,2,1,"span",90),n()),r&2){let e=o.$implicit;i(2),p(e.name),i(2),p(e.type),i(),_(e.required?5:6),i(2),_(e.hint?7:-1)}}function te(r,o){if(r&1&&(t(0,"div",79),P(1,ee,8,4,"div",85,w),n()),r&2){let e=s(2).$implicit;i(),O(e.params)}}function ne(r,o){r&1&&(t(0,"div",80),a(1,"No parameters."),n())}function ie(r,o){if(r&1){let e=M();t(0,"button",91),f("click",function(){C(e);let x=s(5);return b(x.go("heatmap"))}),c(1,"app-icon",92),a(2," View usage in heatmap "),n()}r&2&&(i(),d("size",13))}function oe(r,o){if(r&1&&(t(0,"div",77)(1,"div",78),a(2,"Input schema"),n(),m(3,te,3,0,"div",79)(4,ne,2,0,"div",80),t(5,"div",81),a(6,"Example call"),n(),t(7,"div",82)(8,"span",83),a(9),n(),c(10,"app-copy-btn",29),n(),m(11,ie,3,1,"button",84),n()),r&2){let e=s().$implicit;i(3),_(e.params.length?3:4),i(6),p(e.example),i(),d("text",e.example),i(),_(e.drill?11:-1)}}function ae(r,o){if(r&1){let e=M();t(0,"div",66)(1,"button",67),f("click",function(){let x=C(e).$implicit,H=s(3);return b(H.toggleTool(x.name))}),t(2,"span",68),c(3,"app-icon",12),n(),t(4,"span",69)(5,"span",70),a(6),n(),t(7,"span",71),a(8),n()(),t(9,"span",72)(10,"span",73),a(11),n(),t(12,"span",74),a(13,"calls / 7d"),n()(),t(14,"span",75)(15,"span",73),a(16),n(),t(17,"span",74),a(18,"tok / call"),n()(),c(19,"app-icon",76),n(),m(20,oe,12,4,"div",77),n()}if(r&2){let e=o.$implicit,l=s(3);u("open",l.isToolOpen(e.name)),i(),T("aria-expanded",l.isToolOpen(e.name)),i(),v("background",l.mix(e.color,15))("color",e.color),i(),d("name",e.icon)("size",15),i(3),p(e.name),i(),u("expanded",l.isToolOpen(e.name)),i(),p(e.desc),i(2),u("cold",l.isCold(e)),i(),h("\xD7",e.stat.calls),i(4),v("color",l.isCold(e)?"var(--text-muted)":l.isHeavy(e)?"var(--warn)":"var(--success)"),i(),p(l.isCold(e)?"\u2014":l.fmtK(l.avg(e))),i(3),d("name",l.isToolOpen(e.name)?"chevronDown":"chevronRight")("size",15),i(),_(l.isToolOpen(e.name)?20:-1)}}function re(r,o){if(r&1&&(t(0,"div",46),P(1,ae,21,22,"div",65,w),n()),r&2){let e=s();i(),O(e.tools)}}function le(r,o){r&1&&c(0,"app-empty",47)}function ce(r,o){if(r&1&&(t(0,"div",93),c(1,"span",94),t(2,"span",95)(3,"span",96),a(4),n(),t(5,"span",97),a(6),n()(),t(7,"span",98)(8,"span",99),a(9),n(),t(10,"span",100),a(11),n()()()),r&2){let e=o.$implicit,l=s(3);i(),v("background",l.clientMeta(e.state).color),u("glow",e.state==="active"),i(3),p(e.name),i(2),p(e.host),i(2),v("color",l.clientMeta(e.state).color),i(),p(l.clientMeta(e.state).label),i(2),p(e.last)}}function pe(r,o){if(r&1&&(t(0,"div",46),P(1,ce,12,10,"div",93,w),n()),r&2){let e=s();i(),O(e.usedBy)}}function de(r,o){r&1&&(t(0,"div",52),a(1,"No clients reference this server."),n())}function se(r,o){if(r&1){let e=M();t(0,"div",8)(1,"button",9),f("click",function(){C(e);let x=s();return b(x.back())}),c(2,"app-icon",7),a(3," MCP servers "),n(),t(4,"span",10),a(5),n(),t(6,"app-pill",11),c(7,"app-icon",12),a(8),n(),t(9,"span",13),a(10),n()(),t(11,"div",14),c(12,"div",15),t(13,"div",16)(14,"div",17)(15,"div",18),c(16,"span",19),t(17,"span",20),a(18),n(),t(19,"span",21),a(20),n()(),t(21,"span",22)(22,"span",23),a(23,"Transport"),n(),t(24,"span",24),a(25),n()(),t(26,"span",22)(27,"span",23),a(28,"Uptime"),n(),t(29,"span",24),a(30),n()(),t(31,"span",22)(32,"span",23),a(33,"Protocol"),n(),t(34,"span",24),a(35),n()(),t(36,"span",22)(37,"span",23),a(38,"Tools"),n(),t(39,"span",24),a(40),n()(),c(41,"span",25),t(42,"span",26),c(43,"app-icon",27),t(44,"span",28),a(45),n(),c(46,"app-copy-btn",29),n()(),m(47,J,6,2,"div",30),m(48,Q,6,1,"div",31),n()(),t(49,"div",32)(50,"div",33)(51,"div",34),c(52,"app-icon",35),t(53,"span",36),a(54,"Tools"),n()(),t(55,"div",37),a(56),n(),t(57,"div",38),a(58,"exposed"),n()(),t(59,"div",33)(60,"div",34),c(61,"app-icon",39),t(62,"span",36),a(63,"Calls"),n()(),t(64,"div",37),a(65),n(),t(66,"div",38),a(67,"this week"),n()(),t(68,"div",33)(69,"div",34),c(70,"app-icon",40),t(71,"span",36),a(72,"Result tokens"),n()(),t(73,"div",37),a(74),n(),t(75,"div",38),a(76,"returned to context"),n()(),t(77,"div",33)(78,"div",34),c(79,"app-icon",41),t(80,"span",36),a(81,"Used by"),n()(),t(82,"div",37),a(83),n(),t(84,"div",38),a(85,"clients"),n()()(),t(86,"div",42)(87,"div",43)(88,"div",44)(89,"span",36),a(90),n(),m(91,W,2,0,"span",45),n(),m(92,re,3,0,"div",46)(93,le,1,0,"app-empty",47),n(),t(94,"div",48)(95,"div",49),c(96,"app-icon",50),t(97,"span",51),a(98,"Used by"),n()(),m(99,pe,3,0,"div",46)(100,de,2,0,"div",52),n(),t(101,"div",53)(102,"div",49),c(103,"app-icon",54),t(104,"span",55),a(105,"Configuration"),n(),t(106,"span",56),a(107),n(),c(108,"app-copy-btn",29),n(),t(109,"pre",57),a(110),n()()(),c(111,"div",58)}if(r&2){let e=o,l=s();i(2),d("size",14),i(3),p(e.name),i(),d("color",l.scopeMeta(e.scope).color)("bg",l.mix(l.scopeMeta(e.scope).color)),i(),d("name",l.scopeMeta(e.scope).icon)("size",10),i(),h(" ",l.scopeMeta(e.scope).label," "),i(2),p(l.scopeMeta(e.scope).hint),i(2),v("background",l.stateMeta(e.state).color),i(4),v("background",l.stateMeta(e.state).color),u("glow",e.state==="running")("pulse",e.state==="running"),i(2),p(l.stateMeta(e.state).label),i(2),k("",e.name,"-mcp ",e.version),i(5),p(e.transport),i(5),p(e.uptime),i(5),p(e.protocol),i(5),p(e.tools.length),i(3),d("size",12),i(2),p(e.command),i(),d("text",e.command),i(),_(e.error?47:-1),i(),_(e.state==="disabled"?48:-1),i(4),d("size",12),i(4),p(e.tools.length),i(5),d("size",12),i(4),p(l.totalCalls().toLocaleString()),i(5),d("size",12),i(4),p(l.fmtTok(l.totalTokens())),i(5),d("size",12),i(4),p(e.usedBy.length),i(7),h("Tools \xB7 ",e.tools.length),i(),_(e.tools.length?91:-1),i(),_(e.tools.length?92:93),i(4),d("size",14),i(3),_(e.usedBy.length?99:100),i(4),d("size",14),i(4),p(l.scopeMeta(e.scope).hint),i(),d("text",e.config),i(2),p(e.config)}}var q=class r{api=y(I);route=y(z);router=y(D);resource=F(this.api,()=>"/api/mcp/servers");paramMap=B(this.route.paramMap,{initialValue:this.route.snapshot.paramMap});serverId=g(()=>this.paramMap().get("id")??"");loading=g(()=>this.resource.state().loading);servers=g(()=>{let o=this.resource.state();if(o.loading)return[];let e=o.data?.servers;return e&&e.length?e:A.servers});server=g(()=>this.servers().find(o=>o.id===this.serverId()));notFound=g(()=>!this.loading()&&!this.server());openTool=S(null);isToolOpen(o){return this.openTool()===o}toggleTool(o){this.openTool.update(e=>e===o?null:o)}totalCalls=g(()=>(this.server()?.tools??[]).reduce((o,e)=>o+e.stat.calls,0));totalTokens=g(()=>(this.server()?.tools??[]).reduce((o,e)=>o+e.stat.tokens,0));stateMeta(o){return U[o]}scopeMeta(o){return K[o]}clientMeta(o){return L[o]}mix(o,e=14){return`color-mix(in srgb, ${o} ${e}%, transparent)`}avg(o){return o.stat.calls?Math.round(o.stat.tokens/o.stat.calls):0}isHeavy(o){return this.avg(o)>8e3}isCold(o){return o.stat.calls===0}back(){this.router.navigate(["/mcp"])}go(o){this.router.navigate(["/"+o])}fmtK(o){return o>=1e6?(o/1e6).toFixed(1)+"M":o>=1e3?(o/1e3).toFixed(o>=1e4?0:1)+"k":String(o)}fmtTok(o){return o>=1e6?(o/1e6).toFixed(1)+"M":this.fmtK(o)}static \u0275fac=function(e){return new(e||r)};static \u0275cmp=E({type:r,selectors:[["app-mcp-detail"]],decls:4,vars:1,consts:[[1,"scroll-y","mcp-detail"],[1,"col","gap-12"],["icon","plug","title","Server not found",3,"body"],[1,"skel",2,"height","34px","width","280px","border-radius","8px"],[1,"skel",2,"height","96px","border-radius","12px"],[1,"skel",2,"height","64px","border-radius","12px"],["action","","type","button",1,"btn","btn-secondary","btn-sm",3,"click"],["name","chevronLeft",3,"size"],[1,"row","gap-10","detail-head"],["type","button",1,"btn","btn-ghost","btn-sm",3,"click"],[1,"mono","detail-name"],[3,"color","bg"],[3,"name","size"],[1,"mono","muted","detail-hint"],[1,"card","banner"],[1,"banner-accent"],[1,"banner-body"],[1,"row","gap-16","banner-top"],[1,"row","gap-8","banner-state"],[1,"banner-dot"],[1,"banner-state-label"],[1,"mono","muted","banner-version"],[1,"seg"],[1,"muted","seg-l"],[1,"mono","tabular","seg-v"],[1,"grow"],[1,"row","gap-8","banner-cmd"],["name","command",2,"color","var(--text-muted)","flex-shrink","0",3,"size"],[1,"mono","banner-cmd-text"],[3,"text"],[1,"row","gap-8","banner-error"],[1,"row","gap-8","banner-disabled"],[1,"mcp-tile-grid"],[1,"card","mcp-tile"],[1,"row","gap-6","tile-eyebrow"],["name","plug",2,"color","var(--accent)",3,"size"],[1,"eyebrow"],[1,"mono","tabular","tile-value"],[1,"mono","muted","tile-sub"],["name","wrench",2,"color","var(--node-code)",3,"size"],["name","database",2,"color","var(--node-route)",3,"size"],["name","bot",2,"color","var(--success)",3,"size"],[1,"detail-grid"],[1,"tools-col"],[1,"row","gap-8","tools-head"],[1,"muted","tools-hint"],[1,"col","gap-8"],["icon","plug","title","No tools available","body","This server isn\u2019t exposing any tools \u2014 fix the connection above to load its tool list."],[1,"card","card-pad","usedby-card"],[1,"row","gap-8","panel-head"],["name","bot",2,"color","var(--node-route)",3,"size"],[1,"panel-title"],[1,"muted","usedby-empty"],[1,"card","card-pad","config-card"],["name","settings",2,"color","var(--accent)",3,"size"],[1,"grow","panel-title"],[1,"mono","muted","config-hint"],[1,"mono","scroll-y","config-pre"],[2,"height","24px"],["name","drift",2,"color","var(--error)","flex-shrink","0",3,"size"],[1,"banner-error-text"],["type","button",1,"btn","btn-secondary","btn-sm"],["type","button",1,"btn","btn-primary","btn-sm"],["name","play",3,"size"],[1,"muted","banner-disabled-note"],[1,"card","tool-row",3,"open"],[1,"card","tool-row"],["type","button",1,"row","gap-10","tool-header",3,"click"],[1,"tool-ic"],[1,"grow","tool-main"],[1,"mono","tool-name"],[1,"secondary","tool-desc"],[1,"tool-stat"],[1,"mono","tabular","stat-n"],[1,"mono","tabular","muted","stat-l"],[1,"tool-stat","tok"],[2,"color","var(--text-muted)",3,"name","size"],[1,"tool-expand"],[1,"eyebrow","expand-label",2,"margin-top","2px"],[1,"col","gap-5","param-list"],[1,"muted","param-none"],[1,"eyebrow","expand-label"],[1,"row","gap-8","example-call"],[1,"mono","grow","example-text"],["type","button",1,"btn","btn-secondary","btn-sm","drill-btn"],[1,"row","gap-8","param-row"],[1,"mono","param-name"],[1,"mono","param-type"],["color","var(--error)","bg","var(--error-soft)"],[1,"muted","mono","param-opt"],[1,"mono","muted","param-hint"],["type","button",1,"btn","btn-secondary","btn-sm","drill-btn",3,"click"],["name","heatmap",3,"size"],[1,"row","gap-10","client-row"],[1,"client-dot"],[1,"grow","client-main"],[1,"client-name"],[1,"mono","muted","client-host"],[1,"client-meta"],[1,"mono","client-state"],[1,"mono","muted","client-last"]],template:function(e,l){if(e&1&&(t(0,"div",0),m(1,j,4,0,"div",1)(2,G,4,2,"app-empty",2)(3,se,112,45),n()),e&2){let x;i(),_(l.loading()?1:l.notFound()?2:(x=l.server())?3:-1,x)}},dependencies:[R,V,$,N],styles:['@charset "UTF-8";[_nghost-%COMP%]{display:flex;flex-direction:column;min-height:0;flex:1}.mcp-detail[_ngcontent-%COMP%]{flex:1;min-height:0;padding:18px}.detail-head[_ngcontent-%COMP%]{align-items:center;margin-bottom:14px}.detail-head[_ngcontent-%COMP%] .detail-name[_ngcontent-%COMP%]{font-size:16px;font-weight:600}.detail-head[_ngcontent-%COMP%] .detail-hint[_ngcontent-%COMP%]{font-size:11.5px}.banner[_ngcontent-%COMP%]{padding:0;overflow:hidden;margin-bottom:14px;display:flex}.banner-accent[_ngcontent-%COMP%]{width:3px;flex-shrink:0}.banner-body[_ngcontent-%COMP%]{flex:1;padding:13px 16px;min-width:0}.banner-top[_ngcontent-%COMP%]{flex-wrap:wrap;align-items:center}.banner-state[_ngcontent-%COMP%]{flex-shrink:0;align-items:center}.banner-dot[_ngcontent-%COMP%]{width:9px;height:9px;border-radius:50%}.banner-dot.glow[_ngcontent-%COMP%]{box-shadow:0 0 8px var(--success)}.banner-dot.pulse[_ngcontent-%COMP%]{animation:_ngcontent-%COMP%_mcpPulse 1.6s ease-out infinite}.banner-state-label[_ngcontent-%COMP%]{font-weight:600;font-size:13.5px}.banner-version[_ngcontent-%COMP%]{font-size:12px}.seg[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:6px;flex-shrink:0}.seg[_ngcontent-%COMP%] .seg-l[_ngcontent-%COMP%]{font-size:11px}.seg[_ngcontent-%COMP%] .seg-v[_ngcontent-%COMP%]{font-size:12px;color:var(--text-secondary)}.banner-cmd[_ngcontent-%COMP%]{background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:7px;padding:6px 10px;max-width:360px}.banner-cmd[_ngcontent-%COMP%] .banner-cmd-text[_ngcontent-%COMP%]{font-size:11.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.banner-error[_ngcontent-%COMP%]{margin-top:11px;padding:8px 11px;background:var(--error-soft);border:1px solid rgba(242,85,90,.25);border-radius:7px;align-items:center}.banner-error[_ngcontent-%COMP%] .banner-error-text[_ngcontent-%COMP%]{font-size:12px;color:var(--text-secondary);flex:1}.banner-disabled[_ngcontent-%COMP%]{margin-top:11px;align-items:center}.banner-disabled[_ngcontent-%COMP%] .banner-disabled-note[_ngcontent-%COMP%]{font-size:11.5px}.mcp-tile-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;margin-bottom:16px}.mcp-tile[_ngcontent-%COMP%]{padding:11px 13px;display:flex;flex-direction:column;gap:3px}.mcp-tile[_ngcontent-%COMP%] .tile-eyebrow[_ngcontent-%COMP%]{color:var(--text-muted)}.mcp-tile[_ngcontent-%COMP%] .tile-value[_ngcontent-%COMP%]{font-size:19px;font-weight:650;letter-spacing:-.01em}.mcp-tile[_ngcontent-%COMP%] .tile-sub[_ngcontent-%COMP%]{font-size:10px}.detail-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:16px;align-items:start}.tools-col[_ngcontent-%COMP%]{min-width:0;grid-column:1/-1}.tools-head[_ngcontent-%COMP%]{margin-bottom:10px;align-items:center}.tools-head[_ngcontent-%COMP%] .tools-hint[_ngcontent-%COMP%]{font-size:11px}.tool-row[_ngcontent-%COMP%]{overflow:hidden}.tool-row.open[_ngcontent-%COMP%]{border-color:var(--border-strong)}.tool-header[_ngcontent-%COMP%]{width:100%;padding:11px 13px;cursor:pointer;background:transparent;border:0;text-align:left;color:inherit;align-items:center;transition:background .1s}.tool-header[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.tool-header[_ngcontent-%COMP%]:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}.tool-ic[_ngcontent-%COMP%]{width:30px;height:30px;border-radius:8px;display:grid;place-items:center;flex-shrink:0}.tool-main[_ngcontent-%COMP%]{min-width:0;display:flex;flex-direction:column}.tool-main[_ngcontent-%COMP%] .tool-name[_ngcontent-%COMP%]{font-size:13px;font-weight:600}.tool-main[_ngcontent-%COMP%] .tool-desc[_ngcontent-%COMP%]{font-size:11.5px;margin-top:3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-wrap:pretty}.tool-main[_ngcontent-%COMP%] .tool-desc.expanded[_ngcontent-%COMP%]{white-space:normal;overflow:visible}.tool-stat[_ngcontent-%COMP%]{display:flex;flex-direction:column;align-items:flex-end;flex-shrink:0}.tool-stat.tok[_ngcontent-%COMP%]{width:64px}.tool-stat[_ngcontent-%COMP%] .stat-n[_ngcontent-%COMP%]{font-size:13px;font-weight:600}.tool-stat[_ngcontent-%COMP%] .stat-n.cold[_ngcontent-%COMP%]{color:var(--text-muted)}.tool-stat[_ngcontent-%COMP%] .stat-l[_ngcontent-%COMP%]{font-size:10px}.tool-expand[_ngcontent-%COMP%]{padding:0 13px 13px 53px;animation:_ngcontent-%COMP%_mcpFadeIn .12s ease}.tool-expand[_ngcontent-%COMP%] .expand-label[_ngcontent-%COMP%]{margin-bottom:7px}.param-list[_ngcontent-%COMP%]{margin-bottom:13px}.param-row[_ngcontent-%COMP%]{font-size:12px;align-items:center}.param-row[_ngcontent-%COMP%] .param-name[_ngcontent-%COMP%]{width:110px;color:var(--text-primary);flex-shrink:0}.param-row[_ngcontent-%COMP%] .param-type[_ngcontent-%COMP%]{color:var(--node-route);width:52px;flex-shrink:0}.param-row[_ngcontent-%COMP%] .param-opt[_ngcontent-%COMP%], .param-row[_ngcontent-%COMP%] .param-hint[_ngcontent-%COMP%]{font-size:11px}.param-none[_ngcontent-%COMP%]{font-size:11.5px;margin-bottom:13px}.example-call[_ngcontent-%COMP%]{background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:7px;padding:8px 11px;align-items:center}.example-call[_ngcontent-%COMP%] .example-text[_ngcontent-%COMP%]{font-size:11.5px;color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.drill-btn[_ngcontent-%COMP%]{margin-top:11px}.usedby-card[_ngcontent-%COMP%], .config-card[_ngcontent-%COMP%]{min-width:0}.panel-head[_ngcontent-%COMP%]{margin-bottom:12px;align-items:center}.panel-head[_ngcontent-%COMP%] .panel-title[_ngcontent-%COMP%]{font-weight:600;font-size:12.5px}.panel-head[_ngcontent-%COMP%] .config-hint[_ngcontent-%COMP%]{font-size:10.5px}.client-row[_ngcontent-%COMP%]{padding:9px 10px;border-radius:8px;border:1px solid var(--border-subtle);background:var(--bg-canvas);align-items:center}.client-dot[_ngcontent-%COMP%]{width:8px;height:8px;border-radius:50%;flex-shrink:0}.client-dot.glow[_ngcontent-%COMP%]{box-shadow:0 0 7px var(--success)}.client-main[_ngcontent-%COMP%]{min-width:0;display:flex;flex-direction:column}.client-main[_ngcontent-%COMP%] .client-name[_ngcontent-%COMP%]{font-size:12.5px;font-weight:500}.client-main[_ngcontent-%COMP%] .client-host[_ngcontent-%COMP%]{font-size:10.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.client-meta[_ngcontent-%COMP%]{text-align:right;flex-shrink:0;display:flex;flex-direction:column}.client-meta[_ngcontent-%COMP%] .client-state[_ngcontent-%COMP%]{font-size:10.5px}.client-meta[_ngcontent-%COMP%] .client-last[_ngcontent-%COMP%]{font-size:10px}.usedby-empty[_ngcontent-%COMP%]{font-size:11.5px;padding:4px 0}.config-pre[_ngcontent-%COMP%]{margin:0;font-size:11.5px;line-height:1.65;color:var(--text-secondary);background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:8px;padding:11px 13px;overflow-x:auto;white-space:pre}@keyframes _ngcontent-%COMP%_mcpPulse{0%{box-shadow:0 0 color-mix(in srgb,var(--success) 60%,transparent)}70%{box-shadow:0 0 0 5px transparent}to{box-shadow:0 0 0 0 transparent}}@keyframes _ngcontent-%COMP%_mcpFadeIn{0%{opacity:0}to{opacity:1}}'],changeDetection:0})};export{q as McpDetail};
1
+ import{a as A,b as U,c as K,d as L}from"./chunk-BPCJLNBS.js";import{a as B}from"./chunk-NKPK3BR3.js";import{a as $}from"./chunk-YWIRU745.js";import{a as R}from"./chunk-JLOJCDIY.js";import{a as V}from"./chunk-PZSU53SS.js";import{a as z,c as D}from"./chunk-DOKZOFKM.js";import{c as F}from"./chunk-DTWIJ3GJ.js";import"./chunk-JGDK6YKG.js";import{a as I}from"./chunk-TWVVIWKO.js";import{Aa as c,Ga as M,I as y,Ia as f,Ka as s,M as C,N as b,Ta as v,Ua as u,Va as a,W as S,Wa as p,Xa as h,Ya as k,ea as i,ka as E,lb as g,qa as T,ra as m,sa as _,va as P,wa as O,xa as d,ya as t,za as n,zb as N}from"./chunk-SYGIPC2P.js";import"./chunk-Q7L6LLAK.js";var w=(r,o)=>o.name;function j(r,o){r&1&&(t(0,"div",1),c(1,"div",3)(2,"div",4)(3,"div",5),n())}function G(r,o){if(r&1){let e=M();t(0,"app-empty",2)(1,"button",6),f("click",function(){C(e);let x=s();return b(x.back())}),c(2,"app-icon",7),a(3," Back to MCP servers "),n()()}if(r&2){let e=s();d("body","No MCP server with id \u201C"+e.serverId()+"\u201D is configured."),i(2),d("size",13)}}function J(r,o){if(r&1&&(t(0,"div",30),c(1,"app-icon",59),t(2,"span",60),a(3),n(),t(4,"button",61),a(5,"Re-authenticate"),n()()),r&2){let e=s();i(),d("size",14),i(2),p(e.error)}}function Q(r,o){r&1&&(t(0,"div",31)(1,"button",62),c(2,"app-icon",63),a(3," Enable server"),n(),t(4,"span",64),a(5,"Tools below are declared but not currently exposed."),n()()),r&2&&(i(2),d("size",12))}function W(r,o){r&1&&(t(0,"span",45),a(1,"click a tool for its schema"),n())}function X(r,o){r&1&&(t(0,"app-pill",88),a(1,"required"),n())}function Y(r,o){r&1&&(t(0,"span",89),a(1,"optional"),n())}function Z(r,o){if(r&1&&(t(0,"span",90),a(1),n()),r&2){let e=s().$implicit;i(),h("\xB7 ",e.hint)}}function ee(r,o){if(r&1&&(t(0,"div",85)(1,"span",86),a(2),n(),t(3,"span",87),a(4),n(),m(5,X,2,0,"app-pill",88)(6,Y,2,0,"span",89),m(7,Z,2,1,"span",90),n()),r&2){let e=o.$implicit;i(2),p(e.name),i(2),p(e.type),i(),_(e.required?5:6),i(2),_(e.hint?7:-1)}}function te(r,o){if(r&1&&(t(0,"div",79),P(1,ee,8,4,"div",85,w),n()),r&2){let e=s(2).$implicit;i(),O(e.params)}}function ne(r,o){r&1&&(t(0,"div",80),a(1,"No parameters."),n())}function ie(r,o){if(r&1){let e=M();t(0,"button",91),f("click",function(){C(e);let x=s(5);return b(x.go("heatmap"))}),c(1,"app-icon",92),a(2," View usage in heatmap "),n()}r&2&&(i(),d("size",13))}function oe(r,o){if(r&1&&(t(0,"div",77)(1,"div",78),a(2,"Input schema"),n(),m(3,te,3,0,"div",79)(4,ne,2,0,"div",80),t(5,"div",81),a(6,"Example call"),n(),t(7,"div",82)(8,"span",83),a(9),n(),c(10,"app-copy-btn",29),n(),m(11,ie,3,1,"button",84),n()),r&2){let e=s().$implicit;i(3),_(e.params.length?3:4),i(6),p(e.example),i(),d("text",e.example),i(),_(e.drill?11:-1)}}function ae(r,o){if(r&1){let e=M();t(0,"div",66)(1,"button",67),f("click",function(){let x=C(e).$implicit,H=s(3);return b(H.toggleTool(x.name))}),t(2,"span",68),c(3,"app-icon",12),n(),t(4,"span",69)(5,"span",70),a(6),n(),t(7,"span",71),a(8),n()(),t(9,"span",72)(10,"span",73),a(11),n(),t(12,"span",74),a(13,"calls / 7d"),n()(),t(14,"span",75)(15,"span",73),a(16),n(),t(17,"span",74),a(18,"tok / call"),n()(),c(19,"app-icon",76),n(),m(20,oe,12,4,"div",77),n()}if(r&2){let e=o.$implicit,l=s(3);u("open",l.isToolOpen(e.name)),i(),T("aria-expanded",l.isToolOpen(e.name)),i(),v("background",l.mix(e.color,15))("color",e.color),i(),d("name",e.icon)("size",15),i(3),p(e.name),i(),u("expanded",l.isToolOpen(e.name)),i(),p(e.desc),i(2),u("cold",l.isCold(e)),i(),h("\xD7",e.stat.calls),i(4),v("color",l.isCold(e)?"var(--text-muted)":l.isHeavy(e)?"var(--warn)":"var(--success)"),i(),p(l.isCold(e)?"\u2014":l.fmtK(l.avg(e))),i(3),d("name",l.isToolOpen(e.name)?"chevronDown":"chevronRight")("size",15),i(),_(l.isToolOpen(e.name)?20:-1)}}function re(r,o){if(r&1&&(t(0,"div",46),P(1,ae,21,22,"div",65,w),n()),r&2){let e=s();i(),O(e.tools)}}function le(r,o){r&1&&c(0,"app-empty",47)}function ce(r,o){if(r&1&&(t(0,"div",93),c(1,"span",94),t(2,"span",95)(3,"span",96),a(4),n(),t(5,"span",97),a(6),n()(),t(7,"span",98)(8,"span",99),a(9),n(),t(10,"span",100),a(11),n()()()),r&2){let e=o.$implicit,l=s(3);i(),v("background",l.clientMeta(e.state).color),u("glow",e.state==="active"),i(3),p(e.name),i(2),p(e.host),i(2),v("color",l.clientMeta(e.state).color),i(),p(l.clientMeta(e.state).label),i(2),p(e.last)}}function pe(r,o){if(r&1&&(t(0,"div",46),P(1,ce,12,10,"div",93,w),n()),r&2){let e=s();i(),O(e.usedBy)}}function de(r,o){r&1&&(t(0,"div",52),a(1,"No clients reference this server."),n())}function se(r,o){if(r&1){let e=M();t(0,"div",8)(1,"button",9),f("click",function(){C(e);let x=s();return b(x.back())}),c(2,"app-icon",7),a(3," MCP servers "),n(),t(4,"span",10),a(5),n(),t(6,"app-pill",11),c(7,"app-icon",12),a(8),n(),t(9,"span",13),a(10),n()(),t(11,"div",14),c(12,"div",15),t(13,"div",16)(14,"div",17)(15,"div",18),c(16,"span",19),t(17,"span",20),a(18),n(),t(19,"span",21),a(20),n()(),t(21,"span",22)(22,"span",23),a(23,"Transport"),n(),t(24,"span",24),a(25),n()(),t(26,"span",22)(27,"span",23),a(28,"Uptime"),n(),t(29,"span",24),a(30),n()(),t(31,"span",22)(32,"span",23),a(33,"Protocol"),n(),t(34,"span",24),a(35),n()(),t(36,"span",22)(37,"span",23),a(38,"Tools"),n(),t(39,"span",24),a(40),n()(),c(41,"span",25),t(42,"span",26),c(43,"app-icon",27),t(44,"span",28),a(45),n(),c(46,"app-copy-btn",29),n()(),m(47,J,6,2,"div",30),m(48,Q,6,1,"div",31),n()(),t(49,"div",32)(50,"div",33)(51,"div",34),c(52,"app-icon",35),t(53,"span",36),a(54,"Tools"),n()(),t(55,"div",37),a(56),n(),t(57,"div",38),a(58,"exposed"),n()(),t(59,"div",33)(60,"div",34),c(61,"app-icon",39),t(62,"span",36),a(63,"Calls"),n()(),t(64,"div",37),a(65),n(),t(66,"div",38),a(67,"this week"),n()(),t(68,"div",33)(69,"div",34),c(70,"app-icon",40),t(71,"span",36),a(72,"Result tokens"),n()(),t(73,"div",37),a(74),n(),t(75,"div",38),a(76,"returned to context"),n()(),t(77,"div",33)(78,"div",34),c(79,"app-icon",41),t(80,"span",36),a(81,"Used by"),n()(),t(82,"div",37),a(83),n(),t(84,"div",38),a(85,"clients"),n()()(),t(86,"div",42)(87,"div",43)(88,"div",44)(89,"span",36),a(90),n(),m(91,W,2,0,"span",45),n(),m(92,re,3,0,"div",46)(93,le,1,0,"app-empty",47),n(),t(94,"div",48)(95,"div",49),c(96,"app-icon",50),t(97,"span",51),a(98,"Used by"),n()(),m(99,pe,3,0,"div",46)(100,de,2,0,"div",52),n(),t(101,"div",53)(102,"div",49),c(103,"app-icon",54),t(104,"span",55),a(105,"Configuration"),n(),t(106,"span",56),a(107),n(),c(108,"app-copy-btn",29),n(),t(109,"pre",57),a(110),n()()(),c(111,"div",58)}if(r&2){let e=o,l=s();i(2),d("size",14),i(3),p(e.name),i(),d("color",l.scopeMeta(e.scope).color)("bg",l.mix(l.scopeMeta(e.scope).color)),i(),d("name",l.scopeMeta(e.scope).icon)("size",10),i(),h(" ",l.scopeMeta(e.scope).label," "),i(2),p(l.scopeMeta(e.scope).hint),i(2),v("background",l.stateMeta(e.state).color),i(4),v("background",l.stateMeta(e.state).color),u("glow",e.state==="running")("pulse",e.state==="running"),i(2),p(l.stateMeta(e.state).label),i(2),k("",e.name,"-mcp ",e.version),i(5),p(e.transport),i(5),p(e.uptime),i(5),p(e.protocol),i(5),p(e.tools.length),i(3),d("size",12),i(2),p(e.command),i(),d("text",e.command),i(),_(e.error?47:-1),i(),_(e.state==="disabled"?48:-1),i(4),d("size",12),i(4),p(e.tools.length),i(5),d("size",12),i(4),p(l.totalCalls().toLocaleString()),i(5),d("size",12),i(4),p(l.fmtTok(l.totalTokens())),i(5),d("size",12),i(4),p(e.usedBy.length),i(7),h("Tools \xB7 ",e.tools.length),i(),_(e.tools.length?91:-1),i(),_(e.tools.length?92:93),i(4),d("size",14),i(3),_(e.usedBy.length?99:100),i(4),d("size",14),i(4),p(l.scopeMeta(e.scope).hint),i(),d("text",e.config),i(2),p(e.config)}}var q=class r{api=y(I);route=y(z);router=y(D);resource=F(this.api,()=>"/api/mcp/servers");paramMap=B(this.route.paramMap,{initialValue:this.route.snapshot.paramMap});serverId=g(()=>this.paramMap().get("id")??"");loading=g(()=>this.resource.state().loading);servers=g(()=>{let o=this.resource.state();if(o.loading)return[];let e=o.data?.servers;return e&&e.length?e:A.servers});server=g(()=>this.servers().find(o=>o.id===this.serverId()));notFound=g(()=>!this.loading()&&!this.server());openTool=S(null);isToolOpen(o){return this.openTool()===o}toggleTool(o){this.openTool.update(e=>e===o?null:o)}totalCalls=g(()=>(this.server()?.tools??[]).reduce((o,e)=>o+e.stat.calls,0));totalTokens=g(()=>(this.server()?.tools??[]).reduce((o,e)=>o+e.stat.tokens,0));stateMeta(o){return U[o]}scopeMeta(o){return K[o]}clientMeta(o){return L[o]}mix(o,e=14){return`color-mix(in srgb, ${o} ${e}%, transparent)`}avg(o){return o.stat.calls?Math.round(o.stat.tokens/o.stat.calls):0}isHeavy(o){return this.avg(o)>8e3}isCold(o){return o.stat.calls===0}back(){this.router.navigate(["/mcp"])}go(o){this.router.navigate(["/"+o])}fmtK(o){return o>=1e6?(o/1e6).toFixed(1)+"M":o>=1e3?(o/1e3).toFixed(o>=1e4?0:1)+"k":String(o)}fmtTok(o){return o>=1e6?(o/1e6).toFixed(1)+"M":this.fmtK(o)}static \u0275fac=function(e){return new(e||r)};static \u0275cmp=E({type:r,selectors:[["app-mcp-detail"]],decls:4,vars:1,consts:[[1,"scroll-y","mcp-detail"],[1,"col","gap-12"],["icon","plug","title","Server not found",3,"body"],[1,"skel",2,"height","34px","width","280px","border-radius","8px"],[1,"skel",2,"height","96px","border-radius","12px"],[1,"skel",2,"height","64px","border-radius","12px"],["action","","type","button",1,"btn","btn-secondary","btn-sm",3,"click"],["name","chevronLeft",3,"size"],[1,"row","gap-10","detail-head"],["type","button",1,"btn","btn-ghost","btn-sm",3,"click"],[1,"mono","detail-name"],[3,"color","bg"],[3,"name","size"],[1,"mono","muted","detail-hint"],[1,"card","banner"],[1,"banner-accent"],[1,"banner-body"],[1,"row","gap-16","banner-top"],[1,"row","gap-8","banner-state"],[1,"banner-dot"],[1,"banner-state-label"],[1,"mono","muted","banner-version"],[1,"seg"],[1,"muted","seg-l"],[1,"mono","tabular","seg-v"],[1,"grow"],[1,"row","gap-8","banner-cmd"],["name","command",2,"color","var(--text-muted)","flex-shrink","0",3,"size"],[1,"mono","banner-cmd-text"],[3,"text"],[1,"row","gap-8","banner-error"],[1,"row","gap-8","banner-disabled"],[1,"mcp-tile-grid"],[1,"card","mcp-tile"],[1,"row","gap-6","tile-eyebrow"],["name","plug",2,"color","var(--accent)",3,"size"],[1,"eyebrow"],[1,"mono","tabular","tile-value"],[1,"mono","muted","tile-sub"],["name","wrench",2,"color","var(--node-code)",3,"size"],["name","database",2,"color","var(--node-route)",3,"size"],["name","bot",2,"color","var(--success)",3,"size"],[1,"detail-grid"],[1,"tools-col"],[1,"row","gap-8","tools-head"],[1,"muted","tools-hint"],[1,"col","gap-8"],["icon","plug","title","No tools available","body","This server isn\u2019t exposing any tools \u2014 fix the connection above to load its tool list."],[1,"card","card-pad","usedby-card"],[1,"row","gap-8","panel-head"],["name","bot",2,"color","var(--node-route)",3,"size"],[1,"panel-title"],[1,"muted","usedby-empty"],[1,"card","card-pad","config-card"],["name","settings",2,"color","var(--accent)",3,"size"],[1,"grow","panel-title"],[1,"mono","muted","config-hint"],[1,"mono","scroll-y","config-pre"],[2,"height","24px"],["name","drift",2,"color","var(--error)","flex-shrink","0",3,"size"],[1,"banner-error-text"],["type","button",1,"btn","btn-secondary","btn-sm"],["type","button",1,"btn","btn-primary","btn-sm"],["name","play",3,"size"],[1,"muted","banner-disabled-note"],[1,"card","tool-row",3,"open"],[1,"card","tool-row"],["type","button",1,"row","gap-10","tool-header",3,"click"],[1,"tool-ic"],[1,"grow","tool-main"],[1,"mono","tool-name"],[1,"secondary","tool-desc"],[1,"tool-stat"],[1,"mono","tabular","stat-n"],[1,"mono","tabular","muted","stat-l"],[1,"tool-stat","tok"],[2,"color","var(--text-muted)",3,"name","size"],[1,"tool-expand"],[1,"eyebrow","expand-label",2,"margin-top","2px"],[1,"col","gap-5","param-list"],[1,"muted","param-none"],[1,"eyebrow","expand-label"],[1,"row","gap-8","example-call"],[1,"mono","grow","example-text"],["type","button",1,"btn","btn-secondary","btn-sm","drill-btn"],[1,"row","gap-8","param-row"],[1,"mono","param-name"],[1,"mono","param-type"],["color","var(--error)","bg","var(--error-soft)"],[1,"muted","mono","param-opt"],[1,"mono","muted","param-hint"],["type","button",1,"btn","btn-secondary","btn-sm","drill-btn",3,"click"],["name","heatmap",3,"size"],[1,"row","gap-10","client-row"],[1,"client-dot"],[1,"grow","client-main"],[1,"client-name"],[1,"mono","muted","client-host"],[1,"client-meta"],[1,"mono","client-state"],[1,"mono","muted","client-last"]],template:function(e,l){if(e&1&&(t(0,"div",0),m(1,j,4,0,"div",1)(2,G,4,2,"app-empty",2)(3,se,112,45),n()),e&2){let x;i(),_(l.loading()?1:l.notFound()?2:(x=l.server())?3:-1,x)}},dependencies:[R,V,$,N],styles:['@charset "UTF-8";[_nghost-%COMP%]{display:flex;flex-direction:column;min-height:0;flex:1}.mcp-detail[_ngcontent-%COMP%]{flex:1;min-height:0;padding:18px}.detail-head[_ngcontent-%COMP%]{align-items:center;margin-bottom:14px}.detail-head[_ngcontent-%COMP%] .detail-name[_ngcontent-%COMP%]{font-size:16px;font-weight:600}.detail-head[_ngcontent-%COMP%] .detail-hint[_ngcontent-%COMP%]{font-size:11.5px}.banner[_ngcontent-%COMP%]{padding:0;overflow:hidden;margin-bottom:14px;display:flex}.banner-accent[_ngcontent-%COMP%]{width:3px;flex-shrink:0}.banner-body[_ngcontent-%COMP%]{flex:1;padding:13px 16px;min-width:0}.banner-top[_ngcontent-%COMP%]{flex-wrap:wrap;align-items:center}.banner-state[_ngcontent-%COMP%]{flex-shrink:0;align-items:center}.banner-dot[_ngcontent-%COMP%]{width:9px;height:9px;border-radius:50%}.banner-dot.glow[_ngcontent-%COMP%]{box-shadow:0 0 8px var(--success)}.banner-dot.pulse[_ngcontent-%COMP%]{animation:_ngcontent-%COMP%_mcpPulse 1.6s ease-out infinite}.banner-state-label[_ngcontent-%COMP%]{font-weight:600;font-size:13.5px}.banner-version[_ngcontent-%COMP%]{font-size:12px}.seg[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:6px;flex-shrink:0}.seg[_ngcontent-%COMP%] .seg-l[_ngcontent-%COMP%]{font-size:11px}.seg[_ngcontent-%COMP%] .seg-v[_ngcontent-%COMP%]{font-size:12px;color:var(--text-secondary)}.banner-cmd[_ngcontent-%COMP%]{background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:7px;padding:6px 10px;max-width:360px}.banner-cmd[_ngcontent-%COMP%] .banner-cmd-text[_ngcontent-%COMP%]{font-size:11.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.banner-error[_ngcontent-%COMP%]{margin-top:11px;padding:8px 11px;background:var(--error-soft);border:1px solid rgba(242,85,90,.25);border-radius:7px;align-items:center}.banner-error[_ngcontent-%COMP%] .banner-error-text[_ngcontent-%COMP%]{font-size:12px;color:var(--text-secondary);flex:1}.banner-disabled[_ngcontent-%COMP%]{margin-top:11px;align-items:center}.banner-disabled[_ngcontent-%COMP%] .banner-disabled-note[_ngcontent-%COMP%]{font-size:11.5px}.mcp-tile-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;margin-bottom:16px}.mcp-tile[_ngcontent-%COMP%]{padding:11px 13px;display:flex;flex-direction:column;gap:3px}.mcp-tile[_ngcontent-%COMP%] .tile-eyebrow[_ngcontent-%COMP%]{color:var(--text-muted)}.mcp-tile[_ngcontent-%COMP%] .tile-value[_ngcontent-%COMP%]{font-size:19px;font-weight:650;letter-spacing:-.01em}.mcp-tile[_ngcontent-%COMP%] .tile-sub[_ngcontent-%COMP%]{font-size:10px}.detail-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:16px;align-items:start}.tools-col[_ngcontent-%COMP%]{min-width:0;grid-column:1/-1}.tools-head[_ngcontent-%COMP%]{margin-bottom:10px;align-items:center}.tools-head[_ngcontent-%COMP%] .tools-hint[_ngcontent-%COMP%]{font-size:11px}.tool-row[_ngcontent-%COMP%]{overflow:hidden}.tool-row.open[_ngcontent-%COMP%]{border-color:var(--border-strong)}.tool-header[_ngcontent-%COMP%]{width:100%;padding:11px 13px;cursor:pointer;background:transparent;border:0;text-align:left;color:inherit;align-items:center;transition:background .1s}.tool-header[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.tool-header[_ngcontent-%COMP%]:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}.tool-ic[_ngcontent-%COMP%]{width:30px;height:30px;border-radius:8px;display:grid;place-items:center;flex-shrink:0}.tool-main[_ngcontent-%COMP%]{min-width:0;display:flex;flex-direction:column}.tool-main[_ngcontent-%COMP%] .tool-name[_ngcontent-%COMP%]{font-size:13px;font-weight:600}.tool-main[_ngcontent-%COMP%] .tool-desc[_ngcontent-%COMP%]{font-size:11.5px;margin-top:3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-wrap:pretty}.tool-main[_ngcontent-%COMP%] .tool-desc.expanded[_ngcontent-%COMP%]{white-space:normal;overflow:visible}.tool-stat[_ngcontent-%COMP%]{display:flex;flex-direction:column;align-items:flex-end;flex-shrink:0}.tool-stat.tok[_ngcontent-%COMP%]{width:64px}.tool-stat[_ngcontent-%COMP%] .stat-n[_ngcontent-%COMP%]{font-size:13px;font-weight:600}.tool-stat[_ngcontent-%COMP%] .stat-n.cold[_ngcontent-%COMP%]{color:var(--text-muted)}.tool-stat[_ngcontent-%COMP%] .stat-l[_ngcontent-%COMP%]{font-size:10px}.tool-expand[_ngcontent-%COMP%]{padding:0 13px 13px 53px;animation:_ngcontent-%COMP%_mcpFadeIn .12s ease}.tool-expand[_ngcontent-%COMP%] .expand-label[_ngcontent-%COMP%]{margin-bottom:7px}.param-list[_ngcontent-%COMP%]{margin-bottom:13px}.param-row[_ngcontent-%COMP%]{font-size:12px;align-items:center}.param-row[_ngcontent-%COMP%] .param-name[_ngcontent-%COMP%]{width:110px;color:var(--text-primary);flex-shrink:0}.param-row[_ngcontent-%COMP%] .param-type[_ngcontent-%COMP%]{color:var(--node-route);width:52px;flex-shrink:0}.param-row[_ngcontent-%COMP%] .param-opt[_ngcontent-%COMP%], .param-row[_ngcontent-%COMP%] .param-hint[_ngcontent-%COMP%]{font-size:11px}.param-none[_ngcontent-%COMP%]{font-size:11.5px;margin-bottom:13px}.example-call[_ngcontent-%COMP%]{background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:7px;padding:8px 11px;align-items:center}.example-call[_ngcontent-%COMP%] .example-text[_ngcontent-%COMP%]{font-size:11.5px;color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.drill-btn[_ngcontent-%COMP%]{margin-top:11px}.usedby-card[_ngcontent-%COMP%], .config-card[_ngcontent-%COMP%]{min-width:0}.panel-head[_ngcontent-%COMP%]{margin-bottom:12px;align-items:center}.panel-head[_ngcontent-%COMP%] .panel-title[_ngcontent-%COMP%]{font-weight:600;font-size:12.5px}.panel-head[_ngcontent-%COMP%] .config-hint[_ngcontent-%COMP%]{font-size:10.5px}.client-row[_ngcontent-%COMP%]{padding:9px 10px;border-radius:8px;border:1px solid var(--border-subtle);background:var(--bg-canvas);align-items:center}.client-dot[_ngcontent-%COMP%]{width:8px;height:8px;border-radius:50%;flex-shrink:0}.client-dot.glow[_ngcontent-%COMP%]{box-shadow:0 0 7px var(--success)}.client-main[_ngcontent-%COMP%]{min-width:0;display:flex;flex-direction:column}.client-main[_ngcontent-%COMP%] .client-name[_ngcontent-%COMP%]{font-size:12.5px;font-weight:500}.client-main[_ngcontent-%COMP%] .client-host[_ngcontent-%COMP%]{font-size:10.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.client-meta[_ngcontent-%COMP%]{text-align:right;flex-shrink:0;display:flex;flex-direction:column}.client-meta[_ngcontent-%COMP%] .client-state[_ngcontent-%COMP%]{font-size:10.5px}.client-meta[_ngcontent-%COMP%] .client-last[_ngcontent-%COMP%]{font-size:10px}.usedby-empty[_ngcontent-%COMP%]{font-size:11.5px;padding:4px 0}.config-pre[_ngcontent-%COMP%]{margin:0;font-size:11.5px;line-height:1.65;color:var(--text-secondary);background:var(--bg-canvas);border:1px solid var(--border-subtle);border-radius:8px;padding:11px 13px;overflow-x:auto;white-space:pre}@keyframes _ngcontent-%COMP%_mcpPulse{0%{box-shadow:0 0 color-mix(in srgb,var(--success) 60%,transparent)}70%{box-shadow:0 0 0 5px transparent}to{box-shadow:0 0 0 0 transparent}}@keyframes _ngcontent-%COMP%_mcpFadeIn{0%{opacity:0}to{opacity:1}}'],changeDetection:0})};export{q as McpDetail};
@@ -1 +1 @@
1
- import{a as V}from"./chunk-JLOJCDIY.js";import{a as A}from"./chunk-5NTGUSXJ.js";import{c as F}from"./chunk-PAO2624Y.js";import"./chunk-PBRCKHEQ.js";import{a as $}from"./chunk-3H2EZLZN.js";import{Aa as f,Ea as z,Fa as R,Ga as w,I as S,Ia as y,Ka as p,M as b,N as C,Ta as T,Va as l,W as x,Wa as m,Xa as _,bb as H,ea as o,ka as O,lb as I,qa as k,ra as v,sa as u,ua as E,va as P,wa as M,xa as d,ya as a,za as r,zb as D}from"./chunk-SYGIPC2P.js";import{a as g,b as h}from"./chunk-Q7L6LLAK.js";var B=()=>[0,1,2],L=(i,e)=>e.contentHash;function j(i,e){if(i&1&&(a(0,"div",6),l(1),r()),i&2){let t=p();o(),m(t.errorMsg())}}function U(i,e){i&1&&f(0,"div",9)}function W(i,e){i&1&&P(0,U,1,0,"div",9,E),i&2&&M(H(0,B))}function q(i,e){i&1&&(a(0,"div",7),f(1,"app-icon",5),a(2,"div",10),l(3,"No proposals yet"),r(),a(4,"div",11),l(5,"Run "),a(6,"strong"),l(7,"Analyze"),r(),l(8," to mine your ingested transcripts for recurring patterns worth turning into a durable rule, skill, or hook."),r()()),i&2&&(o(),d("size",28))}function G(i,e){if(i&1&&(a(0,"span",19),l(1),r()),i&2){let t=p().$implicit,n=p(2);o(),m(n.outcomeOf(t.contentHash))}}function J(i,e){i&1&&(a(0,"div",30),l(1,"Loading preview\u2026"),r())}function K(i,e){i&1&&(a(0,"div",31),l(1,"A non-SpecShip file already exists at this path \u2014 apply is blocked to avoid clobbering it."),r())}function Q(i,e){if(i&1&&(v(0,K,2,0,"div",31),a(1,"div",24),l(2,"Preview diff"),r(),a(3,"pre",32),l(4),r()),i&2){let t,n,s=p(2).$implicit,c=p(2);u((t=c.previewOf(s.contentHash))!=null&&t.conflict?0:-1),o(4),m((n=c.previewOf(s.contentHash))==null?null:n.diff)}}function X(i,e){if(i&1&&(a(0,"div",26),v(1,J,2,0,"div",30)(2,Q,5,2),r()),i&2){let t=p().$implicit,n=p(2);o(),u(n.previewOf(t.contentHash)===null?1:2)}}function Y(i,e){if(i&1){let t=w();a(0,"span",33),l(1,"applied"),r(),a(2,"button",34),y("click",function(){b(t);let s=p().$implicit,c=p(2);return C(c.undoProposal(s.contentHash))}),l(3,"Undo"),r()}if(i&2){let t=p().$implicit,n=p(2);o(2),d("disabled",n.isBusy(t.contentHash))}}function Z(i,e){if(i&1){let t=w();a(0,"button",34),y("click",function(){b(t);let s=p().$implicit,c=p(2);return C(c.dismissProposal(s.contentHash))}),l(1,"Dismiss"),r(),a(2,"button",4),y("click",function(){b(t);let s=p().$implicit,c=p(2);return C(c.applyProposal(s.contentHash))}),l(3),r()}if(i&2){let t,n=p().$implicit,s=p(2);d("disabled",s.isBusy(n.contentHash)),o(2),d("disabled",s.isBusy(n.contentHash)||((t=s.previewOf(n.contentHash))==null?null:t.conflict)),o(),_(" ",s.isBusy(n.contentHash)?"Applying\u2026":"Apply"," ")}}function ee(i,e){if(i&1){let t=w();a(0,"div",12),f(1,"div",13),a(2,"div",14)(3,"div",15)(4,"div",16)(5,"div",17)(6,"span",18),l(7),r(),a(8,"app-pill",3),l(9),r(),v(10,G,2,1,"span",19),r(),a(11,"div",20),l(12),r()()(),a(13,"div",21),l(14),r(),a(15,"div",22)(16,"div",23)(17,"div",24),l(18,"Evidence"),r(),a(19,"div",25),l(20),r()(),a(21,"div",23)(22,"div",24),l(23,"Writes to"),r(),a(24,"div",25),l(25),r()()(),v(26,X,3,1,"div",26),a(27,"div",27)(28,"button",28),y("click",function(){let s=b(t).$implicit,c=p(2);return C(c.togglePreview(s.contentHash))}),l(29),r(),f(30,"div",29),v(31,Y,4,1)(32,Z,4,3),r()()()}if(i&2){let t=e.$implicit,n=p(2);k("data-sev",t.severity),o(),T("background",n.sevColor(t.severity)),o(6),m(n.typeLabel(t.type)),o(),d("color",n.sevColor(t.severity))("bg","color-mix(in srgb, "+n.sevColor(t.severity)+" 16%, transparent)"),o(),m(t.severity),o(),u(n.outcomeOf(t.contentHash)?10:-1),o(2),m(t.title),o(2),m(t.body),o(6),m(t.evidence.detail),o(5),m(t.targetPath),o(),u(n.previewOf(t.contentHash)!==void 0?26:-1),o(3),_(" ",n.previewOf(t.contentHash)!==void 0?"Hide preview":"Preview"," "),o(2),u(t.state==="applied"?31:32)}}function te(i,e){if(i&1&&(a(0,"div",8),P(1,ee,33,15,"div",12,L),r()),i&2){let t=p();o(),M(t.proposals())}}var N=class i{api=S($);resource=F(this.api,()=>"/api/reflect?state=open");analyzing=x(!1);previews=x({});busy=x(new Set);outcomes=x({});errorMsg=x(null);proposals=I(()=>{let e=this.resource.state().data?.proposals??[],t={high:0,warn:1,info:2};return[...e].sort((n,s)=>(t[n.severity]??9)-(t[s.severity]??9))});counts=I(()=>{let e=this.resource.state().data?.proposals??[];return{high:e.filter(t=>t.severity==="high").length,warn:e.filter(t=>t.severity==="warn").length,info:e.filter(t=>t.severity==="info").length}});typeLabel(e){return e==="memory_rule"?"memory / rule":e==="skill"?"skill":"hook"}sevColor(e){return e==="high"?"var(--error)":e==="warn"?"var(--warn)":"var(--info)"}isBusy(e){return this.busy().has(e)}previewOf(e){return this.previews()[e]}outcomeOf(e){return this.outcomes()[e]}async analyze(){this.analyzing.set(!0),this.errorMsg.set(null);try{await this.api.post("/api/reflect/analyze",{}),this.resource.refetch()}catch(e){this.errorMsg.set(this.msg(e))}finally{this.analyzing.set(!1)}}async togglePreview(e){let t=this.previews();if(e in t){let n=g({},t);delete n[e],this.previews.set(n);return}this.previews.set(h(g({},t),{[e]:null}));try{let n=await this.api.get(`/api/reflect/${e}/preview`);this.previews.set(h(g({},this.previews()),{[e]:n}))}catch(n){this.errorMsg.set(this.msg(n));let s=g({},this.previews());delete s[e],this.previews.set(s)}}applyProposal(e){return this.mutate(e,`/api/reflect/${e}/apply`,"apply")}undoProposal(e){return this.mutate(e,`/api/reflect/${e}/undo`,"undo")}dismissProposal(e){return this.mutate(e,`/api/reflect/${e}/dismiss`,"dismiss")}async mutate(e,t,n){this.setBusy(e,!0),this.errorMsg.set(null);try{let s=await this.api.post(t,{}),c=s.outcome??(s.ok?"dismissed":"done");this.outcomes.set(h(g({},this.outcomes()),{[e]:c})),this.resource.refetch()}catch(s){this.errorMsg.set(`${n} failed: ${this.msg(s)}`)}finally{this.setBusy(e,!1)}}setBusy(e,t){this.busy.update(n=>{let s=new Set(n);return t?s.add(e):s.delete(e),s})}msg(e){return e instanceof Error?e.message:String(e)}static \u0275fac=function(t){return new(t||i)};static \u0275cmp=O({type:i,selectors:[["app-improvements"]],decls:16,vars:14,consts:[[1,"page","scroll-y"],["icon","sparkles","title","Improvements","sub","Durable fixes mined from your transcripts \u2014 preview, then apply"],["actions",""],[3,"color","bg"],["type","button",1,"btn","btn-primary","btn-sm",3,"click","disabled"],["name","sparkles",3,"size"],[1,"banner-error"],[1,"empty"],[1,"prop-list"],[1,"skel","card-skel"],[1,"empty-title"],[1,"empty-sub"],[1,"prop-card","card"],[1,"sev-bar"],[1,"prop-body"],[1,"row","gap-10","head-row"],[1,"grow",2,"min-width","0"],[1,"row","gap-6","chips"],[1,"type-chip"],[1,"outcome"],[1,"prop-title"],[1,"prop-why"],[1,"prop-meta"],[1,"kv-block"],[1,"eyebrow"],[1,"mono","secondary","detail"],[1,"preview"],[1,"actions"],["type","button",1,"btn","btn-secondary","btn-sm",3,"click"],[1,"grow"],[1,"muted"],[1,"banner-error","small"],[1,"diff","mono"],[1,"applied-tag"],["type","button",1,"btn","btn-secondary","btn-sm",3,"click","disabled"]],template:function(t,n){t&1&&(a(0,"div",0)(1,"app-page-head",1),z(2,2),a(3,"app-pill",3),l(4),r(),a(5,"app-pill",3),l(6),r(),a(7,"app-pill",3),l(8),r(),a(9,"button",4),y("click",function(){return n.analyze()}),f(10,"app-icon",5),l(11),r(),R(),r(),v(12,j,2,1,"div",6),v(13,W,2,1)(14,q,9,1,"div",7)(15,te,3,0,"div",8),r()),t&2&&(o(3),d("color","var(--error)")("bg","var(--error-soft)"),o(),_("",n.counts().high," high"),o(),d("color","var(--warn)")("bg","var(--warn-soft)"),o(),_("",n.counts().warn," warn"),o(),d("color","var(--info)")("bg","var(--info-soft)"),o(),_("",n.counts().info," info"),o(),d("disabled",n.analyzing()),o(),d("size",13),o(),_(" ",n.analyzing()?"Analyzing\u2026":"Analyze"," "),o(),u(n.errorMsg()?12:-1),o(),u(n.resource.state().loading?13:n.proposals().length===0?14:15))},dependencies:[A,V,D],styles:[".page[_ngcontent-%COMP%]{padding:20px 24px 48px}.banner-error[_ngcontent-%COMP%]{background:var(--error-soft);color:var(--error);border:1px solid color-mix(in srgb,var(--error) 30%,transparent);border-radius:8px;padding:10px 12px;font-size:12.5px;margin-bottom:14px}.banner-error.small[_ngcontent-%COMP%]{margin:8px 0;padding:8px 10px;font-size:11.5px}.empty[_ngcontent-%COMP%]{display:flex;flex-direction:column;align-items:center;gap:8px;text-align:center;padding:64px 24px;color:var(--text-muted)}.empty[_ngcontent-%COMP%] .empty-title[_ngcontent-%COMP%]{font-size:15px;font-weight:600;color:var(--text)}.empty[_ngcontent-%COMP%] .empty-sub[_ngcontent-%COMP%]{font-size:12.5px;max-width:460px;line-height:1.5}.card-skel[_ngcontent-%COMP%]{height:132px;border-radius:12px;margin-bottom:12px}.prop-list[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:12px}.prop-card[_ngcontent-%COMP%]{position:relative;display:flex;overflow:hidden;padding:0}.prop-card[_ngcontent-%COMP%] .sev-bar[_ngcontent-%COMP%]{width:3px;flex:0 0 3px}.prop-card[_ngcontent-%COMP%] .prop-body[_ngcontent-%COMP%]{flex:1;min-width:0;padding:14px 16px}.head-row[_ngcontent-%COMP%]{margin-bottom:8px}.chips[_ngcontent-%COMP%]{margin-bottom:6px}.type-chip[_ngcontent-%COMP%]{font-size:10.5px;text-transform:uppercase;letter-spacing:.04em;font-weight:600;color:var(--text-muted);background:var(--surface-2, color-mix(in srgb, var(--text) 7%, transparent));border-radius:5px;padding:2px 7px}.outcome[_ngcontent-%COMP%]{font-size:10.5px;color:var(--success);font-weight:600;text-transform:lowercase}.prop-title[_ngcontent-%COMP%]{font-size:14px;font-weight:600;color:var(--text);line-height:1.35}.prop-why[_ngcontent-%COMP%]{font-size:12.5px;color:var(--text-secondary, var(--text-muted));line-height:1.5;margin-bottom:10px}.prop-meta[_ngcontent-%COMP%]{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:10px}.prop-meta[_ngcontent-%COMP%] .detail[_ngcontent-%COMP%]{font-size:11px;margin-top:2px;word-break:break-all}.preview[_ngcontent-%COMP%]{margin:8px 0 12px}.preview[_ngcontent-%COMP%] .diff[_ngcontent-%COMP%]{background:var(--surface-2, color-mix(in srgb, var(--text) 5%, transparent));border:1px solid var(--border, color-mix(in srgb, var(--text) 12%, transparent));border-radius:8px;padding:10px 12px;font-size:11.5px;line-height:1.5;max-height:280px;overflow:auto;white-space:pre;margin-top:4px}.actions[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;margin-top:4px}.applied-tag[_ngcontent-%COMP%]{font-size:11px;color:var(--success);font-weight:600}"],changeDetection:0})};export{N as Improvements};
1
+ import{a as V}from"./chunk-JLOJCDIY.js";import{a as A}from"./chunk-5NTGUSXJ.js";import{c as F}from"./chunk-DTWIJ3GJ.js";import"./chunk-JGDK6YKG.js";import{a as $}from"./chunk-TWVVIWKO.js";import{Aa as f,Ea as z,Fa as R,Ga as w,I as S,Ia as y,Ka as p,M as b,N as C,Ta as T,Va as l,W as x,Wa as m,Xa as _,bb as H,ea as o,ka as O,lb as I,qa as k,ra as v,sa as u,ua as E,va as P,wa as M,xa as d,ya as a,za as r,zb as D}from"./chunk-SYGIPC2P.js";import{a as g,b as h}from"./chunk-Q7L6LLAK.js";var B=()=>[0,1,2],L=(i,e)=>e.contentHash;function j(i,e){if(i&1&&(a(0,"div",6),l(1),r()),i&2){let t=p();o(),m(t.errorMsg())}}function U(i,e){i&1&&f(0,"div",9)}function W(i,e){i&1&&P(0,U,1,0,"div",9,E),i&2&&M(H(0,B))}function q(i,e){i&1&&(a(0,"div",7),f(1,"app-icon",5),a(2,"div",10),l(3,"No proposals yet"),r(),a(4,"div",11),l(5,"Run "),a(6,"strong"),l(7,"Analyze"),r(),l(8," to mine your ingested transcripts for recurring patterns worth turning into a durable rule, skill, or hook."),r()()),i&2&&(o(),d("size",28))}function G(i,e){if(i&1&&(a(0,"span",19),l(1),r()),i&2){let t=p().$implicit,n=p(2);o(),m(n.outcomeOf(t.contentHash))}}function J(i,e){i&1&&(a(0,"div",30),l(1,"Loading preview\u2026"),r())}function K(i,e){i&1&&(a(0,"div",31),l(1,"A non-SpecShip file already exists at this path \u2014 apply is blocked to avoid clobbering it."),r())}function Q(i,e){if(i&1&&(v(0,K,2,0,"div",31),a(1,"div",24),l(2,"Preview diff"),r(),a(3,"pre",32),l(4),r()),i&2){let t,n,s=p(2).$implicit,c=p(2);u((t=c.previewOf(s.contentHash))!=null&&t.conflict?0:-1),o(4),m((n=c.previewOf(s.contentHash))==null?null:n.diff)}}function X(i,e){if(i&1&&(a(0,"div",26),v(1,J,2,0,"div",30)(2,Q,5,2),r()),i&2){let t=p().$implicit,n=p(2);o(),u(n.previewOf(t.contentHash)===null?1:2)}}function Y(i,e){if(i&1){let t=w();a(0,"span",33),l(1,"applied"),r(),a(2,"button",34),y("click",function(){b(t);let s=p().$implicit,c=p(2);return C(c.undoProposal(s.contentHash))}),l(3,"Undo"),r()}if(i&2){let t=p().$implicit,n=p(2);o(2),d("disabled",n.isBusy(t.contentHash))}}function Z(i,e){if(i&1){let t=w();a(0,"button",34),y("click",function(){b(t);let s=p().$implicit,c=p(2);return C(c.dismissProposal(s.contentHash))}),l(1,"Dismiss"),r(),a(2,"button",4),y("click",function(){b(t);let s=p().$implicit,c=p(2);return C(c.applyProposal(s.contentHash))}),l(3),r()}if(i&2){let t,n=p().$implicit,s=p(2);d("disabled",s.isBusy(n.contentHash)),o(2),d("disabled",s.isBusy(n.contentHash)||((t=s.previewOf(n.contentHash))==null?null:t.conflict)),o(),_(" ",s.isBusy(n.contentHash)?"Applying\u2026":"Apply"," ")}}function ee(i,e){if(i&1){let t=w();a(0,"div",12),f(1,"div",13),a(2,"div",14)(3,"div",15)(4,"div",16)(5,"div",17)(6,"span",18),l(7),r(),a(8,"app-pill",3),l(9),r(),v(10,G,2,1,"span",19),r(),a(11,"div",20),l(12),r()()(),a(13,"div",21),l(14),r(),a(15,"div",22)(16,"div",23)(17,"div",24),l(18,"Evidence"),r(),a(19,"div",25),l(20),r()(),a(21,"div",23)(22,"div",24),l(23,"Writes to"),r(),a(24,"div",25),l(25),r()()(),v(26,X,3,1,"div",26),a(27,"div",27)(28,"button",28),y("click",function(){let s=b(t).$implicit,c=p(2);return C(c.togglePreview(s.contentHash))}),l(29),r(),f(30,"div",29),v(31,Y,4,1)(32,Z,4,3),r()()()}if(i&2){let t=e.$implicit,n=p(2);k("data-sev",t.severity),o(),T("background",n.sevColor(t.severity)),o(6),m(n.typeLabel(t.type)),o(),d("color",n.sevColor(t.severity))("bg","color-mix(in srgb, "+n.sevColor(t.severity)+" 16%, transparent)"),o(),m(t.severity),o(),u(n.outcomeOf(t.contentHash)?10:-1),o(2),m(t.title),o(2),m(t.body),o(6),m(t.evidence.detail),o(5),m(t.targetPath),o(),u(n.previewOf(t.contentHash)!==void 0?26:-1),o(3),_(" ",n.previewOf(t.contentHash)!==void 0?"Hide preview":"Preview"," "),o(2),u(t.state==="applied"?31:32)}}function te(i,e){if(i&1&&(a(0,"div",8),P(1,ee,33,15,"div",12,L),r()),i&2){let t=p();o(),M(t.proposals())}}var N=class i{api=S($);resource=F(this.api,()=>"/api/reflect?state=open");analyzing=x(!1);previews=x({});busy=x(new Set);outcomes=x({});errorMsg=x(null);proposals=I(()=>{let e=this.resource.state().data?.proposals??[],t={high:0,warn:1,info:2};return[...e].sort((n,s)=>(t[n.severity]??9)-(t[s.severity]??9))});counts=I(()=>{let e=this.resource.state().data?.proposals??[];return{high:e.filter(t=>t.severity==="high").length,warn:e.filter(t=>t.severity==="warn").length,info:e.filter(t=>t.severity==="info").length}});typeLabel(e){return e==="memory_rule"?"memory / rule":e==="skill"?"skill":"hook"}sevColor(e){return e==="high"?"var(--error)":e==="warn"?"var(--warn)":"var(--info)"}isBusy(e){return this.busy().has(e)}previewOf(e){return this.previews()[e]}outcomeOf(e){return this.outcomes()[e]}async analyze(){this.analyzing.set(!0),this.errorMsg.set(null);try{await this.api.post("/api/reflect/analyze",{}),this.resource.refetch()}catch(e){this.errorMsg.set(this.msg(e))}finally{this.analyzing.set(!1)}}async togglePreview(e){let t=this.previews();if(e in t){let n=g({},t);delete n[e],this.previews.set(n);return}this.previews.set(h(g({},t),{[e]:null}));try{let n=await this.api.get(`/api/reflect/${e}/preview`);this.previews.set(h(g({},this.previews()),{[e]:n}))}catch(n){this.errorMsg.set(this.msg(n));let s=g({},this.previews());delete s[e],this.previews.set(s)}}applyProposal(e){return this.mutate(e,`/api/reflect/${e}/apply`,"apply")}undoProposal(e){return this.mutate(e,`/api/reflect/${e}/undo`,"undo")}dismissProposal(e){return this.mutate(e,`/api/reflect/${e}/dismiss`,"dismiss")}async mutate(e,t,n){this.setBusy(e,!0),this.errorMsg.set(null);try{let s=await this.api.post(t,{}),c=s.outcome??(s.ok?"dismissed":"done");this.outcomes.set(h(g({},this.outcomes()),{[e]:c})),this.resource.refetch()}catch(s){this.errorMsg.set(`${n} failed: ${this.msg(s)}`)}finally{this.setBusy(e,!1)}}setBusy(e,t){this.busy.update(n=>{let s=new Set(n);return t?s.add(e):s.delete(e),s})}msg(e){return e instanceof Error?e.message:String(e)}static \u0275fac=function(t){return new(t||i)};static \u0275cmp=O({type:i,selectors:[["app-improvements"]],decls:16,vars:14,consts:[[1,"page","scroll-y"],["icon","sparkles","title","Improvements","sub","Durable fixes mined from your transcripts \u2014 preview, then apply"],["actions",""],[3,"color","bg"],["type","button",1,"btn","btn-primary","btn-sm",3,"click","disabled"],["name","sparkles",3,"size"],[1,"banner-error"],[1,"empty"],[1,"prop-list"],[1,"skel","card-skel"],[1,"empty-title"],[1,"empty-sub"],[1,"prop-card","card"],[1,"sev-bar"],[1,"prop-body"],[1,"row","gap-10","head-row"],[1,"grow",2,"min-width","0"],[1,"row","gap-6","chips"],[1,"type-chip"],[1,"outcome"],[1,"prop-title"],[1,"prop-why"],[1,"prop-meta"],[1,"kv-block"],[1,"eyebrow"],[1,"mono","secondary","detail"],[1,"preview"],[1,"actions"],["type","button",1,"btn","btn-secondary","btn-sm",3,"click"],[1,"grow"],[1,"muted"],[1,"banner-error","small"],[1,"diff","mono"],[1,"applied-tag"],["type","button",1,"btn","btn-secondary","btn-sm",3,"click","disabled"]],template:function(t,n){t&1&&(a(0,"div",0)(1,"app-page-head",1),z(2,2),a(3,"app-pill",3),l(4),r(),a(5,"app-pill",3),l(6),r(),a(7,"app-pill",3),l(8),r(),a(9,"button",4),y("click",function(){return n.analyze()}),f(10,"app-icon",5),l(11),r(),R(),r(),v(12,j,2,1,"div",6),v(13,W,2,1)(14,q,9,1,"div",7)(15,te,3,0,"div",8),r()),t&2&&(o(3),d("color","var(--error)")("bg","var(--error-soft)"),o(),_("",n.counts().high," high"),o(),d("color","var(--warn)")("bg","var(--warn-soft)"),o(),_("",n.counts().warn," warn"),o(),d("color","var(--info)")("bg","var(--info-soft)"),o(),_("",n.counts().info," info"),o(),d("disabled",n.analyzing()),o(),d("size",13),o(),_(" ",n.analyzing()?"Analyzing\u2026":"Analyze"," "),o(),u(n.errorMsg()?12:-1),o(),u(n.resource.state().loading?13:n.proposals().length===0?14:15))},dependencies:[A,V,D],styles:[".page[_ngcontent-%COMP%]{padding:20px 24px 48px}.banner-error[_ngcontent-%COMP%]{background:var(--error-soft);color:var(--error);border:1px solid color-mix(in srgb,var(--error) 30%,transparent);border-radius:8px;padding:10px 12px;font-size:12.5px;margin-bottom:14px}.banner-error.small[_ngcontent-%COMP%]{margin:8px 0;padding:8px 10px;font-size:11.5px}.empty[_ngcontent-%COMP%]{display:flex;flex-direction:column;align-items:center;gap:8px;text-align:center;padding:64px 24px;color:var(--text-muted)}.empty[_ngcontent-%COMP%] .empty-title[_ngcontent-%COMP%]{font-size:15px;font-weight:600;color:var(--text)}.empty[_ngcontent-%COMP%] .empty-sub[_ngcontent-%COMP%]{font-size:12.5px;max-width:460px;line-height:1.5}.card-skel[_ngcontent-%COMP%]{height:132px;border-radius:12px;margin-bottom:12px}.prop-list[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:12px}.prop-card[_ngcontent-%COMP%]{position:relative;display:flex;overflow:hidden;padding:0}.prop-card[_ngcontent-%COMP%] .sev-bar[_ngcontent-%COMP%]{width:3px;flex:0 0 3px}.prop-card[_ngcontent-%COMP%] .prop-body[_ngcontent-%COMP%]{flex:1;min-width:0;padding:14px 16px}.head-row[_ngcontent-%COMP%]{margin-bottom:8px}.chips[_ngcontent-%COMP%]{margin-bottom:6px}.type-chip[_ngcontent-%COMP%]{font-size:10.5px;text-transform:uppercase;letter-spacing:.04em;font-weight:600;color:var(--text-muted);background:var(--surface-2, color-mix(in srgb, var(--text) 7%, transparent));border-radius:5px;padding:2px 7px}.outcome[_ngcontent-%COMP%]{font-size:10.5px;color:var(--success);font-weight:600;text-transform:lowercase}.prop-title[_ngcontent-%COMP%]{font-size:14px;font-weight:600;color:var(--text);line-height:1.35}.prop-why[_ngcontent-%COMP%]{font-size:12.5px;color:var(--text-secondary, var(--text-muted));line-height:1.5;margin-bottom:10px}.prop-meta[_ngcontent-%COMP%]{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:10px}.prop-meta[_ngcontent-%COMP%] .detail[_ngcontent-%COMP%]{font-size:11px;margin-top:2px;word-break:break-all}.preview[_ngcontent-%COMP%]{margin:8px 0 12px}.preview[_ngcontent-%COMP%] .diff[_ngcontent-%COMP%]{background:var(--surface-2, color-mix(in srgb, var(--text) 5%, transparent));border:1px solid var(--border, color-mix(in srgb, var(--text) 12%, transparent));border-radius:8px;padding:10px 12px;font-size:11.5px;line-height:1.5;max-height:280px;overflow:auto;white-space:pre;margin-top:4px}.actions[_ngcontent-%COMP%]{display:flex;align-items:center;gap:8px;margin-top:4px}.applied-tag[_ngcontent-%COMP%]{font-size:11px;color:var(--success);font-weight:600}"],changeDetection:0})};export{N as Improvements};
@@ -1 +1 @@
1
- import{a as j}from"./chunk-PBRCKHEQ.js";import{a as A,b as R}from"./chunk-3H2EZLZN.js";import{E as u,I as i,R as b,W as o,X as v,lb as g}from"./chunk-SYGIPC2P.js";import{a as y,b as m}from"./chunk-Q7L6LLAK.js";var w="specship.lastOnline",l=class r{onlineSig=o(!0);lastOnlineAtSig=o(null);online=this.onlineSig.asReadonly();lastOnlineAt=this.lastOnlineAtSig.asReadonly();lastOnlineLabel=g(()=>{let t=this.lastOnlineAtSig();if(t===null)return null;let e=Date.now()-t;return e<1e4?"just now":e<6e4?`${Math.round(e/1e3)}s ago`:e<36e5?`${Math.round(e/6e4)}m ago`:e<864e5?`${Math.round(e/36e5)}h ago`:`${Math.round(e/864e5)}d ago`});constructor(){if(typeof localStorage<"u")try{let t=localStorage.getItem(w),e=t?Number(t):NaN;Number.isFinite(e)&&this.lastOnlineAtSig.set(e)}catch{}typeof window<"u"&&window.addEventListener("offline",()=>this.onlineSig.set(!1))}noteSuccess(){let t=Date.now();if(this.lastOnlineAtSig.set(t),typeof localStorage<"u")try{localStorage.setItem(w,String(t))}catch{}this.onlineSig()||this.onlineSig.set(!0)}noteOffline(){this.onlineSig()&&this.onlineSig.set(!1)}static \u0275fac=function(e){return new(e||r)};static \u0275prov=u({token:r,factory:r.\u0275fac,providedIn:"root"})};var f=class r{api=i(A);projects=i(j);connection=i(l);tickSig=o(0);loadingSig=o(!1);errorSig=o(null);lastRefreshSig=o(null);tick=this.tickSig.asReadonly();loading=this.loadingSig.asReadonly();error=this.errorSig.asReadonly();lastRefreshAt=this.lastRefreshSig.asReadonly();lastRefreshLabel=g(()=>{let t=this.lastRefreshSig();if(t===null)return null;let e=Date.now()-t;return e<5e3?"just now":e<6e4?`${Math.round(e/1e3)}s ago`:e<36e5?`${Math.round(e/6e4)}m ago`:`${Math.round(e/36e5)}h ago`});async triggerGlobalRefresh(){if(!this.loadingSig()){if(!this.connection.online()){this.errorSig.set("Offline \u2014 reconnect to refresh");return}this.loadingSig.set(!0),this.errorSig.set(null);try{let t=this.projects.projectQuery(),e=await this.api.post(`/api/refresh${t}`,{});(e.syncError||e.ingestError)&&this.errorSig.set([e.syncError,e.ingestError].filter(Boolean).join(" \xB7 ")),this.lastRefreshSig.set(Date.now()),this.tickSig.update(d=>d+1)}catch(t){this.errorSig.set(t instanceof Error?t.message:String(t))}finally{this.loadingSig.set(!1)}}}notifyLocalChange(){this.lastRefreshSig.set(Date.now()),this.tickSig.update(t=>t+1)}static \u0275fac=function(e){return new(e||r)};static \u0275prov=u({token:r,factory:r.\u0275fac,providedIn:"root"})};var _="specship.cache:";function M(r){if(typeof localStorage>"u")return null;try{let t=localStorage.getItem(_+r);if(!t)return null;let e=JSON.parse(t);if(e&&typeof e.ts=="number"&&"data"in e)return e}catch{}return null}function O(r,t){let e=Date.now();if(typeof localStorage>"u")return e;try{localStorage.setItem(_+r,JSON.stringify({data:t,ts:e}))}catch{}return e}function K(r,t){let e=o({data:null,loading:!0,error:null,source:"init",noProject:!1,stale:!1,cachedAt:null}),d=i(b),E=i(f),h=i(l),S=o(0),D=()=>{let a=t();if(!a){e.set({data:null,loading:!1,error:null,source:"init",noProject:!1,stale:!1,cachedAt:null});return}s&&s.abort(),s=new AbortController,e.update(n=>m(y({},n),{loading:!0,error:null,noProject:!1})),r.get(a,s.signal).then(n=>{let c=O(a,n);h.noteSuccess(),e.set({data:n,loading:!1,error:null,source:"api",noProject:!1,stale:!1,cachedAt:c})}).catch(n=>{if(n instanceof Error&&n.name==="AbortError")return;if(n instanceof R){h.noteSuccess();let p=n.status===409&&(n.code==="no_project"||n.code==="no_primary");e.set({data:null,loading:!1,error:p?null:n,source:"api",noProject:p,stale:!1,cachedAt:null});return}h.noteOffline();let c=M(a);c?e.set({data:c.data,loading:!1,error:null,source:"api",noProject:!1,stale:!0,cachedAt:c.ts}):e.set({data:null,loading:!1,error:n instanceof Error?n:new Error(String(n)),source:"api",noProject:!1,stale:!0,cachedAt:null})})},s=null;return v(()=>{t(),S(),E.tick(),D()}),d.onDestroy(()=>{s?.abort()}),{state:e,refetch:()=>S.update(a=>a+1)}}export{l as a,f as b,K as c};
1
+ import{a as j}from"./chunk-JGDK6YKG.js";import{a as A,b as R}from"./chunk-TWVVIWKO.js";import{E as u,I as i,R as b,W as o,X as v,lb as g}from"./chunk-SYGIPC2P.js";import{a as y,b as m}from"./chunk-Q7L6LLAK.js";var w="specship.lastOnline",l=class r{onlineSig=o(!0);lastOnlineAtSig=o(null);online=this.onlineSig.asReadonly();lastOnlineAt=this.lastOnlineAtSig.asReadonly();lastOnlineLabel=g(()=>{let t=this.lastOnlineAtSig();if(t===null)return null;let e=Date.now()-t;return e<1e4?"just now":e<6e4?`${Math.round(e/1e3)}s ago`:e<36e5?`${Math.round(e/6e4)}m ago`:e<864e5?`${Math.round(e/36e5)}h ago`:`${Math.round(e/864e5)}d ago`});constructor(){if(typeof localStorage<"u")try{let t=localStorage.getItem(w),e=t?Number(t):NaN;Number.isFinite(e)&&this.lastOnlineAtSig.set(e)}catch{}typeof window<"u"&&window.addEventListener("offline",()=>this.onlineSig.set(!1))}noteSuccess(){let t=Date.now();if(this.lastOnlineAtSig.set(t),typeof localStorage<"u")try{localStorage.setItem(w,String(t))}catch{}this.onlineSig()||this.onlineSig.set(!0)}noteOffline(){this.onlineSig()&&this.onlineSig.set(!1)}static \u0275fac=function(e){return new(e||r)};static \u0275prov=u({token:r,factory:r.\u0275fac,providedIn:"root"})};var f=class r{api=i(A);projects=i(j);connection=i(l);tickSig=o(0);loadingSig=o(!1);errorSig=o(null);lastRefreshSig=o(null);tick=this.tickSig.asReadonly();loading=this.loadingSig.asReadonly();error=this.errorSig.asReadonly();lastRefreshAt=this.lastRefreshSig.asReadonly();lastRefreshLabel=g(()=>{let t=this.lastRefreshSig();if(t===null)return null;let e=Date.now()-t;return e<5e3?"just now":e<6e4?`${Math.round(e/1e3)}s ago`:e<36e5?`${Math.round(e/6e4)}m ago`:`${Math.round(e/36e5)}h ago`});async triggerGlobalRefresh(){if(!this.loadingSig()){if(!this.connection.online()){this.errorSig.set("Offline \u2014 reconnect to refresh");return}this.loadingSig.set(!0),this.errorSig.set(null);try{let t=this.projects.projectQuery(),e=await this.api.post(`/api/refresh${t}`,{});(e.syncError||e.ingestError)&&this.errorSig.set([e.syncError,e.ingestError].filter(Boolean).join(" \xB7 ")),this.lastRefreshSig.set(Date.now()),this.tickSig.update(d=>d+1)}catch(t){this.errorSig.set(t instanceof Error?t.message:String(t))}finally{this.loadingSig.set(!1)}}}notifyLocalChange(){this.lastRefreshSig.set(Date.now()),this.tickSig.update(t=>t+1)}static \u0275fac=function(e){return new(e||r)};static \u0275prov=u({token:r,factory:r.\u0275fac,providedIn:"root"})};var _="specship.cache:";function M(r){if(typeof localStorage>"u")return null;try{let t=localStorage.getItem(_+r);if(!t)return null;let e=JSON.parse(t);if(e&&typeof e.ts=="number"&&"data"in e)return e}catch{}return null}function O(r,t){let e=Date.now();if(typeof localStorage>"u")return e;try{localStorage.setItem(_+r,JSON.stringify({data:t,ts:e}))}catch{}return e}function K(r,t){let e=o({data:null,loading:!0,error:null,source:"init",noProject:!1,stale:!1,cachedAt:null}),d=i(b),E=i(f),h=i(l),S=o(0),D=()=>{let a=t();if(!a){e.set({data:null,loading:!1,error:null,source:"init",noProject:!1,stale:!1,cachedAt:null});return}s&&s.abort(),s=new AbortController,e.update(n=>m(y({},n),{loading:!0,error:null,noProject:!1})),r.get(a,s.signal).then(n=>{let c=O(a,n);h.noteSuccess(),e.set({data:n,loading:!1,error:null,source:"api",noProject:!1,stale:!1,cachedAt:c})}).catch(n=>{if(n instanceof Error&&n.name==="AbortError")return;if(n instanceof R){h.noteSuccess();let p=n.status===409&&(n.code==="no_project"||n.code==="no_primary");e.set({data:null,loading:!1,error:p?null:n,source:"api",noProject:p,stale:!1,cachedAt:null});return}h.noteOffline();let c=M(a);c?e.set({data:c.data,loading:!1,error:null,source:"api",noProject:!1,stale:!0,cachedAt:c.ts}):e.set({data:null,loading:!1,error:n instanceof Error?n:new Error(String(n)),source:"api",noProject:!1,stale:!0,cachedAt:null})})},s=null;return v(()=>{t(),S(),E.tick(),D()}),d.onDestroy(()=>{s?.abort()}),{state:e,refetch:()=>S.update(a=>a+1)}}export{l as a,f as b,K as c};
@@ -1 +1 @@
1
- import{a as te}from"./chunk-QPA2REUE.js";import{a as ee}from"./chunk-YNYVOPWF.js";import{a as Q}from"./chunk-5NTGUSXJ.js";import{a as X}from"./chunk-IOB4JJT4.js";import{c as q}from"./chunk-PAO2624Y.js";import"./chunk-PBRCKHEQ.js";import{a as Z}from"./chunk-3H2EZLZN.js";import{Aa as m,Ba as P,Ca as w,Da as A,Ea as H,Fa as j,I as N,Ia as I,Ka as u,O as z,P as R,Ta as y,Ua as G,Va as c,W as $,Wa as d,Xa as S,Ya as K,bb as C,ea as i,fb as V,gb as Y,ib as U,ka as O,lb as p,pb as k,qa as T,ra as _,sa as h,ua as B,va as v,vb as W,wa as b,xa as g,ya as r,za as s,zb as J}from"./chunk-SYGIPC2P.js";import"./chunk-Q7L6LLAK.js";var ge=(o,e)=>e.label;function fe(o,e){if(o&1&&(z(),A(0,"path")),o&2){let t=e.$implicit;T("d",t.d)("fill",t.color)}}function xe(o,e){if(o&1&&(P(0,"div",3),c(1),w()),o&2){let t=u();i(),d(t.centerSub())}}var E=class o{data=k([]);size=k(150);centerLabel=k("");centerSub=k("");arcs=p(()=>{let e=this.data(),t=e.reduce((x,D)=>x+D.cost,0);if(t<=0)return[];let a=this.size()/2,l=a*.6,f=-Math.PI/2,F=[];for(let x of e){let D=x.cost/t*Math.PI*2,M=f+D,L=D>Math.PI?1:0,ie=a+Math.cos(f)*a,ae=a+Math.sin(f)*a,re=a+Math.cos(M)*a,se=a+Math.sin(M)*a,ce=a+Math.cos(M)*l,de=a+Math.sin(M)*l,le=a+Math.cos(f)*l,pe=a+Math.sin(f)*l;F.push({d:`M ${ie} ${ae} A ${a} ${a} 0 ${L} 1 ${re} ${se} L ${ce} ${de} A ${l} ${l} 0 ${L} 0 ${le} ${pe} Z`,color:x.color,label:x.short||x.model||""}),f=M}return F});static \u0275fac=function(t){return new(t||o)};static \u0275cmp=O({type:o,selectors:[["app-donut"]],inputs:{data:[1,"data"],size:[1,"size"],centerLabel:[1,"centerLabel"],centerSub:[1,"centerSub"]},decls:8,vars:9,consts:[[1,"donut"],[1,"donut-center"],[1,"center-label"],[1,"center-sub"]],template:function(t,n){t&1&&(P(0,"div",0),z(),P(1,"svg"),v(2,fe,1,2,":svg:path",null,ge),w(),R(),P(4,"div",1)(5,"div",2),c(6),w(),_(7,xe,2,1,"div",3),w()()),t&2&&(y("width",n.size(),"px")("height",n.size(),"px"),i(),T("width",n.size())("height",n.size())("viewBox","0 0 "+n.size()+" "+n.size()),i(),b(n.arcs()),i(4),d(n.centerLabel()),i(),h(n.centerSub()?7:-1))},styles:["[_nghost-%COMP%]{display:inline-block}.donut[_ngcontent-%COMP%]{position:relative}.donut-center[_ngcontent-%COMP%]{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;pointer-events:none}.center-label[_ngcontent-%COMP%]{font-variant-numeric:tabular-nums;font-size:18px;font-weight:700;color:var(--text-primary)}.center-sub[_ngcontent-%COMP%]{color:var(--text-muted);font-size:10.5px;margin-top:2px}"],changeDetection:0})};var _e=()=>({value:"today",label:"Today"}),he=()=>({value:"week",label:"This week"}),ve=()=>({value:"month",label:"This month"}),be=()=>({value:"all",label:"All time"}),ye=(o,e,t,n)=>[o,e,t,n],Ce=()=>[0,1,2,3],Me=(o,e)=>e.model,Pe=(o,e)=>e.id;function we(o,e){if(o&1&&m(0,"app-delta",10),o&2){let t=u();g("value",t.wowDelta())("invert",!0)}}function Se(o,e){if(o&1&&(r(0,"div",11)(1,"div",24),c(2),s(),r(3,"div",25),c(4),s()()),o&2){let t=e,n=u();i(2),d(n.fmt$(t.cost)),i(2),K("",t.prompts," prompts \xB7 day ",t.day)}}function ke(o,e){if(o&1&&(r(0,"div",19),m(1,"span",26),r(2,"span",27),c(3),s(),r(4,"span",28),c(5),s(),r(6,"span",29),c(7),s()()),o&2){let t=e.$implicit,n=u();i(),y("background",t.color),i(2),d(t.short),i(2),d(n.fmt$(t.cost)),i(2),S("",n.percentOf(t.cost,n.total()),"%")}}function De(o,e){o&1&&m(0,"div",30)}function Oe(o,e){o&1&&v(0,De,1,0,"div",30,B),o&2&&b(C(0,Ce))}function Ee(o,e){if(o&1&&(r(0,"div",32)(1,"span",33),c(2),s(),r(3,"div",34)(4,"div",35),c(5),s(),r(6,"div",36),m(7,"span",37),s()(),r(8,"span",38),c(9),s(),r(10,"span",39),c(11),s(),r(12,"span",40),c(13),Y(14,"number"),s(),r(15,"span",41),c(16),s()()),o&2){let t=e.$implicit,n=e.$index,a=u(2);G("first",n===0),i(2),d(n+1),i(3),d(t.text),i(2),y("width",t.cost_usd/a.maxPrompt()*100,"%")("background",t.cost_usd/a.maxPrompt()>.66?"var(--error)":"var(--accent)"),i(2),d(a.modelShort(t.model)),i(2),d(a.fmtK(a.promptTokens(t))),i(),y("color",a.cacheColor(a.cacheRate(t))),i(),S("",U(14,14,a.cacheRate(t)*100,"1.0-0"),"%"),i(3),d(a.fmt$(t.cost_usd))}}function ze(o,e){if(o&1&&v(0,Ee,17,17,"div",31,Pe),o&2){let t=u();b(t.topPrompts())}}var $e={"claude-opus-4-7":"#A586F5","claude-opus-4":"#A586F5","claude-sonnet-4-6":"#5B93F2","claude-sonnet-4-7":"#5B93F2","claude-sonnet-4":"#5B93F2","claude-haiku-4-5":"#29D2BE","claude-haiku-4":"#29D2BE"},ne={"claude-opus-4-7":"Opus 4.7","claude-opus-4":"Opus 4","claude-sonnet-4-6":"Sonnet 4.6","claude-sonnet-4-7":"Sonnet 4.7","claude-sonnet-4":"Sonnet 4","claude-haiku-4-5":"Haiku 4.5","claude-haiku-4":"Haiku 4"},oe=class o{api=N(Z);range=$("month");ranges=["today","week","month","all"];hovered=$(null);resource=q(this.api,()=>`/api/claude/costs?range=${this.range()}`);series=p(()=>this.resource.state().data?.series??[]);topPrompts=p(()=>(this.resource.state().data?.topPrompts??[]).slice(0,12));maxPrompt=p(()=>{let e=this.topPrompts();return Math.max(.01,...e.map(t=>t.cost_usd??0))});byModel=p(()=>(this.resource.state().data?.byModel??[]).map(t=>({model:t.model,short:ne[t.model]||t.model,cost:t.cost||0,color:$e[t.model]||"#5C6573"})));total=p(()=>this.resource.state().data?.total??0);wowDelta=p(()=>this.resource.state().data?.wowDelta??0);setRange(e){this.range.set(e)}onHover(e){this.hovered.set(e)}fmt$(e){return"$"+e.toLocaleString("en-US",{minimumFractionDigits:2,maximumFractionDigits:2})}fmtK(e){return e>=1e3?(e/1e3).toFixed(e>=1e4?0:1)+"k":String(e)}promptTokens(e){return(e.input_tokens??0)+(e.output_tokens??0)+(e.cache_creation_tokens??0)+(e.cache_read_tokens??0)}cacheRate(e){let t=(e.input_tokens??0)+(e.cache_creation_tokens??0)+(e.cache_read_tokens??0);return t>0?(e.cache_read_tokens??0)/t:0}cacheColor(e){return e>=.7?"var(--success)":e>=.5?"var(--warn)":"var(--error)"}modelShort(e){return e?ne[e]||e.replace(/^claude-/,""):"?"}percentOf(e,t){return t>0?Math.round(e/t*100):0}static \u0275fac=function(t){return new(t||o)};static \u0275cmp=O({type:o,selectors:[["app-costs"]],decls:34,vars:25,consts:[[1,"page","scroll-y"],["icon","dollar","title","Costs","sub","Where the money goes"],["actions",""],["size","sm",3,"change","value","options"],[1,"top-grid"],[1,"card","card-pad","chart-card"],[1,"chart-header"],[1,"big-number","mono"],[1,"row","gap-8",2,"margin-top","2px"],[1,"muted",2,"font-size","11.5px"],[3,"value","invert"],[2,"text-align","right"],["color","var(--accent)",3,"hover","series","height"],[1,"card","card-pad","donut-card"],[1,"row","gap-8",2,"align-self","flex-start","margin-bottom","8px"],["name","layers",2,"color","var(--node-code)",3,"size"],[2,"font-weight","600","font-size","12.5px"],[3,"data","size","centerLabel","centerSub"],[1,"model-legend"],[1,"legend-row"],[1,"card","card-pad"],[1,"row","gap-8",2,"margin-bottom","12px"],["name","sortAsc",2,"color","var(--accent)",3,"size"],[1,"muted",2,"font-size","11px"],[1,"mono",2,"font-size","13px","font-weight","600"],[1,"muted",2,"font-size","10.5px"],[1,"swatch"],[1,"mono","grow",2,"font-size","11.5px"],[1,"mono",2,"font-size","11.5px"],[1,"mono","muted",2,"font-size","10.5px","width","38px","text-align","right"],[1,"skel","row-skel"],[1,"prompt-row",3,"first"],[1,"prompt-row"],[1,"mono","muted","tabular","rank"],[1,"prompt-grow"],[1,"prompt-text"],[1,"bar-track",2,"margin-top","4px","max-width","280px"],[1,"bar-fill"],[1,"mono","muted","prompt-model"],[1,"mono","muted","tabular","prompt-toks"],[1,"mono","tabular","cache-cell"],[1,"mono","tabular","cost-cell"]],template:function(t,n){if(t&1&&(r(0,"div",0)(1,"app-page-head",1),H(2,2),r(3,"app-segmented",3),I("change",function(l){return n.setRange(l)}),s(),j(),s(),r(4,"div",4)(5,"div",5)(6,"div",6)(7,"div")(8,"div",7),c(9),s(),r(10,"div",8)(11,"span",9),c(12),s(),_(13,we,1,2,"app-delta",10),s()(),_(14,Se,5,3,"div",11),s(),r(15,"app-line-chart",12),I("hover",function(l){return n.onHover(l)}),s()(),r(16,"div",13)(17,"div",14),m(18,"app-icon",15),r(19,"span",16),c(20,"By model"),s()(),m(21,"app-donut",17),r(22,"div",18),v(23,ke,8,5,"div",19,Me),s()()(),r(25,"div",20)(26,"div",21),m(27,"app-icon",22),r(28,"span",16),c(29,"Most expensive prompts"),s(),r(30,"span",23),c(31),s()(),_(32,Oe,2,1)(33,ze,2,0),s()()),t&2){let a;i(3),g("value",n.range())("options",V(20,ye,C(16,_e),C(17,he),C(18,ve),C(19,be))),i(6),d(n.fmt$(n.total())),i(3),S("total \xB7 ",n.range()),i(),h(n.range()!=="all"&&n.wowDelta()!==0?13:-1),i(),h((a=n.hovered())?14:-1,a),i(),g("series",n.series())("height",200),i(3),g("size",14),i(3),g("data",n.byModel())("size",150)("centerLabel","$"+n.total().toFixed(0))("centerSub",n.range()+" window"),i(2),b(n.byModel()),i(4),g("size",14),i(4),S("\xB7 top ",n.topPrompts().length),i(),h(n.resource.state().loading?32:33)}},dependencies:[te,E,Q,X,ee,J,W],styles:["[_nghost-%COMP%]{display:contents}.page[_ngcontent-%COMP%]{flex:1;padding:18px}.muted[_ngcontent-%COMP%]{color:var(--text-muted)}.mono[_ngcontent-%COMP%]{font-family:var(--font-mono)}.grow[_ngcontent-%COMP%]{flex:1}.card[_ngcontent-%COMP%]{background:var(--bg-panel);border:1px solid var(--border-subtle);border-radius:var(--r-lg)}.card-pad[_ngcontent-%COMP%]{padding:14px}.top-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:1.3fr 1fr;gap:14px;margin-bottom:14px}.chart-card[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:10px}.chart-header[_ngcontent-%COMP%]{display:flex;justify-content:space-between;align-items:flex-start}.big-number[_ngcontent-%COMP%]{font-size:34px;font-weight:700;letter-spacing:-.02em}.donut-card[_ngcontent-%COMP%]{display:flex;flex-direction:column;align-items:center;gap:10px}.model-legend[_ngcontent-%COMP%]{width:100%;display:flex;flex-direction:column;gap:6px;margin-top:14px}.legend-row[_ngcontent-%COMP%]{display:flex;gap:8px;align-items:center}.swatch[_ngcontent-%COMP%]{width:9px;height:9px;border-radius:3px;flex-shrink:0}.prompt-row[_ngcontent-%COMP%]{display:grid;grid-template-columns:18px 1fr 70px 54px 44px 56px;gap:12px;align-items:center;padding:9px 0;border-top:1px solid var(--border-subtle)}.prompt-row.first[_ngcontent-%COMP%]{border-top:none}.rank[_ngcontent-%COMP%]{width:16px;font-size:11px}.prompt-grow[_ngcontent-%COMP%]{min-width:0}.prompt-text[_ngcontent-%COMP%]{font-size:12.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.bar-track[_ngcontent-%COMP%]{height:4px;background:#ffffff0f;border-radius:999px;overflow:hidden}.bar-fill[_ngcontent-%COMP%]{display:block;height:100%;border-radius:999px}.prompt-model[_ngcontent-%COMP%]{font-size:10.5px;text-align:right}.prompt-toks[_ngcontent-%COMP%], .cache-cell[_ngcontent-%COMP%]{font-size:11px;text-align:right}.cost-cell[_ngcontent-%COMP%]{font-size:13px;font-weight:600;text-align:right}.skel[_ngcontent-%COMP%]{background:var(--bg-elevated);border-radius:5px;animation:_ngcontent-%COMP%_skeleton 1.4s ease-in-out infinite}.row-skel[_ngcontent-%COMP%]{height:30px;margin:6px 0}@keyframes _ngcontent-%COMP%_skeleton{0%,to{opacity:.5}50%{opacity:.9}}"],changeDetection:0})};export{oe as Costs};
1
+ import{a as te}from"./chunk-QPA2REUE.js";import{a as ee}from"./chunk-YNYVOPWF.js";import{a as Q}from"./chunk-5NTGUSXJ.js";import{a as X}from"./chunk-IOB4JJT4.js";import{c as q}from"./chunk-DTWIJ3GJ.js";import"./chunk-JGDK6YKG.js";import{a as Z}from"./chunk-TWVVIWKO.js";import{Aa as m,Ba as P,Ca as w,Da as A,Ea as H,Fa as j,I as N,Ia as I,Ka as u,O as z,P as R,Ta as y,Ua as G,Va as c,W as $,Wa as d,Xa as S,Ya as K,bb as C,ea as i,fb as V,gb as Y,ib as U,ka as O,lb as p,pb as k,qa as T,ra as _,sa as h,ua as B,va as v,vb as W,wa as b,xa as g,ya as r,za as s,zb as J}from"./chunk-SYGIPC2P.js";import"./chunk-Q7L6LLAK.js";var ge=(o,e)=>e.label;function fe(o,e){if(o&1&&(z(),A(0,"path")),o&2){let t=e.$implicit;T("d",t.d)("fill",t.color)}}function xe(o,e){if(o&1&&(P(0,"div",3),c(1),w()),o&2){let t=u();i(),d(t.centerSub())}}var E=class o{data=k([]);size=k(150);centerLabel=k("");centerSub=k("");arcs=p(()=>{let e=this.data(),t=e.reduce((x,D)=>x+D.cost,0);if(t<=0)return[];let a=this.size()/2,l=a*.6,f=-Math.PI/2,F=[];for(let x of e){let D=x.cost/t*Math.PI*2,M=f+D,L=D>Math.PI?1:0,ie=a+Math.cos(f)*a,ae=a+Math.sin(f)*a,re=a+Math.cos(M)*a,se=a+Math.sin(M)*a,ce=a+Math.cos(M)*l,de=a+Math.sin(M)*l,le=a+Math.cos(f)*l,pe=a+Math.sin(f)*l;F.push({d:`M ${ie} ${ae} A ${a} ${a} 0 ${L} 1 ${re} ${se} L ${ce} ${de} A ${l} ${l} 0 ${L} 0 ${le} ${pe} Z`,color:x.color,label:x.short||x.model||""}),f=M}return F});static \u0275fac=function(t){return new(t||o)};static \u0275cmp=O({type:o,selectors:[["app-donut"]],inputs:{data:[1,"data"],size:[1,"size"],centerLabel:[1,"centerLabel"],centerSub:[1,"centerSub"]},decls:8,vars:9,consts:[[1,"donut"],[1,"donut-center"],[1,"center-label"],[1,"center-sub"]],template:function(t,n){t&1&&(P(0,"div",0),z(),P(1,"svg"),v(2,fe,1,2,":svg:path",null,ge),w(),R(),P(4,"div",1)(5,"div",2),c(6),w(),_(7,xe,2,1,"div",3),w()()),t&2&&(y("width",n.size(),"px")("height",n.size(),"px"),i(),T("width",n.size())("height",n.size())("viewBox","0 0 "+n.size()+" "+n.size()),i(),b(n.arcs()),i(4),d(n.centerLabel()),i(),h(n.centerSub()?7:-1))},styles:["[_nghost-%COMP%]{display:inline-block}.donut[_ngcontent-%COMP%]{position:relative}.donut-center[_ngcontent-%COMP%]{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;pointer-events:none}.center-label[_ngcontent-%COMP%]{font-variant-numeric:tabular-nums;font-size:18px;font-weight:700;color:var(--text-primary)}.center-sub[_ngcontent-%COMP%]{color:var(--text-muted);font-size:10.5px;margin-top:2px}"],changeDetection:0})};var _e=()=>({value:"today",label:"Today"}),he=()=>({value:"week",label:"This week"}),ve=()=>({value:"month",label:"This month"}),be=()=>({value:"all",label:"All time"}),ye=(o,e,t,n)=>[o,e,t,n],Ce=()=>[0,1,2,3],Me=(o,e)=>e.model,Pe=(o,e)=>e.id;function we(o,e){if(o&1&&m(0,"app-delta",10),o&2){let t=u();g("value",t.wowDelta())("invert",!0)}}function Se(o,e){if(o&1&&(r(0,"div",11)(1,"div",24),c(2),s(),r(3,"div",25),c(4),s()()),o&2){let t=e,n=u();i(2),d(n.fmt$(t.cost)),i(2),K("",t.prompts," prompts \xB7 day ",t.day)}}function ke(o,e){if(o&1&&(r(0,"div",19),m(1,"span",26),r(2,"span",27),c(3),s(),r(4,"span",28),c(5),s(),r(6,"span",29),c(7),s()()),o&2){let t=e.$implicit,n=u();i(),y("background",t.color),i(2),d(t.short),i(2),d(n.fmt$(t.cost)),i(2),S("",n.percentOf(t.cost,n.total()),"%")}}function De(o,e){o&1&&m(0,"div",30)}function Oe(o,e){o&1&&v(0,De,1,0,"div",30,B),o&2&&b(C(0,Ce))}function Ee(o,e){if(o&1&&(r(0,"div",32)(1,"span",33),c(2),s(),r(3,"div",34)(4,"div",35),c(5),s(),r(6,"div",36),m(7,"span",37),s()(),r(8,"span",38),c(9),s(),r(10,"span",39),c(11),s(),r(12,"span",40),c(13),Y(14,"number"),s(),r(15,"span",41),c(16),s()()),o&2){let t=e.$implicit,n=e.$index,a=u(2);G("first",n===0),i(2),d(n+1),i(3),d(t.text),i(2),y("width",t.cost_usd/a.maxPrompt()*100,"%")("background",t.cost_usd/a.maxPrompt()>.66?"var(--error)":"var(--accent)"),i(2),d(a.modelShort(t.model)),i(2),d(a.fmtK(a.promptTokens(t))),i(),y("color",a.cacheColor(a.cacheRate(t))),i(),S("",U(14,14,a.cacheRate(t)*100,"1.0-0"),"%"),i(3),d(a.fmt$(t.cost_usd))}}function ze(o,e){if(o&1&&v(0,Ee,17,17,"div",31,Pe),o&2){let t=u();b(t.topPrompts())}}var $e={"claude-opus-4-7":"#A586F5","claude-opus-4":"#A586F5","claude-sonnet-4-6":"#5B93F2","claude-sonnet-4-7":"#5B93F2","claude-sonnet-4":"#5B93F2","claude-haiku-4-5":"#29D2BE","claude-haiku-4":"#29D2BE"},ne={"claude-opus-4-7":"Opus 4.7","claude-opus-4":"Opus 4","claude-sonnet-4-6":"Sonnet 4.6","claude-sonnet-4-7":"Sonnet 4.7","claude-sonnet-4":"Sonnet 4","claude-haiku-4-5":"Haiku 4.5","claude-haiku-4":"Haiku 4"},oe=class o{api=N(Z);range=$("month");ranges=["today","week","month","all"];hovered=$(null);resource=q(this.api,()=>`/api/claude/costs?range=${this.range()}`);series=p(()=>this.resource.state().data?.series??[]);topPrompts=p(()=>(this.resource.state().data?.topPrompts??[]).slice(0,12));maxPrompt=p(()=>{let e=this.topPrompts();return Math.max(.01,...e.map(t=>t.cost_usd??0))});byModel=p(()=>(this.resource.state().data?.byModel??[]).map(t=>({model:t.model,short:ne[t.model]||t.model,cost:t.cost||0,color:$e[t.model]||"#5C6573"})));total=p(()=>this.resource.state().data?.total??0);wowDelta=p(()=>this.resource.state().data?.wowDelta??0);setRange(e){this.range.set(e)}onHover(e){this.hovered.set(e)}fmt$(e){return"$"+e.toLocaleString("en-US",{minimumFractionDigits:2,maximumFractionDigits:2})}fmtK(e){return e>=1e3?(e/1e3).toFixed(e>=1e4?0:1)+"k":String(e)}promptTokens(e){return(e.input_tokens??0)+(e.output_tokens??0)+(e.cache_creation_tokens??0)+(e.cache_read_tokens??0)}cacheRate(e){let t=(e.input_tokens??0)+(e.cache_creation_tokens??0)+(e.cache_read_tokens??0);return t>0?(e.cache_read_tokens??0)/t:0}cacheColor(e){return e>=.7?"var(--success)":e>=.5?"var(--warn)":"var(--error)"}modelShort(e){return e?ne[e]||e.replace(/^claude-/,""):"?"}percentOf(e,t){return t>0?Math.round(e/t*100):0}static \u0275fac=function(t){return new(t||o)};static \u0275cmp=O({type:o,selectors:[["app-costs"]],decls:34,vars:25,consts:[[1,"page","scroll-y"],["icon","dollar","title","Costs","sub","Where the money goes"],["actions",""],["size","sm",3,"change","value","options"],[1,"top-grid"],[1,"card","card-pad","chart-card"],[1,"chart-header"],[1,"big-number","mono"],[1,"row","gap-8",2,"margin-top","2px"],[1,"muted",2,"font-size","11.5px"],[3,"value","invert"],[2,"text-align","right"],["color","var(--accent)",3,"hover","series","height"],[1,"card","card-pad","donut-card"],[1,"row","gap-8",2,"align-self","flex-start","margin-bottom","8px"],["name","layers",2,"color","var(--node-code)",3,"size"],[2,"font-weight","600","font-size","12.5px"],[3,"data","size","centerLabel","centerSub"],[1,"model-legend"],[1,"legend-row"],[1,"card","card-pad"],[1,"row","gap-8",2,"margin-bottom","12px"],["name","sortAsc",2,"color","var(--accent)",3,"size"],[1,"muted",2,"font-size","11px"],[1,"mono",2,"font-size","13px","font-weight","600"],[1,"muted",2,"font-size","10.5px"],[1,"swatch"],[1,"mono","grow",2,"font-size","11.5px"],[1,"mono",2,"font-size","11.5px"],[1,"mono","muted",2,"font-size","10.5px","width","38px","text-align","right"],[1,"skel","row-skel"],[1,"prompt-row",3,"first"],[1,"prompt-row"],[1,"mono","muted","tabular","rank"],[1,"prompt-grow"],[1,"prompt-text"],[1,"bar-track",2,"margin-top","4px","max-width","280px"],[1,"bar-fill"],[1,"mono","muted","prompt-model"],[1,"mono","muted","tabular","prompt-toks"],[1,"mono","tabular","cache-cell"],[1,"mono","tabular","cost-cell"]],template:function(t,n){if(t&1&&(r(0,"div",0)(1,"app-page-head",1),H(2,2),r(3,"app-segmented",3),I("change",function(l){return n.setRange(l)}),s(),j(),s(),r(4,"div",4)(5,"div",5)(6,"div",6)(7,"div")(8,"div",7),c(9),s(),r(10,"div",8)(11,"span",9),c(12),s(),_(13,we,1,2,"app-delta",10),s()(),_(14,Se,5,3,"div",11),s(),r(15,"app-line-chart",12),I("hover",function(l){return n.onHover(l)}),s()(),r(16,"div",13)(17,"div",14),m(18,"app-icon",15),r(19,"span",16),c(20,"By model"),s()(),m(21,"app-donut",17),r(22,"div",18),v(23,ke,8,5,"div",19,Me),s()()(),r(25,"div",20)(26,"div",21),m(27,"app-icon",22),r(28,"span",16),c(29,"Most expensive prompts"),s(),r(30,"span",23),c(31),s()(),_(32,Oe,2,1)(33,ze,2,0),s()()),t&2){let a;i(3),g("value",n.range())("options",V(20,ye,C(16,_e),C(17,he),C(18,ve),C(19,be))),i(6),d(n.fmt$(n.total())),i(3),S("total \xB7 ",n.range()),i(),h(n.range()!=="all"&&n.wowDelta()!==0?13:-1),i(),h((a=n.hovered())?14:-1,a),i(),g("series",n.series())("height",200),i(3),g("size",14),i(3),g("data",n.byModel())("size",150)("centerLabel","$"+n.total().toFixed(0))("centerSub",n.range()+" window"),i(2),b(n.byModel()),i(4),g("size",14),i(4),S("\xB7 top ",n.topPrompts().length),i(),h(n.resource.state().loading?32:33)}},dependencies:[te,E,Q,X,ee,J,W],styles:["[_nghost-%COMP%]{display:contents}.page[_ngcontent-%COMP%]{flex:1;padding:18px}.muted[_ngcontent-%COMP%]{color:var(--text-muted)}.mono[_ngcontent-%COMP%]{font-family:var(--font-mono)}.grow[_ngcontent-%COMP%]{flex:1}.card[_ngcontent-%COMP%]{background:var(--bg-panel);border:1px solid var(--border-subtle);border-radius:var(--r-lg)}.card-pad[_ngcontent-%COMP%]{padding:14px}.top-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:1.3fr 1fr;gap:14px;margin-bottom:14px}.chart-card[_ngcontent-%COMP%]{display:flex;flex-direction:column;gap:10px}.chart-header[_ngcontent-%COMP%]{display:flex;justify-content:space-between;align-items:flex-start}.big-number[_ngcontent-%COMP%]{font-size:34px;font-weight:700;letter-spacing:-.02em}.donut-card[_ngcontent-%COMP%]{display:flex;flex-direction:column;align-items:center;gap:10px}.model-legend[_ngcontent-%COMP%]{width:100%;display:flex;flex-direction:column;gap:6px;margin-top:14px}.legend-row[_ngcontent-%COMP%]{display:flex;gap:8px;align-items:center}.swatch[_ngcontent-%COMP%]{width:9px;height:9px;border-radius:3px;flex-shrink:0}.prompt-row[_ngcontent-%COMP%]{display:grid;grid-template-columns:18px 1fr 70px 54px 44px 56px;gap:12px;align-items:center;padding:9px 0;border-top:1px solid var(--border-subtle)}.prompt-row.first[_ngcontent-%COMP%]{border-top:none}.rank[_ngcontent-%COMP%]{width:16px;font-size:11px}.prompt-grow[_ngcontent-%COMP%]{min-width:0}.prompt-text[_ngcontent-%COMP%]{font-size:12.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.bar-track[_ngcontent-%COMP%]{height:4px;background:#ffffff0f;border-radius:999px;overflow:hidden}.bar-fill[_ngcontent-%COMP%]{display:block;height:100%;border-radius:999px}.prompt-model[_ngcontent-%COMP%]{font-size:10.5px;text-align:right}.prompt-toks[_ngcontent-%COMP%], .cache-cell[_ngcontent-%COMP%]{font-size:11px;text-align:right}.cost-cell[_ngcontent-%COMP%]{font-size:13px;font-weight:600;text-align:right}.skel[_ngcontent-%COMP%]{background:var(--bg-elevated);border-radius:5px;animation:_ngcontent-%COMP%_skeleton 1.4s ease-in-out infinite}.row-skel[_ngcontent-%COMP%]{height:30px;margin:6px 0}@keyframes _ngcontent-%COMP%_skeleton{0%,to{opacity:.5}50%{opacity:.9}}"],changeDetection:0})};export{oe as Costs};