agentfootprint 9.6.0 → 9.7.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/AGENTS.md +1 -1
- package/CLAUDE.md +1 -1
- package/ai-instructions/claude-code/SKILL.md +1 -1
- package/dist/adapters/code/agentcore.js +294 -0
- package/dist/adapters/code/agentcore.js.map +1 -0
- package/dist/adapters/code/local.js +200 -0
- package/dist/adapters/code/local.js.map +1 -0
- package/dist/core/Agent.js +132 -0
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/RunnerBase.js +67 -0
- package/dist/core/RunnerBase.js.map +1 -1
- package/dist/core/agent/stages/toolCalls.js +90 -0
- package/dist/core/agent/stages/toolCalls.js.map +1 -1
- package/dist/core/codeRunnerTool.js +252 -0
- package/dist/core/codeRunnerTool.js.map +1 -0
- package/dist/core/toolSessions.js +396 -0
- package/dist/core/toolSessions.js.map +1 -0
- package/dist/core/tools.js.map +1 -1
- package/dist/doors/providers.js +13 -0
- package/dist/doors/providers.js.map +1 -1
- package/dist/esm/adapters/code/agentcore.d.ts +133 -0
- package/dist/esm/adapters/code/agentcore.js +290 -0
- package/dist/esm/adapters/code/agentcore.js.map +1 -0
- package/dist/esm/adapters/code/local.d.ts +99 -0
- package/dist/esm/adapters/code/local.js +196 -0
- package/dist/esm/adapters/code/local.js.map +1 -0
- package/dist/esm/adapters/types.d.ts +87 -0
- package/dist/esm/core/Agent.d.ts +65 -0
- package/dist/esm/core/Agent.js +133 -1
- package/dist/esm/core/Agent.js.map +1 -1
- package/dist/esm/core/RunnerBase.d.ts +51 -0
- package/dist/esm/core/RunnerBase.js +67 -0
- package/dist/esm/core/RunnerBase.js.map +1 -1
- package/dist/esm/core/agent/stages/toolCalls.d.ts +31 -0
- package/dist/esm/core/agent/stages/toolCalls.js +90 -0
- package/dist/esm/core/agent/stages/toolCalls.js.map +1 -1
- package/dist/esm/core/agent/types.d.ts +23 -2
- package/dist/esm/core/codeRunnerTool.d.ts +120 -0
- package/dist/esm/core/codeRunnerTool.js +247 -0
- package/dist/esm/core/codeRunnerTool.js.map +1 -0
- package/dist/esm/core/toolSessions.d.ts +318 -0
- package/dist/esm/core/toolSessions.js +389 -0
- package/dist/esm/core/toolSessions.js.map +1 -0
- package/dist/esm/core/tools.d.ts +60 -0
- package/dist/esm/core/tools.js.map +1 -1
- package/dist/esm/doors/providers.d.ts +7 -0
- package/dist/esm/doors/providers.js +10 -0
- package/dist/esm/doors/providers.js.map +1 -1
- package/dist/esm/events/payloads.d.ts +50 -0
- package/dist/esm/events/registry.d.ts +9 -1
- package/dist/esm/events/registry.js +8 -0
- package/dist/esm/events/registry.js.map +1 -1
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/mcp/mcpServe.js +37 -1
- package/dist/esm/lib/mcp/mcpServe.js.map +1 -1
- package/dist/esm/lib/trace-toolpack/traceToolpack.js +15 -1
- package/dist/esm/lib/trace-toolpack/traceToolpack.js.map +1 -1
- package/dist/events/registry.js +8 -0
- package/dist/events/registry.js.map +1 -1
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/mcp/mcpServe.js +37 -1
- package/dist/lib/mcp/mcpServe.js.map +1 -1
- package/dist/lib/trace-toolpack/traceToolpack.js +15 -1
- package/dist/lib/trace-toolpack/traceToolpack.js.map +1 -1
- package/dist/types/adapters/code/agentcore.d.ts +134 -0
- package/dist/types/adapters/code/agentcore.d.ts.map +1 -0
- package/dist/types/adapters/code/local.d.ts +100 -0
- package/dist/types/adapters/code/local.d.ts.map +1 -0
- package/dist/types/adapters/types.d.ts +87 -0
- package/dist/types/adapters/types.d.ts.map +1 -1
- package/dist/types/core/Agent.d.ts +65 -0
- package/dist/types/core/Agent.d.ts.map +1 -1
- package/dist/types/core/RunnerBase.d.ts +51 -0
- package/dist/types/core/RunnerBase.d.ts.map +1 -1
- package/dist/types/core/agent/stages/toolCalls.d.ts +31 -0
- package/dist/types/core/agent/stages/toolCalls.d.ts.map +1 -1
- package/dist/types/core/agent/types.d.ts +23 -2
- package/dist/types/core/agent/types.d.ts.map +1 -1
- package/dist/types/core/codeRunnerTool.d.ts +121 -0
- package/dist/types/core/codeRunnerTool.d.ts.map +1 -0
- package/dist/types/core/toolSessions.d.ts +319 -0
- package/dist/types/core/toolSessions.d.ts.map +1 -0
- package/dist/types/core/tools.d.ts +60 -0
- package/dist/types/core/tools.d.ts.map +1 -1
- package/dist/types/doors/providers.d.ts +7 -0
- package/dist/types/doors/providers.d.ts.map +1 -1
- package/dist/types/events/payloads.d.ts +50 -0
- package/dist/types/events/payloads.d.ts.map +1 -1
- package/dist/types/events/registry.d.ts +9 -1
- package/dist/types/events/registry.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/lib/mcp/mcpServe.d.ts.map +1 -1
- package/dist/types/lib/trace-toolpack/traceToolpack.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* toolSessions — the end-signal a tool can be handed, and the tier that fires it.
|
|
3
|
+
*
|
|
4
|
+
* Pattern: Registrar + Template Method for the firing matrix.
|
|
5
|
+
* Role: core primitive. `ToolExecutionContext.onTeardown` registers here;
|
|
6
|
+
* `Agent.run`'s terminals, `RunnerBase.closeToolSessions` and
|
|
7
|
+
* `RunnerBase.shutdown` fire it.
|
|
8
|
+
* Emits: nothing itself. `register()` ANSWERS what it did (started/reused) so
|
|
9
|
+
* the caller — still inside a stage — can emit with a real
|
|
10
|
+
* `runtimeStageId`, and teardown REPORTS (see {@link ToolSessionReport})
|
|
11
|
+
* so the runner can emit the two that fire after the last stage.
|
|
12
|
+
*
|
|
13
|
+
* ── The gap this closes ─────────────────────────────────────────────────────
|
|
14
|
+
* A session-based tool service (a managed code interpreter, a headless browser)
|
|
15
|
+
* is Start → Invoke ×N → Stop. Before 9.7.0 a `Tool` had nowhere to hold the
|
|
16
|
+
* middle of that: `ToolExecutionContext` carried no run or session identity, and
|
|
17
|
+
* nothing in the framework ever said "this is over". So a tool either paid
|
|
18
|
+
* start-up on every call, or held the session in a module-level map — which, in
|
|
19
|
+
* a standing agent serving many people from one process, hands ONE live sandbox
|
|
20
|
+
* to whoever calls next. That is not a leak of memory; it is a leak of a
|
|
21
|
+
* filesystem, an environment and half-run state, across users.
|
|
22
|
+
*
|
|
23
|
+
* ── Why the registration lives on the CONTEXT ───────────────────────────────
|
|
24
|
+
* Not `Tool.dispose()`: a `Tool` is a singleton, built once and shared by every
|
|
25
|
+
* run and every session, so "dispose the tool" cannot mean "dispose this
|
|
26
|
+
* caller's session".
|
|
27
|
+
* Not a lifecycle PORT the consumer wires: that makes the common case (one tool
|
|
28
|
+
* that happens to hold a session) a wiring exercise, and the tool that knows the
|
|
29
|
+
* key is the one that cannot reach the port.
|
|
30
|
+
* `ctx.onTeardown(cleanup, { scope, key })` is the only seam where the key and
|
|
31
|
+
* the resource are both in hand at the same instant.
|
|
32
|
+
*
|
|
33
|
+
* ── The seven laws ──────────────────────────────────────────────────────────
|
|
34
|
+
* 1. **At most once, ever** per registration — the `stopped`-flag mechanism
|
|
35
|
+
* `strategies/lifecycle.ts` uses for strategies, applied one layer down.
|
|
36
|
+
* 2. **Idempotent by `(tool, scope, key)`, first wins.** A second registration
|
|
37
|
+
* under the same key does not replace the first — the first is the one
|
|
38
|
+
* holding the live handle; replacing it would drop that handle on the
|
|
39
|
+
* floor. The repeat is a TOUCH: it refreshes liveness (that is how the
|
|
40
|
+
* idle sweep and the LRU learn a session is still in use) and answers
|
|
41
|
+
* `'reused'`.
|
|
42
|
+
* 3. **Reverse order of registration**, settled with `Promise.allSettled`.
|
|
43
|
+
* 4. **Bounded** by `timeoutMs` (default 5s). Teardown is on the SIGTERM path;
|
|
44
|
+
* an unbounded `stop()` turns a container stop into a wait for SIGKILL.
|
|
45
|
+
* 5. **Never throws into the run** — but **never silent** either. Every
|
|
46
|
+
* failure, and every timeout, is reported. "Swallowed AND silent" is what
|
|
47
|
+
* separates a passive recorder from a resource that did not get released.
|
|
48
|
+
* 6. **Tolerates "already gone."** The far side reaps idle sessions on its own
|
|
49
|
+
* schedule; a `Stop` on a session AWS already collected is a no-op, not an
|
|
50
|
+
* incident. It still reports, so the difference is visible.
|
|
51
|
+
* 7. **Nothing live is ever persisted.** A checkpoint carries what survives
|
|
52
|
+
* `structuredClone`; a session handle does not. A resumed run re-opens.
|
|
53
|
+
*
|
|
54
|
+
* Zero-cost when unused: no tool registers → the runner never builds a tier →
|
|
55
|
+
* the terminal path is one `undefined` check.
|
|
56
|
+
*/
|
|
57
|
+
import { fnv1a } from '../lib/fnv1a.js';
|
|
58
|
+
import { lazyRequire } from '../lib/lazyRequire.js';
|
|
59
|
+
/**
|
|
60
|
+
* Derive the isolation key a tool should hold a session under.
|
|
61
|
+
*
|
|
62
|
+
* ONE implementation, exported, because the derivation is the security
|
|
63
|
+
* boundary. Returns `undefined` when the facts the scope needs are absent —
|
|
64
|
+
* which is a refusal to guess, not a failure: the caller decides whether to
|
|
65
|
+
* narrow the scope loudly or refuse the call.
|
|
66
|
+
*
|
|
67
|
+
* ```
|
|
68
|
+
* session → t=<tenant|_>/p=<principal|_>/s=<sessionId> requires sessionId
|
|
69
|
+
* run → t=<tenant|_>/p=<principal|_>/r=<runId> requires runId
|
|
70
|
+
* call → c=<toolCallId> always available
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* **`sessionId` alone must never key a live session.** The hosting port says
|
|
74
|
+
* why in its own words: a `sessionId` "is not identity and must never be
|
|
75
|
+
* trusted as identity on its own: anyone who can reach the host can put any
|
|
76
|
+
* string here, including someone else's." A code interpreter keyed on
|
|
77
|
+
* `sessionId` alone hands a live sandbox — files, environment, half-run state —
|
|
78
|
+
* to anyone who guesses one. Tenant and principal are in the key whenever they
|
|
79
|
+
* exist; a deployment that has no principal is thereby STATING it is
|
|
80
|
+
* single-principal rather than quietly assuming it.
|
|
81
|
+
*
|
|
82
|
+
* `'shutdown'` is not a key scope: it is when everything goes, not a thing to
|
|
83
|
+
* hold one session under. Ask for it and you get `undefined`.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* const key = toolSessionKey(ctx, 'run');
|
|
87
|
+
* if (!key) throw new Error("run_code: scope 'run' needs a run …");
|
|
88
|
+
*/
|
|
89
|
+
export function toolSessionKey(ctx, scope) {
|
|
90
|
+
if (scope === 'call')
|
|
91
|
+
return `c=${ctx.toolCallId}`;
|
|
92
|
+
if (scope === 'shutdown')
|
|
93
|
+
return undefined;
|
|
94
|
+
const tenant = ctx.identity?.tenant || '_';
|
|
95
|
+
const principal = ctx.identity?.principal || '_';
|
|
96
|
+
const prefix = `t=${tenant}/p=${principal}`;
|
|
97
|
+
if (scope === 'session') {
|
|
98
|
+
return ctx.sessionId ? `${prefix}/s=${ctx.sessionId}` : undefined;
|
|
99
|
+
}
|
|
100
|
+
return ctx.runId ? `${prefix}/r=${ctx.runId}` : undefined;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* A short, stable digest of an isolation key.
|
|
104
|
+
*
|
|
105
|
+
* The key carries tenant, principal and the hosting `sessionId`. Publishing it
|
|
106
|
+
* on the event wire would put a user identifier into every exporter's payload —
|
|
107
|
+
* so the wire carries this instead, which is enough to JOIN two rows and not
|
|
108
|
+
* enough to name whose they are. `meta.sessionId` already carries the session
|
|
109
|
+
* legitimately (9.4.0); the payload does not repeat it.
|
|
110
|
+
*
|
|
111
|
+
* SHA-256, first 12 hex chars, wherever `node:crypto` resolves. In a browser
|
|
112
|
+
* bundle, where it does not, this falls back to the package's non-cryptographic
|
|
113
|
+
* FNV-1a digest — stated here rather than implied, because a fallback nobody
|
|
114
|
+
* documented is how "hashed" comes to mean less than a reader assumed.
|
|
115
|
+
*/
|
|
116
|
+
export function hashSessionKey(key) {
|
|
117
|
+
const crypto = loadCrypto();
|
|
118
|
+
if (crypto)
|
|
119
|
+
return crypto.createHash('sha256').update(key).digest('hex').slice(0, 12);
|
|
120
|
+
return fnv1a(key);
|
|
121
|
+
}
|
|
122
|
+
let cryptoModule;
|
|
123
|
+
function loadCrypto() {
|
|
124
|
+
if (cryptoModule !== undefined)
|
|
125
|
+
return cryptoModule ?? undefined;
|
|
126
|
+
try {
|
|
127
|
+
const mod = lazyRequire('node:crypto');
|
|
128
|
+
cryptoModule = typeof mod?.createHash === 'function' ? mod : null;
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
cryptoModule = null;
|
|
132
|
+
}
|
|
133
|
+
return cryptoModule ?? undefined;
|
|
134
|
+
}
|
|
135
|
+
/** Defaults, named so a test and a docstring cannot drift from the code. */
|
|
136
|
+
export const TOOL_TEARDOWN_TIMEOUT_MS = 5_000;
|
|
137
|
+
/** A session untouched this long is swept on the tier's next interaction. */
|
|
138
|
+
export const TOOL_SESSION_IDLE_MS = 900_000;
|
|
139
|
+
/** How many live registrations one tier holds before it evicts the coldest. */
|
|
140
|
+
export const TOOL_SESSION_MAX_LIVE = 64;
|
|
141
|
+
/**
|
|
142
|
+
* The teardown tier for one runner.
|
|
143
|
+
*
|
|
144
|
+
* Holds nothing until a tool registers, and the runner builds one only when
|
|
145
|
+
* that happens — so an agent whose tools hold no sessions pays a single
|
|
146
|
+
* `undefined` check at each terminal and nothing else.
|
|
147
|
+
*/
|
|
148
|
+
export class ToolSessionTier {
|
|
149
|
+
registrations = new Map();
|
|
150
|
+
timeoutMs;
|
|
151
|
+
idleMs;
|
|
152
|
+
maxLive;
|
|
153
|
+
report;
|
|
154
|
+
now;
|
|
155
|
+
seq = 0;
|
|
156
|
+
constructor(options = {}) {
|
|
157
|
+
this.timeoutMs = options.timeoutMs ?? TOOL_TEARDOWN_TIMEOUT_MS;
|
|
158
|
+
this.idleMs = options.idleMs ?? TOOL_SESSION_IDLE_MS;
|
|
159
|
+
this.maxLive = options.maxLive ?? TOOL_SESSION_MAX_LIVE;
|
|
160
|
+
this.report = options.report ?? (() => { });
|
|
161
|
+
this.now = options.now ?? (() => Date.now());
|
|
162
|
+
}
|
|
163
|
+
/** Live registrations. Diagnostics and tests. */
|
|
164
|
+
liveCount() {
|
|
165
|
+
return this.registrations.size;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Resolve once every teardown this tier started IN THE BACKGROUND has
|
|
169
|
+
* settled.
|
|
170
|
+
*
|
|
171
|
+
* Two firings have no caller to await them: the idle sweep and the LRU
|
|
172
|
+
* eviction, both of which are triggered by a SYNCHRONOUS `register()` inside
|
|
173
|
+
* somebody else's `tool.execute`. They cannot be awaited there without making
|
|
174
|
+
* a cleanup's latency the tool's latency, so they run detached — and this is
|
|
175
|
+
* how a shutdown path, or a test, joins them.
|
|
176
|
+
*/
|
|
177
|
+
async settled() {
|
|
178
|
+
while (this.background.size > 0) {
|
|
179
|
+
await Promise.allSettled([...this.background]);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/** Fires nobody is awaiting — see {@link settled}. */
|
|
183
|
+
background = new Set();
|
|
184
|
+
/** Start a detached fire and keep it joinable. */
|
|
185
|
+
detach(work) {
|
|
186
|
+
this.background.add(work);
|
|
187
|
+
void work.finally(() => this.background.delete(work));
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Register a cleanup, or TOUCH the one already holding this key (law 2).
|
|
191
|
+
*
|
|
192
|
+
* Synchronous and total: it never throws, because it runs inside somebody
|
|
193
|
+
* else's `tool.execute`. Scope support is judged one layer up, where
|
|
194
|
+
* `teardownScopes` is known.
|
|
195
|
+
*
|
|
196
|
+
* @returns `'started'` for a new session, `'reused'` when this call joined
|
|
197
|
+
* one already held, with `calls` counting how many have now shared it. The
|
|
198
|
+
* CALLER announces it, because the caller is the one still inside a stage
|
|
199
|
+
* and able to stamp a real `runtimeStageId` — see {@link RegisterOutcome}.
|
|
200
|
+
*/
|
|
201
|
+
register(origin, cleanup, options = {}) {
|
|
202
|
+
this.sweepIdle();
|
|
203
|
+
const scope = options.scope ?? 'run';
|
|
204
|
+
const key = options.key ?? `${scope}:${origin.tool}`;
|
|
205
|
+
const mapKey = `${origin.tool}${scope}${key}`;
|
|
206
|
+
const existing = this.registrations.get(mapKey);
|
|
207
|
+
if (existing) {
|
|
208
|
+
// First wins — it is the one holding the live handle. The repeat is what
|
|
209
|
+
// tells the sweep and the LRU that this session is still being used.
|
|
210
|
+
existing.touchedMs = this.now();
|
|
211
|
+
existing.calls += 1;
|
|
212
|
+
return { outcome: 'reused', keyHash: existing.keyHash, calls: existing.calls };
|
|
213
|
+
}
|
|
214
|
+
const nowMs = this.now();
|
|
215
|
+
const registration = {
|
|
216
|
+
id: ++this.seq,
|
|
217
|
+
tool: origin.tool,
|
|
218
|
+
scope,
|
|
219
|
+
key,
|
|
220
|
+
keyHash: hashSessionKey(key),
|
|
221
|
+
origin,
|
|
222
|
+
cleanup,
|
|
223
|
+
...(options.runnerId !== undefined && { runnerId: options.runnerId }),
|
|
224
|
+
...(options.label !== undefined && { label: options.label }),
|
|
225
|
+
startedMs: nowMs,
|
|
226
|
+
touchedMs: nowMs,
|
|
227
|
+
calls: 1,
|
|
228
|
+
fired: false,
|
|
229
|
+
};
|
|
230
|
+
this.registrations.set(mapKey, registration);
|
|
231
|
+
this.evictOverflow();
|
|
232
|
+
return { outcome: 'started', keyHash: registration.keyHash, calls: 1 };
|
|
233
|
+
}
|
|
234
|
+
/** Fire every `'call'` registration this tool call opened. */
|
|
235
|
+
fireCall(toolCallId) {
|
|
236
|
+
return this.fire((r) => r.scope === 'call' && r.origin.toolCallId === toolCallId, 'call-end').then(() => undefined);
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Fire `'run'`-scoped registrations at a run terminal.
|
|
240
|
+
*
|
|
241
|
+
* Called from `Agent.run`/`resume` at a terminal that is NOT a pause — and
|
|
242
|
+
* deliberately not from a `finally`, which also runs on the two pause shapes.
|
|
243
|
+
*
|
|
244
|
+
* **`runId` is optional, and the Agent omits it.** A `'run'` scope means
|
|
245
|
+
* "release this when the TURN that opened it ends", and a turn is not a
|
|
246
|
+
* runId: a pause and its resume are one turn across two runs (`resume()`
|
|
247
|
+
* builds a fresh executor with a fresh id). Filtering on the id would leave
|
|
248
|
+
* every session a paused turn had opened alive forever — the failure would
|
|
249
|
+
* look like nothing at all, because the run answered fine.
|
|
250
|
+
*
|
|
251
|
+
* Firing all of them is exactly right under the runner's own
|
|
252
|
+
* ONE-IN-FLIGHT-RUN-PER-AGENT invariant: at a terminal there is no other turn
|
|
253
|
+
* whose sessions these could be. An ABANDONED pause is the interesting case
|
|
254
|
+
* and it lands the right way round too — the next completed turn releases
|
|
255
|
+
* what the abandoned one left holding.
|
|
256
|
+
*
|
|
257
|
+
* Pass an id where a caller really does mean one specific run.
|
|
258
|
+
*/
|
|
259
|
+
fireRun(runId) {
|
|
260
|
+
return this.fire((r) => r.scope === 'run' && (runId === undefined || r.origin.runId === runId), 'run-end').then(() => undefined);
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Fire the `'session'` registrations for one hosting session — or, with no
|
|
264
|
+
* `sessionId`, every `'session'` registration there is.
|
|
265
|
+
*
|
|
266
|
+
* Answers how many it closed, so a composition root can log a number instead
|
|
267
|
+
* of hoping.
|
|
268
|
+
*/
|
|
269
|
+
fireSession(sessionId, reason = 'session-end') {
|
|
270
|
+
return this.fire((r) => r.scope === 'session' && (sessionId === undefined || r.origin.sessionId === sessionId), reason);
|
|
271
|
+
}
|
|
272
|
+
/** Fire EVERYTHING, whatever scope it asked for. The backstop. */
|
|
273
|
+
fireShutdown() {
|
|
274
|
+
return this.fire(() => true, 'shutdown');
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Sweep sessions nobody has touched for `idleMs`.
|
|
278
|
+
*
|
|
279
|
+
* LAZY, on the next tier interaction — never a timer. A library that installs
|
|
280
|
+
* an interval keeps the host process alive, which is the same reason
|
|
281
|
+
* `shutdownOn` refuses to grab signals unless asked.
|
|
282
|
+
*/
|
|
283
|
+
sweepIdle() {
|
|
284
|
+
if (this.registrations.size === 0)
|
|
285
|
+
return;
|
|
286
|
+
const cutoff = this.now() - this.idleMs;
|
|
287
|
+
const stale = [...this.registrations.values()].filter((r) => r.touchedMs <= cutoff);
|
|
288
|
+
if (stale.length === 0)
|
|
289
|
+
return;
|
|
290
|
+
this.detach(this.fire((r) => stale.includes(r), 'idle'));
|
|
291
|
+
}
|
|
292
|
+
evictOverflow() {
|
|
293
|
+
if (this.registrations.size <= this.maxLive)
|
|
294
|
+
return;
|
|
295
|
+
const surplus = this.registrations.size - this.maxLive;
|
|
296
|
+
const coldest = [...this.registrations.values()]
|
|
297
|
+
.sort((a, b) => a.touchedMs - b.touchedMs || a.id - b.id)
|
|
298
|
+
.slice(0, surplus);
|
|
299
|
+
this.detach(this.fire((r) => coldest.includes(r), 'evicted'));
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* The one firing implementation: select, claim (law 1), reverse (law 3),
|
|
303
|
+
* settle everything (law 5).
|
|
304
|
+
*
|
|
305
|
+
* Selection and claiming happen SYNCHRONOUSLY before the first `await`, so
|
|
306
|
+
* two overlapping fires — a shutdown racing an idle sweep — cannot both take
|
|
307
|
+
* the same registration.
|
|
308
|
+
*/
|
|
309
|
+
async fire(match, reason) {
|
|
310
|
+
const claimed = [];
|
|
311
|
+
for (const [mapKey, registration] of this.registrations) {
|
|
312
|
+
if (registration.fired || !match(registration))
|
|
313
|
+
continue;
|
|
314
|
+
registration.fired = true;
|
|
315
|
+
this.registrations.delete(mapKey);
|
|
316
|
+
claimed.push(registration);
|
|
317
|
+
}
|
|
318
|
+
if (claimed.length === 0)
|
|
319
|
+
return 0;
|
|
320
|
+
claimed.sort((a, b) => b.id - a.id); // reverse registration order
|
|
321
|
+
await Promise.allSettled(claimed.map((registration) => this.run(registration, reason)));
|
|
322
|
+
return claimed.length;
|
|
323
|
+
}
|
|
324
|
+
/** One cleanup, bounded, reported either way. Never rethrows. */
|
|
325
|
+
async run(registration, reason) {
|
|
326
|
+
const startedAt = this.now();
|
|
327
|
+
const base = {
|
|
328
|
+
tool: registration.tool,
|
|
329
|
+
scope: registration.scope,
|
|
330
|
+
keyHash: registration.keyHash,
|
|
331
|
+
...(registration.runnerId !== undefined && { runnerId: registration.runnerId }),
|
|
332
|
+
...(registration.label !== undefined && { label: registration.label }),
|
|
333
|
+
reason,
|
|
334
|
+
};
|
|
335
|
+
try {
|
|
336
|
+
await withTimeout(async () => registration.cleanup(), this.timeoutMs, `${registration.tool} teardown`);
|
|
337
|
+
this.report({
|
|
338
|
+
...base,
|
|
339
|
+
kind: 'closed',
|
|
340
|
+
durationMs: this.now() - startedAt,
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
catch (err) {
|
|
344
|
+
// Law 5: swallowed at the caller, never silent on the wire.
|
|
345
|
+
this.report({
|
|
346
|
+
...base,
|
|
347
|
+
kind: 'close-failed',
|
|
348
|
+
durationMs: this.now() - startedAt,
|
|
349
|
+
error: err instanceof Error ? err.message : String(err),
|
|
350
|
+
...(err instanceof Error && { errorClass: err.constructor?.name ?? err.name }),
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
/** A teardown that outran its budget. Named so an alert can route on it. */
|
|
356
|
+
export class ToolTeardownTimeoutError extends Error {
|
|
357
|
+
timeoutMs;
|
|
358
|
+
constructor(what, timeoutMs) {
|
|
359
|
+
super(`${what} did not finish within ${timeoutMs}ms and was abandoned. The cleanup may still ` +
|
|
360
|
+
'be running; the runner stopped waiting so a shutdown cannot hang on a vendor call.');
|
|
361
|
+
this.name = 'ToolTeardownTimeoutError';
|
|
362
|
+
this.timeoutMs = timeoutMs;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Run `work`, giving up after `timeoutMs`.
|
|
367
|
+
*
|
|
368
|
+
* The abandoned promise is deliberately NOT cancelled — there is nothing to
|
|
369
|
+
* cancel a vendor's in-flight `Stop` with, and pretending otherwise would be
|
|
370
|
+
* worse than saying we stopped waiting. The timer is unref'd where the runtime
|
|
371
|
+
* allows it, so a pending teardown can never be the reason a process stays up.
|
|
372
|
+
*/
|
|
373
|
+
async function withTimeout(work, timeoutMs, what) {
|
|
374
|
+
let timer;
|
|
375
|
+
try {
|
|
376
|
+
await Promise.race([
|
|
377
|
+
work(),
|
|
378
|
+
new Promise((_resolve, reject) => {
|
|
379
|
+
timer = setTimeout(() => reject(new ToolTeardownTimeoutError(what, timeoutMs)), timeoutMs);
|
|
380
|
+
timer.unref?.();
|
|
381
|
+
}),
|
|
382
|
+
]);
|
|
383
|
+
}
|
|
384
|
+
finally {
|
|
385
|
+
if (timer !== undefined)
|
|
386
|
+
clearTimeout(timer);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
//# sourceMappingURL=toolSessions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolSessions.js","sourceRoot":"","sources":["../../../src/core/toolSessions.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/core/tools.d.ts
CHANGED
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import type { LLMToolSchema } from '../adapters/types.js';
|
|
10
10
|
import type { Credential, CredentialNeed, CredentialProvider } from '../identity/types.js';
|
|
11
|
+
import type { MemoryIdentity } from '../memory/identity/types.js';
|
|
11
12
|
import type { CheckInDemand } from './checkin.js';
|
|
13
|
+
import type { TeardownOptions, TeardownScope } from './toolSessions.js';
|
|
12
14
|
/**
|
|
13
15
|
* One executable tool the Agent can call.
|
|
14
16
|
*
|
|
@@ -79,6 +81,64 @@ export interface ToolExecutionContext {
|
|
|
79
81
|
/** The credential resolved for this tool's declared `needs` (declare-and-push).
|
|
80
82
|
* Present only when the tool declared a need and it resolved successfully. */
|
|
81
83
|
readonly credential?: Credential;
|
|
84
|
+
/**
|
|
85
|
+
* The run this call belongs to.
|
|
86
|
+
*
|
|
87
|
+
* **Absent when there is no run.** A call served over `mcpServe` is one call,
|
|
88
|
+
* not a turn in a conversation, and minting a synthetic run id there would
|
|
89
|
+
* fabricate a run that never existed. Branch on the absence.
|
|
90
|
+
*/
|
|
91
|
+
readonly runId?: string;
|
|
92
|
+
/**
|
|
93
|
+
* The hosting conversation this run is bound to, when it is bound to one —
|
|
94
|
+
* `HostRequest.sessionId`, threaded through `agent.run({ sessionId })`.
|
|
95
|
+
*
|
|
96
|
+
* Never derived, never defaulted to `runId`, never the anonymous latch.
|
|
97
|
+
*
|
|
98
|
+
* **It is caller data, not identity.** Anyone who can reach the host can put
|
|
99
|
+
* any string here, including someone else's. Never key a live session on it
|
|
100
|
+
* alone — compose it with tenant and principal via {@link toolSessionKey}.
|
|
101
|
+
*/
|
|
102
|
+
readonly sessionId?: string;
|
|
103
|
+
/**
|
|
104
|
+
* The identity the CALLER supplied — `run({ identity })`, the same tuple
|
|
105
|
+
* memory and the permission gate scope on.
|
|
106
|
+
*
|
|
107
|
+
* **Absent when the caller passed none.** Deliberately NOT the run's internal
|
|
108
|
+
* `runIdentity`, which is always populated (it defaults to
|
|
109
|
+
* `{ conversationId: '<runId>' }`): handing that to a tool would publish a
|
|
110
|
+
* synthesized conversation as if somebody had named one.
|
|
111
|
+
*/
|
|
112
|
+
readonly identity?: MemoryIdentity;
|
|
113
|
+
/**
|
|
114
|
+
* Register cleanup for work THIS call started — a code-interpreter session, a
|
|
115
|
+
* browser context, a lease.
|
|
116
|
+
*
|
|
117
|
+
* The tool learns its isolation key at execute time and registers cleanup for
|
|
118
|
+
* exactly that key in the same breath; there is no other seam where both are
|
|
119
|
+
* in hand. Registering twice under one `(tool, scope, key)` is a no-op that
|
|
120
|
+
* keeps the FIRST cleanup (it holds the live handle) and refreshes liveness,
|
|
121
|
+
* so calling this on every execute is the intended shape for a reused
|
|
122
|
+
* session.
|
|
123
|
+
*
|
|
124
|
+
* Throws, naming the door, when `scope` is not in {@link teardownScopes} — a
|
|
125
|
+
* capability nobody implements is a promise the library cannot keep.
|
|
126
|
+
*
|
|
127
|
+
* @example a session that lives as long as the run
|
|
128
|
+
* const key = toolSessionKey(ctx, 'run');
|
|
129
|
+
* const session = await runner.start({ key });
|
|
130
|
+
* ctx.onTeardown?.(() => session.stop(), { scope: 'run', key });
|
|
131
|
+
*/
|
|
132
|
+
onTeardown?(cleanup: () => void | Promise<void>, options?: TeardownOptions): void;
|
|
133
|
+
/**
|
|
134
|
+
* Which teardown scopes this door can actually honour — `[]` means none ever
|
|
135
|
+
* fires here.
|
|
136
|
+
*
|
|
137
|
+
* A FACT to branch on, exactly like `hasCredentials`, rather than an
|
|
138
|
+
* `undefined` to optional-chain past: a tool that wants a run-scoped session
|
|
139
|
+
* needs to know it is talking to a door that has no runs BEFORE it opens one.
|
|
140
|
+
*/
|
|
141
|
+
readonly teardownScopes?: readonly TeardownScope[];
|
|
82
142
|
}
|
|
83
143
|
/**
|
|
84
144
|
* Internal: registry entry keyed by tool name.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../src/core/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../src/core/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAoLxC;;;;;;;;;;;;;;;;;;GAkBG;AACH;;;;;;;GAOG;AACH,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AAEjD;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAa;IAC/C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CACb,yDAAyD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAClF,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACjC,MAAM,MAAM,GACV,IAAI,CAAC,MAAM,GAAG,EAAE;YACd,CAAC,CAAC,SAAS,IAAI,CAAC,MAAM,iBAAiB;YACvC,CAAC,CAAC,mFAAmF,CAAC;QAC1F,MAAM,IAAI,KAAK,CACb,aAAa,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,MAAM,IAAI;YAC/C,sFAAsF;YACtF,wEAAwE;YACxE,0DAA0D,CAC7D,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAa;IACjD,IAAI,CAAC,SAAS,EAAE;QAAE,OAAO;IACzB,IAAI,CAAC;QACH,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,sCAAsC;QACtC,OAAO,CAAC,IAAI,CAAC,4BAA6B,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;IACnE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,OAA0C;IAE1C,qBAAqB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,OAAO;QACL,MAAM,EAAE;YACN,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE;SACvE;QACD,GAAG,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;QAC9C,uEAAuE;QACvE,2DAA2D;QAC3D,GAAG,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,OAAwB,EAAE,CAAC;QACnF,OAAO,EAAE,OAAO,CAAC,OAAO;KACzB,CAAC;AACJ,CAAC"}
|
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
* plus the MCP client/server bridge.
|
|
12
12
|
* • Thinking handlers — per-vendor parsing of extended-thinking blocks,
|
|
13
13
|
* which is a provider concern wearing another hat.
|
|
14
|
+
* • Code runners — `localCodeRunner` (process isolation, on this
|
|
15
|
+
* machine, and it says so) and `agentCoreCodeRunner`
|
|
16
|
+
* (a real managed sandbox). Both are backends behind
|
|
17
|
+
* the `CodeRunner` port; `codeRunnerTool` on the main
|
|
18
|
+
* barrel is the tool that holds one.
|
|
14
19
|
*
|
|
15
20
|
* Each vendor SDK is lazy-required, so importing this door loads no vendor
|
|
16
21
|
* code — only calling a factory does.
|
|
@@ -24,3 +29,5 @@ export * from '../llm-providers.js';
|
|
|
24
29
|
export * from '../embedders/index.js';
|
|
25
30
|
export * from '../tool-providers/index.js';
|
|
26
31
|
export * from '../thinking/index.js';
|
|
32
|
+
export { localCodeRunner, type LocalCodeRunnerOptions } from '../adapters/code/local.js';
|
|
33
|
+
export { agentCoreCodeRunner, type AgentCoreCodeRunnerOptions, type AgentCoreCodeClientLike, type AgentCoreInvokeAnswer, type BedrockAgentCoreCodeSdkModule, } from '../adapters/code/agentcore.js';
|
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
* plus the MCP client/server bridge.
|
|
12
12
|
* • Thinking handlers — per-vendor parsing of extended-thinking blocks,
|
|
13
13
|
* which is a provider concern wearing another hat.
|
|
14
|
+
* • Code runners — `localCodeRunner` (process isolation, on this
|
|
15
|
+
* machine, and it says so) and `agentCoreCodeRunner`
|
|
16
|
+
* (a real managed sandbox). Both are backends behind
|
|
17
|
+
* the `CodeRunner` port; `codeRunnerTool` on the main
|
|
18
|
+
* barrel is the tool that holds one.
|
|
14
19
|
*
|
|
15
20
|
* Each vendor SDK is lazy-required, so importing this door loads no vendor
|
|
16
21
|
* code — only calling a factory does.
|
|
@@ -24,4 +29,9 @@ export * from '../llm-providers.js';
|
|
|
24
29
|
export * from '../embedders/index.js';
|
|
25
30
|
export * from '../tool-providers/index.js';
|
|
26
31
|
export * from '../thinking/index.js';
|
|
32
|
+
// Code runners — the backends behind the `CodeRunner` port (9.7.0). The port
|
|
33
|
+
// types themselves live on the main barrel with `codeRunnerTool`, alongside the
|
|
34
|
+
// other adapter ports.
|
|
35
|
+
export { localCodeRunner } from '../adapters/code/local.js';
|
|
36
|
+
export { agentCoreCodeRunner, } from '../adapters/code/agentcore.js';
|
|
27
37
|
//# sourceMappingURL=providers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"providers.js","sourceRoot":"","sources":["../../../src/doors/providers.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"providers.js","sourceRoot":"","sources":["../../../src/doors/providers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AAErC,6EAA6E;AAC7E,gFAAgF;AAChF,uBAAuB;AACvB,OAAO,EAAE,eAAe,EAA+B,MAAM,2BAA2B,CAAC;AACzF,OAAO,EACL,mBAAmB,GAKpB,MAAM,+BAA+B,CAAC"}
|
|
@@ -624,6 +624,55 @@ export interface ToolsShadowedPayload {
|
|
|
624
624
|
/** That source's id — the skill id, for the provider↔skill pair. */
|
|
625
625
|
readonly dispatchToId?: string;
|
|
626
626
|
}
|
|
627
|
+
/** Shared shape of the four `tools.session_*` payloads. */
|
|
628
|
+
interface ToolSessionPayloadBase {
|
|
629
|
+
/** The tool that registered the cleanup. */
|
|
630
|
+
readonly tool: string;
|
|
631
|
+
/** Which scope it asked for — how long it expected to live. */
|
|
632
|
+
readonly scope: 'call' | 'run' | 'session' | 'shutdown';
|
|
633
|
+
/** Digest of the isolation key. SHA-256 (12 hex chars) where `node:crypto`
|
|
634
|
+
* resolves, FNV-1a in a browser bundle. NEVER the key. */
|
|
635
|
+
readonly keyHash: string;
|
|
636
|
+
/** The adapter holding the resource — `CodeRunner.id`, say. */
|
|
637
|
+
readonly runnerId?: string;
|
|
638
|
+
/** One fact the tool chose to state about what was opened (the language, the
|
|
639
|
+
* browser profile). Never user data. */
|
|
640
|
+
readonly label?: string;
|
|
641
|
+
}
|
|
642
|
+
/** A tool opened something and registered its cleanup. */
|
|
643
|
+
export type ToolsSessionStartedPayload = ToolSessionPayloadBase;
|
|
644
|
+
/**
|
|
645
|
+
* A later call reused the session already held under this key.
|
|
646
|
+
*
|
|
647
|
+
* This is the payoff being measured: `calls` is how many dispatches have shared
|
|
648
|
+
* one start-up. It is also the liveness signal the idle sweep and the LRU bound
|
|
649
|
+
* read, which is why a tool re-registers on every execute rather than only once.
|
|
650
|
+
*/
|
|
651
|
+
export interface ToolsSessionReusedPayload extends ToolSessionPayloadBase {
|
|
652
|
+
/** How many calls have now shared this session, including this one. */
|
|
653
|
+
readonly calls: number;
|
|
654
|
+
}
|
|
655
|
+
/** The cleanup ran. `reason` says which firing site ran it. */
|
|
656
|
+
export interface ToolsSessionClosedPayload extends ToolSessionPayloadBase {
|
|
657
|
+
readonly reason: 'call-end' | 'run-end' | 'session-end' | 'shutdown' | 'idle' | 'evicted';
|
|
658
|
+
/** Wall-clock from registration to close. */
|
|
659
|
+
readonly durationMs: number;
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* The cleanup threw, or outran `toolTeardownTimeoutMs`.
|
|
663
|
+
*
|
|
664
|
+
* Teardown never throws into the run — but it is never SILENT either, and this
|
|
665
|
+
* event is the difference. A vendor `Stop` that fails leaves a live sandbox
|
|
666
|
+
* somebody is still paying for; the run has no way to say so, so this does.
|
|
667
|
+
* `errorClass` mirrors `credential.failed`'s 9.4.0 addition: routable without
|
|
668
|
+
* parsing prose (`'ToolTeardownTimeoutError'` for the budget case).
|
|
669
|
+
*/
|
|
670
|
+
export interface ToolsSessionCloseFailedPayload extends ToolSessionPayloadBase {
|
|
671
|
+
readonly reason: 'call-end' | 'run-end' | 'session-end' | 'shutdown' | 'idle' | 'evicted';
|
|
672
|
+
readonly durationMs: number;
|
|
673
|
+
readonly error: string;
|
|
674
|
+
readonly errorClass?: string;
|
|
675
|
+
}
|
|
627
676
|
/**
|
|
628
677
|
* Emitted when LLM-produced tool args fail validation against the tool's
|
|
629
678
|
* declared `inputSchema` (backlog #9). Fires for BOTH modes that validate:
|
|
@@ -1117,3 +1166,4 @@ export interface AgentThinkingParseFailedPayload {
|
|
|
1117
1166
|
readonly errorName: string;
|
|
1118
1167
|
readonly iteration: number;
|
|
1119
1168
|
}
|
|
1169
|
+
export {};
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* major bump. See agentfootprint_v2_detailed_design.md for rules.
|
|
17
17
|
*/
|
|
18
18
|
import type { AgentfootprintEventEnvelope } from './types.js';
|
|
19
|
-
import type { AgentHandoffPayload, AgentIterationEndPayload, AgentIterationStartPayload, AgentRouteDecidedPayload, AgentTurnEndPayload, AgentTurnStartPayload, CompositionEnterPayload, CompositionExitPayload, ConditionalRouteDecidedPayload, ContextBudgetPressurePayload, ContextEvaluatedPayload, ContextEvictedPayload, ContextInjectedPayload, ContextSlotComposedPayload, CostLimitHitPayload, CostTickPayload, EmbeddingGeneratedPayload, ErrorFatalPayload, ErrorRecoveredPayload, ErrorRetriedPayload, EvalScorePayload, EvalThresholdCrossedPayload, AgentOutputSchemaValidationFailedPayload, AgentOutputContractUnmetPayload, AgentOutputSchemaRetryPayload, AgentThinkingParseFailedPayload, StreamThinkingDeltaPayload, StreamThinkingEndPayload, FallbackTriggeredPayload, LLMEndPayload, LLMStartPayload, LLMTokenPayload, LoopIterationExitPayload, LoopIterationStartPayload, MemoryAttachedPayload, MemoryDetachedPayload, MemoryRetrievedPayload, MemoryStrategyAppliedPayload, MemoryWrittenPayload, ParallelBranchCompletePayload, ParallelForkStartPayload, ParallelMergeEndPayload, PauseRequestPayload, PauseResumePayload, CheckInRequestPayload, CheckInDecisionPayload, PermissionCheckPayload, PermissionGateClosedPayload, PermissionHaltPayload, PermissionGateOpenedPayload, CredentialRequestedPayload, CredentialAcquiredPayload, CredentialAuthorizationRequiredPayload, CredentialFailedPayload, ReliabilityFailFastPayload, ReliabilityRetriedPayload, ReliabilityRecoveredPayload, RiskFlaggedPayload, SkillActivatedPayload, SkillDeactivatedPayload, SkillRejectedPayload, SkillRerouteSupersededPayload, ToolEndPayload, ToolsActivatedPayload, ToolsDeactivatedPayload, ToolsDiscoveryStartedPayload, ToolsDiscoveryCompletedPayload, ToolsDiscoveryFailedPayload, ToolsShadowedPayload, ToolsOfferedPayload, ToolStartPayload, ValidationArgsInvalidPayload, MiddlewareDecisionPayload } from './payloads.js';
|
|
19
|
+
import type { AgentHandoffPayload, AgentIterationEndPayload, AgentIterationStartPayload, AgentRouteDecidedPayload, AgentTurnEndPayload, AgentTurnStartPayload, CompositionEnterPayload, CompositionExitPayload, ConditionalRouteDecidedPayload, ContextBudgetPressurePayload, ContextEvaluatedPayload, ContextEvictedPayload, ContextInjectedPayload, ContextSlotComposedPayload, CostLimitHitPayload, CostTickPayload, EmbeddingGeneratedPayload, ErrorFatalPayload, ErrorRecoveredPayload, ErrorRetriedPayload, EvalScorePayload, EvalThresholdCrossedPayload, AgentOutputSchemaValidationFailedPayload, AgentOutputContractUnmetPayload, AgentOutputSchemaRetryPayload, AgentThinkingParseFailedPayload, StreamThinkingDeltaPayload, StreamThinkingEndPayload, FallbackTriggeredPayload, LLMEndPayload, LLMStartPayload, LLMTokenPayload, LoopIterationExitPayload, LoopIterationStartPayload, MemoryAttachedPayload, MemoryDetachedPayload, MemoryRetrievedPayload, MemoryStrategyAppliedPayload, MemoryWrittenPayload, ParallelBranchCompletePayload, ParallelForkStartPayload, ParallelMergeEndPayload, PauseRequestPayload, PauseResumePayload, CheckInRequestPayload, CheckInDecisionPayload, PermissionCheckPayload, PermissionGateClosedPayload, PermissionHaltPayload, PermissionGateOpenedPayload, CredentialRequestedPayload, CredentialAcquiredPayload, CredentialAuthorizationRequiredPayload, CredentialFailedPayload, ReliabilityFailFastPayload, ReliabilityRetriedPayload, ReliabilityRecoveredPayload, RiskFlaggedPayload, SkillActivatedPayload, SkillDeactivatedPayload, SkillRejectedPayload, SkillRerouteSupersededPayload, ToolEndPayload, ToolsActivatedPayload, ToolsDeactivatedPayload, ToolsDiscoveryStartedPayload, ToolsDiscoveryCompletedPayload, ToolsDiscoveryFailedPayload, ToolsShadowedPayload, ToolsSessionStartedPayload, ToolsSessionReusedPayload, ToolsSessionClosedPayload, ToolsSessionCloseFailedPayload, ToolsOfferedPayload, ToolStartPayload, ValidationArgsInvalidPayload, MiddlewareDecisionPayload } from './payloads.js';
|
|
20
20
|
export declare const EVENT_NAMES: {
|
|
21
21
|
readonly composition: {
|
|
22
22
|
readonly enter: "agentfootprint.composition.enter";
|
|
@@ -71,6 +71,10 @@ export declare const EVENT_NAMES: {
|
|
|
71
71
|
readonly discoveryCompleted: "agentfootprint.tools.discovery_completed";
|
|
72
72
|
readonly discoveryFailed: "agentfootprint.tools.discovery_failed";
|
|
73
73
|
readonly shadowed: "agentfootprint.tools.shadowed";
|
|
74
|
+
readonly sessionStarted: "agentfootprint.tools.session_started";
|
|
75
|
+
readonly sessionReused: "agentfootprint.tools.session_reused";
|
|
76
|
+
readonly sessionClosed: "agentfootprint.tools.session_closed";
|
|
77
|
+
readonly sessionCloseFailed: "agentfootprint.tools.session_close_failed";
|
|
74
78
|
};
|
|
75
79
|
readonly skill: {
|
|
76
80
|
readonly activated: "agentfootprint.skill.activated";
|
|
@@ -175,6 +179,10 @@ export interface AgentfootprintEventMap {
|
|
|
175
179
|
'agentfootprint.tools.discovery_completed': AgentfootprintEventEnvelope<'agentfootprint.tools.discovery_completed', ToolsDiscoveryCompletedPayload>;
|
|
176
180
|
'agentfootprint.tools.discovery_failed': AgentfootprintEventEnvelope<'agentfootprint.tools.discovery_failed', ToolsDiscoveryFailedPayload>;
|
|
177
181
|
'agentfootprint.tools.shadowed': AgentfootprintEventEnvelope<'agentfootprint.tools.shadowed', ToolsShadowedPayload>;
|
|
182
|
+
'agentfootprint.tools.session_started': AgentfootprintEventEnvelope<'agentfootprint.tools.session_started', ToolsSessionStartedPayload>;
|
|
183
|
+
'agentfootprint.tools.session_reused': AgentfootprintEventEnvelope<'agentfootprint.tools.session_reused', ToolsSessionReusedPayload>;
|
|
184
|
+
'agentfootprint.tools.session_closed': AgentfootprintEventEnvelope<'agentfootprint.tools.session_closed', ToolsSessionClosedPayload>;
|
|
185
|
+
'agentfootprint.tools.session_close_failed': AgentfootprintEventEnvelope<'agentfootprint.tools.session_close_failed', ToolsSessionCloseFailedPayload>;
|
|
178
186
|
'agentfootprint.skill.activated': AgentfootprintEventEnvelope<'agentfootprint.skill.activated', SkillActivatedPayload>;
|
|
179
187
|
'agentfootprint.skill.deactivated': AgentfootprintEventEnvelope<'agentfootprint.skill.deactivated', SkillDeactivatedPayload>;
|
|
180
188
|
'agentfootprint.skill.rejected': AgentfootprintEventEnvelope<'agentfootprint.skill.rejected', SkillRejectedPayload>;
|
|
@@ -72,6 +72,10 @@ export const EVENT_NAMES = {
|
|
|
72
72
|
discoveryCompleted: 'agentfootprint.tools.discovery_completed',
|
|
73
73
|
discoveryFailed: 'agentfootprint.tools.discovery_failed',
|
|
74
74
|
shadowed: 'agentfootprint.tools.shadowed',
|
|
75
|
+
sessionStarted: 'agentfootprint.tools.session_started',
|
|
76
|
+
sessionReused: 'agentfootprint.tools.session_reused',
|
|
77
|
+
sessionClosed: 'agentfootprint.tools.session_closed',
|
|
78
|
+
sessionCloseFailed: 'agentfootprint.tools.session_close_failed',
|
|
75
79
|
},
|
|
76
80
|
skill: {
|
|
77
81
|
activated: 'agentfootprint.skill.activated',
|
|
@@ -180,6 +184,10 @@ export const ALL_EVENT_TYPES = [
|
|
|
180
184
|
'agentfootprint.tools.discovery_completed',
|
|
181
185
|
'agentfootprint.tools.discovery_failed',
|
|
182
186
|
'agentfootprint.tools.shadowed',
|
|
187
|
+
'agentfootprint.tools.session_started',
|
|
188
|
+
'agentfootprint.tools.session_reused',
|
|
189
|
+
'agentfootprint.tools.session_closed',
|
|
190
|
+
'agentfootprint.tools.session_close_failed',
|
|
183
191
|
'agentfootprint.validation.args_invalid',
|
|
184
192
|
'agentfootprint.skill.activated',
|
|
185
193
|
'agentfootprint.skill.deactivated',
|