agenthub-multiagent-mcp 1.51.0 → 1.53.0
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 +192 -192
- package/dist/captureHookInstall.d.ts +127 -0
- package/dist/captureHookInstall.d.ts.map +1 -0
- package/dist/captureHookInstall.js +256 -0
- package/dist/captureHookInstall.js.map +1 -0
- package/dist/captureHookInstall.test.d.ts +10 -0
- package/dist/captureHookInstall.test.d.ts.map +1 -0
- package/dist/captureHookInstall.test.js +325 -0
- package/dist/captureHookInstall.test.js.map +1 -0
- package/dist/channel.js +99 -3
- package/dist/channel.js.map +1 -1
- package/dist/client.d.ts +80 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +197 -4
- package/dist/client.js.map +1 -1
- package/dist/client.unit.test.js +50 -0
- package/dist/client.unit.test.js.map +1 -1
- package/dist/daemon.js +217 -3
- package/dist/daemon.js.map +1 -1
- package/dist/hooks/periodicReminder.js +9 -9
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -1
- package/dist/session-capture.sh +410 -0
- package/dist/sessionCapture.d.ts +163 -0
- package/dist/sessionCapture.d.ts.map +1 -0
- package/dist/sessionCapture.js +279 -0
- package/dist/sessionCapture.js.map +1 -0
- package/dist/sessionCapture.test.d.ts +9 -0
- package/dist/sessionCapture.test.d.ts.map +1 -0
- package/dist/sessionCapture.test.js +366 -0
- package/dist/sessionCapture.test.js.map +1 -0
- package/dist/sessionCaptureScript.test.d.ts +16 -0
- package/dist/sessionCaptureScript.test.d.ts.map +1 -0
- package/dist/sessionCaptureScript.test.js +92 -0
- package/dist/sessionCaptureScript.test.js.map +1 -0
- package/dist/setup.js +56 -56
- package/dist/steering.test.d.ts +2 -0
- package/dist/steering.test.d.ts.map +1 -0
- package/dist/steering.test.js +223 -0
- package/dist/steering.test.js.map +1 -0
- package/dist/streamingRuntimeLib.d.ts +391 -0
- package/dist/streamingRuntimeLib.d.ts.map +1 -0
- package/dist/streamingRuntimeLib.js +628 -0
- package/dist/streamingRuntimeLib.js.map +1 -0
- package/dist/streamingRuntimeLib.test.d.ts +2 -0
- package/dist/streamingRuntimeLib.test.d.ts.map +1 -0
- package/dist/streamingRuntimeLib.test.js +233 -0
- package/dist/streamingRuntimeLib.test.js.map +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +149 -13
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/openspec-viz/diagram-generator.js +54 -54
- package/dist/tools/openspec-viz/html-generator.js +503 -503
- package/dist/tools/sessionControl.d.ts +53 -0
- package/dist/tools/sessionControl.d.ts.map +1 -0
- package/dist/tools/sessionControl.js +265 -0
- package/dist/tools/sessionControl.js.map +1 -0
- package/dist/tools/sessionControl.test.d.ts +14 -0
- package/dist/tools/sessionControl.test.d.ts.map +1 -0
- package/dist/tools/sessionControl.test.js +298 -0
- package/dist/tools/sessionControl.test.js.map +1 -0
- package/dist/tools/tools.test.js +5 -2
- package/dist/tools/tools.test.js.map +1 -1
- package/dist/tools/zohoAttachments.test.d.ts +10 -0
- package/dist/tools/zohoAttachments.test.d.ts.map +1 -0
- package/dist/tools/zohoAttachments.test.js +204 -0
- package/dist/tools/zohoAttachments.test.js.map +1 -0
- package/dist/worker.js +10 -10
- package/native/agenthub-memvid/agenthub-memvid.linux-x64-gnu.node +0 -0
- package/native/agenthub-memvid/index.d.ts +58 -58
- package/native/agenthub-memvid/index.js +319 -319
- package/package.json +77 -77
- package/skills/catalog.json +76 -76
- package/skills/commands/close-session.md +144 -144
- package/skills/manifest.json +50 -50
- package/skills/skills/code-brain-hook/SKILL.md +61 -61
- package/skills/skills/file-bug/SKILL.md +75 -75
- package/skills/skills/multiagent-brainstorm/SKILL.md +142 -142
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure helpers for the employee streaming runtime (add-employee-streaming-runtime).
|
|
3
|
+
*
|
|
4
|
+
* Extracted from streamingRuntime.ts so the auth assert, inbound-message decision
|
|
5
|
+
* (self-filter / non-actionable / dedup), turn rendering, and context-recycle
|
|
6
|
+
* decision are unit-testable without an SDK subprocess or a live WebSocket.
|
|
7
|
+
*
|
|
8
|
+
* Verified premise (VPS spike 2026-06-26, org brain #2209): the Claude Agent SDK
|
|
9
|
+
* streaming mode runs on the subscription (CLAUDE_CODE_OAUTH_TOKEN, no
|
|
10
|
+
* ANTHROPIC_API_KEY) and processes a mid-run yielded message in the same session.
|
|
11
|
+
*
|
|
12
|
+
* ---------------------------------------------------------------------------
|
|
13
|
+
* CANONICAL COPY — `employee-runtime/src/streamingRuntimeLib.ts` is vendored
|
|
14
|
+
* from this file and must stay **functionally** in sync (add-multiplayer-sessions
|
|
15
|
+
* §2.4). Change one, change the other in the same commit.
|
|
16
|
+
*
|
|
17
|
+
* Why two copies rather than an import: `employee-runtime` is a separate package
|
|
18
|
+
* precisely because the agent-sdk's peer deps conflict with this package's, so it
|
|
19
|
+
* cannot depend on `agenthub-multiagent-mcp`. The daemon side imports this copy
|
|
20
|
+
* (for the `streamingEnabled()` gate); the runtime imports the vendored one.
|
|
21
|
+
*
|
|
22
|
+
* The two headers differ, and the vendored copy carries fewer prose comments;
|
|
23
|
+
* everything below the header is expected to be identical. Keep it import-free —
|
|
24
|
+
* pure logic only — so neither copy drags a package-specific dependency across.
|
|
25
|
+
* ---------------------------------------------------------------------------
|
|
26
|
+
*/
|
|
27
|
+
export interface AgentMessage {
|
|
28
|
+
id: string;
|
|
29
|
+
from_agent: string;
|
|
30
|
+
to_agent?: string;
|
|
31
|
+
type?: string;
|
|
32
|
+
subject?: string;
|
|
33
|
+
body: string;
|
|
34
|
+
priority?: string;
|
|
35
|
+
}
|
|
36
|
+
/** A handled-id lookup (the surface of HandledMessageStore we depend on). */
|
|
37
|
+
export interface HandledLookup {
|
|
38
|
+
has(id: string): boolean;
|
|
39
|
+
}
|
|
40
|
+
/** §2.1 — the streaming runtime is OFF unless explicitly enabled. */
|
|
41
|
+
export declare function streamingEnabled(env?: NodeJS.ProcessEnv): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Human steering kill switch (add-multiplayer-sessions §4.8). Default **off** —
|
|
44
|
+
* unset, empty, or unrecognised means disabled, and while it is off the producer
|
|
45
|
+
* side does no I/O at all: no transport is declared, nothing is polled, and the
|
|
46
|
+
* runtime loop is what it was before this feature existed.
|
|
47
|
+
*
|
|
48
|
+
* It lives here rather than in a runtime-only module because both producers
|
|
49
|
+
* consult it: the streaming runtime (which declares `turn_queue` and pulls
|
|
50
|
+
* steers) and the one-shot daemon (which declares `one_shot` so its shifts are
|
|
51
|
+
* refused explicitly rather than by accident of having declared nothing).
|
|
52
|
+
* Mirrors the server's `AGENTHUB_SESSION_STEER_ENABLED`; a producer that polled
|
|
53
|
+
* while the server had it off would earn a 503 on every tick.
|
|
54
|
+
*/
|
|
55
|
+
export declare function sessionSteerEnabled(env?: NodeJS.ProcessEnv): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* §D3 — assert subscription auth and fail CLOSED against metered billing. The
|
|
58
|
+
* SDK subprocess inherits the env; if ANTHROPIC_API_KEY were set it would take
|
|
59
|
+
* precedence over the subscription token, so we refuse to start.
|
|
60
|
+
*/
|
|
61
|
+
export declare function assertSubscriptionAuth(env?: NodeJS.ProcessEnv): {
|
|
62
|
+
oauthToken: string;
|
|
63
|
+
};
|
|
64
|
+
export interface InboundDecision {
|
|
65
|
+
/** Whether this event should be yielded into the session as a turn. */
|
|
66
|
+
yield: boolean;
|
|
67
|
+
reason?: "not-a-message" | "no-id" | "self" | "non-actionable" | "duplicate";
|
|
68
|
+
message?: AgentMessage;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Decide whether a raw WS event becomes a session turn. Mirrors the one-shot
|
|
72
|
+
* daemon's at-most-once guards: ignore self-messages, never auto-act on
|
|
73
|
+
* `response`/`status` (loop-safety), and dedup against handled ids. The caller
|
|
74
|
+
* ACKs regardless and records handled ids.
|
|
75
|
+
*/
|
|
76
|
+
export declare function decideInbound(envelope: unknown, agentId: string, handled: HandledLookup): InboundDecision;
|
|
77
|
+
/**
|
|
78
|
+
* The message type a human steer arrives as. Mirrors `sessions.SteerMessageType`
|
|
79
|
+
* on the server, which validates it on the way in — an unrecognised type would be
|
|
80
|
+
* persisted and then framed by whatever branch this function fell through to,
|
|
81
|
+
* which is the same silent-wrong-behaviour class as a dropped steer.
|
|
82
|
+
*/
|
|
83
|
+
export declare const STEER_MESSAGE_TYPE = "steer";
|
|
84
|
+
/**
|
|
85
|
+
* Render an AgentHub message as the text content of a session turn.
|
|
86
|
+
*
|
|
87
|
+
* Two framings, and the distinction is the whole point of §4.3. An inbox message
|
|
88
|
+
* is agent-to-agent: somebody is waiting on an answer, so the turn tells the
|
|
89
|
+
* model to answer with `mcp__agenthub__reply`. A steer is a human leaning over
|
|
90
|
+
* the session and redirecting the work: nobody is waiting on a message, and
|
|
91
|
+
* telling the model to reply would turn "stop rewriting that file" into a note
|
|
92
|
+
* written back to the person who typed it while the work carried on unchanged.
|
|
93
|
+
*/
|
|
94
|
+
export declare function buildTurnContent(m: AgentMessage): string;
|
|
95
|
+
/**
|
|
96
|
+
* Frame a steer as what it is: a direct instruction from a human operator
|
|
97
|
+
* watching this session (§4.3).
|
|
98
|
+
*
|
|
99
|
+
* Deliberately parallel to `buildInstructionTurnContent` in `workstation.ts`,
|
|
100
|
+
* which solves the same problem for a driven personal workspace. Both say the
|
|
101
|
+
* same three things, because all three are load-bearing: who this came from, that
|
|
102
|
+
* it is an instruction rather than correspondence, and that no reply is wanted.
|
|
103
|
+
* The refusal clause is here for the same reason it is there — a human can steer
|
|
104
|
+
* a session into something the agent should not do, and "say so and stop" is a
|
|
105
|
+
* better outcome than either silent compliance or silent refusal.
|
|
106
|
+
*/
|
|
107
|
+
export declare function buildSteerTurnContent(m: AgentMessage): string;
|
|
108
|
+
/** A `session_steer` frame pushed over the per-agent WebSocket. */
|
|
109
|
+
export interface SteerFrame {
|
|
110
|
+
sessionId: string;
|
|
111
|
+
steerId: string;
|
|
112
|
+
text: string;
|
|
113
|
+
createdBy: string;
|
|
114
|
+
messageType: string;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Parse a `session_steer` WebSocket frame (the channel transport's delivery
|
|
118
|
+
* path). Returns `null` for anything that is not a well-formed steer.
|
|
119
|
+
*
|
|
120
|
+
* Lives here rather than in the channel plugin because the plugin is an
|
|
121
|
+
* executable script — importing it to test it would start an MCP server — and
|
|
122
|
+
* because the frame is a wire contract shared with the server, which is the kind
|
|
123
|
+
* of thing that should have one parser and one test.
|
|
124
|
+
*
|
|
125
|
+
* A frame missing an id or text is `null` rather than a partially-populated
|
|
126
|
+
* steer: an instruction with no text delivers nothing, and one with no id cannot
|
|
127
|
+
* be acked, so "deliver it anyway" would produce exactly the accepted-and-dropped
|
|
128
|
+
* outcome the whole transport contract exists to rule out.
|
|
129
|
+
*/
|
|
130
|
+
export declare function parseSteerFrame(envelope: unknown): SteerFrame | null;
|
|
131
|
+
/** The SDK streaming-input user message shape (proven in the spike). */
|
|
132
|
+
export interface SDKUserTurn {
|
|
133
|
+
type: "user";
|
|
134
|
+
message: {
|
|
135
|
+
role: "user";
|
|
136
|
+
content: string;
|
|
137
|
+
};
|
|
138
|
+
parent_tool_use_id: null;
|
|
139
|
+
session_id: string;
|
|
140
|
+
}
|
|
141
|
+
export declare function toUserTurn(content: string, sessionId: string): SDKUserTurn;
|
|
142
|
+
export interface RecycleOptions {
|
|
143
|
+
/** Recycle the session after this many turns. */
|
|
144
|
+
maxTurns: number;
|
|
145
|
+
/** Recycle once cumulative input tokens cross this budget. */
|
|
146
|
+
tokenBudget: number;
|
|
147
|
+
}
|
|
148
|
+
export interface RecycleState {
|
|
149
|
+
turns: number;
|
|
150
|
+
estInputTokens: number;
|
|
151
|
+
}
|
|
152
|
+
export declare function defaultRecycleOptions(env?: NodeJS.ProcessEnv): RecycleOptions;
|
|
153
|
+
/**
|
|
154
|
+
* §D4 — recycle the kept-alive session once it has run enough turns or
|
|
155
|
+
* accumulated enough input-token context, to bound Max-cap consumption. The
|
|
156
|
+
* caller starts a fresh session (carrying a short summary) on `true`.
|
|
157
|
+
*/
|
|
158
|
+
export declare function shouldRecycle(state: RecycleState, opts: RecycleOptions): boolean;
|
|
159
|
+
/**
|
|
160
|
+
* Cumulative counters for one runtime process. Unlike RecycleState (which resets
|
|
161
|
+
* per session to drive the recycle threshold), these survive session recycles and
|
|
162
|
+
* describe the employee's whole run — surfaced via a `/usage`-style log line for
|
|
163
|
+
* operators and the trainer.
|
|
164
|
+
*/
|
|
165
|
+
export interface RuntimeStats {
|
|
166
|
+
turns: number;
|
|
167
|
+
estInputTokens: number;
|
|
168
|
+
estOutputTokens: number;
|
|
169
|
+
sessionRecycles: number;
|
|
170
|
+
reconnects: number;
|
|
171
|
+
dedupHits: number;
|
|
172
|
+
}
|
|
173
|
+
export declare function newRuntimeStats(): RuntimeStats;
|
|
174
|
+
/**
|
|
175
|
+
* Fold one SDK `result` message's usage into the cumulative stats (mutates + returns).
|
|
176
|
+
* estInputTokens counts fresh + cache-read + cache-creation input (matching the
|
|
177
|
+
* recycle accounting); estOutputTokens is the generated output.
|
|
178
|
+
*/
|
|
179
|
+
export declare function recordResultUsage(stats: RuntimeStats, usage: Record<string, number> | undefined): RuntimeStats;
|
|
180
|
+
/**
|
|
181
|
+
* A `/usage`-style structured one-liner for the runtime log — a single greppable
|
|
182
|
+
* line (log-exporter / Loki friendly). Native Prometheus is deliberately deferred
|
|
183
|
+
* (§4.2): the one-shot daemon exposes no metrics series to mirror, so a scrapable
|
|
184
|
+
* log line is the sensible surface for a default-off feature.
|
|
185
|
+
*/
|
|
186
|
+
export declare function formatUsageLine(agentId: string, stats: RuntimeStats, uptimeSec: number): string;
|
|
187
|
+
export interface InSessionMcpEnvOpts {
|
|
188
|
+
apiUrl: string;
|
|
189
|
+
apiKey: string;
|
|
190
|
+
agentId: string;
|
|
191
|
+
userApiKey?: string;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Env for the in-session MCP the streaming runtime launches. Critically sets
|
|
195
|
+
* `AGENTHUB_HEADLESS=true`: without it, a failed startup reconnect routes the
|
|
196
|
+
* model to `agent_register`, which polls a browser-confirm flow for 10 min
|
|
197
|
+
* (3000ms × 200) that nobody can complete in a headless SDK subprocess — the
|
|
198
|
+
* observed ~7-min stall (§3). Headless routes `agent_register` to the fast,
|
|
199
|
+
* non-interactive register instead. A user API key (when the daemon has one) is
|
|
200
|
+
* passed through so any such fallback register is coherent and user-owned rather
|
|
201
|
+
* than a browser round-trip.
|
|
202
|
+
*/
|
|
203
|
+
export declare function inSessionMcpEnv(opts: InSessionMcpEnvOpts): Record<string, string>;
|
|
204
|
+
/**
|
|
205
|
+
* Fail-fast identity guard the runtime previously lacked. The daemon establishes
|
|
206
|
+
* the worker connect token in the workspace's `.agenthub/state` before handing
|
|
207
|
+
* off (and reconnect is a pure re-attach server-side, so the in-session MCP
|
|
208
|
+
* safely shares it). If that state is absent the hand-off is broken; refuse to
|
|
209
|
+
* start sessions (throw → `main()` exits non-zero → the daemon restarts and
|
|
210
|
+
* re-heals identity) rather than letting the in-session MCP hang on registration.
|
|
211
|
+
*/
|
|
212
|
+
export declare function assertWorkerIdentityReady(stateExists: boolean, agentId: string): void;
|
|
213
|
+
/**
|
|
214
|
+
* One row of `POST /api/sessions/{id}/events`.
|
|
215
|
+
*
|
|
216
|
+
* `payload` is a JSON **string**, not an object — that is the wire contract the
|
|
217
|
+
* server and `session-capture.sh` already share, and the dashboard `JSON.parse`s
|
|
218
|
+
* it per event. Do not "improve" it into a nested object; both producers and the
|
|
219
|
+
* reader would have to change together.
|
|
220
|
+
*/
|
|
221
|
+
export interface SessionEvent {
|
|
222
|
+
event_type: string;
|
|
223
|
+
payload: string;
|
|
224
|
+
token_count: number;
|
|
225
|
+
}
|
|
226
|
+
/** One content block inside an SDK message. Every field optional — see SDKStreamMessage. */
|
|
227
|
+
export interface SDKContentBlock {
|
|
228
|
+
type?: string;
|
|
229
|
+
/** `text` blocks */
|
|
230
|
+
text?: string;
|
|
231
|
+
/** `tool_use` blocks */
|
|
232
|
+
id?: string;
|
|
233
|
+
name?: string;
|
|
234
|
+
input?: unknown;
|
|
235
|
+
/** `tool_result` blocks */
|
|
236
|
+
tool_use_id?: string;
|
|
237
|
+
content?: unknown;
|
|
238
|
+
is_error?: boolean;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Structural view of one Agent SDK stream message (§2.1).
|
|
242
|
+
*
|
|
243
|
+
* The runtime loop used to cast the stream to `{ type?, usage? }`, which is why
|
|
244
|
+
* assistant text and tool traffic were never observable: the content was not
|
|
245
|
+
* modelled, so there was nothing downstream to read. This widens the model to
|
|
246
|
+
* the parts we consume.
|
|
247
|
+
*
|
|
248
|
+
* Deliberately structural rather than the SDK's own `SDKMessage`: this module is
|
|
249
|
+
* vendored into the mcp-server package, which does not (and must not) depend on
|
|
250
|
+
* `@anthropic-ai/claude-agent-sdk`. Every field is optional so an unrecognised
|
|
251
|
+
* or newly-added SDK message shape degrades to "no events" instead of throwing
|
|
252
|
+
* inside the runtime's hot loop.
|
|
253
|
+
*/
|
|
254
|
+
export interface SDKStreamMessage {
|
|
255
|
+
type?: string;
|
|
256
|
+
usage?: Record<string, number>;
|
|
257
|
+
message?: {
|
|
258
|
+
role?: string;
|
|
259
|
+
content?: string | SDKContentBlock[];
|
|
260
|
+
};
|
|
261
|
+
parent_tool_use_id?: string | null;
|
|
262
|
+
session_id?: string;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Client-side payload bounds. The server is authoritative for truncation and
|
|
266
|
+
* redaction (add-multiplayer-sessions §1.8/§1.9) and this code deliberately does
|
|
267
|
+
* **not** duplicate either. These bounds exist only so a single event is never
|
|
268
|
+
* megabytes on the wire; they mirror `session-capture.sh`'s TRUNC / TRUNC_SHORT
|
|
269
|
+
* so both producers put comparable volumes in front of the same server pipeline.
|
|
270
|
+
*/
|
|
271
|
+
export declare const PAYLOAD_MAX_CHARS = 8000;
|
|
272
|
+
export declare const PAYLOAD_SUMMARY_MAX_CHARS = 1000;
|
|
273
|
+
/**
|
|
274
|
+
* Turn SDK stream messages into session events (§2.2).
|
|
275
|
+
*
|
|
276
|
+
* The event vocabulary is exactly the one `session-capture.sh` already produces
|
|
277
|
+
* (`assistant_message`, `command_exec`, `file_read`, `file_edit`, `file_write`,
|
|
278
|
+
* `tool_call`) so the dashboard renders hook-captured and runtime-captured
|
|
279
|
+
* sessions identically. No new event types are introduced here.
|
|
280
|
+
*
|
|
281
|
+
* One deliberate difference from the hook: the hook runs PostToolUse and so sees
|
|
282
|
+
* a tool's input and response together, emitting a single merged event. The
|
|
283
|
+
* stream delivers them as two separate messages (`tool_use` on the assistant
|
|
284
|
+
* message, `tool_result` on the following user message), so this emits two
|
|
285
|
+
* events. The class is stateful only to carry `tool_use_id → tool name` across
|
|
286
|
+
* that gap, so the result event can name the tool it belongs to. The map is
|
|
287
|
+
* bounded: a long session must not accumulate ids forever.
|
|
288
|
+
*/
|
|
289
|
+
export declare class SessionEventExtractor {
|
|
290
|
+
private readonly toolNames;
|
|
291
|
+
private readonly maxCorrelations;
|
|
292
|
+
constructor(maxCorrelations?: number);
|
|
293
|
+
extract(message: unknown): SessionEvent[];
|
|
294
|
+
private blocks;
|
|
295
|
+
private fromAssistant;
|
|
296
|
+
private fromToolResults;
|
|
297
|
+
private rememberTool;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* The I/O the emitter needs, injected so the batching/lifecycle logic below is
|
|
301
|
+
* testable without a server and so this module stays free of transport imports
|
|
302
|
+
* (it is vendored into a package that has no session-capture client).
|
|
303
|
+
*/
|
|
304
|
+
export interface SessionEventTransport {
|
|
305
|
+
/** Create the coding session events are recorded under. `null` → run uncaptured. */
|
|
306
|
+
open(): Promise<string | null>;
|
|
307
|
+
post(sessionId: string, events: readonly SessionEvent[]): Promise<void>;
|
|
308
|
+
close(sessionId: string, reason: string): Promise<void>;
|
|
309
|
+
}
|
|
310
|
+
export interface SessionEventEmitterOptions {
|
|
311
|
+
transport: SessionEventTransport;
|
|
312
|
+
/** `false` → a hard no-op: no session is opened and nothing is posted. */
|
|
313
|
+
enabled: boolean;
|
|
314
|
+
/** Flush as soon as this many events are pending. */
|
|
315
|
+
maxBatch?: number;
|
|
316
|
+
/** Flush a partial batch after this long, so a quiet session still streams. */
|
|
317
|
+
flushIntervalMs?: number;
|
|
318
|
+
/** Hard bound on the unsent backlog; events beyond it are dropped, not buffered. */
|
|
319
|
+
maxPending?: number;
|
|
320
|
+
/**
|
|
321
|
+
* Called once, with the session id, the moment the captured session is created.
|
|
322
|
+
*
|
|
323
|
+
* Exists because the open is lazy (see below): the session id does not exist at
|
|
324
|
+
* construction, so anything that needs it — steering declares its transport
|
|
325
|
+
* here (§4.5) — would otherwise have to poll `currentSessionId`. A callback is
|
|
326
|
+
* the earliest that id can possibly be known, and "as early as the session id
|
|
327
|
+
* is known" is the requirement.
|
|
328
|
+
*
|
|
329
|
+
* A throwing listener is caught and logged: capture must not be breakable by a
|
|
330
|
+
* consumer of its lifecycle.
|
|
331
|
+
*/
|
|
332
|
+
onOpen?: (sessionId: string) => void;
|
|
333
|
+
log?: (msg: string) => void;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Batches session events and owns the captured session's lifecycle (§2.3).
|
|
337
|
+
*
|
|
338
|
+
* Why batching: a chatty turn emits an event per text block and per tool call.
|
|
339
|
+
* One HTTP request each would put the runtime's throughput at the mercy of
|
|
340
|
+
* network latency and would trip the server's per-session rate cap on volume
|
|
341
|
+
* that is really one turn. Events are flushed when `maxBatch` accumulates, when
|
|
342
|
+
* `flushIntervalMs` elapses, and unconditionally at turn end and session end, so
|
|
343
|
+
* the tail of a conversation is never left sitting in the buffer.
|
|
344
|
+
*
|
|
345
|
+
* Why lazy open: the session is created on the first event rather than at
|
|
346
|
+
* construction, so an idle employee (the common case — the runtime blocks on the
|
|
347
|
+
* turn queue) creates nothing, and a runtime that crash-loops before producing
|
|
348
|
+
* output does not create a session per retry.
|
|
349
|
+
*
|
|
350
|
+
* Everything here is fail-soft, matching `sessionCapture.ts`: a failed create
|
|
351
|
+
* degrades the whole session to uncaptured (`failed` state, no retry storm), a
|
|
352
|
+
* failed post drops that batch, and no method ever throws. Capture is
|
|
353
|
+
* observability; it must never take down real work.
|
|
354
|
+
*/
|
|
355
|
+
export declare class SessionEventEmitter {
|
|
356
|
+
private readonly transport;
|
|
357
|
+
private readonly enabled;
|
|
358
|
+
private readonly maxBatch;
|
|
359
|
+
private readonly flushIntervalMs;
|
|
360
|
+
private readonly maxPending;
|
|
361
|
+
private readonly onOpen;
|
|
362
|
+
private readonly log;
|
|
363
|
+
private pending;
|
|
364
|
+
private state;
|
|
365
|
+
private openSessionId;
|
|
366
|
+
private timer;
|
|
367
|
+
private chain;
|
|
368
|
+
private dropped;
|
|
369
|
+
private dropWarned;
|
|
370
|
+
constructor(opts: SessionEventEmitterOptions);
|
|
371
|
+
/** The session events are being recorded under, or `null` before/after capture. */
|
|
372
|
+
get currentSessionId(): string | null;
|
|
373
|
+
get pendingCount(): number;
|
|
374
|
+
get droppedCount(): number;
|
|
375
|
+
/** Queue events. Synchronous and non-throwing — safe to call from the stream loop. */
|
|
376
|
+
emit(events: readonly SessionEvent[]): void;
|
|
377
|
+
/** Send everything pending now. Awaits the in-flight post; never throws. */
|
|
378
|
+
flush(): Promise<void>;
|
|
379
|
+
/**
|
|
380
|
+
* Flush the tail and close the captured session. After this the emitter is
|
|
381
|
+
* inert — a late `emit` from a straggling stream message is discarded rather
|
|
382
|
+
* than reopening a session nobody is watching.
|
|
383
|
+
*/
|
|
384
|
+
end(reason: string): Promise<void>;
|
|
385
|
+
private schedule;
|
|
386
|
+
private clearTimer;
|
|
387
|
+
/** Serialized: posts must not race, or the server assigns sequence numbers out of order. */
|
|
388
|
+
private drain;
|
|
389
|
+
private drainOnce;
|
|
390
|
+
}
|
|
391
|
+
//# sourceMappingURL=streamingRuntimeLib.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streamingRuntimeLib.d.ts","sourceRoot":"","sources":["../src/streamingRuntimeLib.ts"],"names":[],"mappings":"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"}
|