@animalabs/agent-framework 0.22.4 → 0.23.1
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 +105 -3
- package/dist/src/agent.d.ts +36 -10
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +76 -32
- package/dist/src/agent.js.map +1 -1
- package/dist/src/code-execution/index.d.ts +1 -1
- package/dist/src/code-execution/index.d.ts.map +1 -1
- package/dist/src/code-execution/index.js.map +1 -1
- package/dist/src/code-execution/py-runner.d.ts +34 -2
- package/dist/src/code-execution/py-runner.d.ts.map +1 -1
- package/dist/src/code-execution/py-runner.js +72 -16
- package/dist/src/code-execution/py-runner.js.map +1 -1
- package/dist/src/code-execution/runtime-py.d.ts +3 -2
- package/dist/src/code-execution/runtime-py.d.ts.map +1 -1
- package/dist/src/code-execution/runtime-py.js +47 -7
- package/dist/src/code-execution/runtime-py.js.map +1 -1
- package/dist/src/code-execution/tool-definition.d.ts +12 -7
- package/dist/src/code-execution/tool-definition.d.ts.map +1 -1
- package/dist/src/code-execution/tool-definition.js +59 -11
- package/dist/src/code-execution/tool-definition.js.map +1 -1
- package/dist/src/config-checks.d.ts +2 -2
- package/dist/src/config-checks.d.ts.map +1 -1
- package/dist/src/config-checks.js +6 -2
- package/dist/src/config-checks.js.map +1 -1
- package/dist/src/framework.d.ts +744 -120
- package/dist/src/framework.d.ts.map +1 -1
- package/dist/src/framework.js +3546 -906
- package/dist/src/framework.js.map +1 -1
- package/dist/src/gate/event-gate.d.ts.map +1 -1
- package/dist/src/gate/event-gate.js +13 -6
- package/dist/src/gate/event-gate.js.map +1 -1
- package/dist/src/held-writes.d.ts +16 -0
- package/dist/src/held-writes.d.ts.map +1 -0
- package/dist/src/held-writes.js +56 -0
- package/dist/src/held-writes.js.map +1 -0
- package/dist/src/index.d.ts +7 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +8 -4
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcpl/capability-grant.d.ts +4 -0
- package/dist/src/mcpl/capability-grant.d.ts.map +1 -1
- package/dist/src/mcpl/capability-grant.js +1 -1
- package/dist/src/mcpl/capability-grant.js.map +1 -1
- package/dist/src/mcpl/channel-registry.d.ts +95 -18
- package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
- package/dist/src/mcpl/channel-registry.js +578 -150
- package/dist/src/mcpl/channel-registry.js.map +1 -1
- package/dist/src/mcpl/convert-block.d.ts +2 -2
- package/dist/src/mcpl/convert-block.d.ts.map +1 -1
- package/dist/src/mcpl/convert-block.js +6 -7
- package/dist/src/mcpl/convert-block.js.map +1 -1
- package/dist/src/mcpl/index.d.ts +5 -1
- package/dist/src/mcpl/index.d.ts.map +1 -1
- package/dist/src/mcpl/index.js +3 -1
- package/dist/src/mcpl/index.js.map +1 -1
- package/dist/src/mcpl/inference-router.d.ts +4 -2
- package/dist/src/mcpl/inference-router.d.ts.map +1 -1
- package/dist/src/mcpl/inference-router.js +6 -7
- package/dist/src/mcpl/inference-router.js.map +1 -1
- package/dist/src/mcpl/log-value.d.ts +7 -0
- package/dist/src/mcpl/log-value.d.ts.map +1 -1
- package/dist/src/mcpl/log-value.js +9 -0
- package/dist/src/mcpl/log-value.js.map +1 -1
- package/dist/src/mcpl/modern-connection.d.ts +227 -0
- package/dist/src/mcpl/modern-connection.d.ts.map +1 -0
- package/dist/src/mcpl/modern-connection.js +1088 -0
- package/dist/src/mcpl/modern-connection.js.map +1 -0
- package/dist/src/mcpl/prefix-rule.d.ts +18 -0
- package/dist/src/mcpl/prefix-rule.d.ts.map +1 -0
- package/dist/src/mcpl/prefix-rule.js +25 -0
- package/dist/src/mcpl/prefix-rule.js.map +1 -0
- package/dist/src/mcpl/protocol-family.d.ts +179 -0
- package/dist/src/mcpl/protocol-family.d.ts.map +1 -0
- package/dist/src/mcpl/protocol-family.js +697 -0
- package/dist/src/mcpl/protocol-family.js.map +1 -0
- package/dist/src/mcpl/push-coalescer.d.ts +38 -19
- package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
- package/dist/src/mcpl/push-coalescer.js +52 -23
- package/dist/src/mcpl/push-coalescer.js.map +1 -1
- package/dist/src/mcpl/reference-fetcher.d.ts +66 -15
- package/dist/src/mcpl/reference-fetcher.d.ts.map +1 -1
- package/dist/src/mcpl/reference-fetcher.js +243 -76
- package/dist/src/mcpl/reference-fetcher.js.map +1 -1
- package/dist/src/mcpl/references.d.ts +63 -18
- package/dist/src/mcpl/references.d.ts.map +1 -1
- package/dist/src/mcpl/references.js +117 -32
- package/dist/src/mcpl/references.js.map +1 -1
- package/dist/src/mcpl/server-connection.d.ts +326 -30
- package/dist/src/mcpl/server-connection.d.ts.map +1 -1
- package/dist/src/mcpl/server-connection.js +995 -212
- package/dist/src/mcpl/server-connection.js.map +1 -1
- package/dist/src/mcpl/server-registry.d.ts +25 -5
- package/dist/src/mcpl/server-registry.d.ts.map +1 -1
- package/dist/src/mcpl/server-registry.js +51 -12
- package/dist/src/mcpl/server-registry.js.map +1 -1
- package/dist/src/mcpl/tool-result-normalize.d.ts +54 -0
- package/dist/src/mcpl/tool-result-normalize.d.ts.map +1 -0
- package/dist/src/mcpl/tool-result-normalize.js +232 -0
- package/dist/src/mcpl/tool-result-normalize.js.map +1 -0
- package/dist/src/mcpl/transport.d.ts +56 -13
- package/dist/src/mcpl/transport.d.ts.map +1 -1
- package/dist/src/mcpl/transport.js +206 -70
- package/dist/src/mcpl/transport.js.map +1 -1
- package/dist/src/mcpl/types.d.ts +66 -20
- package/dist/src/mcpl/types.d.ts.map +1 -1
- package/dist/src/mcpl/types.js.map +1 -1
- package/dist/src/mcpl/visible-content.d.ts +2 -1
- package/dist/src/mcpl/visible-content.d.ts.map +1 -1
- package/dist/src/mcpl/visible-content.js +2 -1
- package/dist/src/mcpl/visible-content.js.map +1 -1
- package/dist/src/module-registry.d.ts +16 -6
- package/dist/src/module-registry.d.ts.map +1 -1
- package/dist/src/module-registry.js +65 -6
- package/dist/src/module-registry.js.map +1 -1
- package/dist/src/modules/api/index.d.ts +1 -1
- package/dist/src/modules/api/index.d.ts.map +1 -1
- package/dist/src/modules/api/index.js +3 -2
- package/dist/src/modules/api/index.js.map +1 -1
- package/dist/src/modules/discord/discord-js-client.d.ts +42 -2
- package/dist/src/modules/discord/discord-js-client.d.ts.map +1 -1
- package/dist/src/modules/discord/discord-js-client.js +268 -65
- package/dist/src/modules/discord/discord-js-client.js.map +1 -1
- package/dist/src/modules/discord/index.d.ts +27 -5
- package/dist/src/modules/discord/index.d.ts.map +1 -1
- package/dist/src/modules/discord/index.js +366 -76
- package/dist/src/modules/discord/index.js.map +1 -1
- package/dist/src/modules/discord/refusal.d.ts +14 -0
- package/dist/src/modules/discord/refusal.d.ts.map +1 -0
- package/dist/src/modules/discord/refusal.js +14 -0
- package/dist/src/modules/discord/refusal.js.map +1 -0
- package/dist/src/modules/discord/types.d.ts +17 -7
- package/dist/src/modules/discord/types.d.ts.map +1 -1
- package/dist/src/modules/health/index.d.ts.map +1 -1
- package/dist/src/modules/health/index.js +6 -2
- package/dist/src/modules/health/index.js.map +1 -1
- package/dist/src/modules/index.d.ts +1 -1
- package/dist/src/modules/index.d.ts.map +1 -1
- package/dist/src/modules/index.js +1 -1
- package/dist/src/modules/index.js.map +1 -1
- package/dist/src/modules/workspace/disk-agreement.d.ts +25 -2
- package/dist/src/modules/workspace/disk-agreement.d.ts.map +1 -1
- package/dist/src/modules/workspace/disk-agreement.js +45 -5
- package/dist/src/modules/workspace/disk-agreement.js.map +1 -1
- package/dist/src/modules/workspace/effects.d.ts +2 -1
- package/dist/src/modules/workspace/effects.d.ts.map +1 -1
- package/dist/src/modules/workspace/effects.js +19 -9
- package/dist/src/modules/workspace/effects.js.map +1 -1
- package/dist/src/modules/workspace/index.d.ts +214 -42
- package/dist/src/modules/workspace/index.d.ts.map +1 -1
- package/dist/src/modules/workspace/index.js +667 -113
- package/dist/src/modules/workspace/index.js.map +1 -1
- package/dist/src/modules/workspace/observe.d.ts +240 -8
- package/dist/src/modules/workspace/observe.d.ts.map +1 -1
- package/dist/src/modules/workspace/observe.js +554 -24
- package/dist/src/modules/workspace/observe.js.map +1 -1
- package/dist/src/modules/workspace/types.d.ts +10 -1
- package/dist/src/modules/workspace/types.d.ts.map +1 -1
- package/dist/src/modules/workspace/types.js.map +1 -1
- package/dist/src/modules/workspace/watcher.d.ts +42 -0
- package/dist/src/modules/workspace/watcher.d.ts.map +1 -1
- package/dist/src/modules/workspace/watcher.js +130 -25
- package/dist/src/modules/workspace/watcher.js.map +1 -1
- package/dist/src/silent-heartbeat.d.ts +112 -39
- package/dist/src/silent-heartbeat.d.ts.map +1 -1
- package/dist/src/silent-heartbeat.js +100 -29
- package/dist/src/silent-heartbeat.js.map +1 -1
- package/dist/src/tool-args.d.ts +40 -0
- package/dist/src/tool-args.d.ts.map +1 -0
- package/dist/src/tool-args.js +207 -0
- package/dist/src/tool-args.js.map +1 -0
- package/dist/src/tool-presentation.d.ts.map +1 -1
- package/dist/src/tool-presentation.js +9 -2
- package/dist/src/tool-presentation.js.map +1 -1
- package/dist/src/types/agent.d.ts +27 -17
- package/dist/src/types/agent.d.ts.map +1 -1
- package/dist/src/types/events.d.ts +8 -0
- package/dist/src/types/events.d.ts.map +1 -1
- package/dist/src/types/framework.d.ts +17 -2
- package/dist/src/types/framework.d.ts.map +1 -1
- package/dist/src/types/module.d.ts +54 -10
- package/dist/src/types/module.d.ts.map +1 -1
- package/dist/src/types/trace.d.ts +2 -2
- package/dist/src/types/trace.d.ts.map +1 -1
- package/package.json +3 -4
- package/src/agent.ts +99 -36
- package/src/code-execution/index.ts +1 -0
- package/src/code-execution/py-runner.ts +104 -17
- package/src/code-execution/runtime-py.ts +47 -7
- package/src/code-execution/tool-definition.ts +65 -11
- package/src/config-checks.ts +4 -2
- package/src/framework.ts +3633 -956
- package/src/gate/event-gate.ts +14 -6
- package/src/held-writes.ts +59 -0
- package/src/index.ts +19 -4
- package/src/mcpl/capability-grant.ts +1 -1
- package/src/mcpl/channel-registry.ts +613 -160
- package/src/mcpl/convert-block.ts +15 -7
- package/src/mcpl/index.ts +14 -1
- package/src/mcpl/inference-router.ts +8 -7
- package/src/mcpl/log-value.ts +10 -0
- package/src/mcpl/modern-connection.ts +1182 -0
- package/src/mcpl/prefix-rule.ts +32 -0
- package/src/mcpl/protocol-family.ts +691 -0
- package/src/mcpl/push-coalescer.ts +67 -29
- package/src/mcpl/reference-fetcher.ts +288 -82
- package/src/mcpl/references.ts +123 -33
- package/src/mcpl/server-connection.ts +1050 -221
- package/src/mcpl/server-registry.ts +50 -12
- package/src/mcpl/tool-result-normalize.ts +294 -0
- package/src/mcpl/transport.ts +204 -62
- package/src/mcpl/types.ts +67 -20
- package/src/mcpl/visible-content.ts +2 -1
- package/src/module-registry.ts +68 -13
- package/src/modules/api/index.ts +3 -2
- package/src/modules/discord/discord-js-client.ts +288 -72
- package/src/modules/discord/index.ts +380 -77
- package/src/modules/discord/refusal.ts +13 -0
- package/src/modules/discord/types.ts +17 -9
- package/src/modules/health/index.ts +6 -2
- package/src/modules/index.ts +1 -1
- package/src/modules/workspace/disk-agreement.ts +46 -5
- package/src/modules/workspace/effects.ts +18 -7
- package/src/modules/workspace/index.ts +722 -124
- package/src/modules/workspace/observe.ts +591 -22
- package/src/modules/workspace/types.ts +10 -1
- package/src/modules/workspace/watcher.ts +126 -25
- package/src/silent-heartbeat.ts +184 -59
- package/src/tool-args.ts +213 -0
- package/src/tool-presentation.ts +9 -2
- package/src/types/agent.ts +27 -17
- package/src/types/events.ts +8 -0
- package/src/types/framework.ts +17 -2
- package/src/types/module.ts +55 -10
- package/src/types/trace.ts +2 -2
package/README.md
CHANGED
|
@@ -64,13 +64,33 @@ Chronicle's audit history.
|
|
|
64
64
|
model: 'claude-opus-4-20250514',
|
|
65
65
|
systemPrompt: '...',
|
|
66
66
|
strategy: new AutobiographicalStrategy({ recentWindowTokens: 30000 }),
|
|
67
|
-
allowedTools: ['search', '
|
|
67
|
+
allowedTools: ['search--query', 'utils', 'files--archive'], // or 'all'
|
|
68
68
|
triggerSources: ['discord'], // or 'all'
|
|
69
69
|
maxTokens: 8192,
|
|
70
70
|
maxStreamTokens: 150_000, // input token budget before stream restart
|
|
71
71
|
}
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
+
`allowedTools` is enforced at dispatch for registered agents. Omission or
|
|
75
|
+
`'all'` permits all tools; an explicit list matches exact names, including
|
|
76
|
+
`module--utility` names. Utilities aren't tools of their own: an agent's model
|
|
77
|
+
and its scripts are offered them only through `utils`, whose `run` checks the
|
|
78
|
+
utility's own name. An agent that should use a utility lists both `utils` and
|
|
79
|
+
`module--utility`. The name alone passes the dispatch check for any call by
|
|
80
|
+
that name, whether the host makes it with `executeToolCall` on the agent's
|
|
81
|
+
behalf or the model or a script makes it without being offered it. The slot
|
|
82
|
+
is hidden when the agent can use no registered utility. If utilities exist
|
|
83
|
+
but none are permitted, `list` returns a failed `ToolResult` with the registered
|
|
84
|
+
and permitted counts and migration advice, and a list containing `utils`
|
|
85
|
+
logs one warning per Agent instance after registration.
|
|
86
|
+
An empty registry still returns a successful empty list.
|
|
87
|
+
|
|
88
|
+
Trusted module calls are exempt from agent allowlists. Genuinely unidentified
|
|
89
|
+
public callers, including unknown legacy caller names, remain unrestricted.
|
|
90
|
+
Framework-created ephemeral and conversation identities fail closed while
|
|
91
|
+
unregistered. Hosts using `createEphemeralAgent` must register and run the
|
|
92
|
+
returned agent through `runEphemeralToCompletion` for tool authority.
|
|
93
|
+
|
|
74
94
|
**Inference modes:**
|
|
75
95
|
- **Streaming** (default in framework): `startStreamWithInjections()` returns a `YieldingStream` that emits tokens, tool calls, and completion events. The framework drives the stream, dispatches tools, and resumes automatically.
|
|
76
96
|
- **Request/response**: `runInferenceWithInjections()` for simple complete-and-return usage with optional `AbortSignal` for cancellation.
|
|
@@ -217,8 +237,11 @@ queue. Switching back to the source branch queues removal of the bot's marker;
|
|
|
217
237
|
returning to the recovery branch queues it again. Initial MCPL events remain
|
|
218
238
|
buffered until the ledger has been reconciled. Startup, reconnect, runtime
|
|
219
239
|
list-change, and online undo use one framework-global generation: every MCPL
|
|
220
|
-
data plane waits while
|
|
221
|
-
marker service.
|
|
240
|
+
data plane waits while the control planes remain live for registration and
|
|
241
|
+
marker service. A connection whose policy exchange is in flight, after a
|
|
242
|
+
connect or a reconnect, keeps both planes closed until the exchange settles,
|
|
243
|
+
since its traffic is admitted against the grant the exchange establishes.
|
|
244
|
+
Awareness marker calls also have a mandatory deadline that is
|
|
222
245
|
independent of `requestTimeoutMs` (including when that value is `0`); configure
|
|
223
246
|
it with `discordAwarenessDeadlineMs` (default 10000ms, clamped to 50..60000ms).
|
|
224
247
|
Configure the online marker with `discordAwarenessEmoji`; the offline CLI
|
|
@@ -255,6 +278,17 @@ defaults to `mcpl--<serverId>`: server `search` with no `toolPrefix` offers
|
|
|
255
278
|
`mcpl--search--query`, and with `toolPrefix: 'search'` it offers
|
|
256
279
|
`search--query`.
|
|
257
280
|
|
|
281
|
+
No two servers' prefixes may meet, since their servers could then give one
|
|
282
|
+
tool name. Two prefixes meet when one is the other's followed by `-`, or
|
|
283
|
+
begins with the other's followed by `--`: server `foo` listing `bar--echo` and
|
|
284
|
+
server `foo--bar` listing `echo` would both give `foo--bar--echo`. `create()`
|
|
285
|
+
refuses such a pair, and so do a runtime connect and a restart (before it
|
|
286
|
+
disconnects anything), naming both servers and the rule. `foo` beside
|
|
287
|
+
`foo-bar` or `foobar` is fine. A server that lists one tool more than once has
|
|
288
|
+
its first listing offered to the model and the rest left out, and each tool
|
|
289
|
+
refresh that finds it raises an `mcpl-tool-duplicate` ops alert naming the
|
|
290
|
+
tools. Its webhook post goes out at most once per server in 15 minutes.
|
|
291
|
+
|
|
258
292
|
These settings take RFC-007 §6.2 patterns (`*` matches any run of characters)
|
|
259
293
|
over that full model-facing name, so they need the prefix:
|
|
260
294
|
|
|
@@ -270,6 +304,72 @@ A pattern that matches no tool is reported once, as a console line and an
|
|
|
270
304
|
A pattern that could name a server's tools is not judged until that server
|
|
271
305
|
has listed them, so late connects and reconnects don't cause early reports.
|
|
272
306
|
|
|
307
|
+
#### Modern MCP servers (2026-07-28)
|
|
308
|
+
|
|
309
|
+
The same `mcplServers` list also takes servers that speak modern MCP
|
|
310
|
+
(revision `2026-07-28`), reached through the official SDK client. The
|
|
311
|
+
configuration chooses the family, and nothing is probed:
|
|
312
|
+
|
|
313
|
+
| Configuration | Family | Transport |
|
|
314
|
+
|---|---|---|
|
|
315
|
+
| `url: 'ws://…'` / `'wss://…'` | MCPL (MCP `2024-11-05`) | WebSocket |
|
|
316
|
+
| `url: 'http://…'` / `'https://…'` | modern MCP | Streamable HTTP (`token` / `accessProvider` as bearer) |
|
|
317
|
+
| `command` | MCPL | stdio |
|
|
318
|
+
| `command` + `protocol: 'modern'` | modern MCP | stdio |
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
{
|
|
322
|
+
mcplServers: [
|
|
323
|
+
{ id: 'docs', url: 'https://mcp.example.com/mcp', accessProvider: getToken },
|
|
324
|
+
{ id: 'search', command: 'search-mcp', protocol: 'modern', reconnect: true },
|
|
325
|
+
],
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
A configuration with both `command` and `url` needs `transport` to say which
|
|
330
|
+
one is used; without it, it is refused rather than silently ignoring one.
|
|
331
|
+
|
|
332
|
+
A modern server's tools get the same prefix, `enabledTools`/`disabledTools`,
|
|
333
|
+
class overrides and dispatch as an MCPL server's, and `listMcplServers()`
|
|
334
|
+
shows its `family`, `protocolVersion` and `transport`. Its config differs in
|
|
335
|
+
three ways:
|
|
336
|
+
- It has no MCPL surface (grant, push, channels, inference requests, feature
|
|
337
|
+
sets). A setting that asks for that surface can't apply, so it is a
|
|
338
|
+
configuration error: `allowHostCommands: true`, an `enabledCapabilities`
|
|
339
|
+
pattern that matches a capability denied by default, `channelSubscription:
|
|
340
|
+
'auto'` or a non-empty list, a scope's non-empty `whitelist`, a
|
|
341
|
+
`toolLifecycle` `observe` or `inputs` block, and a
|
|
342
|
+
`toolLifecycle.maxInputBytes` or an `autofetch` bound above its default.
|
|
343
|
+
A setting
|
|
344
|
+
that only takes something away, or repeats a default, is already
|
|
345
|
+
satisfied, so it is accepted: `enabledFeatureSets` and the rest of
|
|
346
|
+
`enabledCapabilities`, which are allow-lists, `disabledFeatureSets`,
|
|
347
|
+
`disabledCapabilities`, a scope's `blacklist`, `channelSubscription:
|
|
348
|
+
'manual'`, a `toolLifecycle.maxInputBytes` or an `autofetch` bound at or
|
|
349
|
+
below its default, and `shouldTriggerInference`.
|
|
350
|
+
So a host that puts a deny-list on every server it deploys can deploy a
|
|
351
|
+
modern one.
|
|
352
|
+
- `requestTimeoutMs` is one deadline per tool call and must be 1 to 2^31−1;
|
|
353
|
+
0 is refused, where MCPL reads it as no watchdog.
|
|
354
|
+
- Over stdio it takes no credential: `token` or `accessProvider` on one is
|
|
355
|
+
refused.
|
|
356
|
+
|
|
357
|
+
At the deadline, cancellation is requested for a leg still in flight;
|
|
358
|
+
between the rounds of an `input_required` continuation nothing is in flight
|
|
359
|
+
to cancel. Either way the outcome is reported as unknown (`no-response`),
|
|
360
|
+
and the call is never retried. The protocol has no cancel for a paused call,
|
|
361
|
+
so whatever the server holds for it, beyond the `requestState` it gave this
|
|
362
|
+
client, stays until the server lets it go. A call that ends for any other
|
|
363
|
+
reason after the server asked for another round, before its final answer, is
|
|
364
|
+
reported the same way, since the server may already have acted. An MCPL
|
|
365
|
+
server that refuses `2024-11-05` with `-32022` fails with
|
|
366
|
+
`McplProtocolVersionError`, and is not retried. The error names the
|
|
367
|
+
revisions the server says it supports ("none listed" for an empty list), or its error text when it sends no list,
|
|
368
|
+
and when the list includes `2026-07-28` it says to configure the server with
|
|
369
|
+
`protocol: 'modern'` (stdio) or reach it over http(s).
|
|
370
|
+
|
|
371
|
+
Server and transport text the framework records has the server's configured credentials replaced, in both engines. That covers connection traces, console lines, stderr traces, ops alerts, and a tool call's failure as its caller, the model and the `tool:failed` trace get it. The credentials are those the configuration holds and those its dials sent: from the url as each dial sends it (a WebSocket dial sets the token in the query, which writes the whole query again, form-encoded, and an access provider's token can be in it), credential-like path segments and query names, credential-shaped or credential-named query values, and a WebSocket url's userinfo, in their encoded and decoded forms, replaced wherever they occur; every non-empty query parameter as its whole `name=value`, where no letter or digit adjoins it; the static `token`, and each token an access provider handed a dial, the newest sixteen, raw and url-encoded; and a stdio server's `env` values whose names have a part ending in a credential word, such as `GITHUB_TOKEN`, `PGPASSWORD` or `SESSION_COOKIE`, raw and url-encoded. A stdio server's command-line arguments aren't derived. Standalone strings shorter than eight characters stay unchanged because they may be ordinary words; short query values are still removed with their parameter names. Treat a submitted configuration as immutable while the server uses it: apply changes with `restartMcplServer(id, newConfig)`. Secrets neither the configuration holds nor a dial sent remain outside this filtering. JSON-RPC tool answers, and the error a host's own connect raises, pass through as sent.
|
|
372
|
+
|
|
273
373
|
#### Feature sets
|
|
274
374
|
|
|
275
375
|
`enabledFeatureSets` and `disabledFeatureSets` select which of a server's
|
|
@@ -335,6 +435,8 @@ The non-streaming path uses `AbortSignal` forwarded to `membrane.stream()`, whic
|
|
|
335
435
|
|
|
336
436
|
A turn whose stream is cancelled this way, or by `agent.cancelStream()`, ends as a stop, whether the stream reports the cancel as `aborted`, as an `error`, or by just closing: one `inference:aborted` carrying the caller's reason (`user` when none was given), a `[turn-interrupted]` note in the agent's context, and never `inference:exhausted`, which is for failed inferences. A stream that membrane aborts on its own, at a deadline or on an error (reason `timeout` or `error`), is a failed inference. `stop()` and an operator's quiesce abandon end a turn as a stop too, with their own reasons, `shutdown` and `quiesce_abandoned`, and write no note. A stopped stream still writes its inference-log row, with `success: false`.
|
|
337
437
|
|
|
438
|
+
A caller's stop and an operator's quiesce abandon also reach a turn that has no live stream: one running its modules' `gatherContext`, its MCPL hooks or its compile, one waiting to retry a failed inference or compile (`abortInference()` and an operator's abandon end the wait, and a stop through `Agent.cancelStream()` waits for it to run out), and one whose tool-result guard is waiting to retry after a refusal, which holds only the round's finished stream. The turn ends at its next check, before it sends anything more, as a stop on a live stream ends it, and a turn whose compile fails after the stop ends at the failure, before a provider hold, the error policy's retry or `inference:exhausted`. A caller's stop leaves the note saying the turn was stopped before it sent anything or before it finished, and an operator's abandon leaves none. `abortInference()` returns `true` for such a turn. In the guard's wait, `stop()` ends the turn as a stop with reason `shutdown`, and an operator's abandon ends it as the abandon, even when a caller's stop came first; with both, it ends as `stop()`'s. `stop()` drops a turn in its hooks, its compile or a wait to retry before it sends anything, as before, and drops one whose compile fails while it runs, once a caller's stop has reached it, rather than ending it as that stop. While the failure of a turn's stream is reported (`inference:failed`), the agent no longer holds that stream, so `abortInference()` from a listener reports `false`. A failure to build a turn's request is reported while the turn's check is still ahead, so there `abortInference()` reports `true`, and the turn ends at that check. A stop made where no check of a turn is ahead stops nothing, and doesn't end the agent's next turn: while the agent is idle, while a turn finishes its last delivery, while a budget restart or a non-streaming turn's tool results wait to start the turn's next call, and while a provider-capacity hold or a provider's stated wait has parked a turn until the hold ends.
|
|
439
|
+
|
|
338
440
|
## API Server
|
|
339
441
|
|
|
340
442
|
WebSocket server for external clients (UIs, scripts, other agents).
|
package/dist/src/agent.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Membrane, NormalizedRequest, ContentBlock, YieldingStream } from '@animalabs/membrane';
|
|
2
2
|
import type { CacheWireReceipt } from './kv-unified-wire.js';
|
|
3
3
|
import { ToolResultGuard } from './tool-result-guard.js';
|
|
4
|
-
import { type SilentHeartbeatTick } from './silent-heartbeat.js';
|
|
4
|
+
import { type RequestOnlyPrompt, type SilentHeartbeatTick } from './silent-heartbeat.js';
|
|
5
5
|
export interface ActivationRequestOptions {
|
|
6
6
|
/** The silent heartbeat tick this request answers, if any. */
|
|
7
7
|
silentHeartbeat?: SilentHeartbeatTick;
|
|
@@ -12,6 +12,13 @@ export interface ActivationRequestOptions {
|
|
|
12
12
|
export interface StartStreamResult {
|
|
13
13
|
stream: YieldingStream;
|
|
14
14
|
request: NormalizedRequest;
|
|
15
|
+
/** The request-only `[Continue]` prompt this request's reply follows, if
|
|
16
|
+
* any, read from the request: a new one when it ends on `[Continue]`;
|
|
17
|
+
* else, when it ends on tool results, the prompt of the reply that called
|
|
18
|
+
* those tools (`toolLoopPrompt`); else none. The framework stamps the
|
|
19
|
+
* reply's rows with it (`metadata.promptedBy`), for later compiles to
|
|
20
|
+
* render it before them. */
|
|
21
|
+
continuePrompt?: RequestOnlyPrompt;
|
|
15
22
|
takeKvSubmission?: () => {
|
|
16
23
|
submissionId: string;
|
|
17
24
|
wireReceipt: CacheWireReceipt;
|
|
@@ -429,20 +436,24 @@ export declare class Agent {
|
|
|
429
436
|
* may show a withheld stub before its place is added; the activation waits
|
|
430
437
|
* for them around its call.
|
|
431
438
|
*/
|
|
432
|
-
|
|
439
|
+
private assembleActivationRequest;
|
|
433
440
|
/**
|
|
434
441
|
* The request fields that come from this agent's own settings: its model
|
|
435
442
|
* config, prompt caching and cache TTL, prefill message, provider
|
|
436
443
|
* parameters and participant name. Every request the agent sends takes
|
|
437
|
-
* them from here, a framework turn's (
|
|
444
|
+
* them from here, a framework turn's (assembleActivationRequest) and the
|
|
438
445
|
* direct API's (runInferenceWithInjections), so a setting reaches both or
|
|
439
446
|
* neither.
|
|
440
447
|
*/
|
|
441
448
|
private requestSettings;
|
|
442
|
-
/**
|
|
443
|
-
*
|
|
444
|
-
|
|
445
|
-
|
|
449
|
+
/** The request `assembleActivationRequest` builds (see there), for preview
|
|
450
|
+
* and debug tooling: what this agent's next activation would send. */
|
|
451
|
+
buildActivationRequest(availableTools: ToolDefinition[], injections?: ContextInjection[], budget?: TokenBudget, compressionTools?: ToolDefinition[], options?: ActivationRequestOptions): Promise<NormalizedRequest>;
|
|
452
|
+
/** Stored rows that follow a request-only turn, memoized on the store's
|
|
453
|
+
* cached message array (ContextManager returns the same array until the
|
|
454
|
+
* store changes). */
|
|
455
|
+
private requestOnlyIndex;
|
|
456
|
+
private indexRequestOnlyRows;
|
|
446
457
|
/**
|
|
447
458
|
* Start a yielding stream with context injections.
|
|
448
459
|
* Same as startStream but passes injections through to compile.
|
|
@@ -476,14 +487,29 @@ export declare class Agent {
|
|
|
476
487
|
* report the cancel as `error` with no reason at all, so this record is
|
|
477
488
|
* the only provenance a host-side cancel has. */
|
|
478
489
|
private _pendingCancel;
|
|
490
|
+
/** The most recent cancelStream() made while this agent held no stream:
|
|
491
|
+
* during a turn's hooks or compile, while it waits to retry, or while no
|
|
492
|
+
* check of a turn is ahead at all. The framework collects it at the check
|
|
493
|
+
* ahead of it, which ends the turn, and the next start drops one no check
|
|
494
|
+
* collected, so a stop made while none was ahead, such as a host's
|
|
495
|
+
* interrupt of every agent, ends nothing. */
|
|
496
|
+
private _stopWithoutStream;
|
|
479
497
|
/**
|
|
480
498
|
* Cancel the stream this agent's state holds (streaming, waiting on its
|
|
481
499
|
* tools, or ready at a tool boundary with every result in), and reset to
|
|
482
|
-
* idle.
|
|
483
|
-
*
|
|
484
|
-
*
|
|
500
|
+
* idle. With no stream, the stop is kept for the turn in progress, which
|
|
501
|
+
* the framework ends at its next check, before it sends anything more, if
|
|
502
|
+
* one is still ahead; otherwise the next start drops it. `reason` is
|
|
503
|
+
* provenance for the framework's inference:aborted trace and marker
|
|
504
|
+
* metadata (e.g. 'zombie_reclaim', 'subagent_cancel'); it never reaches
|
|
505
|
+
* the provider.
|
|
485
506
|
*/
|
|
486
507
|
cancelStream(reason?: string): void;
|
|
508
|
+
/** Collect (and clear) the cancelStream() made while this agent held no
|
|
509
|
+
* stream, if one was made since the last collection. */
|
|
510
|
+
takeStopWithoutStream(): {
|
|
511
|
+
reason?: string;
|
|
512
|
+
} | undefined;
|
|
487
513
|
/** Collect (and clear) the cancel that ended the current stream, if this
|
|
488
514
|
* side issued one. The stream driver calls it once, while the stream
|
|
489
515
|
* still owns the agent, at the stream's terminal event (`aborted`
|
package/dist/src/agent.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAqB,iBAAiB,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGxH,OAAO,KAAK,EAAE,gBAAgB,EAAyB,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,OAAO,
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/agent.ts"],"names":[],"mappings":"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"}
|
package/dist/src/agent.js
CHANGED
|
@@ -3,7 +3,8 @@ import { createHash } from 'node:crypto';
|
|
|
3
3
|
import { ToolResultGuard } from './tool-result-guard.js';
|
|
4
4
|
import { withoutTokenEstimates } from './thinking-token-stamp.js';
|
|
5
5
|
import { assertBooleanSetting, holdsSettings } from './config-checks.js';
|
|
6
|
-
import {
|
|
6
|
+
import { CONTINUE_ROW, continueTurn, indexRequestOnlyRows, renderRequestOnlyRows, silentHeartbeatSeparatorTurn, tickKey, toolLoopPrompt, } from './silent-heartbeat.js';
|
|
7
|
+
import { randomUUID } from 'node:crypto';
|
|
7
8
|
import { nonErrorResultText, truncateForHistory, DEFAULT_TOOL_RESULT_INLINE_MAX_CHARS, } from './tool-result-history.js';
|
|
8
9
|
function stableHash(value) {
|
|
9
10
|
const encode = (item) => {
|
|
@@ -1070,7 +1071,7 @@ export class Agent {
|
|
|
1070
1071
|
* may show a withheld stub before its place is added; the activation waits
|
|
1071
1072
|
* for them around its call.
|
|
1072
1073
|
*/
|
|
1073
|
-
async
|
|
1074
|
+
async assembleActivationRequest(availableTools, injections, budget, compressionTools = availableTools, options = {}) {
|
|
1074
1075
|
// Compression may revisit hidden tools in recorded history. Keep its full
|
|
1075
1076
|
// definition set separate from the resident's advertised tools: the
|
|
1076
1077
|
// autobiographical strategy must declare the same tools on its
|
|
@@ -1120,17 +1121,31 @@ export class Agent {
|
|
|
1120
1121
|
.filter((m) => m.content.length > 0);
|
|
1121
1122
|
// The framework's own pricing stamp never goes out (thinking-token-stamp.ts).
|
|
1122
1123
|
messages = withoutTokenEstimates(messages);
|
|
1123
|
-
// Silent heartbeat ticks
|
|
1124
|
-
//
|
|
1125
|
-
// cannot merge the
|
|
1126
|
-
//
|
|
1127
|
-
//
|
|
1128
|
-
//
|
|
1129
|
-
//
|
|
1130
|
-
|
|
1131
|
-
|
|
1124
|
+
// Silent heartbeat ticks and replies to a [Continue] turn store no
|
|
1125
|
+
// prompt row. Render each request-only turn before its response's first
|
|
1126
|
+
// surviving row, so the wire formatter cannot merge the response into the
|
|
1127
|
+
// previous assistant message and every later request keeps the prefix
|
|
1128
|
+
// the response was minted under (see silent-heartbeat.ts for what can
|
|
1129
|
+
// and cannot be matched). The request that minted the response ended on
|
|
1130
|
+
// that same turn, so the prefix it caches is the one every later compile
|
|
1131
|
+
// renders. "First" is per agent: a broadcast tick shares its eventId with
|
|
1132
|
+
// every resident.
|
|
1133
|
+
const index = this.indexRequestOnlyRows();
|
|
1134
|
+
const rendered = renderRequestOnlyRows(messages, index, this.name);
|
|
1135
|
+
messages = rendered.messages;
|
|
1136
|
+
// A tick opens wherever its separator isn't already rendered: on its first
|
|
1137
|
+
// request, and on a restart whose compile left none of the tick's rows,
|
|
1138
|
+
// so the restart's reply follows the separator, where every later compile
|
|
1139
|
+
// renders it.
|
|
1132
1140
|
const openingTick = options.silentHeartbeat !== undefined
|
|
1133
|
-
&& !
|
|
1141
|
+
&& !rendered.separatedTicks.has(tickKey(options.silentHeartbeat));
|
|
1142
|
+
// The [Continue] prompt this request's reply follows, read from the
|
|
1143
|
+
// request itself: a new one when it ends on [Continue]; else, when it
|
|
1144
|
+
// ends on tool results, the prompt of the reply that called those tools,
|
|
1145
|
+
// whose tool loop this reply continues; else none. A request that ends
|
|
1146
|
+
// on anything else (a message that arrived during a cooldown, say) gets
|
|
1147
|
+
// a reply that follows that message and carries no prompt.
|
|
1148
|
+
let continuePrompt;
|
|
1134
1149
|
if (openingTick) {
|
|
1135
1150
|
messages = [...messages, silentHeartbeatSeparatorTurn()];
|
|
1136
1151
|
}
|
|
@@ -1138,24 +1153,26 @@ export class Agent {
|
|
|
1138
1153
|
// Safety: ensure messages don't end with an assistant message.
|
|
1139
1154
|
// Some models reject trailing assistant messages ("prefill not supported"),
|
|
1140
1155
|
// and after context compression a stale assistant turn can end up last.
|
|
1141
|
-
messages = [...messages,
|
|
1142
|
-
|
|
1143
|
-
content: [{ type: 'text', text: '[Continue]' }],
|
|
1144
|
-
}];
|
|
1156
|
+
messages = [...messages, continueTurn()];
|
|
1157
|
+
continuePrompt = { turn: randomUUID(), text: CONTINUE_ROW };
|
|
1145
1158
|
}
|
|
1146
|
-
|
|
1159
|
+
else {
|
|
1160
|
+
continuePrompt = toolLoopPrompt(messages.at(-1), index);
|
|
1161
|
+
}
|
|
1162
|
+
const request = {
|
|
1147
1163
|
messages: this.toolResultGuard.prepareRequest(messages),
|
|
1148
1164
|
system: this.buildSystemPrompt(systemInjections),
|
|
1149
1165
|
tools: availableTools.length > 0 ? availableTools : undefined,
|
|
1150
1166
|
...this.requestSettings(),
|
|
1151
1167
|
...(kvUnified ? { cacheMarkers: 'cm-owned' } : {}),
|
|
1152
1168
|
};
|
|
1169
|
+
return { request, ...(continuePrompt ? { continuePrompt } : {}) };
|
|
1153
1170
|
}
|
|
1154
1171
|
/**
|
|
1155
1172
|
* The request fields that come from this agent's own settings: its model
|
|
1156
1173
|
* config, prompt caching and cache TTL, prefill message, provider
|
|
1157
1174
|
* parameters and participant name. Every request the agent sends takes
|
|
1158
|
-
* them from here, a framework turn's (
|
|
1175
|
+
* them from here, a framework turn's (assembleActivationRequest) and the
|
|
1159
1176
|
* direct API's (runInferenceWithInjections), so a setting reaches both or
|
|
1160
1177
|
* neither.
|
|
1161
1178
|
*/
|
|
@@ -1174,24 +1191,30 @@ export class Agent {
|
|
|
1174
1191
|
assistantParticipant: this.name,
|
|
1175
1192
|
};
|
|
1176
1193
|
}
|
|
1177
|
-
/**
|
|
1178
|
-
*
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1194
|
+
/** The request `assembleActivationRequest` builds (see there), for preview
|
|
1195
|
+
* and debug tooling: what this agent's next activation would send. */
|
|
1196
|
+
async buildActivationRequest(availableTools, injections, budget, compressionTools = availableTools, options = {}) {
|
|
1197
|
+
return (await this.assembleActivationRequest(availableTools, injections, budget, compressionTools, options)).request;
|
|
1198
|
+
}
|
|
1199
|
+
/** Stored rows that follow a request-only turn, memoized on the store's
|
|
1200
|
+
* cached message array (ContextManager returns the same array until the
|
|
1201
|
+
* store changes). */
|
|
1202
|
+
requestOnlyIndex = null;
|
|
1203
|
+
indexRequestOnlyRows() {
|
|
1204
|
+
const empty = { ticks: new Map(), prompts: new Map() };
|
|
1182
1205
|
const cm = this.contextManager;
|
|
1183
1206
|
if (typeof cm.getAllMessages !== 'function')
|
|
1184
1207
|
return empty;
|
|
1185
1208
|
try {
|
|
1186
1209
|
const stored = cm.getAllMessages();
|
|
1187
|
-
if (this.
|
|
1188
|
-
return this.
|
|
1189
|
-
const index =
|
|
1190
|
-
this.
|
|
1210
|
+
if (this.requestOnlyIndex?.source === stored)
|
|
1211
|
+
return this.requestOnlyIndex.index;
|
|
1212
|
+
const index = indexRequestOnlyRows(stored, this.name);
|
|
1213
|
+
this.requestOnlyIndex = { source: stored, index };
|
|
1191
1214
|
return index;
|
|
1192
1215
|
}
|
|
1193
1216
|
catch (error) {
|
|
1194
|
-
console.error(`[
|
|
1217
|
+
console.error(`[request-only-rows] ${this.name}: could not index stored rows; request-only turns omitted:`, error);
|
|
1195
1218
|
return empty;
|
|
1196
1219
|
}
|
|
1197
1220
|
}
|
|
@@ -1244,7 +1267,7 @@ export class Agent {
|
|
|
1244
1267
|
// Compiled only once each withheld stub's annotation has finished,
|
|
1245
1268
|
// including one that began during the compile, and after a stub edit that
|
|
1246
1269
|
// failed has been retried (see afterAnnotations).
|
|
1247
|
-
const request = await this.toolResultGuard.afterAnnotations(() => this.
|
|
1270
|
+
const { request, continuePrompt } = await this.toolResultGuard.afterAnnotations(() => this.assembleActivationRequest(availableTools, injections, budget, compressionTools, options));
|
|
1248
1271
|
request.messages = this.toolResultGuard.prepareRequest(request.messages, true);
|
|
1249
1272
|
const receiptAware = this.contextManager
|
|
1250
1273
|
.getStrategy?.();
|
|
@@ -1287,6 +1310,7 @@ export class Agent {
|
|
|
1287
1310
|
return {
|
|
1288
1311
|
stream,
|
|
1289
1312
|
request,
|
|
1313
|
+
...(continuePrompt ? { continuePrompt } : {}),
|
|
1290
1314
|
...(kvEnabled
|
|
1291
1315
|
? {
|
|
1292
1316
|
takeKvSubmission: () => kvQueue.shift(),
|
|
@@ -1375,20 +1399,40 @@ export class Agent {
|
|
|
1375
1399
|
* report the cancel as `error` with no reason at all, so this record is
|
|
1376
1400
|
* the only provenance a host-side cancel has. */
|
|
1377
1401
|
_pendingCancel;
|
|
1402
|
+
/** The most recent cancelStream() made while this agent held no stream:
|
|
1403
|
+
* during a turn's hooks or compile, while it waits to retry, or while no
|
|
1404
|
+
* check of a turn is ahead at all. The framework collects it at the check
|
|
1405
|
+
* ahead of it, which ends the turn, and the next start drops one no check
|
|
1406
|
+
* collected, so a stop made while none was ahead, such as a host's
|
|
1407
|
+
* interrupt of every agent, ends nothing. */
|
|
1408
|
+
_stopWithoutStream;
|
|
1378
1409
|
/**
|
|
1379
1410
|
* Cancel the stream this agent's state holds (streaming, waiting on its
|
|
1380
1411
|
* tools, or ready at a tool boundary with every result in), and reset to
|
|
1381
|
-
* idle.
|
|
1382
|
-
*
|
|
1383
|
-
*
|
|
1412
|
+
* idle. With no stream, the stop is kept for the turn in progress, which
|
|
1413
|
+
* the framework ends at its next check, before it sends anything more, if
|
|
1414
|
+
* one is still ahead; otherwise the next start drops it. `reason` is
|
|
1415
|
+
* provenance for the framework's inference:aborted trace and marker
|
|
1416
|
+
* metadata (e.g. 'zombie_reclaim', 'subagent_cancel'); it never reaches
|
|
1417
|
+
* the provider.
|
|
1384
1418
|
*/
|
|
1385
1419
|
cancelStream(reason) {
|
|
1386
1420
|
if ('stream' in this._state && this._state.stream) {
|
|
1387
1421
|
this._pendingCancel = { reason };
|
|
1388
1422
|
this._state.stream.cancel();
|
|
1389
1423
|
}
|
|
1424
|
+
else {
|
|
1425
|
+
this._stopWithoutStream = { reason };
|
|
1426
|
+
}
|
|
1390
1427
|
this._state = { status: 'idle' };
|
|
1391
1428
|
}
|
|
1429
|
+
/** Collect (and clear) the cancelStream() made while this agent held no
|
|
1430
|
+
* stream, if one was made since the last collection. */
|
|
1431
|
+
takeStopWithoutStream() {
|
|
1432
|
+
const s = this._stopWithoutStream;
|
|
1433
|
+
this._stopWithoutStream = undefined;
|
|
1434
|
+
return s;
|
|
1435
|
+
}
|
|
1392
1436
|
/** Collect (and clear) the cancel that ended the current stream, if this
|
|
1393
1437
|
* side issued one. The stream driver calls it once, while the stream
|
|
1394
1438
|
* still owns the agent, at the stream's terminal event (`aborted`
|