@aexol/spectral 0.8.5 → 0.8.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.
Files changed (158) hide show
  1. package/dist/agent/index.d.ts +1 -1
  2. package/dist/agent/index.d.ts.map +1 -1
  3. package/dist/agent/index.js +11 -11
  4. package/dist/cli.js +1 -1
  5. package/dist/commands/serve.d.ts +3 -3
  6. package/dist/commands/serve.d.ts.map +1 -1
  7. package/dist/commands/serve.js +5 -2
  8. package/dist/config.d.ts +1 -1
  9. package/dist/config.js +1 -1
  10. package/dist/designer/index.d.ts +3 -3
  11. package/dist/designer/index.d.ts.map +1 -1
  12. package/dist/designer/index.js +9 -9
  13. package/dist/extensions/aexol-mcp.d.ts +6 -6
  14. package/dist/extensions/aexol-mcp.d.ts.map +1 -1
  15. package/dist/extensions/aexol-mcp.js +12 -12
  16. package/dist/extensions/kanban-bridge.d.ts +2 -2
  17. package/dist/extensions/kanban-bridge.d.ts.map +1 -1
  18. package/dist/extensions/kanban-bridge.js +3 -3
  19. package/dist/extensions/openrouter-attribution.d.ts +1 -1
  20. package/dist/extensions/openrouter-attribution.d.ts.map +1 -1
  21. package/dist/extensions/openrouter-attribution.js +2 -2
  22. package/dist/extensions/spectral-vision-fallback.d.ts +1 -1
  23. package/dist/extensions/spectral-vision-fallback.d.ts.map +1 -1
  24. package/dist/extensions/spectral-vision-fallback.js +3 -3
  25. package/dist/index.d.ts +4 -4
  26. package/dist/index.js +4 -4
  27. package/dist/mcp/commands.d.ts +1 -1
  28. package/dist/mcp/commands.d.ts.map +1 -1
  29. package/dist/mcp/commands.js +1 -1
  30. package/dist/mcp/config.d.ts +5 -5
  31. package/dist/mcp/config.d.ts.map +1 -1
  32. package/dist/mcp/config.js +15 -15
  33. package/dist/mcp/host-html-template.js +3 -3
  34. package/dist/mcp/index.d.ts +1 -1
  35. package/dist/mcp/index.d.ts.map +1 -1
  36. package/dist/mcp/index.js +15 -13
  37. package/dist/mcp/init.d.ts +1 -1
  38. package/dist/mcp/init.d.ts.map +1 -1
  39. package/dist/mcp/init.js +4 -4
  40. package/dist/mcp/mcp-oauth-provider.js +1 -1
  41. package/dist/mcp/proxy-modes.d.ts +1 -1
  42. package/dist/mcp/proxy-modes.d.ts.map +1 -1
  43. package/dist/mcp/proxy-modes.js +2 -2
  44. package/dist/mcp/server-manager.js +2 -2
  45. package/dist/mcp/state-getter.d.ts +14 -0
  46. package/dist/mcp/state-getter.d.ts.map +1 -0
  47. package/dist/mcp/state-getter.js +21 -0
  48. package/dist/mcp/tool-registrar.js +1 -1
  49. package/dist/mcp/ui-server.js +1 -1
  50. package/dist/mcp/ui-stream-types.d.ts +11 -11
  51. package/dist/mcp/ui-stream-types.d.ts.map +1 -1
  52. package/dist/mcp/ui-stream-types.js +5 -5
  53. package/dist/mcp/utils.d.ts +2 -2
  54. package/dist/mcp/utils.d.ts.map +1 -1
  55. package/dist/mcp/utils.js +10 -10
  56. package/dist/mcp-client.d.ts +1 -1
  57. package/dist/mcp-client.js +1 -1
  58. package/dist/memory/commands/status.d.ts +1 -1
  59. package/dist/memory/commands/status.d.ts.map +1 -1
  60. package/dist/memory/commands/status.js +2 -2
  61. package/dist/memory/commands/view.d.ts +1 -1
  62. package/dist/memory/commands/view.d.ts.map +1 -1
  63. package/dist/memory/commands/view.js +2 -2
  64. package/dist/memory/hooks/compaction-hook.d.ts +1 -1
  65. package/dist/memory/hooks/compaction-hook.d.ts.map +1 -1
  66. package/dist/memory/hooks/compaction-hook.js +5 -5
  67. package/dist/memory/hooks/compaction-trigger.d.ts +1 -1
  68. package/dist/memory/hooks/compaction-trigger.d.ts.map +1 -1
  69. package/dist/memory/hooks/compaction-trigger.js +3 -3
  70. package/dist/memory/hooks/observer-trigger.d.ts +1 -1
  71. package/dist/memory/hooks/observer-trigger.d.ts.map +1 -1
  72. package/dist/memory/hooks/observer-trigger.js +4 -4
  73. package/dist/memory/index.d.ts +1 -1
  74. package/dist/memory/index.d.ts.map +1 -1
  75. package/dist/memory/index.js +9 -9
  76. package/dist/memory/tools/read-project-observations.d.ts +1 -1
  77. package/dist/memory/tools/read-project-observations.d.ts.map +1 -1
  78. package/dist/memory/tools/read-project-observations.js +2 -2
  79. package/dist/memory/tools/recall-observation.d.ts +1 -1
  80. package/dist/memory/tools/recall-observation.d.ts.map +1 -1
  81. package/dist/memory/tools/recall-observation.js +2 -2
  82. package/dist/memory/tools/write-project-observation.d.ts +1 -1
  83. package/dist/memory/tools/write-project-observation.d.ts.map +1 -1
  84. package/dist/memory/tools/write-project-observation.js +2 -2
  85. package/dist/preflight.d.ts +1 -1
  86. package/dist/preflight.js +1 -1
  87. package/dist/relay/auto-research.d.ts +2 -2
  88. package/dist/relay/auto-research.js +34 -34
  89. package/dist/relay/dispatcher.d.ts +15 -6
  90. package/dist/relay/dispatcher.d.ts.map +1 -1
  91. package/dist/relay/dispatcher.js +33 -6
  92. package/dist/sdk/ai/types.d.ts +1 -1
  93. package/dist/sdk/ai/utils/oauth/openai-codex.d.ts +1 -1
  94. package/dist/sdk/ai/utils/oauth/openai-codex.js +2 -2
  95. package/dist/sdk/coding-agent/core/agent-session.d.ts +2 -2
  96. package/dist/sdk/coding-agent/core/agent-session.js +3 -3
  97. package/dist/sdk/coding-agent/core/auth-storage.d.ts +2 -2
  98. package/dist/sdk/coding-agent/core/auth-storage.js +2 -2
  99. package/dist/sdk/coding-agent/core/bash-executor.js +1 -1
  100. package/dist/sdk/coding-agent/core/compaction/branch-summarization.js +1 -1
  101. package/dist/sdk/coding-agent/core/compaction/compaction.js +1 -1
  102. package/dist/sdk/coding-agent/core/extensions/loader.d.ts.map +1 -1
  103. package/dist/sdk/coding-agent/core/extensions/loader.js +18 -22
  104. package/dist/sdk/coding-agent/core/extensions/runner.d.ts.map +1 -1
  105. package/dist/sdk/coding-agent/core/extensions/runner.js +1 -1
  106. package/dist/sdk/coding-agent/core/extensions/types.d.ts +9 -9
  107. package/dist/sdk/coding-agent/core/extensions/types.d.ts.map +1 -1
  108. package/dist/sdk/coding-agent/core/package-manager.d.ts +1 -1
  109. package/dist/sdk/coding-agent/core/package-manager.d.ts.map +1 -1
  110. package/dist/sdk/coding-agent/core/package-manager.js +14 -14
  111. package/dist/sdk/coding-agent/core/sdk.d.ts +1 -1
  112. package/dist/sdk/coding-agent/core/sdk.js +2 -2
  113. package/dist/sdk/coding-agent/core/session-manager.d.ts +2 -2
  114. package/dist/sdk/coding-agent/core/session-manager.d.ts.map +1 -1
  115. package/dist/sdk/coding-agent/core/system-prompt.js +7 -7
  116. package/dist/sdk/coding-agent/core/tools/bash.d.ts +2 -2
  117. package/dist/sdk/coding-agent/core/tools/bash.js +3 -3
  118. package/dist/sdk/coding-agent/core/tools/output-accumulator.js +1 -1
  119. package/dist/sdk/coding-agent/migrations.d.ts +1 -1
  120. package/dist/sdk/coding-agent/migrations.js +4 -4
  121. package/dist/sdk/coding-agent/modes/print-mode.d.ts +2 -2
  122. package/dist/sdk/coding-agent/modes/print-mode.js +2 -2
  123. package/dist/sdk/coding-agent/utils/clipboard-image.js +1 -1
  124. package/dist/sdk/coding-agent/utils/spectral-user-agent.d.ts +2 -0
  125. package/dist/sdk/coding-agent/utils/spectral-user-agent.d.ts.map +1 -0
  126. package/dist/sdk/coding-agent/utils/spectral-user-agent.js +3 -0
  127. package/dist/sdk/coding-agent/utils/version-check.d.ts +5 -5
  128. package/dist/sdk/coding-agent/utils/version-check.d.ts.map +1 -1
  129. package/dist/sdk/coding-agent/utils/version-check.js +7 -7
  130. package/dist/sdk/coding-agent/utils/windows-self-update.js +1 -1
  131. package/dist/server/agent-bridge.d.ts +33 -33
  132. package/dist/server/agent-bridge.d.ts.map +1 -1
  133. package/dist/server/agent-bridge.js +58 -58
  134. package/dist/server/handlers/mcp-status.d.ts +21 -0
  135. package/dist/server/handlers/mcp-status.d.ts.map +1 -0
  136. package/dist/server/handlers/mcp-status.js +52 -0
  137. package/dist/server/handlers/sessions.d.ts +1 -1
  138. package/dist/server/handlers/sessions.js +1 -1
  139. package/dist/server/handlers/settings.d.ts +30 -0
  140. package/dist/server/handlers/settings.d.ts.map +1 -0
  141. package/dist/server/handlers/settings.js +123 -0
  142. package/dist/server/paths.d.ts +2 -2
  143. package/dist/server/paths.js +2 -2
  144. package/dist/server/session-stream.d.ts +25 -25
  145. package/dist/server/session-stream.d.ts.map +1 -1
  146. package/dist/server/session-stream.js +43 -34
  147. package/dist/server/shutdown.d.ts +3 -3
  148. package/dist/server/shutdown.d.ts.map +1 -1
  149. package/dist/server/shutdown.js +3 -3
  150. package/dist/server/storage.d.ts +4 -4
  151. package/dist/server/storage.js +6 -6
  152. package/dist/server/wire.d.ts +8 -8
  153. package/dist/server/wire.d.ts.map +1 -1
  154. package/dist/server/wire.js +1 -1
  155. package/package.json +1 -1
  156. package/dist/sdk/coding-agent/utils/pi-user-agent.d.ts +0 -2
  157. package/dist/sdk/coding-agent/utils/pi-user-agent.d.ts.map +0 -1
  158. package/dist/sdk/coding-agent/utils/pi-user-agent.js +0 -3
