@koda-sl/baker-bridge 0.39.13 → 0.39.20

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 (68) hide show
  1. package/README.md +27 -6
  2. package/dist/hono/agent-session.d.ts +55 -0
  3. package/dist/hono/agent-session.d.ts.map +1 -0
  4. package/dist/hono/agent-session.js +165 -0
  5. package/dist/hono/agent-session.js.map +1 -0
  6. package/dist/hono/agent-session.test.d.ts +2 -0
  7. package/dist/hono/agent-session.test.d.ts.map +1 -0
  8. package/dist/hono/agent-session.test.js +151 -0
  9. package/dist/hono/agent-session.test.js.map +1 -0
  10. package/dist/hono/agent.d.ts +7 -38
  11. package/dist/hono/agent.d.ts.map +1 -1
  12. package/dist/hono/agent.js +108 -487
  13. package/dist/hono/agent.js.map +1 -1
  14. package/dist/hono/attachments.d.ts +0 -9
  15. package/dist/hono/attachments.d.ts.map +1 -1
  16. package/dist/hono/attachments.js +35 -31
  17. package/dist/hono/attachments.js.map +1 -1
  18. package/dist/hono/bridge-job.d.ts +120 -0
  19. package/dist/hono/bridge-job.d.ts.map +1 -0
  20. package/dist/hono/bridge-job.js +326 -0
  21. package/dist/hono/bridge-job.js.map +1 -0
  22. package/dist/hono/bridge-job.test.d.ts +2 -0
  23. package/dist/hono/bridge-job.test.d.ts.map +1 -0
  24. package/dist/hono/bridge-job.test.js +332 -0
  25. package/dist/hono/bridge-job.test.js.map +1 -0
  26. package/dist/hono/convex.d.ts +2 -8
  27. package/dist/hono/convex.d.ts.map +1 -1
  28. package/dist/hono/convex.js +89 -192
  29. package/dist/hono/convex.js.map +1 -1
  30. package/dist/hono/convex.test.js +22 -0
  31. package/dist/hono/convex.test.js.map +1 -1
  32. package/dist/hono/relay.d.ts +101 -0
  33. package/dist/hono/relay.d.ts.map +1 -0
  34. package/dist/hono/relay.js +205 -0
  35. package/dist/hono/relay.js.map +1 -0
  36. package/dist/hono/relay.test.d.ts +2 -0
  37. package/dist/hono/relay.test.d.ts.map +1 -0
  38. package/dist/hono/relay.test.js +225 -0
  39. package/dist/hono/relay.test.js.map +1 -0
  40. package/dist/hono/repo-context.d.ts.map +1 -1
  41. package/dist/hono/repo-context.js +5 -5
  42. package/dist/hono/repo-context.js.map +1 -1
  43. package/dist/hono/runtime-files.d.ts +58 -0
  44. package/dist/hono/runtime-files.d.ts.map +1 -0
  45. package/dist/hono/runtime-files.js +82 -0
  46. package/dist/hono/runtime-files.js.map +1 -0
  47. package/dist/hono/runtime-files.test.d.ts +2 -0
  48. package/dist/hono/runtime-files.test.d.ts.map +1 -0
  49. package/dist/hono/runtime-files.test.js +43 -0
  50. package/dist/hono/runtime-files.test.js.map +1 -0
  51. package/dist/hono/sandbox-content.d.ts +43 -0
  52. package/dist/hono/sandbox-content.d.ts.map +1 -0
  53. package/dist/hono/sandbox-content.js +136 -0
  54. package/dist/hono/sandbox-content.js.map +1 -0
  55. package/dist/hono/sandbox-content.test.d.ts +2 -0
  56. package/dist/hono/sandbox-content.test.d.ts.map +1 -0
  57. package/dist/hono/sandbox-content.test.js +107 -0
  58. package/dist/hono/sandbox-content.test.js.map +1 -0
  59. package/dist/hono/server.d.ts +6 -1
  60. package/dist/hono/server.d.ts.map +1 -1
  61. package/dist/hono/server.js +45 -120
  62. package/dist/hono/server.js.map +1 -1
  63. package/dist/hono/server.test.js +2 -4
  64. package/dist/hono/server.test.js.map +1 -1
  65. package/dist/hono/session-store.d.ts.map +1 -1
  66. package/dist/hono/session-store.js +12 -7
  67. package/dist/hono/session-store.js.map +1 -1
  68. package/package.json +3 -3
