@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.
- package/README.md +27 -6
- package/dist/hono/agent-session.d.ts +55 -0
- package/dist/hono/agent-session.d.ts.map +1 -0
- package/dist/hono/agent-session.js +165 -0
- package/dist/hono/agent-session.js.map +1 -0
- package/dist/hono/agent-session.test.d.ts +2 -0
- package/dist/hono/agent-session.test.d.ts.map +1 -0
- package/dist/hono/agent-session.test.js +151 -0
- package/dist/hono/agent-session.test.js.map +1 -0
- package/dist/hono/agent.d.ts +7 -38
- package/dist/hono/agent.d.ts.map +1 -1
- package/dist/hono/agent.js +108 -487
- package/dist/hono/agent.js.map +1 -1
- package/dist/hono/attachments.d.ts +0 -9
- package/dist/hono/attachments.d.ts.map +1 -1
- package/dist/hono/attachments.js +35 -31
- package/dist/hono/attachments.js.map +1 -1
- package/dist/hono/bridge-job.d.ts +120 -0
- package/dist/hono/bridge-job.d.ts.map +1 -0
- package/dist/hono/bridge-job.js +326 -0
- package/dist/hono/bridge-job.js.map +1 -0
- package/dist/hono/bridge-job.test.d.ts +2 -0
- package/dist/hono/bridge-job.test.d.ts.map +1 -0
- package/dist/hono/bridge-job.test.js +332 -0
- package/dist/hono/bridge-job.test.js.map +1 -0
- package/dist/hono/convex.d.ts +2 -8
- package/dist/hono/convex.d.ts.map +1 -1
- package/dist/hono/convex.js +89 -192
- package/dist/hono/convex.js.map +1 -1
- package/dist/hono/convex.test.js +22 -0
- package/dist/hono/convex.test.js.map +1 -1
- package/dist/hono/relay.d.ts +101 -0
- package/dist/hono/relay.d.ts.map +1 -0
- package/dist/hono/relay.js +205 -0
- package/dist/hono/relay.js.map +1 -0
- package/dist/hono/relay.test.d.ts +2 -0
- package/dist/hono/relay.test.d.ts.map +1 -0
- package/dist/hono/relay.test.js +225 -0
- package/dist/hono/relay.test.js.map +1 -0
- package/dist/hono/repo-context.d.ts.map +1 -1
- package/dist/hono/repo-context.js +5 -5
- package/dist/hono/repo-context.js.map +1 -1
- package/dist/hono/runtime-files.d.ts +58 -0
- package/dist/hono/runtime-files.d.ts.map +1 -0
- package/dist/hono/runtime-files.js +82 -0
- package/dist/hono/runtime-files.js.map +1 -0
- package/dist/hono/runtime-files.test.d.ts +2 -0
- package/dist/hono/runtime-files.test.d.ts.map +1 -0
- package/dist/hono/runtime-files.test.js +43 -0
- package/dist/hono/runtime-files.test.js.map +1 -0
- package/dist/hono/sandbox-content.d.ts +43 -0
- package/dist/hono/sandbox-content.d.ts.map +1 -0
- package/dist/hono/sandbox-content.js +136 -0
- package/dist/hono/sandbox-content.js.map +1 -0
- package/dist/hono/sandbox-content.test.d.ts +2 -0
- package/dist/hono/sandbox-content.test.d.ts.map +1 -0
- package/dist/hono/sandbox-content.test.js +107 -0
- package/dist/hono/sandbox-content.test.js.map +1 -0
- package/dist/hono/server.d.ts +6 -1
- package/dist/hono/server.d.ts.map +1 -1
- package/dist/hono/server.js +45 -120
- package/dist/hono/server.js.map +1 -1
- package/dist/hono/server.test.js +2 -4
- package/dist/hono/server.test.js.map +1 -1
- package/dist/hono/session-store.d.ts.map +1 -1
- package/dist/hono/session-store.js +12 -7
- package/dist/hono/session-store.js.map +1 -1
- 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
|
|
116
|
-
|
|
117
|
-
|
|
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
|
|
163
|
-
|
|
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 @@
|
|
|
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":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,YAAY,EAA6B,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAGnG,SAAS,QAAQ;IACf,IAAI,OAA4B,CAAC;IACjC,IAAI,MAAmC,CAAC;IACxC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC1C,OAAO,GAAG,GAAG,CAAC;QACd,MAAM,GAAG,GAAG,CAAC;IACf,CAAC,CAAC,CAAC;IACH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AACtC,CAAC;AAED,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,aAAa,GAAG,QAAQ,EAA0B,CAAC;QACzD,IAAI,YAAgD,CAAC;QACrD,MAAM,QAAQ,GAAyB;YACrC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ;gBAC1B,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,EAAE;oBACtC,OAAO,EAAE,aAAa,CAAC,OAAO;oBAC9B,MAAM,EAAE,aAAa,CAAC,MAAM;iBAC7B,CAAC,CAAC;gBACH,YAAY,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC;gBAC3C,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC;YACxE,CAAC;SACF,CAAC;QACF,MAAM,WAAW,GAAuB,EAAE,CAAC;QAC3C,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,UAAU,EAAE;YAC3C,cAAc,EAAE,GAAG,EAAE,CAAC,QAAQ;YAC9B,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE;gBACpB,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC1B,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;YAC3B,CAAC;YACD,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE;SACnC,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;QAC9F,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;QAExB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEvF,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QAC/C,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QAChD,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAAC;IAChG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;QACnF,MAAM,UAAU,GAAG,QAAQ,EAAoB,CAAC;QAChD,MAAM,WAAW,GAAyD,EAAE,CAAC;QAC7E,MAAM,YAAY,GAAa,EAAE,CAAC;QAClC,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,UAAU,EAAE;YAC3C,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC;gBACrB,OAAO,CAAC,GAAG,EAAE,QAAQ;oBACnB,IAAI,GAAG,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;wBAC5B,QAAQ,CAAC,WAAW,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;wBACpG,OAAO,UAAU,CAAC,OAAO,CAAC;oBAC5B,CAAC;oBACD,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAC;gBACxF,CAAC;aACF,CAAC;YACF,QAAQ,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE;gBACzB,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;gBAClD,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;YAC3B,CAAC;YACD,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE;YAClC,gBAAgB,EAAE,GAAG;SACtB,CAAC,CAAC;QAEH,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;QACzF,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;QACxB,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3F,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;QACxB,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;QAExD,MAAM,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;QACpF,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QACzC,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC;YAC1B,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,iBAAiB,EAAE,EAAE;SAC7F,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,WAAW,GAAuB,EAAE,CAAC;QAC3C,MAAM,YAAY,GAAa,EAAE,CAAC;QAClC,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,UAAU,EAAE;YAC3C,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC;gBACrB,OAAO,CAAC,GAAG,EAAE,QAAQ;oBACnB,OAAO,IAAI,OAAO,CAAmB,CAAC,OAAO,EAAE,EAAE;wBAC/C,QAAQ,CAAC,WAAW,CAAC,gBAAgB,CACnC,OAAO,EACP,GAAG,EAAE;4BACH,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;4BAC9B,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;wBAC7C,CAAC,EACD,EAAE,IAAI,EAAE,IAAI,EAAE,CACf,CAAC;oBACJ,CAAC,CAAC,CAAC;gBACL,CAAC;aACF,CAAC;YACF,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE;gBACpB,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC1B,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;YAC3B,CAAC;YACD,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE;YAClC,aAAa,EAAE,CAAC;YAChB,kBAAkB,EAAE,CAAC;SACtB,CAAC,CAAC;QAEH,MAAM,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QAElH,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QACzC,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;QACpE,MAAM,aAAa,GAAG,QAAQ,EAA0B,CAAC;QACzD,MAAM,QAAQ,GAAyB;YACrC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ;gBAC1B,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,EAAE;oBACtC,OAAO,EAAE,aAAa,CAAC,OAAO;oBAC9B,MAAM,EAAE,aAAa,CAAC,MAAM;iBAC7B,CAAC,CAAC;gBACH,MAAM,aAAa,CAAC,OAAO,CAAC;gBAC5B,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;YAC3C,CAAC;SACF,CAAC;QACF,MAAM,WAAW,GAAuB,EAAE,CAAC;QAC3C,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,UAAU,EAAE;YAC3C,cAAc,EAAE,GAAG,EAAE,CAAC,QAAQ;YAC9B,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE;gBACpB,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC1B,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;YAC3B,CAAC;YACD,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE;SACnC,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;QAC9F,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;QAExB,OAAO,CAAC,KAAK,EAAE,CAAC;QAEhB,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QAC/C,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,IAAI,GAAG,GAAG,KAAK,CAAC;QAChB,MAAM,QAAQ,GAAG,IAAI,oBAAoB,CAAC;YACxC,aAAa,EAAE,CAAC,QAAQ,EAAE,EAAE,CAC1B,IAAI,YAAY,CAAC,QAAQ,EAAE;gBACzB,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;gBAC7F,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE;gBACjC,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE;gBAClC,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG;aACf,CAAC;YACJ,SAAS,EAAE,GAAG;YACd,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG;SACf,CAAC,CAAC;QAEH,MAAM,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QACpC,MAAM,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAClC,GAAG,GAAG,KAAK,CAAC;QACZ,MAAM,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QACpC,GAAG,GAAG,KAAK,CAAC;QAEZ,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAExB,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/hono/agent.d.ts
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
33
|
-
private
|
|
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<
|
|
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 {};
|
package/dist/hono/agent.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/hono/agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
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"}
|