@@ -9,9 +9,9 @@
9
9
  * ourselves with a leading-segment check (NOT a global string replace —
10
10
  * `~user/...` and embedded `~` are intentionally left alone).
11
11
  * - Validation: the path must exist, must be a directory, and must be
12
- * readable. We do NOT attempt to verify writability — pi may want to
12
+ * readable. We do NOT attempt to verify writability — spectral may want to
13
13
  * create files inside it, but failure modes there surface naturally
14
- * through pi's tools, and a write probe here would create stray files.
14
+ * through spectral's tools, and a write probe here would create stray files.
15
15
  *
16
16
  * Both helpers are synchronous because they're called on hot HTTP paths
17
17
  * (POST /api/projects) where blocking is acceptable: the operation is rare
@@ -9,9 +9,9 @@
9
9
  * ourselves with a leading-segment check (NOT a global string replace —
10
10
  * `~user/...` and embedded `~` are intentionally left alone).
11
11
  * - Validation: the path must exist, must be a directory, and must be
12
- * readable. We do NOT attempt to verify writability — pi may want to
12
+ * readable. We do NOT attempt to verify writability — spectral may want to
13
13
  * create files inside it, but failure modes there surface naturally
14
- * through pi's tools, and a write probe here would create stray files.
14
+ * through spectral's tools, and a write probe here would create stray files.
15
15
  *