package/README.md CHANGED
@@ -112,9 +112,10 @@ Convex action ──POST /message/async──▶ Bridge AgentSession
112
112
  - **Stop button** flips the thread to `cancelled` via Convex first (UI is
113
113
  freed immediately) and best-effort POSTs `/message/abort` to kill the SDK.
114
114
  - **AskUserQuestion** posts `/api/chat/input-request` and blocks until the
115
- dashboard answers via Convex action → bridge `/answer-question`. Convex
116
- persists the answer before proxying it so a bridge restart does not erase the
117
- user's response.
115
+ dashboard answers via Convex action → bridge `/answer-question`, with a 15m
116
+ bridge-side timeout so unanswered questions do not leave runs hanging forever.
117
+ Convex persists the answer before proxying it so a bridge restart does not
118
+ erase the user's response.
118
119
  - **Turn Result changes and output guards** use Claude Agent SDK structured
119
120
  output. Convex sends the current accumulated `chat.changes` snapshot as
120
121
  context; the bridge asks the SDK for the full satisfied-artifact snapshot and
@@ -159,13 +160,14 @@ oversized images still block the commit.
159
160
  ## Resilience
160
161
 
161
162
  - All Convex POSTs retry 3× with exponential backoff (1s, 2s, 4s).
162
- - Persistent failures of `/api/chat/event` and `/api/chat/complete` are
163
- appended to `~/.baker/relay-errors.jsonl` for post-mortem.
163
+ - Persistent failures of non-silent Convex callbacks are appended to
164
+ `~/.baker/relay-errors.jsonl` for post-mortem.
164
165
  - The SDK iterator is wrapped in a 30 min watchdog: if no event arrives for
165
166
  that long, the run is aborted and the thread is marked errored.
166
167
  - A 45s heartbeat keeps the Convex thread alive during long tool executions
167
168
  when no SDK events are flowing. Without it, the 2 min stale-thread cron
168
- would falsely timeout active threads.
169
+ would falsely timeout active threads. Failed heartbeat POSTs are logged to
170
+ `~/.baker/relay-errors.jsonl` with the thread and turn ids for diagnosis.
169
171
  - The session registry evicts entries idle for >24h to bound memory.
170
172
  - Convex dispatches include a bounded rendered current-thread history snapshot.
171
173
  The bridge uses the local SDK session id when valid, but falls back to this
@@ -203,6 +205,25 @@ returned in the dispatch response besides 202.
203
205
  writing further. No globally-mutable abort flag.
204
206
  - **Single-writer to Convex** — there is no parallel WebSocket. Convex is the
205
207
  only place the UI reads state from, eliminating dual-write races.
208
+ - **Relay-owned callbacks** — stream preview buffering, callback ordering, heartbeat
209
+ delivery, and completion drain behavior live behind the Relay module so callback
210
+ behavior is tested at the Bridge-to-Convex seam.
211
+ - **Bridge Job execution** — one dispatched turn is executed by the Bridge Job
212
+ executor, which owns prompt preparation, SDK query/resume fallback, message
213
+ consumption, AskUserQuestion blocking, output guards, and final outcome
214
+ classification while `AgentSession` stays focused on thread continuity and
215
+ active-run replacement.
216
+ - **Agent Session coordination** — per-thread sessions own active Bridge Job
217
+ replacement/drain, abort propagation, pending AskUserQuestion answers, and
218
+ idle eviction while preserving the public `/message/*` and `/answer-question`
219
+ endpoint behavior.
220
+ - **Sandbox Content API** — local file-backed `/company`, `/brand`, `/knowledge`,
221
+ `/landings`, `/documents`, and `/flows` endpoints share one content module for
222
+ slug/path safety, markdown cleanup, flow encryption/decryption, and document
223
+ format lookup while keeping HTTP response shapes unchanged.
224
+ - **Bridge Local Runtime Files** — session continuity, attachments, Relay Error
225
+ logs, and sandbox content roots derive their filesystem locations from one
226
+ runtime-files module, keeping production paths stable while tests use temp roots.
206
227
 
