@specship/specship-win32-arm64 0.11.4 → 0.11.6
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.
- package/lib/dist/server/chat/classify.js +110 -0
- package/lib/dist/server/routes/chat-answer.js +488 -0
- package/lib/dist/server/routes/chat.js +145 -0
- package/lib/dist/server/server.js +2 -0
- package/lib/dist/statusline/index.d.ts.map +1 -1
- package/lib/dist/statusline/index.js +6 -1
- package/lib/dist/statusline/index.js.map +1 -1
- package/lib/dist/statusline/render.d.ts +7 -0
- package/lib/dist/statusline/render.d.ts.map +1 -1
- package/lib/dist/statusline/render.js +10 -1
- package/lib/dist/statusline/render.js.map +1 -1
- package/lib/dist/statusline/usage-limits.d.ts +12 -0
- package/lib/dist/statusline/usage-limits.d.ts.map +1 -1
- package/lib/dist/statusline/usage-limits.js +38 -0
- package/lib/dist/statusline/usage-limits.js.map +1 -1
- package/lib/dist/web/chunk-6FZTSHJS.js +3 -0
- package/lib/dist/web/index.html +1 -1
- package/lib/dist/web/{main-FHGJXJSF.js → main-A6QZ3DLK.js} +1 -1
- package/lib/node_modules/.package-lock.json +1 -1
- package/lib/package.json +1 -1
- package/package.json +1 -1
- package/lib/dist/web/chunk-VPUORMLB.js +0 -3
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* POST /api/chat (REQ-DASH-CHAT-001).
|
|
3
|
+
*
|
|
4
|
+
* The dashboard chat's server endpoint. It answers a free-form question
|
|
5
|
+
* **deterministically from the project's own indexed knowledge base** — the
|
|
6
|
+
* code graph, specs, and domain facts — with **no language model and no
|
|
7
|
+
* network call** (A2). All the answering logic lives in the pure, Fastify-free
|
|
8
|
+
* core (`chat-answer.ts`) so determinism / no-LLM is unit-testable in isolation;
|
|
9
|
+
* this file is only the HTTP shell.
|
|
10
|
+
*
|
|
11
|
+
* Project-scoped like the spec / domain / maintainability routes: chat answers
|
|
12
|
+
* come from one project's graph + spec layer, so the handler resolves the
|
|
13
|
+
* active instance and 409s when no project is selectable (mirrors
|
|
14
|
+
* `domain.ts`). Driven entirely through instance methods via the core, so the
|
|
15
|
+
* server never runtime-imports the `@specship/specship` package (which would
|
|
16
|
+
* silently serve a stale build).
|
|
17
|
+
*
|
|
18
|
+
* The question is routed by the deterministic, I/O-free classifier
|
|
19
|
+
* (`../chat/classify.ts`, REQ-DASH-CHAT-002) to the matching knowledge-base
|
|
20
|
+
* query via `answerForIntent`. Two shapes are served:
|
|
21
|
+
*
|
|
22
|
+
* - `POST /api/chat` — returns the fully-composed answer in one JSON response.
|
|
23
|
+
* - `GET /api/chat/stream` — faux-streams the SAME answer as a paced SSE
|
|
24
|
+
* event sequence (REQ-DASH-CHAT-003): the full answer is computed first,
|
|
25
|
+
* then emitted as `thinking` → `tool` → `result_summary` → `chunk`… →
|
|
26
|
+
* `done`. The chunking is presentation pacing only; a client disconnect ends
|
|
27
|
+
* the stream cleanly without throwing (A4).
|
|
28
|
+
*/
|
|
29
|
+
import { answerForIntent, chunkAnswer } from './chat-answer.js';
|
|
30
|
+
import { classifyIntent } from '../chat/classify.js';
|
|
31
|
+
export async function registerChatRoutes(app) {
|
|
32
|
+
app.post('/api/chat', async (req, reply) => {
|
|
33
|
+
const cg = await app.activeCg(req);
|
|
34
|
+
if (!cg) {
|
|
35
|
+
reply.code(409).send({ error: 'no project selected', code: 'no_project' });
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const body = (req.body ?? {});
|
|
39
|
+
const question = typeof body.question === 'string' ? body.question.trim() : '';
|
|
40
|
+
if (question.length === 0) {
|
|
41
|
+
reply.code(400).send({ error: 'question is required', code: 'bad_request' });
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const classified = classifyIntent(question);
|
|
45
|
+
const { found, answer, sources } = answerForIntent(cg, classified);
|
|
46
|
+
return { found, answer, sources };
|
|
47
|
+
});
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// GET /api/chat/stream (REQ-DASH-CHAT-003) — the faux-streaming variant.
|
|
50
|
+
//
|
|
51
|
+
// GET + SSE so the browser's native `EventSource` (via ApiService) drives it.
|
|
52
|
+
// The answer is composed in full BEFORE the first chunk is written (A3), then
|
|
53
|
+
// paced out as named events. Writes go straight to `reply.raw` and the handler
|
|
54
|
+
// returns without awaiting the pacing — mirrors `events.ts`; the setTimeout
|
|
55
|
+
// chain keeps writing after the handler resolves and `reply.raw.end()` closes
|
|
56
|
+
// the stream after the `done` sentinel. Every write is guarded so a client
|
|
57
|
+
// disconnect (which flips `closed` and clears the timer) ends cleanly (A4).
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
app.get('/api/chat/stream', async (req, reply) => {
|
|
60
|
+
const cg = await app.activeCg(req);
|
|
61
|
+
if (!cg) {
|
|
62
|
+
reply.code(409).send({ error: 'no project selected', code: 'no_project' });
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const q = req.query?.question;
|
|
66
|
+
const question = typeof q === 'string' ? q.trim() : '';
|
|
67
|
+
if (question.length === 0) {
|
|
68
|
+
reply.code(400).send({ error: 'question is required', code: 'bad_request' });
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
// Compose the whole answer up front — chunk boundaries/pacing below affect
|
|
72
|
+
// presentation only, never content (A3).
|
|
73
|
+
const classified = classifyIntent(question);
|
|
74
|
+
const { found, answer, sources } = answerForIntent(cg, classified);
|
|
75
|
+
const chunks = chunkAnswer(answer);
|
|
76
|
+
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');
|
|
80
|
+
let closed = false;
|
|
81
|
+
let timer;
|
|
82
|
+
const write = (event, data) => {
|
|
83
|
+
if (closed)
|
|
84
|
+
return;
|
|
85
|
+
try {
|
|
86
|
+
reply.raw.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
/* peer gone — stop writing */
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
// A client disconnect ends the stream cleanly: stop the pacing, write no more.
|
|
93
|
+
req.raw.on('close', () => {
|
|
94
|
+
closed = true;
|
|
95
|
+
if (timer)
|
|
96
|
+
clearTimeout(timer);
|
|
97
|
+
});
|
|
98
|
+
// Pre-chunk events, in the order the spec fixes (A1).
|
|
99
|
+
write('thinking', { started: true });
|
|
100
|
+
write('tool', { name: tool.name, input: tool.input });
|
|
101
|
+
write('result_summary', { found, sourceCount: sources.length });
|
|
102
|
+
// Pace the answer chunks, then the terminal `done` sentinel.
|
|
103
|
+
let idx = 0;
|
|
104
|
+
const step = () => {
|
|
105
|
+
if (closed)
|
|
106
|
+
return;
|
|
107
|
+
if (idx >= chunks.length) {
|
|
108
|
+
write('done', { found, sources });
|
|
109
|
+
if (!closed) {
|
|
110
|
+
try {
|
|
111
|
+
reply.raw.end();
|
|
112
|
+
}
|
|
113
|
+
catch { /* already closed */ }
|
|
114
|
+
}
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
write('chunk', { text: chunks[idx] });
|
|
118
|
+
idx += 1;
|
|
119
|
+
timer = setTimeout(step, CHUNK_PACING_MS);
|
|
120
|
+
};
|
|
121
|
+
step();
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
/** Inter-chunk delay for the faux-stream — small, presentation-only pacing. */
|
|
125
|
+
const CHUNK_PACING_MS = 24;
|
|
126
|
+
/**
|
|
127
|
+
* The truthful tool-call the answer came from (REQ-DASH-CHAT-004.A2) — the
|
|
128
|
+
* capability name the UI renders in its tool card, plus the real query input.
|
|
129
|
+
* Maps each classified intent to the specship capability that answered it; the
|
|
130
|
+
* input is the classifier's own query so the card reflects what actually ran.
|
|
131
|
+
*/
|
|
132
|
+
function toolForIntent(classified) {
|
|
133
|
+
const input = classified.query.trim();
|
|
134
|
+
switch (classified.intent) {
|
|
135
|
+
case 'callers': return { name: 'specship_callers', input };
|
|
136
|
+
case 'callees': return { name: 'specship_callees', input };
|
|
137
|
+
case 'impact': return { name: 'specship_impact', input };
|
|
138
|
+
case 'spec': return { name: 'specship_spec', input };
|
|
139
|
+
case 'domain': return { name: 'specship_spec', input };
|
|
140
|
+
case 'drift': return { name: 'specship_drifted', input };
|
|
141
|
+
case 'explore': return { name: 'specship_explore', input };
|
|
142
|
+
case 'search':
|
|
143
|
+
default: return { name: 'specship_search', input };
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -31,6 +31,7 @@ import { registerEventsRoutes } from './routes/events.js';
|
|
|
31
31
|
import { registerReflectRoutes } from './routes/reflect.js';
|
|
32
32
|
import { registerMaintainabilityRoutes } from './routes/maintainability.js';
|
|
33
33
|
import { registerDomainRoutes } from './routes/domain.js';
|
|
34
|
+
import { registerChatRoutes } from './routes/chat.js';
|
|
34
35
|
/**
|
|
35
36
|
* Lazy-import the specship core. Two delivery shapes are supported:
|
|
36
37
|
*
|
|
@@ -172,6 +173,7 @@ export async function createServer(options) {
|
|
|
172
173
|
await registerReflectRoutes(app);
|
|
173
174
|
await registerMaintainabilityRoutes(app);
|
|
174
175
|
await registerDomainRoutes(app);
|
|
176
|
+
await registerChatRoutes(app);
|
|
175
177
|
// Optional: serve the built Angular UI from `webDir` and fall back to
|
|
176
178
|
// index.html for client-side routes. Must register AFTER the /api/*
|
|
177
179
|
// routes so they take precedence over the SPA wildcard.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/statusline/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/C,YAAY,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAgCzC;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,UAAyB,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/statusline/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/C,YAAY,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAgCzC;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,UAAyB,GAAG,MAAM,CAkCvF"}
|
|
@@ -122,9 +122,12 @@ function buildSegment(rawStdin, noColor = !!process.env.NO_COLOR) {
|
|
|
122
122
|
// formats reset times in local time.
|
|
123
123
|
const usage = (0, usage_limits_1.usageFromStatuslineInput)(rawStdin) ?? (0, usage_limits_1.readUsageLimits)();
|
|
124
124
|
const now = Date.now();
|
|
125
|
+
// Context-usage element (REQ-STATUSLINE-009) — from the same stdin.
|
|
126
|
+
const context = (0, usage_limits_1.contextFromStatuslineInput)(rawStdin);
|
|
127
|
+
const ctxWarnPct = (0, usage_limits_1.resolveCtxWarnPct)();
|
|
125
128
|
if (!root) {
|
|
126
129
|
// No SpecShip project here — render the idle degraded line.
|
|
127
|
-
return (0, render_1.renderSegment)({ cache: null, marker: null, run: null, usage, now, noColor });
|
|
130
|
+
return (0, render_1.renderSegment)({ cache: null, marker: null, run: null, usage, now, context, ctxWarnPct, noColor });
|
|
128
131
|
}
|
|
129
132
|
return (0, render_1.renderSegment)({
|
|
130
133
|
cache: (0, cache_1.readStatuslineCache)(root),
|
|
@@ -132,6 +135,8 @@ function buildSegment(rawStdin, noColor = !!process.env.NO_COLOR) {
|
|
|
132
135
|
run: (0, active_run_1.readActiveRun)(root),
|
|
133
136
|
usage,
|
|
134
137
|
now,
|
|
138
|
+
context,
|
|
139
|
+
ctxWarnPct,
|
|
135
140
|
noColor,
|
|
136
141
|
});
|
|
137
142
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/statusline/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuDH,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/statusline/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -25,6 +25,13 @@ export interface RenderInput {
|
|
|
25
25
|
* time; keeps this function pure (no clock). Required when `usage` is present.
|
|
26
26
|
*/
|
|
27
27
|
now?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Claude's `context_window.used_percentage` (0-100) from stdin, or null/undefined
|
|
30
|
+
* to omit the CTX element (REQ-STATUSLINE-009). SpecShip never fabricates it.
|
|
31
|
+
*/
|
|
32
|
+
context?: number | null;
|
|
33
|
+
/** Context-usage warning threshold (percent); CTX escalates at/above it. */
|
|
34
|
+
ctxWarnPct?: number;
|
|
28
35
|
/** When true, emit no ANSI escapes. */
|
|
29
36
|
noColor: boolean;
|
|
30
37
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/statusline/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEjF,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC;IAC7B,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC;IACtB;;;;OAIG;IACH,KAAK,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3B;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,OAAO,EAAE,OAAO,CAAC;CAClB;AA+CD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/statusline/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEjF,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC;IAC7B,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC;IACtB;;;;OAIG;IACH,KAAK,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3B;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,OAAO,EAAE,OAAO,CAAC;CAClB;AA+CD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CA6DxD"}
|
|
@@ -57,7 +57,7 @@ function paint(noColor, code, s) {
|
|
|
57
57
|
* a minimal `◈ specship … ◈` when caches are absent rather than erroring.
|
|
58
58
|
*/
|
|
59
59
|
function renderSegment(input) {
|
|
60
|
-
const { cache, marker, run, usage, now, noColor } = input;
|
|
60
|
+
const { cache, marker, run, usage, now, context, ctxWarnPct, noColor } = input;
|
|
61
61
|
const c = (code, s) => paint(noColor, code, s);
|
|
62
62
|
const orn = c(COLOR.orn, '◈');
|
|
63
63
|
const sep = c(COLOR.frame, ' ◆ ');
|
|
@@ -89,6 +89,15 @@ function renderSegment(input) {
|
|
|
89
89
|
const label = run.specId ? `${run.specId}·${run.status}` : run.status;
|
|
90
90
|
parts.push(c(COLOR.run, label));
|
|
91
91
|
}
|
|
92
|
+
// Context-usage element (REQ-STATUSLINE-009) — Claude's real context %, with
|
|
93
|
+
// an escalating compaction warning past the threshold. Advisory only;
|
|
94
|
+
// SpecShip cannot compact. Omitted when no real percentage is available.
|
|
95
|
+
if (context != null && Number.isFinite(context)) {
|
|
96
|
+
const warn = context >= (ctxWarnPct ?? 80);
|
|
97
|
+
const color = warn ? COLOR.pending : COLOR.calls; // amber when high, else gold
|
|
98
|
+
const hint = warn ? ' ⚠ compact' : '';
|
|
99
|
+
parts.push(c(color, `CTX ${bar(context)} ${Math.round(context)}%${hint}`));
|
|
100
|
+
}
|
|
92
101
|
// Usage-limit sub-segment (REQ-STATUSLINE-008) — ONLY for windows with real
|
|
93
102
|
// numbers; SpecShip never estimates. `now` formats reset times in local time.
|
|
94
103
|
if (usage && now != null) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/statusline/render.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/statusline/render.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,6 +22,18 @@ import { UsageLimits } from './types';
|
|
|
22
22
|
* either window may be independently null.
|
|
23
23
|
*/
|
|
24
24
|
export declare function usageFromStatuslineInput(raw: string): UsageLimits | null;
|
|
25
|
+
/**
|
|
26
|
+
* Parse Claude Code's status-line stdin JSON for context-window usage
|
|
27
|
+
* (REQ-STATUSLINE-009). Returns `context_window.used_percentage` (0-100) or null
|
|
28
|
+
* when it's absent, null (early session), or unparseable.
|
|
29
|
+
*/
|
|
30
|
+
export declare function contextFromStatuslineInput(raw: string): number | null;
|
|
31
|
+
/**
|
|
32
|
+
* Resolve the context-usage warning threshold from `SPECSHIP_CTX_WARN_PCT`
|
|
33
|
+
* (REQ-STATUSLINE-009), falling back to the default when unset, non-numeric, or
|
|
34
|
+
* out of the 0-100 range.
|
|
35
|
+
*/
|
|
36
|
+
export declare function resolveCtxWarnPct(raw?: string | undefined): number;
|
|
25
37
|
export interface ReadUsageOptions {
|
|
26
38
|
/** Override the file path (defaults to `$SPECSHIP_USAGE_FILE` or `~/.specship/usage-limits.json`). */
|
|
27
39
|
file?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usage-limits.d.ts","sourceRoot":"","sources":["../../src/statusline/usage-limits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,OAAO,EAAE,WAAW,EAAe,MAAM,SAAS,CAAC;AAEnD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAcxE;AAiBD,MAAM,WAAW,gBAAgB;IAC/B,sGAAsG;IACtG,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iFAAiF;IACjF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,yDAAyD;AACzD,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAYD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,GAAE,gBAAqB,GAAG,WAAW,GAAG,IAAI,CA4B/E"}
|
|
1
|
+
{"version":3,"file":"usage-limits.d.ts","sourceRoot":"","sources":["../../src/statusline/usage-limits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,OAAO,EAAE,WAAW,EAAe,MAAM,SAAS,CAAC;AAEnD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAcxE;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYrE;AAKD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAM,GAAG,SAA6C,GAAG,MAAM,CAKrG;AAiBD,MAAM,WAAW,gBAAgB;IAC/B,sGAAsG;IACtG,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iFAAiF;IACjF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,yDAAyD;AACzD,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAYD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,GAAE,gBAAqB,GAAG,WAAW,GAAG,IAAI,CA4B/E"}
|
|
@@ -50,6 +50,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
50
50
|
})();
|
|
51
51
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
52
52
|
exports.usageFromStatuslineInput = usageFromStatuslineInput;
|
|
53
|
+
exports.contextFromStatuslineInput = contextFromStatuslineInput;
|
|
54
|
+
exports.resolveCtxWarnPct = resolveCtxWarnPct;
|
|
53
55
|
exports.usageFilePath = usageFilePath;
|
|
54
56
|
exports.readUsageLimits = readUsageLimits;
|
|
55
57
|
const fs = __importStar(require("fs"));
|
|
@@ -79,6 +81,42 @@ function usageFromStatuslineInput(raw) {
|
|
|
79
81
|
return null;
|
|
80
82
|
return { session, weekly };
|
|
81
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Parse Claude Code's status-line stdin JSON for context-window usage
|
|
86
|
+
* (REQ-STATUSLINE-009). Returns `context_window.used_percentage` (0-100) or null
|
|
87
|
+
* when it's absent, null (early session), or unparseable.
|
|
88
|
+
*/
|
|
89
|
+
function contextFromStatuslineInput(raw) {
|
|
90
|
+
let json;
|
|
91
|
+
try {
|
|
92
|
+
json = JSON.parse(raw);
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
const cw = json.context_window;
|
|
98
|
+
if (!cw || typeof cw !== 'object')
|
|
99
|
+
return null;
|
|
100
|
+
const used = cw.used_percentage;
|
|
101
|
+
if (typeof used !== 'number' || !Number.isFinite(used))
|
|
102
|
+
return null;
|
|
103
|
+
return Math.max(0, Math.min(100, used));
|
|
104
|
+
}
|
|
105
|
+
/** Default context-usage warning threshold (percent). */
|
|
106
|
+
const DEFAULT_CTX_WARN_PCT = 80;
|
|
107
|
+
/**
|
|
108
|
+
* Resolve the context-usage warning threshold from `SPECSHIP_CTX_WARN_PCT`
|
|
109
|
+
* (REQ-STATUSLINE-009), falling back to the default when unset, non-numeric, or
|
|
110
|
+
* out of the 0-100 range.
|
|
111
|
+
*/
|
|
112
|
+
function resolveCtxWarnPct(raw = process.env.SPECSHIP_CTX_WARN_PCT) {
|
|
113
|
+
if (raw == null || raw.trim() === '')
|
|
114
|
+
return DEFAULT_CTX_WARN_PCT;
|
|
115
|
+
const n = Number(raw);
|
|
116
|
+
if (!Number.isFinite(n) || n < 0 || n > 100)
|
|
117
|
+
return DEFAULT_CTX_WARN_PCT;
|
|
118
|
+
return n;
|
|
119
|
+
}
|
|
82
120
|
/** One `rate_limits.{five_hour,seven_day}` entry → a remaining-capacity window. */
|
|
83
121
|
function windowFromRateLimit(w) {
|
|
84
122
|
if (!w || typeof w !== 'object')
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usage-limits.js","sourceRoot":"","sources":["../../src/statusline/usage-limits.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAaH,4DAcC;AA2BD,sCAEC;AAgBD,0CA4BC;
|
|
1
|
+
{"version":3,"file":"usage-limits.js","sourceRoot":"","sources":["../../src/statusline/usage-limits.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{a as W}from"./chunk-JLOJCDIY.js";import{a as G}from"./chunk-YV5LB22R.js";import{b as U}from"./chunk-WBJ5VEB5.js";import{a as Q}from"./chunk-IOB4JJT4.js";import{a as K}from"./chunk-3H2EZLZN.js";import{Aa as x,Ga as k,I as O,Ia as h,Ka as s,M as v,N as y,Ra as N,Sa as H,Ta as R,Ua as B,Va as l,W as w,Wa as u,Xa as g,Ya as $,aa as z,ea as i,ka as V,lb as D,qa as T,qb as L,ra as p,sa as _,ta as F,ua as A,va as C,wa as f,xa as m,ya as o,yb as j,za as a,zb as q}from"./chunk-SYGIPC2P.js";import{a as S,b as M}from"./chunk-Q7L6LLAK.js";var te=["listEl"],ne=(t,n)=>n.name,Z=(t,n)=>n.qualifiedName,ie=(t,n)=>n.target,oe=(t,n)=>n.cmd;function ae(t,n){if(t&1&&(o(0,"div",22),x(1,"div",24),a()),t&2){let e=s().$implicit,r=s();i(),m("innerHTML",r.renderMd(e.text),z)}}function re(t,n){if(t&1&&(o(0,"div",39)(1,"div",40),l(2,"output"),a(),o(3,"div",41),l(4),a()()),t&2){let e=s().$implicit;i(4),u(e.output)}}function le(t,n){if(t&1){let e=k();o(0,"div",31)(1,"button",32),h("click",function(){let d=v(e).$implicit,c=s(3).$implicit,b=s();return y(b.toggleToolCall(c,d))}),x(2,"app-icon",33)(3,"app-icon",34),o(4,"span",35),l(5),o(6,"span",36),l(7),a()(),o(8,"span",37),x(9,"app-icon",38),l(10),a()(),p(11,re,5,1,"div",39),a()}if(t&2){let e=n.$implicit;i(),T("aria-expanded",e.open),i(),m("name",e.open?"chevronDown":"chevronRight")("size",12),i(),m("size",12),i(2),g(" ",e.name),i(2),g("(",e.input,")"),i(2),m("size",9),i(),g(" ",e.status," "),i(),_(e.open?11:-1)}}function de(t,n){if(t&1&&C(0,le,12,9,"div",31,ne),t&2){let e=s(2).$implicit;f(e.tools)}}function se(t,n){if(t&1&&l(0),t&2){let e=s(2).$implicit;g(":",e.line)}}function ce(t,n){if(t&1&&(l(0),p(1,se,1,1)),t&2){let e=s().$implicit;g(" \xB7 ",e.filePath),i(),_(e.line?1:-1)}}function pe(t,n){if(t&1&&l(0),t&2){let e=s().$implicit;g(" \xB7 ",e.ref," ")}}function _e(t,n){if(t&1&&(o(0,"div",47),l(1),a()),t&2){let e=s(3).$implicit;i(),u(e.detail.signature)}}function me(t,n){if(t&1&&(o(0,"pre",48),l(1),a()),t&2){let e=s(3).$implicit;i(),u(e.detail.body)}}function xe(t,n){if(t&1&&(o(0,"div",51),l(1),o(2,"span",36),l(3),a()()),t&2){let e=n.$implicit;i(),g("",e.name," "),i(2),$("",e.filePath,":",e.line)}}function ue(t,n){if(t&1&&(o(0,"div",49)(1,"div",50),l(2,"callers"),a(),C(3,xe,4,3,"div",51,Z),a()),t&2){let e=s(3).$implicit;i(3),f(e.detail.callers)}}function ge(t,n){if(t&1&&(o(0,"div",51),l(1),o(2,"span",36),l(3),a()()),t&2){let e=n.$implicit;i(),g("",e.name," "),i(2),$("",e.filePath,":",e.line)}}function he(t,n){if(t&1&&(o(0,"div",49)(1,"div",50),l(2,"callees"),a(),C(3,ge,4,3,"div",51,Z),a()),t&2){let e=s(3).$implicit;i(3),f(e.detail.callees)}}function Ce(t,n){if(t&1&&(p(0,_e,2,1,"div",47),p(1,me,2,1,"pre",48),p(2,ue,5,0,"div",49),p(3,he,5,0,"div",49)),t&2){let e=s(2).$implicit;_(e.detail!=null&&e.detail.signature?0:-1),i(),_(e.detail!=null&&e.detail.body?1:-1),i(),_(!(e.detail==null||e.detail.callers==null)&&e.detail.callers.length?2:-1),i(),_(!(e.detail==null||e.detail.callees==null)&&e.detail.callees.length?3:-1)}}function fe(t,n){if(t&1&&(o(0,"pre",48),l(1),a()),t&2){let e=s(3).$implicit;i(),u(e.detail.body)}}function be(t,n){if(t&1&&(o(0,"div",52)(1,"span",53),l(2),a(),x(3,"app-state-pill",54),a()),t&2){let e=n.$implicit;i(2),u(e.target),i(),m("state",e.state)}}function ve(t,n){if(t&1&&(o(0,"div",49)(1,"div",50),l(2,"links"),a(),C(3,be,4,2,"div",52,ie),a()),t&2){let e=s(3).$implicit;i(3),f(e.detail.links)}}function ye(t,n){if(t&1&&(p(0,fe,2,1,"pre",48),p(1,ve,5,0,"div",49)),t&2){let e=s(2).$implicit;_(e.detail!=null&&e.detail.body?0:-1),i(),_(!(e.detail==null||e.detail.links==null)&&e.detail.links.length?1:-1)}}function we(t,n){if(t&1&&(o(0,"pre",48),l(1),a()),t&2){let e=s(3).$implicit;i(),u(e.detail.body)}}function ke(t,n){if(t&1&&p(0,we,2,1,"pre",48),t&2){let e=s(2).$implicit;_(e.detail!=null&&e.detail.body?0:-1)}}function Se(t,n){if(t&1&&(o(0,"div",46),p(1,Ce,4,4)(2,ye,2,2)(3,ke,1,1),a()),t&2){let e=s().$implicit;i(),_(e.kind==="symbol"?1:e.kind==="spec"?2:3)}}function Me(t,n){if(t&1){let e=k();o(0,"div",43)(1,"button",44),h("click",function(){let d=v(e).$index,c=s(3).$index,b=s();return y(b.toggleDetail(c,d))}),x(2,"app-icon",33),o(3,"span",35),l(4),o(5,"span",36),p(6,ce,2,2)(7,pe,1,1),a()(),o(8,"span",45),l(9),a()(),p(10,Se,4,1,"div",46),a()}if(t&2){let e=n.$implicit,r=n.$index,d=s(3).$index,c=s();i(),T("aria-expanded",c.isDetailOpen(d,r)),i(),m("name",c.isDetailOpen(d,r)?"chevronDown":"chevronRight")("size",12),i(2),g(" ",e.label),i(2),_(e.filePath?6:7),i(3),u(e.kind),i(),_(c.isDetailOpen(d,r)?10:-1)}}function Te(t,n){if(t&1&&(o(0,"div",30)(1,"div",42),l(2),a(),C(3,Me,11,7,"div",43,F),a()),t&2){let e=s(2).$implicit;i(2),g("Retrieved detail \xB7 ",e.sources.length),i(),f(e.sources)}}function Ee(t,n){if(t&1&&(o(0,"div",23)(1,"div",25),x(2,"app-logo-mark",26),o(3,"span",27),l(4,"specship"),a()(),o(5,"div",28),x(6,"div",29),p(7,de,2,0),p(8,Te,5,1,"div",30),a()()),t&2){let e=s().$implicit,r=s();i(2),m("size",22)("glow",!1),i(4),m("innerHTML",r.renderMd(e.text),z),i(),_(e.tools!=null&&e.tools.length?7:-1),i(),_(e.sources!=null&&e.sources.length?8:-1)}}function Pe(t,n){if(t&1&&p(0,ae,2,1,"div",22)(1,Ee,9,5,"div",23),t&2){let e=n.$implicit;_(e.role==="user"?0:1)}}function Oe(t,n){t&1&&(o(0,"div",5),x(1,"span",55),l(2," thinking with specship context\u2026 "),a())}function ze(t,n){if(t&1&&(o(0,"span",59),l(1),a()),t&2){let e=s().$implicit;i(),u(e.arg)}}function Fe(t,n){if(t&1){let e=k();o(0,"button",57),h("click",function(){let d=v(e).$implicit,c=s(2);return y(c.pickSlash(d.cmd))}),o(1,"span",58),l(2),a(),p(3,ze,2,1,"span",59),o(4,"span",60),l(5),a()()}if(t&2){let e=n.$implicit;i(2),u(e.cmd),i(),_(e.arg?3:-1),i(2),u(e.desc)}}function $e(t,n){if(t&1&&(o(0,"div",8),C(1,Fe,6,3,"button",56,oe),a()),t&2){let e=s();i(),f(e.filteredSlash())}}function De(t,n){if(t&1){let e=k();o(0,"div",20)(1,"button",61),h("click",function(){v(e);let d=s();return y(d.toggleContext())}),x(2,"app-icon",62),a()()}t&2&&(i(2),m("size",14))}function Ie(t,n){if(t&1){let e=k();o(0,"div",77)(1,"button",81),h("click",function(){let d=v(e).$implicit,c=s(2);return y(c.toggleTool(d))}),x(2,"span",82),a(),o(3,"span",83),l(4),a()()}if(t&2){let e=n.$implicit,r=s(2);i(),B("on",r.enabledTools().has(e)),T("aria-pressed",r.enabledTools().has(e))("aria-label",e+(r.enabledTools().has(e)?" enabled":" disabled")),i(2),R("color",r.enabledTools().has(e)?"var(--text-primary)":"var(--text-muted)"),i(),u(e)}}function Ve(t,n){if(t&1){let e=k();o(0,"aside",21)(1,"div",63)(2,"span",64),l(3,"Context"),a(),o(4,"button",65),h("click",function(){v(e);let d=s();return y(d.toggleContext())}),x(5,"app-icon",66),a()(),o(6,"div",67)(7,"div",68),x(8,"app-icon",69),o(9,"div",70)(10,"div",71),l(11,"Project"),a(),o(12,"div",72),l(13,"~/dev/specship"),a()()(),o(14,"div",68),x(15,"app-icon",73),o(16,"div",70)(17,"div",71),l(18,"Indexed files"),a(),o(19,"div",74),l(20),a()()(),o(21,"div",68),x(22,"app-icon",75),o(23,"div",70)(24,"div",71),l(25,"Drift queue"),a(),o(26,"div",74),l(27,"\u2013 links"),a()()(),o(28,"div",76),l(29,"MCP tools"),a(),C(30,Ie,5,7,"div",77,A),a(),o(32,"div",78)(33,"div",79),l(34,"Tool access"),a(),o(35,"app-segmented",80),h("change",function(d){v(e);let c=s();return y(c.setToolAccess(d))}),a()()()}if(t&2){let e=s();i(5),m("size",13),i(3),m("size",13),i(7),m("size",13),i(5),u(e.api.isConfigured?"\u2013":"offline"),i(2),m("size",13),i(8),f(e.mcpTools),i(5),m("value",e.toolAccess())("options",e.toolAccessOptions)}}var J=[{cmd:"/ss-spec",arg:"REQ-ID | new <desc>",desc:"Intent door \u2014 view, author, implement, or review a spec"},{cmd:"/ss-explore",arg:"symbols | from\u2192to",desc:"Reads door \u2014 explore an area, trace a flow, or get impact"},{cmd:"/ss-check",arg:"(gate) | drifted | health",desc:"Gate & health door \u2014 run the gate, review drift, or see health"}],X=["specship_explore","specship_search","specship_spec","specship_link_verify"],Y=class t{sanitizer=O(j);api=O(K);listEl=L("listEl");closeStream;messages=w([{role:"assistant",text:`Hi \u2014 ask anything about your specs, code, or recent Claude Code sessions.
|
|
2
|
+
|
|
3
|
+
Try **/ss-spec REQ-AUTH-005** to inspect a requirement, or **/ss-explore validateSession** to walk its callers.`}]);draft=w("");thinking=w(!1);contextCollapsed=w(!1);enabledTools=w(new Set(X));toolAccess=w("safe");slashCommands=J;mcpTools=X;toolAccessOptions=[{value:"ask",label:"Ask"},{value:"safe",label:"Auto-safe"},{value:"all",label:"All"}];showSlash=D(()=>{let n=this.draft();return n.startsWith("/")&&!n.includes(" ")});filteredSlash=D(()=>{let n=this.draft();return J.filter(e=>e.cmd.startsWith(n))});setDraft(n){this.draft.set(n)}onKey(n){n.key==="Enter"&&!n.shiftKey&&(n.preventDefault(),this.send())}send(){let n=this.draft().trim();if(!n)return;this.draft.set(""),this.messages.update(d=>[...d,{role:"user",text:n}]),this.thinking.set(!0),this.scrollToBottom();let e=this.messages().length;this.messages.update(d=>[...d,{role:"assistant",text:"",tools:[]}]),this.closeStream?.();let r="/api/chat/stream?question="+encodeURIComponent(n);this.closeStream=this.api.openEventStream(r,(d,c)=>this.onStreamEvent(e,d,c),()=>this.endStream(),["thinking","tool","result_summary","chunk","done"])}onStreamEvent(n,e,r){switch(e){case"tool":{let d=r??{};this.patchMsg(n,c=>M(S({},c),{tools:[...c.tools??[],{name:d.name??"",input:d.input??"",output:"",status:"ok"}]}));break}case"result_summary":{let d=r??{},c=d.sourceCount??0,b=d.found?`${c} source${c===1?"":"s"} returned`:"no matches in the index";this.patchMsg(n,E=>{let P=E.tools??[];return P.length===0?E:M(S({},E),{tools:P.map((I,ee)=>ee===P.length-1?M(S({},I),{output:b}):I)})});break}case"chunk":{let c=(r??{}).text??"";this.patchMsg(n,b=>M(S({},b),{text:b.text+c})),this.scrollToBottom();break}case"done":{let d=r??{};d.sources?.length&&this.patchMsg(n,c=>M(S({},c),{sources:d.sources})),this.endStream();break}}}patchMsg(n,e){this.messages.update(r=>r.map((d,c)=>c===n?e(d):d))}endStream(){this.thinking.set(!1),this.closeStream?.(),this.closeStream=void 0,this.scrollToBottom()}ngOnDestroy(){this.closeStream?.(),this.closeStream=void 0}pickSlash(n){this.draft.set(n+" ")}toggleTool(n){this.enabledTools.update(e=>{let r=new Set(e);return r.has(n)?r.delete(n):r.add(n),r})}setToolAccess(n){this.toolAccess.set(n)}toggleContext(){this.contextCollapsed.update(n=>!n)}toggleToolCall(n,e){e.open=!e.open,this.messages.update(r=>[...r])}openDetails=w(new Set);detailKey(n,e){return`${n}:${e}`}isDetailOpen(n,e){return this.openDetails().has(this.detailKey(n,e))}toggleDetail(n,e){let r=this.detailKey(n,e);this.openDetails.update(d=>{let c=new Set(d);return c.has(r)?c.delete(r):c.add(r),c})}renderMd(n){let e=n.replace(/&/g,"&").replace(/</g,"<").replace(/\*\*(.+?)\*\*/g,'<strong style="color:var(--text-primary)">$1</strong>').replace(/`(.+?)`/g,'<code class="mono" style="font-size:12px;background:var(--bg-canvas);padding:1px 5px;border-radius:4px;border:1px solid var(--border-subtle);color:var(--node-spec)">$1</code>').replace(/\n\n/g,"<br/><br/>").replace(/\n/g,"<br/>");return this.sanitizer.bypassSecurityTrustHtml(e)}scrollToBottom(){setTimeout(()=>{let n=this.listEl()?.nativeElement;n&&(n.scrollTop=n.scrollHeight)},0)}static \u0275fac=function(e){return new(e||t)};static \u0275cmp=V({type:t,selectors:[["app-chat"]],viewQuery:function(e,r){e&1&&N(r.listEl,te,5),e&2&&H()},decls:29,vars:8,consts:[["listEl",""],[1,"chat-page"],[1,"chat-col"],[1,"thread","scroll-y"],[1,"thread-inner"],[1,"row","gap-8","muted","thinking"],[1,"composer"],[1,"composer-inner"],["role","listbox","aria-label","Slash commands",1,"slash-menu"],[1,"composer-box","row"],["type","button","title","Attach files or spec IDs",1,"btn","btn-ghost","btn-sm","attach-btn"],["name","paperclip",3,"size"],["placeholder","Ask with specship context\u2026 / for commands, Tab to complete spec IDs","rows","1",1,"composer-ta",3,"input","keydown","value"],["type","button","aria-label","Send message",1,"btn","btn-primary","btn-sm","send-btn",3,"click","disabled"],["name","send",3,"size"],[1,"composer-footer","row","gap-8"],[1,"row","gap-6"],["name","bot",3,"size"],[1,"muted",2,"font-size","10.5px"],[1,"grow"],[1,"ctx-collapsed"],["aria-label","Context panel",1,"ctx-panel","col"],[1,"msg-user"],[1,"msg-assistant"],[1,"bubble-user",3,"innerHTML"],[1,"row","gap-8","asst-meta"],["aria-hidden","true",3,"size","glow"],[2,"font-size","12px","font-weight","600"],[1,"asst-body"],[1,"bubble-asst",3,"innerHTML"],[1,"detail-list"],[1,"tool-call"],["type","button",1,"tool-header","row","gap-8",3,"click"],[2,"color","var(--text-muted)",3,"name","size"],["name","wrench",2,"color","var(--node-code)",3,"size"],[1,"mono","grow",2,"font-size","11.5px"],[1,"muted"],[1,"pill",2,"font-size","9.5px","color","var(--success)","background","var(--success-soft)"],["name","check",3,"size"],[1,"tool-output"],[1,"mono","muted",2,"font-size","10.5px","margin-bottom","3px"],[1,"mono",2,"font-size","11.5px","color","var(--text-secondary)"],[1,"eyebrow",2,"margin","4px 0 2px"],[1,"source-detail"],["type","button",1,"detail-header","row","gap-8",3,"click"],[1,"pill",2,"font-size","9.5px","color","var(--text-muted)","background","var(--bg-canvas)"],[1,"detail-body"],[1,"mono","detail-sig"],[1,"mono","detail-src"],[1,"detail-rel"],[1,"mono","muted","detail-rel-label"],[1,"mono","detail-rel-item"],[1,"row","gap-8","detail-rel-item"],[1,"mono","grow"],[3,"state"],[1,"thinking-dot"],["type","button","role","option",1,"slash-item","row","gap-8"],["type","button","role","option",1,"slash-item","row","gap-8",3,"click"],[1,"mono",2,"font-size","12px","color","var(--accent)"],[1,"mono","muted",2,"font-size","11px"],[1,"muted","grow",2,"font-size","11px","text-align","right"],["type","button","title","Show context",1,"btn","btn-ghost","btn-xs",3,"click"],["name","chevronLeft",3,"size"],[1,"ctx-header","row"],[1,"eyebrow","grow"],["type","button",1,"btn","btn-ghost","btn-xs",3,"click"],["name","chevronRight",3,"size"],[1,"ctx-body","scroll-y"],[1,"ctx-row","row","gap-8"],["name","folder",2,"color","var(--text-muted)","flex-shrink","0",3,"size"],[2,"min-width","0"],[1,"muted",2,"font-size","10px"],[1,"mono",2,"font-size","11.5px","overflow","hidden","text-overflow","ellipsis","white-space","nowrap"],["name","box",2,"color","var(--text-muted)","flex-shrink","0",3,"size"],[1,"mono",2,"font-size","11.5px"],["name","drift",2,"color","var(--warn)","flex-shrink","0",3,"size"],[1,"eyebrow",2,"margin","16px 0 8px"],[1,"row","gap-8",2,"padding","5px 0"],[1,"ctx-footer"],[1,"eyebrow",2,"margin-bottom","6px"],["size","sm",3,"change","value","options"],["type","button",1,"toggle-btn",3,"click"],[1,"toggle-thumb"],[1,"mono",2,"font-size","11px"]],template:function(e,r){e&1&&(o(0,"div",1)(1,"div",2)(2,"div",3,0)(4,"div",4),C(5,Pe,2,1,null,null,F),p(7,Oe,3,0,"div",5),a()(),o(8,"div",6)(9,"div",7),p(10,$e,3,0,"div",8),o(11,"div",9)(12,"button",10),x(13,"app-icon",11),a(),o(14,"textarea",12),h("input",function(c){return r.setDraft(c.target.value)})("keydown",function(c){return r.onKey(c)}),a(),o(15,"button",13),h("click",function(){return r.send()}),x(16,"app-icon",14),a()(),o(17,"div",15)(18,"div",16)(19,"app-pill"),x(20,"app-icon",17),l(21," Opus 4 "),a(),o(22,"span",18),l(23,"single thread \xB7 this project"),a()(),x(24,"span",19),o(25,"span",18),l(26,"Enter to send \xB7 Shift+Enter for newline"),a()()()()(),p(27,De,3,1,"div",20)(28,Ve,36,7,"aside",21),a()),e&2&&(i(5),f(r.messages()),i(2),_(r.thinking()?7:-1),i(3),_(r.showSlash()&&r.filteredSlash().length>0?10:-1),i(3),m("size",15),i(),m("value",r.draft()),i(),m("disabled",!r.draft().trim()),i(),m("size",14),i(4),m("size",10),i(7),_(r.contextCollapsed()?27:28))},dependencies:[q,W,Q,U,G],styles:["[_nghost-%COMP%]{display:flex;flex:1;min-height:0}.chat-page[_ngcontent-%COMP%]{display:flex;flex:1;min-height:0;min-width:0}.chat-col[_ngcontent-%COMP%]{display:flex;flex-direction:column;flex:1;min-width:0;min-height:0}.thread[_ngcontent-%COMP%]{flex:1;padding:20px 24px;overflow-y:auto}.thread-inner[_ngcontent-%COMP%]{max-width:760px;margin:0 auto}.msg-user[_ngcontent-%COMP%]{display:flex;justify-content:flex-end;margin-bottom:18px}.bubble-user[_ngcontent-%COMP%]{max-width:76%;background:var(--bg-elevated);border:1px solid var(--border-subtle);border-radius:12px 12px 4px;padding:9px 13px;font-size:13.5px;line-height:1.55}.msg-assistant[_ngcontent-%COMP%]{margin-bottom:22px}.asst-meta[_ngcontent-%COMP%]{align-items:center;margin-bottom:8px}.asst-logo[_ngcontent-%COMP%]{display:inline-grid;place-items:center;width:22px;height:22px;border-radius:50%;background:var(--accent);color:#fff;font-size:11px;font-weight:700;flex-shrink:0}.asst-body[_ngcontent-%COMP%]{padding-left:30px}.bubble-asst[_ngcontent-%COMP%]{font-size:13.5px;line-height:1.62;color:var(--text-secondary);text-wrap:pretty;margin-bottom:4px}.tool-call[_ngcontent-%COMP%]{border:1px solid var(--border-subtle);border-radius:7px;margin-top:8px;overflow:hidden;background:var(--bg-canvas)}.tool-header[_ngcontent-%COMP%]{width:100%;background:transparent;border:none;cursor:pointer;padding:6px 10px;text-align:left;color:inherit;font-family:var(--font-ui)}.tool-header[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.tool-header[_ngcontent-%COMP%]:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}.tool-output[_ngcontent-%COMP%]{padding:8px 10px 10px 30px;border-top:1px solid var(--border-subtle)}.detail-list[_ngcontent-%COMP%]{margin-top:10px;display:flex;flex-direction:column;gap:6px}.source-detail[_ngcontent-%COMP%]{border:1px solid var(--border-subtle);border-radius:7px;overflow:hidden;background:var(--bg-canvas)}.detail-header[_ngcontent-%COMP%]{width:100%;background:transparent;border:none;cursor:pointer;padding:6px 10px;text-align:left;color:inherit;font-family:var(--font-ui)}.detail-header[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.detail-header[_ngcontent-%COMP%]:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}.detail-body[_ngcontent-%COMP%]{padding:8px 10px 10px;border-top:1px solid var(--border-subtle);display:flex;flex-direction:column;gap:8px}.detail-sig[_ngcontent-%COMP%]{font-size:11.5px;color:var(--node-code);white-space:pre-wrap;word-break:break-word}.detail-src[_ngcontent-%COMP%]{margin:0;padding:8px 10px;font-size:11.5px;line-height:1.5;color:var(--text-secondary);background:var(--bg-base);border:1px solid var(--border-subtle);border-radius:5px;overflow-x:auto;white-space:pre;max-height:320px;overflow-y:auto}.detail-rel-label[_ngcontent-%COMP%]{font-size:10.5px;margin-bottom:3px}.detail-rel-item[_ngcontent-%COMP%]{font-size:11.5px;color:var(--text-secondary);padding:1px 0}.thinking[_ngcontent-%COMP%]{padding-left:30px;font-size:12px}.thinking-dot[_ngcontent-%COMP%]{width:6px;height:6px;border-radius:50%;background:var(--accent);animation:skeleton 1s infinite;flex-shrink:0}.composer[_ngcontent-%COMP%]{padding:12px 24px 18px;border-top:1px solid var(--border-subtle);flex-shrink:0}.composer-inner[_ngcontent-%COMP%]{max-width:760px;margin:0 auto;position:relative}.composer-box[_ngcontent-%COMP%]{align-items:flex-end;background:var(--bg-panel);border:1px solid var(--border-subtle);border-radius:12px;padding:8px;gap:8px}.attach-btn[_ngcontent-%COMP%]{padding:7px;flex-shrink:0}.send-btn[_ngcontent-%COMP%]{padding:7px 10px;flex-shrink:0}.composer-ta[_ngcontent-%COMP%]{flex:1;resize:none;background:transparent;border:none;outline:none;color:var(--text-primary);font-size:13.5px;font-family:var(--font-ui);line-height:1.5;padding:5px 2px;max-height:120px}.composer-ta[_ngcontent-%COMP%]::placeholder{color:var(--text-muted)}.composer-footer[_ngcontent-%COMP%]{margin-top:8px;align-items:center}.slash-menu[_ngcontent-%COMP%]{position:absolute;bottom:100%;left:0;margin-bottom:8px;background:var(--bg-elevated);border:1px solid var(--border-strong);border-radius:8px;box-shadow:var(--shadow-pop);padding:5px;width:320px;z-index:10}.slash-item[_ngcontent-%COMP%]{width:100%;background:transparent;border:none;cursor:pointer;padding:6px 9px;border-radius:5px;text-align:left;color:inherit;font-family:var(--font-ui)}.slash-item[_ngcontent-%COMP%]:hover{background:var(--bg-hover)}.slash-item[_ngcontent-%COMP%]:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}.ctx-collapsed[_ngcontent-%COMP%]{width:40px;flex-shrink:0;border-left:1px solid var(--border-subtle);display:flex;justify-content:center;padding-top:12px}.ctx-panel[_ngcontent-%COMP%]{width:264px;flex-shrink:0;border-left:1px solid var(--border-subtle);background:var(--bg-panel);display:flex;flex-direction:column;min-height:0}.ctx-header[_ngcontent-%COMP%]{padding:11px 13px;border-bottom:1px solid var(--border-subtle);align-items:center}.ctx-body[_ngcontent-%COMP%]{flex:1;padding:13px;overflow-y:auto;min-height:0}.ctx-row[_ngcontent-%COMP%]{padding:5px 0;align-items:flex-start}.ctx-footer[_ngcontent-%COMP%]{padding:12px;border-top:1px solid var(--border-subtle)}.toggle-btn[_ngcontent-%COMP%]{width:30px;height:17px;border-radius:999px;border:none;cursor:pointer;padding:2px;background:var(--bg-elevated);display:flex;justify-content:flex-start;align-items:center;transition:background .12s,justify-content .12s;flex-shrink:0}.toggle-btn.on[_ngcontent-%COMP%]{background:var(--accent);justify-content:flex-end}.toggle-btn[_ngcontent-%COMP%]:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.toggle-thumb[_ngcontent-%COMP%]{width:13px;height:13px;border-radius:50%;background:#fff;flex-shrink:0}.eyebrow[_ngcontent-%COMP%]{color:var(--text-muted);font-size:10.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase}.muted[_ngcontent-%COMP%]{color:var(--text-muted)}.mono[_ngcontent-%COMP%]{font-family:var(--font-mono)}.pill[_ngcontent-%COMP%]{display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:600;padding:3px 9px;border-radius:999px;line-height:1.4;white-space:nowrap}.grow[_ngcontent-%COMP%]{flex:1}"],changeDetection:0})};export{Y as Chat};
|
package/lib/dist/web/index.html
CHANGED
|
@@ -142,5 +142,5 @@
|
|
|
142
142
|
})();
|
|
143
143
|
</script>
|
|
144
144
|
<app-root></app-root>
|
|
145
|
-
<link rel="modulepreload" href="chunk-2IVSOVQZ.js"><link rel="modulepreload" href="chunk-YV5LB22R.js"><link rel="modulepreload" href="chunk-DOKZOFKM.js"><link rel="modulepreload" href="chunk-PAO2624Y.js"><link rel="modulepreload" href="chunk-PBRCKHEQ.js"><link rel="modulepreload" href="chunk-3H2EZLZN.js"><link rel="modulepreload" href="chunk-SYGIPC2P.js"><link rel="modulepreload" href="chunk-Q7L6LLAK.js"><script src="main-
|
|
145
|
+
<link rel="modulepreload" href="chunk-2IVSOVQZ.js"><link rel="modulepreload" href="chunk-YV5LB22R.js"><link rel="modulepreload" href="chunk-DOKZOFKM.js"><link rel="modulepreload" href="chunk-PAO2624Y.js"><link rel="modulepreload" href="chunk-PBRCKHEQ.js"><link rel="modulepreload" href="chunk-3H2EZLZN.js"><link rel="modulepreload" href="chunk-SYGIPC2P.js"><link rel="modulepreload" href="chunk-Q7L6LLAK.js"><script src="main-A6QZ3DLK.js" type="module"></script></body>
|
|
146
146
|
</html>
|