16
16
  * Both helpers are synchronous because they're called on hot HTTP paths
17
17
  * (POST /api/projects) where blocking is acceptable: the operation is rare
@@ -4,14 +4,14 @@
4
4
  * Background: prior to this module each WebSocket owned its own `AgentBridge`
5
5
  * instance and the routes layer enforced single-writer-wins (4001 eviction)
6
6
  * to keep that bridge unique per session. That model lost data on browser
7
- * refresh — the WS close torn down the pi process mid-stream, and a re-open
7
+ * refresh — the WS close torn down the spectral process mid-stream, and a re-open
8
8
  * couldn't recover what hadn't yet hit `agent_end` (and thus SQLite).
9
9
  *
10
10
  * New model:
11
11
  * - Pi lifecycle is per **Spectral session**, not per WS.
12
12
  * - 0..N WebSockets may attach to the same session simultaneously. Each
13
13
  * gets the same broadcast stream of events.
14
- * - When a WS detaches (close, error, refresh), the pi process keeps
14
+ * - When a WS detaches (close, error, refresh), the spectral process keeps
15
15
  * running. Closing every tab does NOT cancel the in-flight turn —
16
16
  * it runs to completion and persists on `agent_end` as before.
17
17
  * - On `attach`, the manager hands back a replay payload: full DB history
@@ -24,7 +24,7 @@
24
24
  * for MVP.
25
25
  *
26
26
  * Failure modes:
27
- * - Pi throws synchronously in `prompt()` → bridge surfaces as `error`
27
+ * - spectral throws synchronously in `prompt()` → bridge surfaces as `error`
28
28
  * event; manager broadcasts and clears `currentTurn`.
29
29
  * - One subscriber's `ws.send` throws → caught, logged, removed from the
30
30
  * subscriber set; broadcast continues to the rest.
@@ -33,7 +33,7 @@
33
33
  *
34
34
  * TODO (future): idle GC. A `SessionStream` with `subscribers.size === 0`
35
35
  * and no current turn could be disposed after some grace window (e.g. 5
36
- * minutes) to release pi resources for chronically-idle sessions. Skipped
36
+ * minutes) to release spectral resources for chronically-idle sessions. Skipped
37
37
  * for now — streams accumulate for the lifetime of the server process.
38
38
  */
39
39
  import { type AgentBridgeOptions } from "./agent-bridge.js";
