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.
Files changed (98) hide show
  1. package/AGENTS.md +1 -1
  2. package/CLAUDE.md +1 -1
  3. package/ai-instructions/claude-code/SKILL.md +1 -1
  4. package/dist/adapters/code/agentcore.js +294 -0
  5. package/dist/adapters/code/agentcore.js.map +1 -0
  6. package/dist/adapters/code/local.js +200 -0
  7. package/dist/adapters/code/local.js.map +1 -0
  8. package/dist/core/Agent.js +132 -0
  9. package/dist/core/Agent.js.map +1 -1
  10. package/dist/core/RunnerBase.js +67 -0
  11. package/dist/core/RunnerBase.js.map +1 -1
  12. package/dist/core/agent/stages/toolCalls.js +90 -0
  13. package/dist/core/agent/stages/toolCalls.js.map +1 -1
  14. package/dist/core/codeRunnerTool.js +252 -0
  15. package/dist/core/codeRunnerTool.js.map +1 -0
  16. package/dist/core/toolSessions.js +396 -0
  17. package/dist/core/toolSessions.js.map +1 -0
  18. package/dist/core/tools.js.map +1 -1
  19. package/dist/doors/providers.js +13 -0
  20. package/dist/doors/providers.js.map +1 -1
  21. package/dist/esm/adapters/code/agentcore.d.ts +133 -0
  22. package/dist/esm/adapters/code/agentcore.js +290 -0
  23. package/dist/esm/adapters/code/agentcore.js.map +1 -0
  24. package/dist/esm/adapters/code/local.d.ts +99 -0
  25. package/dist/esm/adapters/code/local.js +196 -0
  26. package/dist/esm/adapters/code/local.js.map +1 -0
  27. package/dist/esm/adapters/types.d.ts +87 -0
  28. package/dist/esm/core/Agent.d.ts +65 -0
  29. package/dist/esm/core/Agent.js +133 -1
  30. package/dist/esm/core/Agent.js.map +1 -1
  31. package/dist/esm/core/RunnerBase.d.ts +51 -0
  32. package/dist/esm/core/RunnerBase.js +67 -0
  33. package/dist/esm/core/RunnerBase.js.map +1 -1
  34. package/dist/esm/core/agent/stages/toolCalls.d.ts +31 -0
  35. package/dist/esm/core/agent/stages/toolCalls.js +90 -0
  36. package/dist/esm/core/agent/stages/toolCalls.js.map +1 -1
  37. package/dist/esm/core/agent/types.d.ts +23 -2
  38. package/dist/esm/core/codeRunnerTool.d.ts +120 -0
  39. package/dist/esm/core/codeRunnerTool.js +247 -0
  40. package/dist/esm/core/codeRunnerTool.js.map +1 -0
  41. package/dist/esm/core/toolSessions.d.ts +318 -0
  42. package/dist/esm/core/toolSessions.js +389 -0
  43. package/dist/esm/core/toolSessions.js.map +1 -0
  44. package/dist/esm/core/tools.d.ts +60 -0
  45. package/dist/esm/core/tools.js.map +1 -1
  46. package/dist/esm/doors/providers.d.ts +7 -0
  47. package/dist/esm/doors/providers.js +10 -0
  48. package/dist/esm/doors/providers.js.map +1 -1
  49. package/dist/esm/events/payloads.d.ts +50 -0
  50. package/dist/esm/events/registry.d.ts +9 -1
  51. package/dist/esm/events/registry.js +8 -0
  52. package/dist/esm/events/registry.js.map +1 -1
  53. package/dist/esm/index.d.ts +2 -0
  54. package/dist/esm/index.js +5 -0
  55. package/dist/esm/index.js.map +1 -1
  56. package/dist/esm/lib/mcp/mcpServe.js +37 -1
  57. package/dist/esm/lib/mcp/mcpServe.js.map +1 -1
  58. package/dist/esm/lib/trace-toolpack/traceToolpack.js +15 -1
  59. package/dist/esm/lib/trace-toolpack/traceToolpack.js.map +1 -1
  60. package/dist/events/registry.js +8 -0
  61. package/dist/events/registry.js.map +1 -1
  62. package/dist/index.js +14 -1
  63. package/dist/index.js.map +1 -1
  64. package/dist/lib/mcp/mcpServe.js +37 -1
  65. package/dist/lib/mcp/mcpServe.js.map +1 -1
  66. package/dist/lib/trace-toolpack/traceToolpack.js +15 -1
  67. package/dist/lib/trace-toolpack/traceToolpack.js.map +1 -1
  68. package/dist/types/adapters/code/agentcore.d.ts +134 -0
  69. package/dist/types/adapters/code/agentcore.d.ts.map +1 -0
  70. package/dist/types/adapters/code/local.d.ts +100 -0
  71. package/dist/types/adapters/code/local.d.ts.map +1 -0
  72. package/dist/types/adapters/types.d.ts +87 -0
  73. package/dist/types/adapters/types.d.ts.map +1 -1
  74. package/dist/types/core/Agent.d.ts +65 -0
  75. package/dist/types/core/Agent.d.ts.map +1 -1
  76. package/dist/types/core/RunnerBase.d.ts +51 -0
  77. package/dist/types/core/RunnerBase.d.ts.map +1 -1
  78. package/dist/types/core/agent/stages/toolCalls.d.ts +31 -0
  79. package/dist/types/core/agent/stages/toolCalls.d.ts.map +1 -1
  80. package/dist/types/core/agent/types.d.ts +23 -2
  81. package/dist/types/core/agent/types.d.ts.map +1 -1
  82. package/dist/types/core/codeRunnerTool.d.ts +121 -0
  83. package/dist/types/core/codeRunnerTool.d.ts.map +1 -0
  84. package/dist/types/core/toolSessions.d.ts +319 -0
  85. package/dist/types/core/toolSessions.d.ts.map +1 -0
  86. package/dist/types/core/tools.d.ts +60 -0
  87. package/dist/types/core/tools.d.ts.map +1 -1
  88. package/dist/types/doors/providers.d.ts +7 -0
  89. package/dist/types/doors/providers.d.ts.map +1 -1
  90. package/dist/types/events/payloads.d.ts +50 -0
  91. package/dist/types/events/payloads.d.ts.map +1 -1
  92. package/dist/types/events/registry.d.ts +9 -1
  93. package/dist/types/events/registry.d.ts.map +1 -1
  94. package/dist/types/index.d.ts +2 -0
  95. package/dist/types/index.d.ts.map +1 -1
  96. package/dist/types/lib/mcp/mcpServe.d.ts.map +1 -1
  97. package/dist/types/lib/trace-toolpack/traceToolpack.d.ts.map +1 -1
  98. package/package.json +1 -1
