@animalabs/agent-framework 0.8.0 → 0.9.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/dist/src/agent.d.ts +10 -0
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +33 -3
- package/dist/src/agent.js.map +1 -1
- package/dist/src/framework.d.ts +171 -15
- package/dist/src/framework.d.ts.map +1 -1
- package/dist/src/framework.js +1059 -224
- package/dist/src/framework.js.map +1 -1
- package/dist/src/gate/event-gate.d.ts +11 -0
- package/dist/src/gate/event-gate.d.ts.map +1 -1
- package/dist/src/gate/event-gate.js +66 -0
- package/dist/src/gate/event-gate.js.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcpl/capability-grant.d.ts +115 -0
- package/dist/src/mcpl/capability-grant.d.ts.map +1 -0
- package/dist/src/mcpl/capability-grant.js +291 -0
- package/dist/src/mcpl/capability-grant.js.map +1 -0
- package/dist/src/mcpl/capability-mask.d.ts +51 -0
- package/dist/src/mcpl/capability-mask.d.ts.map +1 -0
- package/dist/src/mcpl/capability-mask.js +190 -0
- package/dist/src/mcpl/capability-mask.js.map +1 -0
- package/dist/src/mcpl/channel-registry.d.ts +3 -1
- package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
- package/dist/src/mcpl/channel-registry.js +163 -36
- package/dist/src/mcpl/channel-registry.js.map +1 -1
- package/dist/src/mcpl/checkpoint-manager.d.ts +8 -3
- package/dist/src/mcpl/checkpoint-manager.d.ts.map +1 -1
- package/dist/src/mcpl/checkpoint-manager.js +28 -8
- package/dist/src/mcpl/checkpoint-manager.js.map +1 -1
- package/dist/src/mcpl/errors.d.ts +6 -0
- package/dist/src/mcpl/errors.d.ts.map +1 -1
- package/dist/src/mcpl/errors.js +6 -0
- package/dist/src/mcpl/errors.js.map +1 -1
- package/dist/src/mcpl/feature-set-manager.d.ts +10 -1
- package/dist/src/mcpl/feature-set-manager.d.ts.map +1 -1
- package/dist/src/mcpl/feature-set-manager.js +45 -4
- package/dist/src/mcpl/feature-set-manager.js.map +1 -1
- package/dist/src/mcpl/hook-orchestrator.d.ts +10 -14
- package/dist/src/mcpl/hook-orchestrator.d.ts.map +1 -1
- package/dist/src/mcpl/hook-orchestrator.js +58 -67
- package/dist/src/mcpl/hook-orchestrator.js.map +1 -1
- package/dist/src/mcpl/index.d.ts +1 -1
- package/dist/src/mcpl/index.d.ts.map +1 -1
- package/dist/src/mcpl/index.js.map +1 -1
- package/dist/src/mcpl/prose-stream-router.d.ts +9 -0
- package/dist/src/mcpl/prose-stream-router.d.ts.map +1 -1
- package/dist/src/mcpl/prose-stream-router.js +16 -0
- package/dist/src/mcpl/prose-stream-router.js.map +1 -1
- package/dist/src/mcpl/push-handler.d.ts.map +1 -1
- package/dist/src/mcpl/push-handler.js +20 -2
- package/dist/src/mcpl/push-handler.js.map +1 -1
- package/dist/src/mcpl/server-connection.d.ts +93 -9
- package/dist/src/mcpl/server-connection.d.ts.map +1 -1
- package/dist/src/mcpl/server-connection.js +231 -32
- package/dist/src/mcpl/server-connection.js.map +1 -1
- package/dist/src/mcpl/server-registry.d.ts.map +1 -1
- package/dist/src/mcpl/server-registry.js +4 -3
- package/dist/src/mcpl/server-registry.js.map +1 -1
- package/dist/src/mcpl/tags.d.ts +24 -0
- package/dist/src/mcpl/tags.d.ts.map +1 -0
- package/dist/src/mcpl/tags.js +52 -0
- package/dist/src/mcpl/tags.js.map +1 -0
- package/dist/src/mcpl/transport.d.ts.map +1 -1
- package/dist/src/mcpl/transport.js +10 -0
- package/dist/src/mcpl/transport.js.map +1 -1
- package/dist/src/mcpl/types.d.ts +159 -64
- package/dist/src/mcpl/types.d.ts.map +1 -1
- package/dist/src/mcpl/types.js +16 -2
- package/dist/src/mcpl/types.js.map +1 -1
- package/dist/src/refusal-reactions.d.ts +27 -0
- package/dist/src/refusal-reactions.d.ts.map +1 -0
- package/dist/src/refusal-reactions.js +35 -0
- package/dist/src/refusal-reactions.js.map +1 -0
- package/dist/src/tool-result-history.d.ts +10 -0
- package/dist/src/tool-result-history.d.ts.map +1 -1
- package/dist/src/tool-result-history.js +16 -5
- package/dist/src/tool-result-history.js.map +1 -1
- package/dist/src/types/agent.d.ts +35 -0
- package/dist/src/types/agent.d.ts.map +1 -1
- package/dist/src/types/framework.d.ts +16 -0
- package/dist/src/types/framework.d.ts.map +1 -1
- package/dist/src/types/trace.d.ts +24 -0
- package/dist/src/types/trace.d.ts.map +1 -1
- package/dist/test/channel-registry-routing.test.js +38 -10
- package/dist/test/channel-registry-routing.test.js.map +1 -1
- package/dist/test/channel-registry-typing.test.js +10 -1
- package/dist/test/channel-registry-typing.test.js.map +1 -1
- package/dist/test/checkpoint-attribution.test.js +168 -8
- package/dist/test/checkpoint-attribution.test.js.map +1 -1
- package/dist/test/conversation-fork-injection-scoping.test.js +8 -3
- package/dist/test/conversation-fork-injection-scoping.test.js.map +1 -1
- package/dist/test/event-gate-selfwake.test.d.ts +15 -0
- package/dist/test/event-gate-selfwake.test.d.ts.map +1 -0
- package/dist/test/event-gate-selfwake.test.js +125 -0
- package/dist/test/event-gate-selfwake.test.js.map +1 -0
- package/dist/test/machine-close-provenance.test.js +6 -0
- package/dist/test/machine-close-provenance.test.js.map +1 -1
- package/dist/test/mcpl-awareness-barrier.test.js +10 -0
- package/dist/test/mcpl-awareness-barrier.test.js.map +1 -1
- package/dist/test/mcpl-capability-grant.test.d.ts +10 -0
- package/dist/test/mcpl-capability-grant.test.d.ts.map +1 -0
- package/dist/test/mcpl-capability-grant.test.js +109 -0
- package/dist/test/mcpl-capability-grant.test.js.map +1 -0
- package/dist/test/mcpl-capability-scoping.test.d.ts +2 -0
- package/dist/test/mcpl-capability-scoping.test.d.ts.map +1 -0
- package/dist/test/mcpl-capability-scoping.test.js +266 -0
- package/dist/test/mcpl-capability-scoping.test.js.map +1 -0
- package/dist/test/mcpl-gate-roundtrip.test.js +13 -0
- package/dist/test/mcpl-gate-roundtrip.test.js.map +1 -1
- package/dist/test/mcpl-list-status.test.d.ts +2 -0
- package/dist/test/mcpl-list-status.test.d.ts.map +1 -0
- package/dist/test/mcpl-list-status.test.js +78 -0
- package/dist/test/mcpl-list-status.test.js.map +1 -0
- package/dist/test/mcpl-manifest-changed.test.d.ts +2 -0
- package/dist/test/mcpl-manifest-changed.test.d.ts.map +1 -0
- package/dist/test/mcpl-manifest-changed.test.js +177 -0
- package/dist/test/mcpl-manifest-changed.test.js.map +1 -0
- package/dist/test/mcpl-reconnect-events.test.js +27 -2
- package/dist/test/mcpl-reconnect-events.test.js.map +1 -1
- package/dist/test/mcpl-reconnect-reregistration.test.js +53 -17
- package/dist/test/mcpl-reconnect-reregistration.test.js.map +1 -1
- package/dist/test/mcpl-request-timeout.test.js +1 -1
- package/dist/test/mcpl-request-timeout.test.js.map +1 -1
- package/dist/test/physical-window-restart.test.d.ts +14 -0
- package/dist/test/physical-window-restart.test.d.ts.map +1 -0
- package/dist/test/physical-window-restart.test.js +222 -0
- package/dist/test/physical-window-restart.test.js.map +1 -0
- package/dist/test/present-while-acting.test.js +199 -1
- package/dist/test/present-while-acting.test.js.map +1 -1
- package/dist/test/refusal-reaction-baseline.test.d.ts +2 -0
- package/dist/test/refusal-reaction-baseline.test.d.ts.map +1 -0
- package/dist/test/refusal-reaction-baseline.test.js +74 -0
- package/dist/test/refusal-reaction-baseline.test.js.map +1 -0
- package/dist/test/state-scaling-e2e.test.js +7 -1
- package/dist/test/state-scaling-e2e.test.js.map +1 -1
- package/dist/test/state-scaling.test.js +9 -1
- package/dist/test/state-scaling.test.js.map +1 -1
- package/dist/test/tool-result-spill.test.d.ts +13 -0
- package/dist/test/tool-result-spill.test.d.ts.map +1 -0
- package/dist/test/tool-result-spill.test.js +463 -0
- package/dist/test/tool-result-spill.test.js.map +1 -0
- package/dist/test/trunk-channel-routing.test.js +45 -0
- package/dist/test/trunk-channel-routing.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/agent.ts +37 -3
- package/src/framework.ts +1219 -248
- package/src/gate/event-gate.ts +72 -0
- package/src/index.ts +1 -0
- package/src/mcpl/capability-grant.ts +319 -0
- package/src/mcpl/capability-mask.ts +228 -0
- package/src/mcpl/channel-registry.ts +167 -39
- package/src/mcpl/checkpoint-manager.ts +28 -8
- package/src/mcpl/errors.ts +7 -0
- package/src/mcpl/feature-set-manager.ts +50 -5
- package/src/mcpl/hook-orchestrator.ts +64 -86
- package/src/mcpl/index.ts +0 -2
- package/src/mcpl/prose-stream-router.ts +17 -0
- package/src/mcpl/push-handler.ts +18 -2
- package/src/mcpl/server-connection.ts +262 -34
- package/src/mcpl/server-registry.ts +4 -3
- package/src/mcpl/tags.ts +50 -0
- package/src/mcpl/transport.ts +11 -0
- package/src/mcpl/types.ts +176 -78
- package/src/refusal-reactions.ts +37 -0
- package/src/tool-result-history.ts +17 -5
- package/src/types/agent.ts +36 -0
- package/src/types/framework.ts +17 -0
- package/src/types/trace.ts +22 -0
package/src/mcpl/types.ts
CHANGED
|
@@ -99,22 +99,32 @@ export interface McplResourceContent {
|
|
|
99
99
|
* Parsed from the server's `initialize` response.
|
|
100
100
|
*/
|
|
101
101
|
export interface McplCapabilities {
|
|
102
|
-
/** MCPL protocol version (e.g., "0.
|
|
102
|
+
/** MCPL protocol version (e.g., "0.5") */
|
|
103
103
|
version: string;
|
|
104
104
|
|
|
105
|
+
/** §17.2 canonical content digest; absent = manifest fixed at initialize. */
|
|
106
|
+
revision?: string;
|
|
107
|
+
|
|
105
108
|
/** Server supports push/event */
|
|
106
109
|
pushEvents?: boolean;
|
|
107
110
|
|
|
108
|
-
/**
|
|
111
|
+
/**
|
|
112
|
+
* Context hooks — §5.1 recursive shape. Boolean `true` at any level is
|
|
113
|
+
* shorthand for every leaf beneath it. `afterInference` is REMOVED in
|
|
114
|
+
* 0.5.0 (replaced by metadata-only inference/lifecycle, §10.5).
|
|
115
|
+
*/
|
|
109
116
|
contextHooks?: {
|
|
110
|
-
beforeInference?: boolean
|
|
111
|
-
|
|
117
|
+
beforeInference?: boolean | {
|
|
118
|
+
observe?: boolean;
|
|
119
|
+
inject?: { system?: boolean; beforeUser?: boolean; afterUser?: boolean };
|
|
120
|
+
};
|
|
112
121
|
};
|
|
113
122
|
|
|
114
|
-
/** Server-initiated inference
|
|
115
|
-
inferenceRequest?: {
|
|
116
|
-
|
|
117
|
-
|
|
123
|
+
/** Server-initiated inference. `true` = the capability with no refinements. */
|
|
124
|
+
inferenceRequest?: boolean | { streaming?: boolean };
|
|
125
|
+
|
|
126
|
+
/** Server consumes inference/lifecycle notifications (§10.5). */
|
|
127
|
+
inferenceLifecycle?: boolean;
|
|
118
128
|
|
|
119
129
|
/** Server supports model/info requests */
|
|
120
130
|
modelInfo?: boolean;
|
|
@@ -122,8 +132,8 @@ export interface McplCapabilities {
|
|
|
122
132
|
/** Declared feature sets (keyed by feature set name) */
|
|
123
133
|
featureSets?: Record<string, FeatureSetDeclaration>;
|
|
124
134
|
|
|
125
|
-
/** Channel capabilities */
|
|
126
|
-
channels?: McplChannelCapabilities;
|
|
135
|
+
/** Channel capabilities — §14.1 object of leaves, or `true` for all. */
|
|
136
|
+
channels?: boolean | McplChannelCapabilities;
|
|
127
137
|
}
|
|
128
138
|
|
|
129
139
|
/**
|
|
@@ -134,23 +144,28 @@ export interface McplHostCapabilities {
|
|
|
134
144
|
version: string;
|
|
135
145
|
pushEvents?: boolean;
|
|
136
146
|
contextHooks?: {
|
|
137
|
-
beforeInference?: boolean
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
streaming?: boolean;
|
|
147
|
+
beforeInference?: boolean | {
|
|
148
|
+
observe?: boolean;
|
|
149
|
+
inject?: { system?: boolean; beforeUser?: boolean; afterUser?: boolean };
|
|
150
|
+
};
|
|
142
151
|
};
|
|
152
|
+
inferenceRequest?: boolean | { streaming?: boolean };
|
|
153
|
+
inferenceLifecycle?: boolean;
|
|
154
|
+
modelInfo?: boolean;
|
|
143
155
|
featureSets?: boolean;
|
|
144
|
-
channels?: McplChannelCapabilities;
|
|
156
|
+
channels?: boolean | McplChannelCapabilities;
|
|
145
157
|
}
|
|
146
158
|
|
|
147
|
-
/** Channel
|
|
159
|
+
/** Channel capability leaves (§14.1). `observe` was the pre-0.5 name for
|
|
160
|
+
* what split into `incoming` — removed, not aliased. */
|
|
148
161
|
export interface McplChannelCapabilities {
|
|
149
162
|
register?: boolean;
|
|
150
|
-
publish?: boolean;
|
|
151
|
-
observe?: boolean;
|
|
152
163
|
lifecycle?: boolean;
|
|
164
|
+
publish?: boolean;
|
|
165
|
+
incoming?: boolean;
|
|
153
166
|
streaming?: boolean;
|
|
167
|
+
acknowledge?: boolean;
|
|
168
|
+
typing?: boolean;
|
|
154
169
|
}
|
|
155
170
|
|
|
156
171
|
// ============================================================================
|
|
@@ -209,6 +224,15 @@ export interface McplServerConfig {
|
|
|
209
224
|
*/
|
|
210
225
|
accessProvider?: () => Promise<string | null>;
|
|
211
226
|
|
|
227
|
+
/**
|
|
228
|
+
* Host-owned authority for the `host/command` admin surface (undo / hide /
|
|
229
|
+
* unstick). DEFAULT FALSE: no §6.2 capability path exists for it, and the
|
|
230
|
+
* grant cannot confer it — only this config, decided by the operator, can
|
|
231
|
+
* (PR #79 review blocker 9). The one legitimate fleet user is
|
|
232
|
+
* discord-mcpl's slash-command relay.
|
|
233
|
+
*/
|
|
234
|
+
allowHostCommands?: boolean;
|
|
235
|
+
|
|
212
236
|
/** Feature sets to enable on connect */
|
|
213
237
|
enabledFeatureSets?: string[];
|
|
214
238
|
|
|
@@ -233,6 +257,37 @@ export interface McplServerConfig {
|
|
|
233
257
|
*/
|
|
234
258
|
disabledTools?: string[];
|
|
235
259
|
|
|
260
|
+
/**
|
|
261
|
+
* Capability allow-list: dotted paths as the server advertises them in its
|
|
262
|
+
* initialize response (`pushEvents`, `contextHooks.beforeInference`,
|
|
263
|
+
* `contextHooks.afterInference`, `inferenceRequest`, `modelInfo`,
|
|
264
|
+
* `channels`, `channels.streaming`, …). `*` matches one dot-segment
|
|
265
|
+
* (feature-set pattern rules), and a pattern matching a parent
|
|
266
|
+
* (`contextHooks`) covers every flag beneath it.
|
|
267
|
+
*
|
|
268
|
+
* If set, only advertised capabilities matching at least one pattern
|
|
269
|
+
* survive the handshake; everything else behaves as if the server had
|
|
270
|
+
* never advertised it. This is the host-side gate on hook fan-out: a
|
|
271
|
+
* server whose `contextHooks.afterInference` is masked never receives
|
|
272
|
+
* turn text, no matter what it self-advertises. Masked server-initiated
|
|
273
|
+
* capabilities (`pushEvents`, `inferenceRequest`, whole-`channels`) are
|
|
274
|
+
* also enforced inbound — the connection rejects those methods with
|
|
275
|
+
* CAPABILITY_DISABLED (-32002).
|
|
276
|
+
*
|
|
277
|
+
* `disabledCapabilities` takes precedence on conflict. `version` and
|
|
278
|
+
* `featureSets` are not maskable here — feature sets have their own
|
|
279
|
+
* enable/disable knobs above.
|
|
280
|
+
*/
|
|
281
|
+
enabledCapabilities?: string[];
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Capability deny-list (same paths and wildcard syntax as
|
|
285
|
+
* enabledCapabilities). Wins over enabledCapabilities on conflict.
|
|
286
|
+
* `disabledCapabilities: ['contextHooks.*']` is the one-line "this server
|
|
287
|
+
* gets no hook visibility" switch.
|
|
288
|
+
*/
|
|
289
|
+
disabledCapabilities?: string[];
|
|
290
|
+
|
|
236
291
|
/** Scope configurations per feature set */
|
|
237
292
|
scopes?: Record<string, ScopeConfig>;
|
|
238
293
|
|
|
@@ -352,16 +407,51 @@ export interface FeatureSetDeclaration {
|
|
|
352
407
|
* Spec Section 6.7.
|
|
353
408
|
*/
|
|
354
409
|
export interface FeatureSetsUpdateParams {
|
|
355
|
-
/**
|
|
410
|
+
/**
|
|
411
|
+
* The effective capability grant (§5.4) — the sole normative allowlist.
|
|
412
|
+
* Full §6.2 paths. Absence of a path is denial. In the Request form an
|
|
413
|
+
* absent FIELD is a grant of nothing (§5.3 as pinned 2026-08-02), never
|
|
414
|
+
* "no change".
|
|
415
|
+
*/
|
|
416
|
+
effectiveCapabilities?: string[];
|
|
417
|
+
|
|
418
|
+
/** Advertised-but-denied paths. Diagnostic only (§5.4) — MUST NOT
|
|
419
|
+
* participate in any authorization decision on either side. */
|
|
420
|
+
deniedCapabilities?: string[];
|
|
421
|
+
|
|
422
|
+
/** Feature sets to enable. Absent = no constraint (derivation governs);
|
|
423
|
+
* present = allowlist (§5.3 as pinned). */
|
|
356
424
|
enabled?: string[];
|
|
357
425
|
|
|
358
426
|
/** Feature sets to disable */
|
|
359
427
|
disabled?: string[];
|
|
360
|
-
|
|
361
|
-
/** Scope configurations per feature set */
|
|
362
|
-
scopes?: Record<string, ScopeConfig>;
|
|
363
428
|
}
|
|
364
429
|
|
|
430
|
+
/**
|
|
431
|
+
* featureSets/update result — the degradation receipt (§6.7). Consequence
|
|
432
|
+
* testimony, never policy authority: the host MUST NOT widen any grant in
|
|
433
|
+
* response to anything in here.
|
|
434
|
+
*/
|
|
435
|
+
export type FeatureSetsUpdateResult =
|
|
436
|
+
| {
|
|
437
|
+
accepted: true;
|
|
438
|
+
/** Omitted when nothing degraded (§6.7). */
|
|
439
|
+
mode?: 'degraded';
|
|
440
|
+
unavailableFeatures?: Array<{
|
|
441
|
+
featureSet: string;
|
|
442
|
+
missingCapabilities: string[];
|
|
443
|
+
effect: string;
|
|
444
|
+
}>;
|
|
445
|
+
notes?: string[];
|
|
446
|
+
}
|
|
447
|
+
| {
|
|
448
|
+
accepted: false;
|
|
449
|
+
/** REQUIRED on refusal (§6.7): the server names which applies. */
|
|
450
|
+
fallback: 'mcp-only' | 'close';
|
|
451
|
+
missingCapabilities?: string[];
|
|
452
|
+
reason?: string;
|
|
453
|
+
};
|
|
454
|
+
|
|
365
455
|
/**
|
|
366
456
|
* featureSets/changed params (Server → Host, Notification).
|
|
367
457
|
* Spec Section 6.7.
|
|
@@ -556,18 +646,48 @@ export interface PushEventResult {
|
|
|
556
646
|
* Distinct from membrane's ModelInfo which tracks requested vs actual model.
|
|
557
647
|
* Spec Section 10.1.
|
|
558
648
|
*/
|
|
649
|
+
/**
|
|
650
|
+
* inference/lifecycle params (Host → Server, Notification). SPEC §10.5.
|
|
651
|
+
*
|
|
652
|
+
* BEST-EFFORT: the host attempts exactly one terminal phase per `started`
|
|
653
|
+
* on every exit path it controls, but an unacknowledged Notification cannot
|
|
654
|
+
* guarantee delivery — consumers MUST dedupe by inferenceId and MUST retain
|
|
655
|
+
* a safety timeout. Carries no content: `modifiedResponse` and the blocking
|
|
656
|
+
* hook form are gone with context/afterInference.
|
|
657
|
+
*/
|
|
658
|
+
export interface InferenceLifecycleParams {
|
|
659
|
+
inferenceId: string;
|
|
660
|
+
conversationId: string;
|
|
661
|
+
turnIndex: number;
|
|
662
|
+
phase: 'started' | 'completed' | 'aborted' | 'failed';
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
/** mcpl/manifestChanged params (Server → Host, Notification). §17.3. */
|
|
666
|
+
export interface ManifestChangedParams {
|
|
667
|
+
/** §17.2 canonical content digest. Untrusted; equality-only. */
|
|
668
|
+
revision: string;
|
|
669
|
+
/** Subset of the three §17.1 domains. A hint the host MAY ignore. */
|
|
670
|
+
domains: Array<'capabilities' | 'featureSets' | 'tagOntology'>;
|
|
671
|
+
}
|
|
672
|
+
|
|
559
673
|
export interface McplModelInfo {
|
|
560
674
|
/** Model identifier (e.g., "claude-opus-4-5-20251101") */
|
|
561
675
|
id: string;
|
|
562
676
|
|
|
563
|
-
/** Model vendor (e.g., "anthropic")
|
|
564
|
-
|
|
677
|
+
/** Model vendor (e.g., "anthropic"). Omitted when the host has no
|
|
678
|
+
* truthful source — never fabricated. */
|
|
679
|
+
vendor?: string;
|
|
565
680
|
|
|
566
|
-
/** Context window size in tokens
|
|
567
|
-
|
|
681
|
+
/** Context window size in tokens. Omitted when unknown (a numeric field
|
|
682
|
+
* cannot express "unknown", and a fabricated 200000 was false for
|
|
683
|
+
* residents configured at 300k/600k — PR #79 review). The §12.2
|
|
684
|
+
* model/info RESULT requires it, which is why this host does not
|
|
685
|
+
* advertise modelInfo; hook params carry honesty-over-completeness. */
|
|
686
|
+
contextWindow?: number;
|
|
568
687
|
|
|
569
|
-
/** Model capabilities (e.g., ["vision", "tools"])
|
|
570
|
-
|
|
688
|
+
/** Model capabilities (e.g., ["vision", "tools"]). Omitted when the
|
|
689
|
+
* host has no truthful source. */
|
|
690
|
+
capabilities?: string[];
|
|
571
691
|
}
|
|
572
692
|
|
|
573
693
|
/**
|
|
@@ -629,53 +749,6 @@ export interface BeforeInferenceResult {
|
|
|
629
749
|
contextInjections: McplContextInjection[];
|
|
630
750
|
}
|
|
631
751
|
|
|
632
|
-
/**
|
|
633
|
-
* context/afterInference params (Host → Server, Request or Notification).
|
|
634
|
-
* Spec Section 10.5.
|
|
635
|
-
*/
|
|
636
|
-
export interface AfterInferenceParams {
|
|
637
|
-
/** Inference identifier (matches beforeInference) */
|
|
638
|
-
inferenceId: string;
|
|
639
|
-
|
|
640
|
-
/** Persistent across turns */
|
|
641
|
-
conversationId: string;
|
|
642
|
-
|
|
643
|
-
/** 0-indexed turn number */
|
|
644
|
-
turnIndex: number;
|
|
645
|
-
|
|
646
|
-
/** Original user input */
|
|
647
|
-
userMessage: string | null;
|
|
648
|
-
|
|
649
|
-
/** Generated assistant response */
|
|
650
|
-
assistantMessage: string;
|
|
651
|
-
|
|
652
|
-
/** Model metadata */
|
|
653
|
-
model: McplModelInfo;
|
|
654
|
-
|
|
655
|
-
/** Token usage */
|
|
656
|
-
usage: {
|
|
657
|
-
inputTokens: number;
|
|
658
|
-
outputTokens: number;
|
|
659
|
-
cacheCreationTokens?: number;
|
|
660
|
-
cacheReadTokens?: number;
|
|
661
|
-
};
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
/**
|
|
665
|
-
* context/afterInference result (Server → Host, only for blocking hooks).
|
|
666
|
-
* Spec Section 10.5.
|
|
667
|
-
*/
|
|
668
|
-
export interface AfterInferenceResult {
|
|
669
|
-
/** Feature set that provided this response */
|
|
670
|
-
featureSet: string;
|
|
671
|
-
|
|
672
|
-
/** Modified response text (replaces assistantMessage if present) */
|
|
673
|
-
modifiedResponse?: string;
|
|
674
|
-
|
|
675
|
-
/** Arbitrary metadata */
|
|
676
|
-
metadata?: Record<string, unknown>;
|
|
677
|
-
}
|
|
678
|
-
|
|
679
752
|
// ============================================================================
|
|
680
753
|
// Section 11 — Server-Initiated Inference
|
|
681
754
|
// ============================================================================
|
|
@@ -861,7 +934,14 @@ export interface ChannelsRegisterParams {
|
|
|
861
934
|
* channels/register result (Host → Server).
|
|
862
935
|
*/
|
|
863
936
|
export interface ChannelsRegisterResult {
|
|
937
|
+
/** Legacy pre-0.5 field: ids accepted. Kept for un-migrated servers. */
|
|
864
938
|
registered: string[];
|
|
939
|
+
/**
|
|
940
|
+
* §14.5 itemized results — one entry per SUBMITTED descriptor. 0.5
|
|
941
|
+
* servers key off this: a missing verdict is not a verdict, and a result
|
|
942
|
+
* without `results` is read by strict servers as accepting nothing.
|
|
943
|
+
*/
|
|
944
|
+
results: Array<{ id: string; accepted: boolean; reason?: string }>;
|
|
865
945
|
}
|
|
866
946
|
|
|
867
947
|
/**
|
|
@@ -1033,6 +1113,8 @@ export interface ChannelIncomingMessageResult {
|
|
|
1033
1113
|
messageId: string;
|
|
1034
1114
|
accepted: boolean;
|
|
1035
1115
|
conversationId?: string;
|
|
1116
|
+
/** §14.5: why a message was rejected (e.g. unknown/unregistered channel). */
|
|
1117
|
+
reason?: string;
|
|
1036
1118
|
}
|
|
1037
1119
|
|
|
1038
1120
|
// ============================================================================
|
|
@@ -1066,9 +1148,13 @@ export const McplMethod = {
|
|
|
1066
1148
|
// Push events (Server → Host)
|
|
1067
1149
|
PushEvent: 'push/event',
|
|
1068
1150
|
|
|
1069
|
-
// Context hooks (Host → Server)
|
|
1151
|
+
// Context hooks (Host → Server). context/afterInference is gone with the
|
|
1152
|
+
// rest of its surface: removed from the spec in 0.5.0 (§10.5, replaced by
|
|
1153
|
+
// inference/lifecycle), never sent by the runtime, and not part of the
|
|
1154
|
+
// package's public API. Pre-0.5 SERVERS' wire handlers for it are their
|
|
1155
|
+
// own compatibility surface, retired on the fleet-on-0.5 evidence
|
|
1156
|
+
// schedule, not here.
|
|
1070
1157
|
BeforeInference: 'context/beforeInference',
|
|
1071
|
-
AfterInference: 'context/afterInference',
|
|
1072
1158
|
|
|
1073
1159
|
// Server-initiated inference (Server → Host / Host → Server)
|
|
1074
1160
|
InferenceRequest: 'inference/request',
|
|
@@ -1077,6 +1163,18 @@ export const McplMethod = {
|
|
|
1077
1163
|
// Model info (Server → Host)
|
|
1078
1164
|
ModelInfo: 'model/info',
|
|
1079
1165
|
|
|
1166
|
+
// Inference lifecycle (Host → Server, Notification) — §10.5, replaces
|
|
1167
|
+
// context/afterInference. Metadata only; BEST-EFFORT delivery.
|
|
1168
|
+
InferenceLifecycle: 'inference/lifecycle',
|
|
1169
|
+
|
|
1170
|
+
// Server manifest changes (§17). manifestChanged is S→H Notification —
|
|
1171
|
+
// an opaque revision plus changed domains, NO payload, deliberately
|
|
1172
|
+
// ungated (§17.3: gating it would silence exactly the servers whose
|
|
1173
|
+
// grants just narrowed). manifest is H→S Request returning the complete
|
|
1174
|
+
// current experimental.mcpl object, never a delta.
|
|
1175
|
+
ManifestChanged: 'mcpl/manifestChanged',
|
|
1176
|
+
Manifest: 'mcpl/manifest',
|
|
1177
|
+
|
|
1080
1178
|
// Feature sets
|
|
1081
1179
|
FeatureSetsUpdate: 'featureSets/update',
|
|
1082
1180
|
FeatureSetsChanged: 'featureSets/changed',
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Refusal-reaction markers — the single source of truth for the emoji the
|
|
3
|
+
* framework places on a message when inference is refused (see
|
|
4
|
+
* AgentFramework.reactToRefusal), exported so host composition can derive
|
|
5
|
+
* a protective suppression baseline from the exact set the framework emits.
|
|
6
|
+
*
|
|
7
|
+
* These annotations are placed by the framework on the resident's account
|
|
8
|
+
* and must never re-enter a resident's context as reaction events — that is
|
|
9
|
+
* the self-amplifying loop behind the 8/3 Mythos incident. The Discord
|
|
10
|
+
* adapter suppresses them when its operator config or the host-injected
|
|
11
|
+
* `DISCORD_SUPPRESSED_REACTIONS_BASELINE` names them; keeping the emitted
|
|
12
|
+
* set and the exported baseline as one constant is what makes drift between
|
|
13
|
+
* "what we stamp" and "what we suppress" structurally impossible, rather
|
|
14
|
+
* than a promise kept in two files.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/** Refusal category → Discord reaction emoji. Unknown categories get the
|
|
18
|
+
* fallback marker. */
|
|
19
|
+
export const REFUSAL_REACTIONS: Readonly<Record<string, string>> = {
|
|
20
|
+
bio: '☣️',
|
|
21
|
+
chem: '🧪',
|
|
22
|
+
nuclear: '☢️',
|
|
23
|
+
cyber: '💻',
|
|
24
|
+
reasoning_extraction: '🧠',
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/** Marker used when the refusal category has no dedicated emoji. */
|
|
28
|
+
export const REFUSAL_REACTION_FALLBACK = '🛑';
|
|
29
|
+
|
|
30
|
+
/** Every marker the framework can emit — the category map plus the
|
|
31
|
+
* fallback, deduplicated, in stable declaration order. This IS the
|
|
32
|
+
* protective baseline: host composition serializes it (comma-joined) into
|
|
33
|
+
* `DISCORD_SUPPRESSED_REACTIONS_BASELINE` for adapters that render
|
|
34
|
+
* reactions. */
|
|
35
|
+
export const REFUSAL_REACTION_BASELINE: readonly string[] = [
|
|
36
|
+
...new Set([...Object.values(REFUSAL_REACTIONS), REFUSAL_REACTION_FALLBACK]),
|
|
37
|
+
];
|
|
@@ -16,14 +16,26 @@
|
|
|
16
16
|
|
|
17
17
|
import { safeSlice } from './safe-slice.js';
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* House-safe default inline cap (chars) for tool results, error results, and
|
|
21
|
+
* background-script wake payloads (issue #89: a resident should never eat a
|
|
22
|
+
* 42k blob they didn't ask for). Durable per-residence value comes from
|
|
23
|
+
* `FrameworkConfig.toolResultInlineMaxChars`; a temporary per-agent lift from
|
|
24
|
+
* agent_settings `tool_result_inline_max_chars`.
|
|
25
|
+
*/
|
|
26
|
+
export const DEFAULT_TOOL_RESULT_INLINE_MAX_CHARS = 5000;
|
|
27
|
+
|
|
19
28
|
export function toolResultDataToHistoryString(data: unknown, maxChars?: number): string {
|
|
20
29
|
const fromArray = tryHistoryStringFromContentArray(data);
|
|
21
30
|
const str = fromArray ?? JSON.stringify(data);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
31
|
+
return maxChars ? truncateForHistory(str, maxChars) : str;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Bounded copy of an arbitrary string with the standard truncation notice. */
|
|
35
|
+
export function truncateForHistory(str: string, maxChars: number): string {
|
|
36
|
+
if (str.length <= maxChars) return str;
|
|
37
|
+
return safeSlice(str, 0, maxChars)
|
|
38
|
+
+ '\n\n[truncated — original was ' + str.length + ' chars]';
|
|
27
39
|
}
|
|
28
40
|
|
|
29
41
|
/**
|
package/src/types/agent.ts
CHANGED
|
@@ -48,6 +48,17 @@ export interface AgentConfig {
|
|
|
48
48
|
* restarts with recompiled (compressed) context. Default: 150000. */
|
|
49
49
|
maxStreamTokens?: number;
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* The model's PHYSICAL context window (provider hard cap, e.g. 200000).
|
|
53
|
+
* When set, the framework projects each continuation round's real size
|
|
54
|
+
* (cache-inclusive input of the prior round + the blocks about to be
|
|
55
|
+
* appended + reserve for response) and restarts the stream through a fresh
|
|
56
|
+
* compile instead of dispatching a request the provider will 400
|
|
57
|
+
* (issue #92: a legal compile can walk past the physical window mid-turn).
|
|
58
|
+
* Unset → no projection; only the maxStreamTokens restart applies.
|
|
59
|
+
*/
|
|
60
|
+
physicalWindowTokens?: number;
|
|
61
|
+
|
|
51
62
|
/** Per-agent context compile budget (input tokens). When unset, the
|
|
52
63
|
* ContextManager's built-in default (100k) applies. */
|
|
53
64
|
contextBudgetTokens?: number;
|
|
@@ -122,6 +133,31 @@ export interface AgentConfig {
|
|
|
122
133
|
* a poison turn. Default: off (a refusal just surfaces a marker + reaction).
|
|
123
134
|
*/
|
|
124
135
|
refusalHandling?: {
|
|
136
|
+
/**
|
|
137
|
+
* Same-model retries on a content-policy refusal, performed by MEMBRANE
|
|
138
|
+
* at the provider seam (passed through as `refusalRetries`). Default 0.
|
|
139
|
+
*
|
|
140
|
+
* Near the classifier's threshold a refusal is probabilistic rather than a
|
|
141
|
+
* property of the payload: identical bytes pass and refuse minutes apart
|
|
142
|
+
* (mythos, 2026-07-27 replay reps). So the first response is to ask again
|
|
143
|
+
* — no context surgery, no fallback model. Membrane replays the SAME
|
|
144
|
+
* request immediately and cache-warm, so only the discarded output tokens
|
|
145
|
+
* are real spend.
|
|
146
|
+
*
|
|
147
|
+
* Retrying in the framework instead was tried and removed: a requeue
|
|
148
|
+
* recompiles, so the attempts are correlated rather than fresh draws, and
|
|
149
|
+
* it cannot tell a streaming consumer to drop the abandoned attempt.
|
|
150
|
+
* Membrane announces each retry with a `retrying` stream event, which
|
|
151
|
+
* driveStream handles by discarding what was streamed.
|
|
152
|
+
*
|
|
153
|
+
* Retries are spent before the framework sees the refusal at all, so the
|
|
154
|
+
* escalation order is: membrane retries -> autoRewind (if on) -> the
|
|
155
|
+
* refusal reaction, which therefore means "the border is close" rather
|
|
156
|
+
* than firing on every near-threshold flip.
|
|
157
|
+
*
|
|
158
|
+
* Native tool mode only — see the XML-mode warning in Membrane.
|
|
159
|
+
*/
|
|
160
|
+
retries?: number;
|
|
125
161
|
/** Auto-rewind the triggering turn on refusal and retry. Default false. */
|
|
126
162
|
autoRewind?: boolean;
|
|
127
163
|
/** Max consecutive rewinds before giving up a turn. Default 3. */
|
package/src/types/framework.ts
CHANGED
|
@@ -138,6 +138,23 @@ export interface FrameworkConfig {
|
|
|
138
138
|
*/
|
|
139
139
|
codeExecution?: CodeExecutionConfig;
|
|
140
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Durable inline cap (chars) for tool results — successes AND errors — and
|
|
143
|
+
* background-script wake payloads. Content over the cap is written to a
|
|
144
|
+
* workspace file under `tool-results/` (deterministic `<date>-<callId>.txt`
|
|
145
|
+
* name, overwritten on collision, retained until the workspace owner
|
|
146
|
+
* deletes it — never auto-GC'd) and replaced inline by a bounded preview
|
|
147
|
+
* plus the file reference; with no writable workspace the fallback is
|
|
148
|
+
* explicit plain truncation. Default 5000 (house-safe; issue #89). Must be
|
|
149
|
+
* >= 1000. A resident's own agent_settings value
|
|
150
|
+
* `tool_result_inline_max_chars` (durable, persisted in framework state)
|
|
151
|
+
* takes precedence over this for that agent; the EFFECTIVE cap for every
|
|
152
|
+
* source is min(desired, strategy bound) — desired values above the
|
|
153
|
+
* strategy-derived bound (maxMessageTokens * 4) are hard-clamped to it,
|
|
154
|
+
* with the clamp reported via agent_settings get.
|
|
155
|
+
*/
|
|
156
|
+
toolResultInlineMaxChars?: number;
|
|
157
|
+
|
|
141
158
|
/** Inference routing policy for server-initiated inference (optional). */
|
|
142
159
|
inferenceRouting?: InferenceRoutingPolicy;
|
|
143
160
|
|
package/src/types/trace.ts
CHANGED
|
@@ -169,6 +169,19 @@ export type TraceEvent =
|
|
|
169
169
|
agentStatus: string;
|
|
170
170
|
result: unknown;
|
|
171
171
|
})
|
|
172
|
+
| (TraceEventBase & {
|
|
173
|
+
/**
|
|
174
|
+
* A writable workspace existed but the oversized-result spill write
|
|
175
|
+
* failed (size cap, storeBlob failure, …) — the over-cap tail was NOT
|
|
176
|
+
* retained. Distinct from the no-workspace fallback, which is silent
|
|
177
|
+
* by design (nothing unexpected happened).
|
|
178
|
+
*/
|
|
179
|
+
type: 'tool:spill_failed';
|
|
180
|
+
label: string;
|
|
181
|
+
path: string;
|
|
182
|
+
contentLength: number;
|
|
183
|
+
error: string;
|
|
184
|
+
})
|
|
172
185
|
|
|
173
186
|
// Module lifecycle
|
|
174
187
|
| (TraceEventBase & { type: 'module:added'; moduleName: string })
|
|
@@ -339,6 +352,15 @@ export type TraceEvent =
|
|
|
339
352
|
/** True when a background reconnect loop will keep retrying. */
|
|
340
353
|
willRetry: boolean;
|
|
341
354
|
})
|
|
355
|
+
| (TraceEventBase & {
|
|
356
|
+
/** §17.6: the ONE normalized receipt per manifest change — closed
|
|
357
|
+
* host-derived impact vocabulary, never a server-authored flag. */
|
|
358
|
+
type: 'mcpl:manifest-change-receipt';
|
|
359
|
+
serverId: string;
|
|
360
|
+
revision: string | null;
|
|
361
|
+
announcedDomains: string[];
|
|
362
|
+
impacts: Array<{ impact: string; subject: string; disposition: string }>;
|
|
363
|
+
})
|
|
342
364
|
| (TraceEventBase & {
|
|
343
365
|
type: 'mcpl:server-reconnected';
|
|
344
366
|
serverId: string;
|