207
228
  ## Development
208
229
 
@@ -0,0 +1,55 @@
1
+ import type { BridgeJob, BridgeJobControls, BridgeJobOutcome } from "./bridge-job.ts";
2
+ type AskUserAnswer = {
3
+ toolUseId: string;
4
+ answers: Record<string, string>;
5
+ };
6
+ export type AgentSessionExecutor = {
7
+ execute(job: BridgeJob, controls: BridgeJobControls): Promise<BridgeJobOutcome>;
8
+ };
9
+ type AgentSessionDependencies = {
10
+ createExecutor(): AgentSessionExecutor;
11
+ complete(outcome: BridgeJobOutcome, job: BridgeJob): Promise<void>;
12
+ heartbeat(job: BridgeJob): Promise<void>;
13
+ replaceTimeoutMs?: number;
14
+ heartbeatIntervalMs?: number;
15
+ sdkWatchdogMs?: number;
16
+ watchdogIntervalMs?: number;
17
+ now?: () => number;
18
+ };
19
+ export declare class AgentSession {
20
+ readonly threadId: string;
21
+ private readonly dependencies;
22
+ private readonly pendingQuestions;
23
+ private activeRun;
24
+ private activeAbort;
25
+ private streamingPromise;
26
+ private replacingStream;
27
+ lastUsedAt: number;
28
+ constructor(threadId: string, dependencies: AgentSessionDependencies);
29
+ start(job: BridgeJob): Promise<void>;
30
+ abort(): void;
31
+ answer(input: AskUserAnswer): boolean;
32
+ private run;
33
+ }
34
+ type AgentSessionRegistryDependencies<TSession extends {
35
+ lastUsedAt: number;
36
+ abort(): void;
37
+ }> = {
38
+ createSession(threadId: string): TSession | Promise<TSession>;
39
+ idleTtlMs: number;
40
+ now?: () => number;
41
+ };
42
+ export declare class AgentSessionRegistry<TSession extends {
43
+ lastUsedAt: number;
44
+ abort(): void;
45
+ } = AgentSession> {
46
+ private readonly sessions;
47
+ private readonly dependencies;
48
+ constructor(dependencies: AgentSessionRegistryDependencies<TSession>);
49
+ get(threadId: string): Promise<TSession>;
50
+ abort(threadId: string): boolean;
51
+ sweepIdle(now?: number): void;
52
+ has(threadId: string): boolean;
53
+ }
54
+ export {};
55
+ //# sourceMappingURL=agent-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-session.d.ts","sourceRoot":"","sources":["../../src/hono/agent-session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,gBAAgB,EAAmB,MAAM,iBAAiB,CAAC;AAOvG,KAAK,aAAa,GAAG;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,CAAC,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACjF,CAAC;AAEF,KAAK,wBAAwB,GAAG;IAC9B,cAAc,IAAI,oBAAoB,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,gBAAgB,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,SAAS,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB,CAAC;AAEF,qBAAa,YAAY;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA2B;IACxD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAsC;IACvE,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,WAAW,CAAgC;IACnD,OAAO,CAAC,gBAAgB,CAA8B;IACtD,OAAO,CAAC,eAAe,CAAS;IAChC,UAAU,EAAE,MAAM,CAAC;gBAEP,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,wBAAwB;IAM9D,KAAK,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAuC1C,KAAK,IAAI,IAAI;IAYb,MAAM,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO;YAUvB,GAAG;CA2DlB;AAED,KAAK,gCAAgC,CAAC,QAAQ,SAAS;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,IAAI,IAAI,CAAA;CAAE,IAAI;IAC9F,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9D,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB,CAAC;AAEF,qBAAa,oBAAoB,CAAC,QAAQ,SAAS;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,IAAI,IAAI,CAAA;CAAE,GAAG,YAAY;IACrG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA+B;IACxD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA6C;gBAE9D,YAAY,EAAE,gCAAgC,CAAC,QAAQ,CAAC;IAI9D,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAW9C,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAShC,SAAS,CAAC,GAAG,SAAwC,GAAG,IAAI;IAS5D,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;CAG/B"}
@@ -0,0 +1,165 @@
1
+ const DEFAULT_REPLACE_TIMEOUT_MS = 30_000;
2
+ const DEFAULT_HEARTBEAT_INTERVAL_MS = 45_000;
3
+ const DEFAULT_SDK_WATCHDOG_MS = 30 * 60 * 1000;
4
+ const DEFAULT_WATCHDOG_INTERVAL_MS = 30_000;
5
+ export class AgentSession {
6
+ threadId;
7
+ dependencies;
8
+ pendingQuestions = new Map();
9
+ activeRun = null;
10
+ activeAbort = null;
11
+ streamingPromise = null;
12
+ replacingStream = false;
13
+ lastUsedAt;
14
+ constructor(threadId, dependencies) {
15
+ this.threadId = threadId;
16
+ this.dependencies = dependencies;
17
+ this.lastUsedAt = (dependencies.now ?? Date.now)();
18
+ }
19
+ async start(job) {
20
+ if (this.streamingPromise) {
21
+ const previousPromise = this.streamingPromise;
22
+ this.replacingStream = true;
23
+ this.abort();
24
+ try {
25
+ await Promise.race([
26
+ previousPromise,
27
+ new Promise((_, reject) => setTimeout(() => reject(new Error("previous stream timed out")), this.dependencies.replaceTimeoutMs ?? DEFAULT_REPLACE_TIMEOUT_MS)),
28
+ ]);
29
+ }
30
+ catch (err) {
31
+ console.error(`[AgentSession] previous stream did not drain on thread ${this.threadId} — forcing reset:`, err instanceof Error ? err.message : err);
32
+ }
33
+ finally {
34
+ if (this.streamingPromise === previousPromise) {
35
+ this.streamingPromise = null;
36
+ }
37
+ this.replacingStream = false;
38
+ }
39
+ }
40
+ const runPromise = this.run(job);
41
+ this.streamingPromise = runPromise;
42
+ try {
43
+ await runPromise;
44
+ }
45
+ finally {
46
+ if (this.streamingPromise === runPromise) {
47
+ this.streamingPromise = null;
48
+ }
49
+ }
50
+ }
51
+ abort() {
52
+ this.activeRun = null;
53
+ if (this.activeAbort) {
54
+ this.activeAbort.abort();
55
+ this.activeAbort = null;
56
+ }
57
+ for (const [id, pending] of this.pendingQuestions) {
58
+ this.pendingQuestions.delete(id);
59
+ pending.reject(new Error("AskUserQuestion aborted"));
60
+ }
61
+ }
62
+ answer(input) {
63
+ const pending = this.pendingQuestions.get(input.toolUseId);
64
+ if (!pending) {
65
+ return false;
66
+ }
67
+ pending.resolve(input.answers);
68
+ this.pendingQuestions.delete(input.toolUseId);
69
+ return true;
70
+ }
71
+ async run(job) {
72
+ const runToken = Symbol("agent-run");
73
+ this.activeRun = runToken;
74
+ this.lastUsedAt = (this.dependencies.now ?? Date.now)();
75
+ const abortController = new AbortController();
76
+ this.activeAbort = abortController;
77
+ let lastEventAt = (this.dependencies.now ?? Date.now)();
78
+ const heartbeat = setInterval(() => void this.dependencies.heartbeat(job), this.dependencies.heartbeatIntervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS).unref();
79
+ const watchdog = setInterval(() => {
80
+ const now = (this.dependencies.now ?? Date.now)();
81
+ if (now - lastEventAt <= (this.dependencies.sdkWatchdogMs ?? DEFAULT_SDK_WATCHDOG_MS)) {
82
+ return;
83
+ }
84
+ console.error(`[AgentSession] watchdog: no SDK event for ${this.dependencies.sdkWatchdogMs ?? DEFAULT_SDK_WATCHDOG_MS}ms — aborting thread ${this.threadId}`);
85
+ this.abort();
86
+ }, this.dependencies.watchdogIntervalMs ?? DEFAULT_WATCHDOG_INTERVAL_MS).unref();
87
+ try {
88
+ let outcome;
89
+ try {
90
+ outcome = await this.dependencies.createExecutor().execute(job, {
91
+ runToken,
92
+ abortSignal: abortController.signal,
93
+ abortController,
94
+ pendingQuestions: this.pendingQuestions,
95
+ markEvent: () => {
96
+ lastEventAt = (this.dependencies.now ?? Date.now)();
97
+ this.lastUsedAt = lastEventAt;
98
+ },
99
+ isActive: () => this.activeRun === runToken,
100
+ });
101
+ }
102
+ catch (error) {
103
+ outcome =
104
+ this.activeRun === runToken
105
+ ? { kind: "errored", costUsd: 0, errors: [errorMessage(error)] }
106
+ : { kind: "cancelled", costUsd: 0 };
107
+ }
108
+ if (outcome.kind === "cancelled" || this.activeRun !== runToken) {
109
+ const replacedByAnotherRun = this.replacingStream || this.activeRun !== null;
110
+ if (!replacedByAnotherRun) {
111
+ await this.dependencies.complete({ kind: "cancelled", costUsd: outcome.costUsd, model: outcome.model }, job);
112
+ }
113
+ return;
114
+ }
115
+ await this.dependencies.complete(outcome, job);
116
+ }
117
+ finally {
118
+ clearInterval(heartbeat);
119
+ clearInterval(watchdog);
120
+ if (this.activeAbort === abortController) {
121
+ this.activeAbort = null;
122
+ }
123
+ }
124
+ }
125
+ }
126
+ export class AgentSessionRegistry {
127
+ sessions = new Map();
128
+ dependencies;
129
+ constructor(dependencies) {
130
+ this.dependencies = dependencies;
131
+ }
132
+ async get(threadId) {
133
+ const existing = this.sessions.get(threadId);
134
+ if (existing) {
135
+ existing.lastUsedAt = (this.dependencies.now ?? Date.now)();
136
+ return existing;
137
+ }
138
+ const session = await this.dependencies.createSession(threadId);
139
+ this.sessions.set(threadId, session);
140
+ return session;
141
+ }
142
+ abort(threadId) {
143
+ const session = this.sessions.get(threadId);
144
+ if (!session) {
145
+ return false;
146
+ }
147
+ session.abort();
148
+ return true;
149
+ }
150
+ sweepIdle(now = (this.dependencies.now ?? Date.now)()) {
151
+ const cutoff = now - this.dependencies.idleTtlMs;
152
+ for (const [threadId, session] of this.sessions) {
153
+ if (session.lastUsedAt < cutoff) {
154
+ this.sessions.delete(threadId);
155
+ }
156
+ }
157
+ }
158
+ has(threadId) {
159
+ return this.sessions.has(threadId);
160
+ }
161
+ }
162
+ function errorMessage(error) {
163
+ return error instanceof Error ? error.message : String(error);
164
+ }
165
+ //# sourceMappingURL=agent-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-session.js","sourceRoot":"","sources":["../../src/hono/agent-session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=agent-session.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-session.test.d.ts","sourceRoot":"","sources":["../../src/hono/agent-session.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,151 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { AgentSession, AgentSessionRegistry } from "./agent-session.js";
3
+ function deferred() {
4
+ let resolve;
5
+ let reject;
6
+ const promise = new Promise((res, rej) => {
7
+ resolve = res;
8
+ reject = rej;
9
+ });
10
+ return { promise, resolve, reject };
11
+ }
12
+ describe("AgentSession", () => {
13
+ it("resolves a pending AskUserQuestion answer on the same Bridge Job", async () => {
14
+ const pendingAnswer = deferred();
15
+ let updatedInput;
16
+ const executor = {
17
+ async execute(_job, controls) {
18
+ controls.pendingQuestions.set("tool_1", {
19
+ resolve: pendingAnswer.resolve,
20
+ reject: pendingAnswer.reject,
21
+ });
22
+ updatedInput = await pendingAnswer.promise;
23
+ return { kind: "completed", costUsd: 0.25, model: "claude-opus-4-6" };
24
+ },
25
+ };
26
+ const completions = [];
27
+ const session = new AgentSession("thread_1", {
28
+ createExecutor: () => executor,
29
+ complete: (outcome) => {
30
+ completions.push(outcome);
31
+ return Promise.resolve();
32
+ },
33
+ heartbeat: () => Promise.resolve(),
34
+ });
35
+ const started = session.start({ threadId: "thread_1", turnId: "turn_1", prompt: "question" });
36
+ await Promise.resolve();
37
+ expect(session.answer({ toolUseId: "tool_1", answers: { choice: "yes" } })).toBe(true);
38
+ await expect(started).resolves.toBeUndefined();
39
+ expect(updatedInput).toEqual({ choice: "yes" });
40
+ expect(completions).toEqual([{ kind: "completed", costUsd: 0.25, model: "claude-opus-4-6" }]);
41
+ });
42
+ it("replaces an in-flight Bridge Job and completes only the replacement", async () => {
43
+ const firstDrain = deferred();
44
+ const completions = [];
45
+ const abortedTurns = [];
46
+ const session = new AgentSession("thread_1", {
47
+ createExecutor: () => ({
48
+ execute(job, controls) {
49
+ if (job.turnId === "turn_1") {
50
+ controls.abortSignal.addEventListener("abort", () => abortedTurns.push(job.turnId), { once: true });
51
+ return firstDrain.promise;
52
+ }
53
+ return Promise.resolve({ kind: "completed", costUsd: 0.5, model: "claude-opus-4-6" });
54
+ },
55
+ }),
56
+ complete: (outcome, job) => {
57
+ completions.push({ turnId: job.turnId, outcome });
58
+ return Promise.resolve();
59
+ },
60
+ heartbeat: () => Promise.resolve(),
61
+ replaceTimeoutMs: 100,
62
+ });
63
+ const first = session.start({ threadId: "thread_1", turnId: "turn_1", prompt: "first" });
64
+ await Promise.resolve();
65
+ const second = session.start({ threadId: "thread_1", turnId: "turn_2", prompt: "second" });
66
+ await Promise.resolve();
67
+ firstDrain.resolve({ kind: "cancelled", costUsd: 0.1 });
68
+ await expect(Promise.all([first, second])).resolves.toEqual([undefined, undefined]);
69
+ expect(abortedTurns).toEqual(["turn_1"]);
70
+ expect(completions).toEqual([
71
+ { turnId: "turn_2", outcome: { kind: "completed", costUsd: 0.5, model: "claude-opus-4-6" } },
72
+ ]);
73
+ });
74
+ it("aborts a Bridge Job when the SDK watchdog expires", async () => {
75
+ const completions = [];
76
+ const abortedTurns = [];
77
+ const session = new AgentSession("thread_1", {
78
+ createExecutor: () => ({
79
+ execute(job, controls) {
80
+ return new Promise((resolve) => {
81
+ controls.abortSignal.addEventListener("abort", () => {
82
+ abortedTurns.push(job.turnId);
83
+ resolve({ kind: "cancelled", costUsd: 0 });
84
+ }, { once: true });
85
+ });
86
+ },
87
+ }),
88
+ complete: (outcome) => {
89
+ completions.push(outcome);
90
+ return Promise.resolve();
91
+ },
92
+ heartbeat: () => Promise.resolve(),
93
+ sdkWatchdogMs: 1,
94
+ watchdogIntervalMs: 1,
95
+ });
96
+ await expect(session.start({ threadId: "thread_1", turnId: "turn_1", prompt: "stall" })).resolves.toBeUndefined();
97
+ expect(abortedTurns).toEqual(["turn_1"]);
98
+ expect(completions).toEqual([{ kind: "cancelled", costUsd: 0 }]);
99
+ });
100
+ it("rejects pending AskUserQuestion answers when aborted", async () => {
101
+ const pendingAnswer = deferred();
102
+ const executor = {
103
+ async execute(_job, controls) {
104
+ controls.pendingQuestions.set("tool_1", {
105
+ resolve: pendingAnswer.resolve,
106
+ reject: pendingAnswer.reject,
107
+ });
108
+ await pendingAnswer.promise;
109
+ return { kind: "completed", costUsd: 0 };
110
+ },
111
+ };
112
+ const completions = [];
113
+ const session = new AgentSession("thread_1", {
114
+ createExecutor: () => executor,
115
+ complete: (outcome) => {
116
+ completions.push(outcome);
117
+ return Promise.resolve();
118
+ },
119
+ heartbeat: () => Promise.resolve(),
120
+ });
121
+ const started = session.start({ threadId: "thread_1", turnId: "turn_1", prompt: "question" });
122
+ await Promise.resolve();
123
+ session.abort();
124
+ await expect(started).resolves.toBeUndefined();
125
+ expect(completions).toEqual([{ kind: "cancelled", costUsd: 0 }]);
126
+ });
127
+ });
128
+ describe("AgentSessionRegistry", () => {
129
+ it("evicts only sessions idle beyond the TTL", async () => {
130
+ let now = 1_000;
131
+ const registry = new AgentSessionRegistry({
132
+ createSession: (threadId) => new AgentSession(threadId, {
133
+ createExecutor: () => ({ execute: () => Promise.resolve({ kind: "completed", costUsd: 0 }) }),
134
+ complete: () => Promise.resolve(),
135
+ heartbeat: () => Promise.resolve(),
136
+ now: () => now,
137
+ }),
138
+ idleTtlMs: 100,
139
+ now: () => now,
140
+ });
141
+ await registry.get("active_thread");
142
+ await registry.get("idle_thread");
143
+ now = 1_050;
144
+ await registry.get("active_thread");
145
+ now = 1_125;
146
+ registry.sweepIdle(now);
147
+ expect(registry.has("active_thread")).toBe(true);
148
+ expect(registry.has("idle_thread")).toBe(false);
149
+ });
150
+ });
151
+ //# sourceMappingURL=agent-session.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-session.test.js","sourceRoot":"","sources":["../../src/hono/agent-session.test.ts"],"names":[],"mappings":"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"}
@@ -3,54 +3,23 @@ import type { ChatAttachment, ChatChange, DispatchHistorySnapshot } from "./type
3
3
  export declare function buildRehydratedPrompt(content: string, history?: DispatchHistorySnapshot): string;