package/AGENTS.md CHANGED
@@ -475,7 +475,7 @@ Resilience decorators live on the `agentfootprint/resilience` subpath
475
475
  (not the main barrel). Each preserves the `LLMProvider` interface and
476
476
  stacks freely.
477
477
 
478
- ### Observability — 73 typed events across 20 domains
478
+ ### Observability — 77 typed events across 20 domains
479
479
 
480
480
  ```typescript
481
481
  agent.on('agentfootprint.context.injected', (e) =>
package/CLAUDE.md CHANGED
@@ -60,7 +60,7 @@ Traps: `src/observability/` holds the finder IMPLEMENTATIONS (canonical home; `d
60
60
  - **Embedder fingerprint** (8.9.0) → `Embedder.id` (optional; every shipped embedder sets one, and NONE include dims — the store appends `@<dims>` itself, so an id carrying its own size double-stamps) + `indexDocuments` defaulting `embedderId` to it + `SqliteVectorStore.reconcileFingerprint` (the only comparison site). Rule: dimensions ALWAYS decide, model ids decide only when BOTH sides named themselves — refusing on an absent name would block the majority of callers who never pass `embedderId`.
61
61
  - **Retrieval record** (8.8.0) → FOUR stages write one object in sequence: `loadRelevant` (candidates+scores+threshold verdicts) → `pickByBudget` (re-marks admitted→over-budget/over-max-entries) → `formatDefault` (`promptFragment` + `promptPosition`) → the read mount's outputMapper lifts it to root as `retrievalEvidence_<id>`. `memoryRecallInjections` then splits ONE recall into one ActiveInjection PER CHUNK — guarded by a byte-equality check (`fragments.join('\n\n') === systemContent`) that falls back to the single injection rather than change the prompt. `rank` (score order) and `promptPosition` (picker order) are DIFFERENT and both load-bearing: joining fragments in rank order reproduces the right bytes in a sequence the model never saw.
62
62
  - **AgentState** → all 8 stages/ files, both builders' mappers, memory-wire STRING-TYPED keys ('runIdentity'/'turnNumber'/… buildAgentChart.ts:177-180 — not refactor-safe), finalizeResult's `reliabilityFail*`/`policyHalt*` reads (rename silently kills the typed errors).