@@ -59,7 +59,7 @@ export interface BridgeLike {
59
59
  prompt(text: string, images?: ImageAttachment[]): Promise<void>;
60
60
  dispose(): void;
61
61
  /**
62
- * Manually compact the session context via pi's built-in compaction.
62
+ * Manually compact the session context via spectral's built-in compaction.
63
63
  * Fires compaction_start / compaction_end events through the bridge's
64
64
  * emit callback. Used by the Fork & Compact flow after the first
65
65
  * assistant turn of a forked session completes.
@@ -67,7 +67,7 @@ export interface BridgeLike {
67
67
  compact?(customInstructions?: string): Promise<void>;
68
68
  /**
69
69
  * Optional sticky reasoning effort. Maps frontend effort strings
70
- * (xhigh|high|medium|low|minimal|none) to pi ThinkingLevel.
70
+ * (xhigh|high|medium|low|minimal|none) to spectral ThinkingLevel.
71
71
  */
72
72
  setReasoningEffort?(effort: string | undefined): void;
73
73
  /**
@@ -86,7 +86,7 @@ export interface BridgeLike {
86
86
  */
87
87
  getFirstAvailableModelId?(): string | undefined;
88
88
  /**
89
- * Return current session context usage from pi's built-in estimator.
89
+ * Return current session context usage from spectral's built-in estimator.
90
90
  * Returns `undefined` when the bridge hasn't started yet or the model
91
91
  * has no context window configured.
92
92
  */
@@ -153,7 +153,7 @@ export interface SessionMemoryStatus {
153
153
  export interface AttachResult {
154
154
  history: WireMessage[];
155
155
  currentTurn: InProgressTurnSnapshot | null;
156
- /** Resolves when the underlying pi session is ready (or rejects on start failure). */
156
+ /** Resolves when the underlying spectral session is ready (or rejects on start failure). */
157
157
  ready: Promise<void>;
158
158
  /** True when this session was created via "Fork & Compact" and has not yet
159
159
  * triggered its first compaction. The dispatcher includes this in
@@ -169,18 +169,18 @@ export interface SessionStreamManagerOptions {
169
169
  /**
170
170
  * Fallback cwd used ONLY when a session has no resolvable project (which
171
171
  * shouldn't happen in normal operation since FK enforces it). Sessions
172
- * with a valid project always run pi against `project.path`.
172
+ * with a valid project always run spectral against `project.path`.
173
173
  */
174
174
  cwd: string;
175
175
  /**
176
- * Backend base URL — threaded into every AgentBridge so pi proxies all
176
+ * Backend base URL — threaded into every AgentBridge so spectral proxies all
177
177
  * inference through `${backendUrl}/v1` instead of reading
178
178
  * `~/.spectral/agent/auth.json`. Required in production; tests that supply a
179
179
  * `bridgeFactory` may pass any non-empty placeholder.
180
180
  */
181
181
  backendUrl: string;
182
182
  /**
183
- * Machine JWT — used as the Bearer credential pi sends to the backend
183
+ * Machine JWT — used as the Bearer credential spectral sends to the backend
184
184
  * proxy on every inference call. See `backendUrl` for context.
185
185
  */
186
186
  machineJwt: string;
@@ -198,7 +198,7 @@ export declare class SessionStreamManager {
198
198
  private disposed;
199
199
  constructor(opts: SessionStreamManagerOptions);
200
200
  /**
201
- * Attach a subscriber to a session. Lazily creates the underlying pi
201
+ * Attach a subscriber to a session. Lazily creates the underlying spectral
202
202
  * session on first attach. The caller is responsible for sending the
203
203
  * initial `session_ready` frame using the returned replay payload (this
204
204
  * keeps wire-protocol concerns in the routes layer).
@@ -208,7 +208,7 @@ export declare class SessionStreamManager {
208
208
  */
209
209
  attach(sessionId: string, subscriber: Subscriber): AttachResult;
210
210
  /**
211
- * Detach a subscriber. Idempotent. Does NOT dispose the underlying pi
211
+ * Detach a subscriber. Idempotent. Does NOT dispose the underlying spectral
212
212
  * session — even when subscribers reach zero, the in-flight turn must
213
213
  * complete and persist.
214
214
  */
@@ -226,8 +226,8 @@ export declare class SessionStreamManager {
226
226
  getSessionMemoryDetails(sessionId: string): WireSessionMemoryDetails;
227
227
  compactSession(sessionId: string): Promise<void>;
228
228
  /**
229
- * Persist a user message and forward it to pi. Resolves after the user
230
- * message is persisted + pi is invoked (NOT after the turn completes —
229
+ * Persist a user message and forward it to spectral. Resolves after the user
230
+ * message is persisted + spectral is invoked (NOT after the turn completes —
231
231
  * the turn lifetime is observed via the broadcast stream).
232
232
  *
233
233
  * Broadcast ordering:
@@ -242,15 +242,15 @@ export declare class SessionStreamManager {
242
242
  * - When `modelId` is provided, we apply it via `bridge.setModel()` and
243
243
  * persist to SQLite for cross-restart recovery, BEFORE invoking
244
244
  * `bridge.prompt()`. If `setModel` fails (unknown model, registry
245
- * unavailable, pi-side error) the bridge has already emitted an
245
+ * unavailable, agent-side error) the bridge has already emitted an
246
246
  * `error` wire event and we drop the prompt to avoid running it
247
247
  * against the wrong model.
248
248
  * - When `modelId` is omitted, we look up SQLite. If a previous turn
249
249
  * persisted a value, we reapply it on this turn (this is the
250
- * cross-restart recovery path: a fresh server process has lost pi's
250
+ * cross-restart recovery path: a fresh server process has lost spectral's
251
251
  * in-memory model state, so we re-pin from durable storage).
252
252
  * - When neither envelope nor SQLite have a value, we leave model
253
- * selection to pi's own settings file (pre-Phase-3 behaviour).
253
+ * selection to spectral's own settings file (pre-Phase-3 behaviour).
254
254
  */
255
255
  prompt(sessionId: string, content: string, modelId?: string, images?: ImageAttachment[], reasoningEffort?: string): Promise<void>;
256
256
  /**
@@ -273,7 +273,7 @@ export declare class SessionStreamManager {
273
273
  activeTurnCount(): number;
274
274
  /**
275
275
  * Cancel the in-flight turn for a session (user pressed Stop in the UI).
276
- * Disposes the pi bridge and broadcasts `agent_end` so all subscribers
276
+ * Disposes the agent bridge and broadcasts `agent_end` so all subscribers
277
277
  * see the turn close. The stream itself is kept alive — the next user
278
278
  * message (via `prompt()`) will lazily create a fresh bridge.
279
279
  *
@@ -282,10 +282,10 @@ export declare class SessionStreamManager {
282
282
  */
283
283
  cancelTurn(sessionId: string): void;
284
284
  /**
285
- * Tear down a single session's stream — disposes the pi bridge and clears
285
+ * Tear down a single session's stream — disposes the agent bridge and clears
286
286
  * subscribers. Idempotent. Called by the routes layer right before
287
287
  * `DELETE /api/sessions/:id` so the SQL cascade doesn't leave a zombie
288
- * pi process driving events at a session that no longer exists.
288
+ * spectral process driving events at a session that no longer exists.
289
289
  *
290
290
  * Does NOT remove the session from the store — that's the caller's job.
291
291
  */
@@ -294,7 +294,7 @@ export declare class SessionStreamManager {
294
294
  * Tear down every stream whose session belongs to the given list of ids.
295
295
  * Used by the project-delete path: the route layer reads the project's
296
296
  * session ids from `deleteProject()` and passes them here BEFORE the SQL
297
- * cascade fires, so no pi process ever observes the FK cascade.
297
+ * cascade fires, so no spectral process ever observes the FK cascade.
298
298
  */
299
299
  disposeProjectStreams(sessionIds: readonly string[]): void;
300
300
  /**
@@ -309,7 +309,7 @@ export declare class SessionStreamManager {
309
309
  setLoopActive(sessionId: string, active: boolean, originalPrompt?: string, maxIterations?: number, goal?: string): void;
310
310
  /**
311
311
  * Fork & Compact: trigger compaction after the first assistant turn of a
312
- * forked session. Uses pi's built-in `compact()` which generates a summary
312
+ * forked session. Uses spectral's built-in `compact()` which generates a summary
313
313
  * of older context, retaining the most recent ~20K tokens (including the
314
314
  * user's new message + the assistant's response).
315
315
  *
@@ -326,11 +326,11 @@ export declare class SessionStreamManager {
326
326
  * so we poll stream.compacting briefly. If compaction hasn't started after
327
327
  * a short grace period, we check whether the context window exceeds the
328
328
  * threshold and proactively trigger compaction via the bridge (which
329
- * invokes pi's full pipeline, including the session_before_compact hook
329
+ * invokes spectral's full pipeline, including the session_before_compact hook
330
330
  * where the observational memory extension provides its summary).
331
331
  *
332
332
  * A duplicate call from the extension's delayed compaction trigger is
333
- * harmless — pi throws "Already compacted" which the extension catches.
333
+ * harmless — spectral throws "Already compacted" which the extension catches.
334
334
  */
335
335
  /**
336
336
  * Send the next prompt for an autonomous loop iteration, compacting first
@@ -1 +1 @@
1
- {"version":3,"file":"session-stream.d.ts","sourceRoot":"","sources":["../../src/server/session-stream.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session-stream.d.ts","sourceRoot":"","sources":["../../src/server/session-stream.ts"],"names":[],"mappings":"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"}
@@ -4,14 +4,14 @@
4
4
  * Background: prior to this module each WebSocket owned its own `AgentBridge`
5
5
  * instance and the routes layer enforced single-writer-wins (4001 eviction)
6
6
  * to keep that bridge unique per session. That model lost data on browser
7
- * refresh — the WS close torn down the pi process mid-stream, and a re-open
7
+ * refresh — the WS close torn down the spectral process mid-stream, and a re-open
8
8
  * couldn't recover what hadn't yet hit `agent_end` (and thus SQLite).
9
9
  *
10
10
  * New model:
11
11
  * - Pi lifecycle is per **Spectral session**, not per WS.
12
12
  * - 0..N WebSockets may attach to the same session simultaneously. Each
13
13
  * gets the same broadcast stream of events.
14
- * - When a WS detaches (close, error, refresh), the pi process keeps
14
+ * - When a WS detaches (close, error, refresh), the spectral process keeps
15
15
  * running. Closing every tab does NOT cancel the in-flight turn —
16
16
  * it runs to completion and persists on `agent_end` as before.
17
17
  * - On `attach`, the manager hands back a replay payload: full DB history
@@ -24,7 +24,7 @@
24
24
  * for MVP.
25
25
  *
26
26
  * Failure modes:
27
- * - Pi throws synchronously in `prompt()` → bridge surfaces as `error`
27
+ * - spectral throws synchronously in `prompt()` → bridge surfaces as `error`
28
28
  * event; manager broadcasts and clears `currentTurn`.
29
29
  * - One subscriber's `ws.send` throws → caught, logged, removed from the
30
30
  * subscriber set; broadcast continues to the rest.
@@ -33,7 +33,7 @@
33
33
  *
34
34
  * TODO (future): idle GC. A `SessionStream` with `subscribers.size === 0`
35
35
  * and no current turn could be disposed after some grace window (e.g. 5
36
- * minutes) to release pi resources for chronically-idle sessions. Skipped
36
+ * minutes) to release spectral resources for chronically-idle sessions. Skipped
37
37
  * for now — streams accumulate for the lifetime of the server process.
38
38
  */
39
39
  import { randomUUID } from "node:crypto";
@@ -54,13 +54,13 @@ const MAX_LOOP_ITERATIONS = 100;
54
54
  const LOOP_COMPACTION_THRESHOLD_TOKENS = 50_000;
55
55
  /**
56
56
  * Defensive cap for fresh-bridge history replay when we already have a
57
- * persisted observational-memory snapshot. Pi's own compaction keeps a
57
+ * persisted observational-memory snapshot. spectral's own compaction keeps a
58
58
  * recent live tail verbatim and summarizes the older prefix; replaying the
59
59
  * entire SQLite transcript after restart defeats that and can explode the
60
60
  * next prompt. We therefore rehydrate only an approximate recent tail.
61
61
  *
62
62
  * Keep this conservative — the tail is rehydrated as raw user/assistant
63
- * messages PLUS pi reconstructs tool-result messages from events_jsonl,
63
+ * messages PLUS spectral reconstructs tool-result messages from events_jsonl,
64
64
  * so the actual context inflation is 3-8× the stored token estimate.
65
65
  */
66
66
  const REHYDRATION_TAIL_TOKEN_BUDGET = 20_000;
@@ -251,7 +251,7 @@ export class SessionStreamManager {
251
251
  });
252
252
  }
253
253
  /**
254
- * Attach a subscriber to a session. Lazily creates the underlying pi
254
+ * Attach a subscriber to a session. Lazily creates the underlying spectral
255
255
  * session on first attach. The caller is responsible for sending the
256
256
  * initial `session_ready` frame using the returned replay payload (this
257
257
  * keeps wire-protocol concerns in the routes layer).
@@ -281,7 +281,7 @@ export class SessionStreamManager {
281
281
  };
282
282
  }
283
283
  /**
284
- * Detach a subscriber. Idempotent. Does NOT dispose the underlying pi
284
+ * Detach a subscriber. Idempotent. Does NOT dispose the underlying spectral
285
285
  * session — even when subscribers reach zero, the in-flight turn must
286
286
  * complete and persist.
287
287
  */
@@ -454,11 +454,12 @@ export class SessionStreamManager {
454
454
  finally {
455
455
  if (stream.compacting)
456
456
  stream.compacting = false;
457
+ this.maybeAutoDequeue(stream);
457
458
  }
458
459
  }
459
460
  /**
460
- * Persist a user message and forward it to pi. Resolves after the user
461
- * message is persisted + pi is invoked (NOT after the turn completes —
461
+ * Persist a user message and forward it to spectral. Resolves after the user
462
+ * message is persisted + spectral is invoked (NOT after the turn completes —
462
463
  * the turn lifetime is observed via the broadcast stream).
463
464
  *
464
465
  * Broadcast ordering:
@@ -473,15 +474,15 @@ export class SessionStreamManager {
473
474
  * - When `modelId` is provided, we apply it via `bridge.setModel()` and
474
475
  * persist to SQLite for cross-restart recovery, BEFORE invoking
475
476
  * `bridge.prompt()`. If `setModel` fails (unknown model, registry
476
- * unavailable, pi-side error) the bridge has already emitted an
477
+ * unavailable, agent-side error) the bridge has already emitted an
477
478
  * `error` wire event and we drop the prompt to avoid running it
478
479
  * against the wrong model.
479
480
  * - When `modelId` is omitted, we look up SQLite. If a previous turn
480
481
  * persisted a value, we reapply it on this turn (this is the
481
- * cross-restart recovery path: a fresh server process has lost pi's
482
+ * cross-restart recovery path: a fresh server process has lost spectral's
482
483
  * in-memory model state, so we re-pin from durable storage).
483
484
  * - When neither envelope nor SQLite have a value, we leave model
484
- * selection to pi's own settings file (pre-Phase-3 behaviour).
485
+ * selection to spectral's own settings file (pre-Phase-3 behaviour).
485
486
  */
486
487
  async prompt(sessionId, content, modelId, images, reasoningEffort) {
487
488
  if (this.disposed)
@@ -531,7 +532,7 @@ export class SessionStreamManager {
531
532
  this.store.deleteMessage(messageId);
532
533
  },
533
534
  onError: (err) => {
534
- console.error(`[spectral] error: pi bridge error: ${err.message}`);
535
+ console.error(`[spectral] error: agent bridge error: ${err.message}`);
535
536
  },
536
537
  };
537
538
  stream.bridge = this.bridgeFactory(bridgeOpts);
@@ -548,7 +549,7 @@ export class SessionStreamManager {
548
549
  throw e;
549
550
  });
550
551
  }
551
- // Wait for pi to be ready before we persist + invoke. If start failed,
552
+ // Wait for spectral to be ready before we persist + invoke. If start failed,
552
553
  // surface to all subscribers instead of throwing into the route handler.
553
554
  try {
554
555
  await stream.ready;
@@ -562,7 +563,7 @@ export class SessionStreamManager {
562
563
  // whitelist). Order:
563
564
  // a) If envelope carried a `modelId`, use it.
564
565
  // b) Else, look up the per-session persisted modelId in SQLite
565
- // (cross-restart recovery — server restart wipes pi's in-memory
566
+ // (cross-restart recovery — server restart wipes spectral's in-memory
566
567
  // session model state, but our durable store has the last value).
567
568
  // c) Else, ask the bridge for the first available model from the
568
569
  // backend whitelist (same sortOrder the frontend uses for its
@@ -602,7 +603,7 @@ export class SessionStreamManager {
602
603
  // Sticky reasoning-effort resolution. Same order as modelId:
603
604
  // a) Envelope-supplied value → apply + persist.
604
605
  // b) Otherwise, look up the persisted value from SQLite.
605
- // c) When neither is present, leave pi's current thinking level unchanged.
606
+ // c) When neither is present, leave spectral's current thinking level unchanged.
606
607
  // We apply BEFORE persisting the user message so the turn runs with the
607
608
  // correct reasoning level.
608
609
  const effectiveReasoningEffort = reasoningEffort ?? this.store.getSessionReasoningEffort(sessionId) ?? undefined;
@@ -637,7 +638,7 @@ export class SessionStreamManager {
637
638
  // 2. Broadcast the persisted message so every tab — including the one
638
639
  // that sent the prompt — appends an authoritative user turn.
639
640
  this.broadcast(stream, { type: "user_message_appended", message: stored });
640
- // 3. Open a new in-flight turn. Allocated even before pi emits anything
641
+ // 3. Open a new in-flight turn. Allocated even before spectral emits anything
641
642
  // so a re-attach immediately after `prompt` sees the turn.
642
643
  stream.currentTurn = {
643
644
  turnId: randomUUID(),
@@ -645,7 +646,7 @@ export class SessionStreamManager {
645
646
  events: [],
646
647
  assistantText: "",
647
648
  };
648
- // 4. Fire pi. `prompt` resolves on agent_end; errors are handled inside
649
+ // 4. Fire spectral. `prompt` resolves on agent_end; errors are handled inside
649
650
  // AgentBridge (it emits `error` for us). We don't await — broadcast is
650
651
  // driven by the bridge's emit callback.
651
652
  void stream.bridge.prompt(content, images);
@@ -694,7 +695,7 @@ export class SessionStreamManager {
694
695
  }
695
696
  /**
696
697
  * Cancel the in-flight turn for a session (user pressed Stop in the UI).
697
- * Disposes the pi bridge and broadcasts `agent_end` so all subscribers
698
+ * Disposes the agent bridge and broadcasts `agent_end` so all subscribers
698
699
  * see the turn close. The stream itself is kept alive — the next user
699
700
  * message (via `prompt()`) will lazily create a fresh bridge.
700
701
  *
@@ -712,12 +713,12 @@ export class SessionStreamManager {
712
713
  stream.loopGoal = null;
713
714
  stream.loopIterationCount = 0;
714
715
  // Capture whether a turn is in-flight BEFORE we dispose the bridge.
715
- // dispose() tears down pi, which can cause the in-flight prompt()
716
+ // dispose() tears down spectral, which can cause the in-flight prompt()
716
717
  // promise to reject synchronously/microtask and emit an error event
717
718
  // through handleBridgeEvent — which clears currentTurn. We must
718
719
  // broadcast agent_end regardless of what dispose() does to currentTurn.
719
720
  const hadTurn = stream.currentTurn != null;
720
- // Dispose the pi bridge immediately — this tears down pi's session and
721
+ // Dispose the agent bridge immediately — this tears down spectral's session and
721
722
  // unsubscribe. The bridge's own event handler is detached; no further
722
723
  // events will flow. We broadcast agent_end ourselves below.
723
724
  try {
@@ -738,10 +739,11 @@ export class SessionStreamManager {
738
739
  // Broadcast agent_end so all subscribers close their open turn and
739
740
  // re-enable their composers. Use the pre-disposal flag — dispose()
740
741
  // may have cleared currentTurn via an error event from the torn-down
741
- // pi session.
742
+ // spectral session.
742
743
  if (hadTurn) {
743
744
  this.broadcast(stream, { type: "agent_end" });
744
745
  stream.currentTurn = null;
746
+ this.maybeAutoDequeue(stream);
745
747
  }
746
748
  // Don't delete the stream — the subscribers are still attached and the
747
749
  // next `prompt()` call will create a fresh bridge via `createStream()`.
@@ -749,10 +751,10 @@ export class SessionStreamManager {
749
751
  // recreate one.
750
752
  }
751
753
  /**
752
- * Tear down a single session's stream — disposes the pi bridge and clears
754
+ * Tear down a single session's stream — disposes the agent bridge and clears
753
755
  * subscribers. Idempotent. Called by the routes layer right before
754
756
  * `DELETE /api/sessions/:id` so the SQL cascade doesn't leave a zombie
755
- * pi process driving events at a session that no longer exists.
757
+ * spectral process driving events at a session that no longer exists.
756
758
  *
757
759
  * Does NOT remove the session from the store — that's the caller's job.
758
760
  */
@@ -771,7 +773,7 @@ export class SessionStreamManager {
771
773
  // ignore
772
774
  }
773
775
  // Best-effort: notify any still-open subscribers so they close cleanly
774
- // rather than hanging on a dead pi process. We don't broadcast through
776
+ // rather than hanging on a dead spectral process. We don't broadcast through
775
777
  // `broadcast()` because that would re-enter the dead-subscriber pruning
776
778
  // loop on a stream we're about to drop anyway.
777
779
  for (const sub of stream.subscribers) {
@@ -791,7 +793,7 @@ export class SessionStreamManager {
791
793
  * Tear down every stream whose session belongs to the given list of ids.
792
794
  * Used by the project-delete path: the route layer reads the project's
793
795
  * session ids from `deleteProject()` and passes them here BEFORE the SQL
794
- * cascade fires, so no pi process ever observes the FK cascade.
796
+ * cascade fires, so no spectral process ever observes the FK cascade.
795
797
  */
796
798
  disposeProjectStreams(sessionIds) {
797
799
  for (const sid of sessionIds) {
@@ -827,7 +829,7 @@ export class SessionStreamManager {
827
829
  }
828
830
  /**
829
831
  * Fork & Compact: trigger compaction after the first assistant turn of a
830
- * forked session. Uses pi's built-in `compact()` which generates a summary
832
+ * forked session. Uses spectral's built-in `compact()` which generates a summary
831
833
  * of older context, retaining the most recent ~20K tokens (including the
832
834
  * user's new message + the assistant's response).
833
835
  *
@@ -861,6 +863,7 @@ export class SessionStreamManager {
861
863
  // best-effort
862
864
  }
863
865
  console.log(`[spectral] fork-compact completed for ${stream.sessionId}`);
866
+ this.maybeAutoDequeue(stream);
864
867
  })
865
868
  .catch((err) => {
866
869
  stream.compacting = false;
@@ -877,6 +880,7 @@ export class SessionStreamManager {
877
880
  catch {
878
881
  // best-effort
879
882
  }
883
+ this.maybeAutoDequeue(stream);
880
884
  });
881
885
  }
882
886
  /**
@@ -888,11 +892,11 @@ export class SessionStreamManager {
888
892
  * so we poll stream.compacting briefly. If compaction hasn't started after
889
893
  * a short grace period, we check whether the context window exceeds the
890
894
  * threshold and proactively trigger compaction via the bridge (which
891
- * invokes pi's full pipeline, including the session_before_compact hook
895
+ * invokes spectral's full pipeline, including the session_before_compact hook
892
896
  * where the observational memory extension provides its summary).
893
897
  *
894
898
  * A duplicate call from the extension's delayed compaction trigger is
895
- * harmless — pi throws "Already compacted" which the extension catches.
899
+ * harmless — spectral throws "Already compacted" which the extension catches.
896
900
  */
897
901
  /**
898
902
  * Send the next prompt for an autonomous loop iteration, compacting first
@@ -1019,14 +1023,14 @@ export class SessionStreamManager {
1019
1023
  this.store.deleteMessage(messageId);
1020
1024
  },
1021
1025
  onError: (err) => {
1022
- console.error(`[spectral] error: pi bridge error: ${err.message}`);
1026
+ console.error(`[spectral] error: agent bridge error: ${err.message}`);
1023
1027
  },
1024
1028
  };
1025
1029
  stream.bridge = this.bridgeFactory(bridgeOpts);
1026
1030
  stream.ready = stream.bridge
1027
1031
  .start()
1028
1032
  .then(() => {
1029
- // After pi has replayed history into its session manager, populate
1033
+ // After spectral has replayed history into its session manager, populate
1030
1034
  // context window state from its built-in getContextUsage() estimator.
1031
1035
  // Historical sessions need this — without it, the initial
1032
1036
  // session_ready carries null fields and the context-window bar
@@ -1064,6 +1068,7 @@ export class SessionStreamManager {
1064
1068
  }
1065
1069
  }
1066
1070
  }
1071
+ this.maybeAutoDequeue(stream);
1067
1072
  })
1068
1073
  .catch((err) => {
1069
1074
  const e = err instanceof Error ? err : new Error(String(err));
@@ -1080,7 +1085,7 @@ export class SessionStreamManager {
1080
1085
  }
1081
1086
  handleBridgeEvent(stream, event) {
1082
1087
  // Buffer replayable events into the in-flight turn. We intentionally
1083
- // accept events even if currentTurn is null (rare race: pi emits before
1088
+ // accept events even if currentTurn is null (rare race: spectral emits before
1084
1089
  // prompt() opened the turn), in which case we open one defensively so
1085
1090
  // late attachers see the events. The first event in such a case is
1086
1091
  // typically `message_start`.
@@ -1131,7 +1136,7 @@ export class SessionStreamManager {
1131
1136
  // which fires before agent_end).
1132
1137
  //
1133
1138
  // Track context window state from token_usage events — the bridge emits
1134
- // cumulative session-wide values from pi's getContextUsage(). This lets
1139
+ // cumulative session-wide values from spectral's getContextUsage(). This lets
1135
1140
  // late-attaching subsribers (reconnects / multi-tab) get the latest
1136
1141
  // context window state via session_ready.
1137
1142
  if (event.type === "token_usage") {
@@ -1388,6 +1393,10 @@ export class SessionStreamManager {
1388
1393
  * Returns true if a prompt was dequeued and a turn started.
1389
1394
  */
1390
1395
  maybeAutoDequeue(stream) {
1396
+ if (stream.currentTurn || stream.compacting)
1397
+ return false;
1398
+ if (stream.loopActive && stream.loopOriginalPrompt)
1399
+ return false;
1391
1400
  const next = this.store.dequeuePrompt(stream.sessionId);
1392
1401
  if (!next)
1393
1402
  return false;
@@ -23,12 +23,12 @@
23
23
  * - Close the relay (code 1000, reason "shutdown") and dispose the
24
24
  * manager. The dispose order matters: relay first so the backend
25
25
  * sees a clean close before our local state goes; manager second so
26
- * any pi processes get torn down deterministically.
26
+ * any spectral processes get torn down deterministically.
27
27
  * - Close the SQLite store (best-effort — a failure here just gets
28
28
  * logged; the process is exiting anyway).
29
29
  * - Exit with the supplied code (default 0).
30
30
  * 2. Second SIGINT/SIGTERM during the grace period: skip the wait, force
31
- * immediate exit with code 1. We don't want a hung pi process to
31
+ * immediate exit with code 1. We don't want a hung spectral process to
32
32
  * prevent operators from killing the server with a second Ctrl-C.
33
33
  *
34
34
  * The function is intentionally framework-free — it takes plain callbacks
@@ -65,7 +65,7 @@ export interface GracefulShutdownOptions {
65
65
  inFlightCount?: () => number;
66
66
  /** Close the relay with code 1000 / reason "shutdown". */
67
67
  closeRelay?: () => void | Promise<void>;
68
- /** Dispose the SessionStreamManager (kills pi processes). */
68
+ /** Dispose the SessionStreamManager (kills spectral processes). */
69
69
  disposeManager?: () => void | Promise<void>;
70
70
  /** Close the SQLite store. Failures are logged, not rethrown. */
71
71
  closeStore?: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"shutdown.d.ts","sourceRoot":"","sources":["../../src/server/shutdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,EAAE;IAAE,cAAc,EAAE,OAAO,CAAA;CAEpD,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED,MAAM,WAAW,uBAAuB;IACtC,wEAAwE;IACxE,MAAM,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IACjD;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,MAAM,CAAC;IAC7B,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,6DAA6D;IAC7D,cAAc,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,yEAAyE;IACzE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC;;;OAGG;IACH,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAaD,oEAAoE;AACpE,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,GAAE,uBAA4B,GACjC,OAAO,CAAC,IAAI,CAAC,CAmGf"}
1
+ {"version":3,"file":"shutdown.d.ts","sourceRoot":"","sources":["../../src/server/shutdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,EAAE;IAAE,cAAc,EAAE,OAAO,CAAA;CAEpD,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED,MAAM,WAAW,uBAAuB;IACtC,wEAAwE;IACxE,MAAM,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IACjD;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,MAAM,CAAC;IAC7B,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,mEAAmE;IACnE,cAAc,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,yEAAyE;IACzE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC;;;OAGG;IACH,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAaD,oEAAoE;AACpE,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,GAAE,uBAA4B,GACjC,OAAO,CAAC,IAAI,CAAC,CAmGf"}
@@ -23,12 +23,12 @@
23
23
  * - Close the relay (code 1000, reason "shutdown") and dispose the
24
24
  * manager. The dispose order matters: relay first so the backend
25
25
  * sees a clean close before our local state goes; manager second so
26
- * any pi processes get torn down deterministically.
26
+ * any spectral processes get torn down deterministically.
27
27
  * - Close the SQLite store (best-effort — a failure here just gets
28
28
  * logged; the process is exiting anyway).
29
29
  * - Exit with the supplied code (default 0).
30
30
  * 2. Second SIGINT/SIGTERM during the grace period: skip the wait, force
31
- * immediate exit with code 1. We don't want a hung pi process to
31
+ * immediate exit with code 1. We don't want a hung spectral process to
32
32
  * prevent operators from killing the server with a second Ctrl-C.
33
33
  *
34
34
  * The function is intentionally framework-free — it takes plain callbacks
@@ -89,7 +89,7 @@ export async function gracefulShutdown(opts = {}) {
89
89
  entryCount += 1;
90
90
  // Second signal during a graceful shutdown: don't wait around, just go.
91
91
  // Code 1 signals "abnormal exit" — operators wanted out NOW, not after
92
- // pi finishes its turn.
92
+ // spectral finishes its turn.
93
93
  if (entryCount > 1) {
94
94
  try {
95
95
  logger.error("Shutdown forced by repeated signal — exiting immediately.");
@@ -19,7 +19,7 @@
19
19
  *
20
20
  * Foreign keys are enabled so DELETE FROM projects cascades to sessions
21
21
  * cascades to messages. The route layer must still tear down any in-flight
22
- * pi streams BEFORE deleting — see `SessionStreamManager.disposeProjectStreams`.
22
+ * agent streams BEFORE deleting — see `SessionStreamManager.disposeProjectStreams`.
23
23
  *
24
24
  * The repo is intentionally a thin wrapper. We do NOT expose `Database`
25
25
  * itself — callers go through the typed methods so we can swap the backend
@@ -130,7 +130,7 @@ export declare class SessionStore {
130
130
  updateProject(id: string, input: UpdateProjectInput): WireProject | null;
131
131
  /**
132
132
  * Delete a project. Cascades to sessions and messages via FK.
133
- * Caller MUST tear down any active SessionStream subscribers / pi
133
+ * Caller MUST tear down any active SessionStream subscribers / spectral
134
134
  * processes for sessions in this project BEFORE invoking this.
135
135
  * Returns the list of session ids that belonged to the project (so
136
136
  * the caller can include them in the stream-teardown call).
@@ -172,8 +172,8 @@ export declare class SessionStore {
172
172
  * the session does not exist. The CLI uses this for cross-restart recovery:
173
173
  * when an envelope arrives WITHOUT a `modelId` but SQLite has a value
174
174
  * persisted from an earlier turn, we apply the persisted value before
175
- * forwarding to pi. When neither envelope nor SQLite have a value, we
176
- * leave model selection to pi's own settings file (pre-Phase-3 behaviour).
175
+ * forwarding to spectral. When neither envelope nor SQLite have a value, we
176
+ * leave model selection to spectral's own settings file (pre-Phase-3 behaviour).
177
177
  */
178
178
  getSessionModel(sessionId: string): string | null;
179
179
  /**