4
4
  export declare function isResumeSessionError(error: unknown): boolean;
5
5
  export declare function isRecoverableToolUseConcurrencyError(error: unknown): boolean;
6
- declare class AgentSession {
6
+ declare class BridgeRuntimeSession {
7
7
  readonly threadId: string;
8
8
  private sessionId;
9
- private pendingQuestions;
10
- /** Identity token for the currently-running stream. abort() nulls this; if a
11
- * later check sees a different value, the run knows it was abandoned. This
12
- * replaces a global `aborted` flag whose reset-on-entry was racy. */
13
- private activeRun;
14
- private activeAbort;
15
- private streamingPromise;
16
- private replacingStream;
17
- private currentTurnTools;
18
9
  private model;
19
- /** Accumulated text from stream_event text_delta — used to synthesize an
20
- * assistant event when the SDK doesn't emit one (pure-text, no tool calls). */
21
- private turnText;
22
- private postedAssistantEvent;
23
- private sawUserVisibleSdkMessage;
24
- private turnResult;
25
- lastUsedAt: number;
10
+ private readonly agentSession;
26
11
  constructor(threadId: string);
27
- /** Cancel any in-flight run. The next status check inside runStream will trip. */
12
+ get lastUsedAt(): number;
13
+ set lastUsedAt(value: number);
28
14
  abort(): void;
29
15
  setSessionId(id: string): void;
30
16
  resolveQuestion(toolUseId: string, answers: Record<string, string>): boolean;
31
17
  sendAndStream(content: string, attachments: ChatAttachment[] | undefined, history: DispatchHistorySnapshot | undefined, turnId: string, currentChanges?: ChatChange[]): Promise<void>;
32
- private runStream;
33
- private startRun;
34
- private streamPreparedRun;
35
- private startWatchdog;
36
- private runWithResumeFallback;
37
- private recordInitialContextSource;
38
- private canRetryWithRehydration;
39
- private recordSessionRepairFallback;
40
- private runQueryOnce;
41
- private consumeSdkMessage;
42
- private completeSuccessfulRun;
43
- private postSyntheticAssistantEvent;
44
- private recordRehydrationFailure;
45
- private handleStreamEvent;
46
- private handleContentBlockStart;
47
- private handleMessage;
48
- private preparePrompt;
49
- private selectPreparedPrompt;
18
+ private createBridgeJobExecutor;
19
+ private completeBridgeJobOutcome;
50
20
  private completeWithCancel;
51
- private completeWithError;
52
21
  }
53
- export declare function getOrCreateSession(threadId: string): Promise<AgentSession>;
22
+ export declare function getOrCreateSession(threadId: string): Promise<BridgeRuntimeSession>;
54
23
  export declare function abortSession(threadId: string): boolean;
55
24
  export declare function getSlashCommands(): Promise<SlashCommand[]>;
56
25
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/hono/agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAuB,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAsBxF,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAsBtF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,MAAM,CAMhG;AAMD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAa5D;AAED,wBAAgB,oCAAoC,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAK5E;AAsDD,cAAM,YAAY;IAChB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,gBAAgB,CAAsC;IAE9D;;0EAEsE;IACtE,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,WAAW,CAAgC;IACnD,OAAO,CAAC,gBAAgB,CAA8B;IACtD,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,KAAK,CAAqB;IAClC;oFACgF;IAChF,OAAO,CAAC,QAAQ,CAAM;IACtB,OAAO,CAAC,oBAAoB,CAAS;IACrC,OAAO,CAAC,wBAAwB,CAAS;IACzC,OAAO,CAAC,UAAU,CAAkE;IACpF,UAAU,EAAE,MAAM,CAAc;gBAEpB,QAAQ,EAAE,MAAM;IAI5B,kFAAkF;IAClF,KAAK,IAAI,IAAI;IAgBb,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAI9B,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO;IAUtE,aAAa,CACjB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,cAAc,EAAE,GAAG,SAAS,EACzC,OAAO,EAAE,uBAAuB,GAAG,SAAS,EAC5C,MAAM,EAAE,MAAM,EACd,cAAc,CAAC,EAAE,UAAU,EAAE,GAC5B,OAAO,CAAC,IAAI,CAAC;YAoCF,SAAS;IAiCvB,OAAO,CAAC,QAAQ;YAaF,iBAAiB;IAyB/B,OAAO,CAAC,aAAa;YAeP,qBAAqB;IA8CnC,OAAO,CAAC,0BAA0B;IAiClC,OAAO,CAAC,uBAAuB;IAQ/B,OAAO,CAAC,2BAA2B;YAqBrB,YAAY;YA0BZ,iBAAiB;YAiCjB,qBAAqB;YAiBrB,2BAA2B;IAYzC,OAAO,CAAC,wBAAwB;IAchC,OAAO,CAAC,iBAAiB;IAoBzB,OAAO,CAAC,uBAAuB;YAiBjB,aAAa;YAgBb,aAAa;YAmBb,oBAAoB;YAQpB,kBAAkB;YAalB,iBAAiB;CAgBhC;AAkHD,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAahF;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAOtD;AAWD,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAuBhE"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/hono/agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,YAAY,EAAE,MAAM,gCAAgC,CAAC;AA+B5E,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AActF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,MAAM,CAEhG;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE5D;AAED,wBAAgB,oCAAoC,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE5E;AAOD,cAAM,oBAAoB;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;gBAEhC,QAAQ,EAAE,MAAM;IAa5B,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,IAAI,UAAU,CAAC,KAAK,EAAE,MAAM,EAE3B;IAED,KAAK,IAAI,IAAI;IAIb,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAI9B,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO;IAI5E,aAAa,CACX,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,cAAc,EAAE,GAAG,SAAS,EACzC,OAAO,EAAE,uBAAuB,GAAG,SAAS,EAC5C,MAAM,EAAE,MAAM,EACd,cAAc,CAAC,EAAE,UAAU,EAAE,GAC5B,OAAO,CAAC,IAAI,CAAC;IAYhB,OAAO,CAAC,uBAAuB;YAkDjB,wBAAwB;YAqBxB,kBAAkB;CAMjC;AAsBD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAElF;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEtD;AAWD,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAuBhE"}