63
- - **events/** → 73 typed events across 20 domains (counts anti-drift-tested against this file — update BOTH when adding events): ALL_EVENT_TYPES exhaustiveness tests, DomainWildcard hand-list, ~42 importers (recorders, strategies, stream, commentary).
63
+ - **events/** → 77 typed events across 20 domains (counts anti-drift-tested against this file — update BOTH when adding events): ALL_EVENT_TYPES exhaustiveness tests, DomainWildcard hand-list, ~42 importers (recorders, strategies, stream, commentary).
64
64
  - **adapters/types.ts LLMMessage/LLMRequest** → 62 importers: tool_use round-trip (toolCalls.ts:115-135), wire assembly (callLLM.ts:150-160), providers, cache strategies, security/extractSequence, reliability loop.
65
65
  - **Cache** → strategy registration is a MODULE SIDE EFFECT (src/index.ts:15-17); an entry point skipping that import silently falls back to NoOp. Resolved once per Agent at construction (Agent.ts:347).
66
66
  - **Injection engine eval semantics** → Evaluate stage cursor keystone (buildInjectionEngineSubflow.ts:214-222), Route stage MIRRORS slot filters (keep in sync with buildSystemPromptSlot), read_skill gate (toolCalls.ts:747). The gate's allowed set is TWO kinds of id (8.4.0): a HOP (`deps.allowedSkillIds` = `graph.reachableSkills(cursor)` — activates AND moves the cursor) ∪ an OPEN skill (`deps.openSkillIds` = `Agent.openSkillIds()`, Agent.ts:1052 — a registered skill whose trigger is `llm-activated` AND that the graph declares no incoming edge to; activates, never moves the cursor). Both clauses are load-bearing: the trigger test is "read_skill can really activate this", the edge test keeps a bare model edge `.route(a,m)` from-gated. **8.5.0** extends the SAME trigger test three ways: a decision `tree()` returns `[]` from `reachableSkills` (leaves compile to `rule` triggers, so a pick could only be accepted then dropped — the gate refuses with a tree-specific message, `deps.skillGraphIsTree`, derived in AgentBuilder from `graph.nodes.some(kind==='predicate')`); `surfaceMode:'tool-only'` is refused at agent build for any skill whose trigger is not `llm-activated` (skillBodyDelivery.ts — the read_skill tool result is the only channel that mode has, and the graph never calls read_skill); and `read_skill`'s DESCRIPTION is rebuilt per iteration from `reachableSkills(cursor) ∪ open` (Agent.readSkillOfferFor → buildToolsSlot's `readSkillFor`). **The read_skill ENUM must stay the full catalog** — `toolArgValidation` defaults to `'enforce'` and runs at toolCalls.ts:570, BEFORE the gate at :765, and sets `error = true` which the gate skips; narrowing the enum silently retires the teaching refusal, `skill.rejected`, routeRecorder's rejection hops and the rejected-cap governor.
@@ -379,7 +379,7 @@ if (isPaused(result)) {
379
379
  }
380
380
  ```
381
381
 
382
- ## Observability — 73 typed events × 20 domains
382
+ ## Observability — 77 typed events × 20 domains
383
383
 
384
384
  ```typescript
385
385
  agent.on('agentfootprint.context.injected', (e) =>
@@ -0,0 +1,294 @@
1
+ "use strict";
2
+ /**
3
+ * agentCoreCodeRunner — AWS Bedrock AgentCore Code Interpreter behind the
4
+ * {@link CodeRunner} port (peer-dep `@aws-sdk/client-bedrock-agentcore`).
5
+ *
6
+ * import { agentCoreCodeRunner } from 'agentfootprint/providers';
7
+ * const runner = agentCoreCodeRunner({ region: 'us-east-1', identifier: 'aws.codeinterpreter.v1' });
8
+ *
9
+ * A REAL sandbox, which is the point: `localCodeRunner` gives you process
10
+ * isolation on your own machine and says so; this gives you a managed,
11
+ * network-and-filesystem-isolated environment, and the tool code is identical
12
+ * across the swap.
13
+ *
14
+ * ── The three operations, verified against the SDK ──────────────────────────
15
+ * Pinned in `test/adapters/aws/awsCommandPin.ts`, and verified against a real
16
+ * install of `@aws-sdk/client-bedrock-agentcore` 3.1108.0:
17
+ *
18
+ * • `StartCodeInterpreterSessionCommand`
19
+ * in `{ codeInterpreterIdentifier, name?, sessionTimeoutSeconds? }`
20
+ * out `{ codeInterpreterIdentifier, sessionId, createdAt }`
21
+ * • `InvokeCodeInterpreterCommand`
22
+ * in `{ codeInterpreterIdentifier, sessionId, name: 'executeCode',
23
+ * arguments: { code, language } }`
24
+ * out `{ sessionId, stream }` — an **event stream**, not a body (below)
25
+ * • `StopCodeInterpreterSessionCommand`
26
+ * in `{ codeInterpreterIdentifier, sessionId }` ← the session ID, not a URI
27
+ * out `{ codeInterpreterIdentifier, sessionId, lastUpdatedAt }`
28
+ *
29
+ * **`Invoke` answers with an `AsyncIterable`.** `InvokeCodeInterpreterResponse`
30
+ * is `{ sessionId?, stream?: AsyncIterable<CodeInterpreterStreamOutput> }`, and
31
+ * every member of that union is either `{ result }` or a modelled EXCEPTION —
32
+ * `accessDeniedException`, `throttlingException`, `validationException`, and
33
+ * four more. An adapter that read a `body` field would find `undefined` and
34
+ * report an empty success on every call, and one that iterated only for
35
+ * `result` would treat an AccessDenied as "the code printed nothing." So this
36
+ * drains the stream, raises the exception members BY NAME, and folds the
37
+ * result members into one `CodeResult`.
38
+ *
39
+ * The payload lands twice: `structuredContent` carries `{ stdout, stderr,
40
+ * exitCode, executionTime }` and `content[]` carries typed blocks. The
41
+ * structured half is preferred because it is typed; the text blocks are the
42
+ * fallback for a response that only filled the other one.
43
+ *
44
+ * ── How this talks to the SDK (the 9.4.0 law) ───────────────────────────────
45
+ * Through `client.send(new SomeCommand(input))`, never a method on the client.
46
+ * A bare `@aws-sdk/client-*` **Client is command-based**: its prototype carries
47
+ * `send` and `destroy` and nothing else — verified again for this adapter
48
+ * (`BedrockAgentCoreClient.prototype.startCodeInterpreterSession` is
49
+ * `undefined`; the shortcut exists only on the aggregated `BedrockAgentCore`).
50
+ * Three adapters have shipped that bug in this package.
51
+ *
52
+ * ── Credentials ─────────────────────────────────────────────────────────────
53
+ * Standard AWS credential resolution (the SDK's own chain). A tool holding a
54
+ * long-lived session must NOT cache a `Credential` object from `ctx.credential`
55
+ * past the call that produced it — a session outliving a run outlives its
56
+ * token. Re-resolve per execute through `ctx.credentials`.
57
+ *
58
+ * Pattern: Adapter (GoF) + lazy peer-dep load — the SDK is required only when
59
+ * `start()` first runs (or never, if you inject `_client` / `_sdk`).
60
+ */
61
+ Object.defineProperty(exports, "__esModule", { value: true });
62
+ exports.agentCoreCodeRunner = void 0;
63
+ const lazyRequire_js_1 = require("../../lib/lazyRequire.js");
64
+ const DEFAULT_MAX_OUTPUT_CHARS = 8_000;
65
+ /** The service's own name for "run this code". Not a name we chose. */
66
+ const EXECUTE_CODE = 'executeCode';
67
+ function agentCoreCodeRunner(options) {
68
+ const id = options.id ?? 'agentcore-code-runner';
69
+ const maxOutputChars = options.maxOutputChars ?? DEFAULT_MAX_OUTPUT_CHARS;
70
+ let client;
71
+ const resolve = () => {
72
+ client ??= options._client ?? createCodeClient(options);
73
+ return client;
74
+ };
75
+ return {
76
+ id,
77
+ async start(req) {
78
+ const api = resolve();
79
+ const started = await api.startSession({
80
+ codeInterpreterIdentifier: options.identifier,
81
+ // The isolation key names the session on AWS's side too, so an operator
82
+ // reading the console sees the same partition the runtime enforces. It
83
+ // is a HASH-free label AWS documents as non-unique; the key is already
84
+ // the caller's own composition, never widened here.
85
+ name: sessionName(req.key),
86
+ ...(options.sessionTimeoutSeconds !== undefined && {
87
+ sessionTimeoutSeconds: options.sessionTimeoutSeconds,
88
+ }),
89
+ });
90
+ const sessionId = started.sessionId;
91
+ if (!sessionId) {
92
+ throw new Error('agentCoreCodeRunner: StartCodeInterpreterSession returned no sessionId. ' +
93
+ 'Nothing can be invoked or stopped without one, so this is raised rather than ' +
94
+ 'carried forward as an unusable session.');
95
+ }
96
+ let stopped = false;
97
+ return {
98
+ id: sessionId,
99
+ async execute(exec) {
100
+ if (stopped) {
101
+ throw new Error(`agentCoreCodeRunner: session ${sessionId} was stopped; open a new one to run more code.`);
102
+ }
103
+ const answer = await api.invoke({
104
+ codeInterpreterIdentifier: options.identifier,
105
+ sessionId,
106
+ name: EXECUTE_CODE,
107
+ arguments: {
108
+ code: exec.code,
109
+ ...(exec.language ?? req.language ?? options.language
110
+ ? { language: exec.language ?? req.language ?? options.language ?? 'python' }
111
+ : {}),
112
+ },
113
+ });
114
+ const stdout = cut(answer.stdout, maxOutputChars);
115
+ const stderr = cut(answer.stderr, maxOutputChars);
116
+ const truncated = {
117
+ ...(stdout.cut && { stdout: true }),
118
+ ...(stderr.cut && { stderr: true }),
119
+ ...((stdout.cut || stderr.cut) && {
120
+ ofChars: Math.max(answer.stdout.length, answer.stderr.length),
121
+ }),
122
+ };
123
+ return {
124
+ // `isError` is the service's own verdict; a non-zero exit is ours.
125
+ ok: answer.isError !== true && (answer.exitCode ?? 0) === 0,
126
+ stdout: stdout.text,
127
+ stderr: stderr.text,
128
+ ...(answer.exitCode !== undefined && { exitCode: answer.exitCode }),
129
+ ...(Object.keys(truncated).length > 0 && { truncated }),
130
+ };
131
+ },
132
+ async stop() {
133
+ if (stopped)
134
+ return;
135
+ stopped = true;
136
+ try {
137
+ await api.stopSession({
138
+ codeInterpreterIdentifier: options.identifier,
139
+ sessionId,
140
+ });
141
+ }
142
+ catch (err) {
143
+ // "Already gone" is the EXPECTED shape here, not an incident: the
144
+ // session TTL is enforced by AWS, so a run that idled past it finds
145
+ // the session collected. Anything else is re-raised, and the tier
146
+ // reports it on `tools.session_close_failed`.
147
+ if (!isAlreadyGone(err))
148
+ throw err;
149
+ }
150
+ },
151
+ };
152
+ },
153
+ };
154
+ }
155
+ exports.agentCoreCodeRunner = agentCoreCodeRunner;
156
+ /** A session label from the isolation key — AWS's `name` is a human handle. */
157
+ function sessionName(key) {
158
+ // Keep it recognisable and within the service's naming charset.
159
+ return `af-${key.replace(/[^A-Za-z0-9_-]/g, '-')}`.slice(0, 100);
160
+ }
161
+ function isAlreadyGone(err) {
162
+ const name = err instanceof Error ? err.name : '';
163
+ return name === 'ResourceNotFoundException' || name === 'ValidationException';
164
+ }
165
+ /**
166
+ * Map {@link AgentCoreCodeClientLike} onto the real SDK commands.
167
+ *
168
+ * Two things this function owns and nothing else does: the COMMAND FORM (see
169
+ * the module header), and the DRAIN of `InvokeCodeInterpreterResponse.stream`.
170
+ */
171
+ function createCodeClient(options) {
172
+ let mod;
173
+ if (options._sdk) {
174
+ mod = options._sdk;
175
+ }
176
+ else {
177
+ try {
178
+ // Lazy peer-dep: only loaded when no _client/_sdk is injected and start() runs.
179
+ mod = (0, lazyRequire_js_1.lazyRequire)('@aws-sdk/client-bedrock-agentcore');
180
+ }
181
+ catch {
182
+ throw new Error('agentCoreCodeRunner requires the `@aws-sdk/client-bedrock-agentcore` peer dependency.\n' +
183
+ ' Install: npm install @aws-sdk/client-bedrock-agentcore\n' +
184
+ ' Or pass `_client` for a pre-built or mock client.\n' +
185
+ ' For a local dev loop with no AWS at all, use `localCodeRunner()`.');
186
+ }
187
+ }
188
+ if (!mod.BedrockAgentCoreClient) {
189
+ throw new Error('agentCoreCodeRunner: `@aws-sdk/client-bedrock-agentcore` is installed but ' +
190
+ '`BedrockAgentCoreClient` was not found. Update the SDK.');
191
+ }
192
+ const sdk = new mod.BedrockAgentCoreClient({ ...(options.region && { region: options.region }) });
193
+ const send = async (Ctor, name, input) => {
194
+ if (!Ctor) {
195
+ throw new Error(`agentCoreCodeRunner: \`@aws-sdk/client-bedrock-agentcore\` is missing ${name}. ` +
196
+ 'Upgrade the SDK, or pass `_client` with your own mapping.');
197
+ }
198
+ return sdk.send(new Ctor(input));
199
+ };
200
+ return {
201
+ async startSession(input) {
202
+ const r = (await send(mod.StartCodeInterpreterSessionCommand, 'StartCodeInterpreterSessionCommand', input));
203
+ return { ...(r?.sessionId !== undefined && { sessionId: r.sessionId }) };
204
+ },
205
+ async invoke(input) {
206
+ const r = (await send(mod.InvokeCodeInterpreterCommand, 'InvokeCodeInterpreterCommand', input));
207
+ return drainStream(r?.stream);
208
+ },
209
+ async stopSession(input) {
210
+ await send(mod.StopCodeInterpreterSessionCommand, 'StopCodeInterpreterSessionCommand', input);
211
+ },
212
+ };
213
+ }
214
+ /** Every modelled error member of the stream union, in SDK spelling. */
215
+ const STREAM_ERROR_MEMBERS = [
216
+ 'accessDeniedException',
217
+ 'conflictException',
218
+ 'internalServerException',
219
+ 'resourceNotFoundException',
220
+ 'serviceQuotaExceededException',
221
+ 'throttlingException',
222
+ 'validationException',
223
+ ];
224
+ /**
225
+ * Drain the event stream into one answer.
226
+ *
227
+ * An ERROR MEMBER RAISES. This is the honesty line for this adapter: the SDK
228
+ * models seven failure shapes as ordinary members of the stream union, so an
229
+ * `AccessDeniedException` arrives as a value, not a rejection. Folding it in
230
+ * as empty output would report a clean run in which the code "printed
231
+ * nothing" — a silent success, at the exact moment an operator most needs the
232
+ * word "AccessDenied".
233
+ */
234
+ async function drainStream(stream) {
235
+ if (!stream) {
236
+ throw new Error('agentCoreCodeRunner: InvokeCodeInterpreter returned no stream. The response carries ' +
237
+ 'its payload as an event stream (`response.stream`), so an absent one is a broken ' +
238
+ 'call, not an empty result.');
239
+ }
240
+ let stdout = '';
241
+ let stderr = '';
242
+ let exitCode;
243
+ let isError = false;
244
+ for await (const event of stream) {
245
+ for (const member of STREAM_ERROR_MEMBERS) {
246
+ const raised = event[member];
247
+ if (raised) {
248
+ const error = new Error(`agentCoreCodeRunner: ${member} from InvokeCodeInterpreter — ` +
249
+ `${raised.message ?? 'no message supplied'}`);
250
+ error.name = member.charAt(0).toUpperCase() + member.slice(1);
251
+ throw error;
252
+ }
253
+ }
254
+ const result = event.result;
255
+ if (!result)
256
+ continue;
257
+ if (result.isError === true)
258
+ isError = true;
259
+ const structured = result.structuredContent;
260
+ if (structured) {
261
+ if (structured.stdout !== undefined)
262
+ stdout += structured.stdout;
263
+ if (structured.stderr !== undefined)
264
+ stderr += structured.stderr;
265
+ if (structured.exitCode !== undefined)
266
+ exitCode = structured.exitCode;
267
+ }
268
+ else {
269
+ // Fallback: a response that filled only the typed content blocks. Text
270
+ // blocks are the readable half; a binary/resource block is described by
271
+ // name rather than inlined, because inlining it is the bug this port exists
272
+ // to prevent.
273
+ for (const block of result.content ?? []) {
274
+ if (block.text !== undefined)
275
+ stdout += block.text;
276
+ else if (block.name !== undefined)
277
+ stdout += `[${block.type ?? 'resource'}: ${block.name}]`;
278
+ }
279
+ }
280
+ }
281
+ return {
282
+ stdout,
283
+ stderr,
284
+ ...(exitCode !== undefined && { exitCode }),
285
+ ...(isError && { isError }),
286
+ };
287
+ }
288
+ /** Cut to `max` characters, saying whether it cut. */
289
+ function cut(text, max) {
290
+ if (text.length <= max)
291
+ return { text, cut: false };
292
+ return { text: text.slice(0, max), cut: true };
293
+ }
294
+ //# sourceMappingURL=agentcore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agentcore.js","sourceRoot":"","sources":["../../../src/adapters/code/agentcore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,200 @@
1
+ "use strict";
2
+ /**
3
+ * localCodeRunner — run code in a child process, on this machine.
4
+ *
5
+ * Pattern: Adapter (GoF) over `node:child_process`.
6
+ * Role: the dev default behind the {@link CodeRunner} port. `agentCoreCodeRunner`
7
+ * is the production swap; the tool code does not change.
8
+ * Emits: nothing. The tool that owns the session emits.
9
+ *
10
+ * ── ISOLATION, NOT A SANDBOX. Read this before deploying it. ────────────────
11
+ * The name is `localCodeRunner`, never `sandboxedCodeRunner`, and the
12
+ * difference is not modesty — it is the whole security posture.
13
+ *
14
+ * What a child process DOES give you:
15
+ * • a separate process and heap — a crash or an OOM takes the child, not you;
16
+ * • kill on timeout, so runaway code has a ceiling;
17
+ * • no inherited stdin, so nothing can block waiting for a terminal;
18
+ * • an environment ALLOWLIST — `process.env` is not inherited (only `PATH`,
19
+ * so the interpreter can be found), so an `AWS_SECRET_ACCESS_KEY` in your
20
+ * shell is not in the model's reach;
21
+ * • a working directory, by convention.
22
+ *
23
+ * What it does NOT give you, at all:
24
+ * • a filesystem jail — the code can read and write anywhere this process can;
25
+ * • a network jail — it can call out;
26
+ * • CPU or memory limits beyond the timeout;
27
+ * • any protection from code that deletes something outside `cwd`.
28
+ *
29
+ * So: a development loop, a trusted-input pipeline, a machine you would be
30
+ * relaxed about a shell script running on. NOT arbitrary model-written code
31
+ * from an untrusted user, on a host with anything on it. For that, run a real
32
+ * sandbox behind the same port — `agentCoreCodeRunner`, a gVisor container, a
33
+ * Firecracker VM — and keep the tool identical.
34
+ *
35
+ * **In-process `eval` / `node:vm` is refused outright.** Node's own
36
+ * documentation says `vm` is not a security mechanism ("do not use it to run
37
+ * untrusted code"), so shipping it as one would be theater: the same code
38
+ * reaching the same globals, wearing a word that makes a reader stop checking.
39
+ * A subprocess is genuinely a boundary; it is just a smaller one than the word
40
+ * "sandbox" implies. The library teaches refusals for things that are WRONG and
41
+ * honest names for things that are merely LIMITED — running local code in a dev
42
+ * loop is not wrong, and calling it a sandbox is.
43
+ *
44
+ * @example
45
+ * const agent = Agent.create({ provider })
46
+ * .tool(codeRunnerTool({ runner: localCodeRunner() }))
47
+ * .build();
48
+ */
49
+ Object.defineProperty(exports, "__esModule", { value: true });
50
+ exports.localCodeRunner = void 0;
51
+ const lazyRequire_js_1 = require("../../lib/lazyRequire.js");
52
+ const DEFAULT_TIMEOUT_MS = 30_000;
53
+ const DEFAULT_MAX_OUTPUT_CHARS = 8_000;
54
+ /** How each supported language is invoked when no `command` was given. */
55
+ const DEFAULT_COMMANDS = {
56
+ javascript: ['node', '-e'],
57
+ js: ['node', '-e'],
58
+ node: ['node', '-e'],
59
+ typescript: ['npx', 'tsx', '-e'],
60
+ ts: ['npx', 'tsx', '-e'],
61
+ python: ['python3', '-c'],
62
+ python3: ['python3', '-c'],
63
+ py: ['python3', '-c'],
64
+ };
65
+ function localCodeRunner(options = {}) {
66
+ const id = options.id ?? 'local-code-runner';
67
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
68
+ const maxOutputChars = options.maxOutputChars ?? DEFAULT_MAX_OUTPUT_CHARS;
69
+ return {
70
+ id,
71
+ start(req) {
72
+ // A local session is a NAME and a working directory, not a live handle:
73
+ // each execution is its own process. Saying so matters — a consumer who
74
+ // assumed variables carry between calls (they do on AgentCore, whose
75
+ // session is a live kernel) would silently get different semantics.
76
+ // `codeRunnerTool` states this in the tool description it hands the model.
77
+ const sessionId = `local:${req.key}`;
78
+ let stopped = false;
79
+ return Promise.resolve({
80
+ id: sessionId,
81
+ async execute(exec) {
82
+ if (stopped) {
83
+ throw new Error(`localCodeRunner: session ${sessionId} was stopped; open a new one to run more code.`);
84
+ }
85
+ const language = exec.language ?? req.language ?? 'javascript';
86
+ const command = options.command ?? DEFAULT_COMMANDS[language.toLowerCase()];
87
+ if (!command || command.length === 0) {
88
+ throw new Error(`localCodeRunner: no command for language '${language}'. ` +
89
+ `Known: ${Object.keys(DEFAULT_COMMANDS).join(', ')}. ` +
90
+ "Pass `command: ['your-interpreter', '-c']` for anything else.");
91
+ }
92
+ const [file, ...args] = command;
93
+ const raw = await runChild(resolveChildProcess(options), file, [...args, exec.code], {
94
+ cwd: options.cwd ?? process.cwd(),
95
+ // ALLOWLIST. `process.env` is deliberately NOT spread in — only
96
+ // PATH, so the OS can find the interpreter, and it is overridable.
97
+ env: { PATH: process.env.PATH ?? '', ...(options.env ?? {}) },
98
+ timeoutMs: exec.timeoutMs ?? timeoutMs,
99
+ ...(exec.signal && { signal: exec.signal }),
100
+ });
101
+ const stdout = cut(raw.stdout, maxOutputChars);
102
+ const stderr = cut(raw.stderr, maxOutputChars);
103
+ const truncated = {
104
+ ...(stdout.cut && { stdout: true }),
105
+ ...(stderr.cut && { stderr: true }),
106
+ ...((stdout.cut || stderr.cut) && {
107
+ ofChars: Math.max(raw.stdout.length, raw.stderr.length),
108
+ }),
109
+ };
110
+ return {
111
+ ok: raw.exitCode === 0,
112
+ stdout: stdout.text,
113
+ stderr: stderr.text,
114
+ ...(raw.exitCode !== undefined && { exitCode: raw.exitCode }),
115
+ // Present IFF something was actually cut — an empty object here
116
+ // would read as "truncation happened, magnitude unknown".
117
+ ...(Object.keys(truncated).length > 0 && { truncated }),
118
+ };
119
+ },
120
+ stop() {
121
+ // Nothing to release: each execution already ended with its process.
122
+ // Idempotent, and it refuses later executions rather than silently
123
+ // starting a fresh process under a session the caller closed.
124
+ stopped = true;
125
+ return Promise.resolve();
126
+ },
127
+ });
128
+ },
129
+ };
130
+ }
131
+ exports.localCodeRunner = localCodeRunner;
132
+ function resolveChildProcess(options) {
133
+ if (options._childProcess)
134
+ return options._childProcess;
135
+ try {
136
+ return (0, lazyRequire_js_1.lazyRequire)('node:child_process');
137
+ }
138
+ catch {
139
+ throw new Error('localCodeRunner needs `node:child_process`, which this runtime does not provide ' +
140
+ '(a browser bundle, or a restricted worker). Use a remote runner — ' +
141
+ '`agentCoreCodeRunner` — or supply your own `CodeRunner`.');
142
+ }
143
+ }
144
+ /**
145
+ * One child process, promisified.
146
+ *
147
+ * A NON-ZERO EXIT IS NOT A REJECTION. Code that fails is a normal answer here —
148
+ * the model wrote it, it needs to read the traceback, and turning that into a
149
+ * thrown tool error would replace the one thing that teaches the next attempt
150
+ * with `error: true`. What DOES reject is the runner failing to run at all
151
+ * (interpreter missing, timeout, abort), because that is not the code's answer.
152
+ */
153
+ async function runChild(mod, file, args, opts) {
154
+ const execFile = mod.execFile;
155
+ if (typeof execFile !== 'function') {
156
+ throw new Error('localCodeRunner: `node:child_process` resolved but `execFile` is missing.');
157
+ }
158
+ return new Promise((resolve, reject) => {
159
+ execFile(file, args, {
160
+ cwd: opts.cwd,
161
+ env: opts.env,
162
+ timeout: opts.timeoutMs,
163
+ // Generous, because the CUT is ours to make and to report — letting the
164
+ // runtime's own buffer overflow would surface as an error whose message
165
+ // says nothing about how much was lost.
166
+ maxBuffer: 32 * 1024 * 1024,
167
+ ...(opts.signal && { signal: opts.signal }),
168
+ }, (error, stdout, stderr) => {
169
+ if (!error) {
170
+ resolve({ stdout: String(stdout ?? ''), stderr: String(stderr ?? ''), exitCode: 0 });
171
+ return;
172
+ }
173
+ if (error.killed === true) {
174
+ reject(new Error(`localCodeRunner: the code did not finish within ${opts.timeoutMs}ms and the ` +
175
+ 'process was killed. Raise `timeoutMs`, or have the code do less per call.'));
176
+ return;
177
+ }
178
+ if (typeof error.code === 'string') {
179
+ // ENOENT and friends — the interpreter itself is not here. Naming it
180
+ // beats handing the model a traceback it cannot act on.
181
+ reject(new Error(`localCodeRunner: could not run '${file}' (${error.code}). ` +
182
+ 'Install the interpreter, or pass `command` pointing at one.'));
183
+ return;
184
+ }
185
+ // A real non-zero exit: the code ran and failed. That IS the result.
186
+ resolve({
187
+ stdout: String(stdout ?? ''),
188
+ stderr: String(stderr ?? '') || error.message,
189
+ exitCode: typeof error.code === 'number' ? error.code : 1,
190
+ });
191
+ });
192
+ });
193
+ }
194
+ /** Cut to `max` characters, saying whether it cut. */
195
+ function cut(text, max) {
196
+ if (text.length <= max)
197
+ return { text, cut: false };
198
+ return { text: text.slice(0, max), cut: true };
199
+ }
200
+ //# sourceMappingURL=local.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local.js","sourceRoot":"","sources":["../../../src/adapters/code/local.ts"],"names":[],"mappings":"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"}