@sema-agent/core 7.52.0 → 7.53.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +194 -0
- package/README.md +3 -1
- package/dist/agents/cross-session-envelope.d.ts +8 -0
- package/dist/agents/cross-session-envelope.js +6 -0
- package/dist/agents/cross-session-judge.d.ts +21 -1
- package/dist/agents/cross-session-judge.js +8 -0
- package/dist/agents/cross-session-ref.d.ts +5 -0
- package/dist/agents/cross-session-ref.js +1 -0
- package/dist/agents/org-delivery-gate.d.ts +122 -0
- package/dist/agents/org-delivery-gate.js +69 -0
- package/dist/agents/peer-held-queue.d.ts +9 -4
- package/dist/agents/peer-held-queue.js +6 -5
- package/dist/agents/peer-session-drain.d.ts +35 -5
- package/dist/agents/peer-session-drain.js +271 -180
- package/dist/agents/read-inbox-tool.d.ts +7 -0
- package/dist/agents/read-inbox-tool.js +5 -1
- package/dist/agents/subagent.d.ts +3 -0
- package/dist/agents/subagent.js +99 -72
- package/dist/agents/tool-filter.d.ts +18 -0
- package/dist/agents/tool-filter.js +6 -0
- package/dist/brain/anthropic.d.ts +6 -1
- package/dist/brain/anthropic.js +4 -4
- package/dist/brain/model-presets.js +2 -1
- package/dist/brain/route-adjudicator.d.ts +6 -0
- package/dist/brain/routing.d.ts +24 -1
- package/dist/brain/routing.js +54 -19
- package/dist/brain/timeout.js +5 -4
- package/dist/core/a2a.d.ts +5 -2
- package/dist/core/a2a.js +30 -13
- package/dist/core/allow-entry.d.ts +2 -1
- package/dist/core/allow-entry.js +2 -2
- package/dist/core/auto-compaction.d.ts +57 -0
- package/dist/core/auto-compaction.js +28 -2
- package/dist/core/checkpoint-store.d.ts +29 -20
- package/dist/core/checkpoint-store.js +3 -3
- package/dist/core/compliance.js +3 -1
- package/dist/core/effective-path-target.d.ts +25 -6
- package/dist/core/effective-path-target.js +24 -2
- package/dist/core/engine-notice.d.ts +13 -2
- package/dist/core/gate-fold.js +3 -2
- package/dist/core/gate-lanes.js +11 -13
- package/dist/core/gate-outcome.d.ts +11 -6
- package/dist/core/governance-codes.d.ts +3 -1
- package/dist/core/governance-codes.js +3 -0
- package/dist/core/hands-band-screen.d.ts +7 -0
- package/dist/core/hands-band-screen.js +32 -0
- package/dist/core/hooks.d.ts +7 -5
- package/dist/core/hooks.js +5 -3
- package/dist/core/locked-config.d.ts +84 -32
- package/dist/core/locked-config.js +128 -42
- package/dist/core/mcp-probe.js +1 -1
- package/dist/core/mcp-server-spec.d.ts +88 -10
- package/dist/core/mcp-server-spec.js +183 -33
- package/dist/core/mcp.d.ts +21 -14
- package/dist/core/mcp.js +55 -51
- package/dist/core/memory-engine/engine.d.ts +14 -19
- package/dist/core/memory-engine/engine.js +7 -5
- package/dist/core/mode-policy.d.ts +3 -18
- package/dist/core/mode-policy.js +2 -16
- package/dist/core/mods/kernel/dispatch.js +13 -15
- package/dist/core/mods/kernel/events.d.ts +9 -6
- package/dist/core/mods/kernel/events.js +2 -2
- package/dist/core/mods/kernel/receive.d.ts +39 -10
- package/dist/core/mods/kernel/receive.js +119 -54
- package/dist/core/mods/kernel/site-rules.d.ts +80 -15
- package/dist/core/mods/kernel/site-rules.js +232 -40
- package/dist/core/mods/stations.d.ts +0 -6
- package/dist/core/mods/stations.js +0 -7
- package/dist/core/mounted-mcp.d.ts +57 -0
- package/dist/core/mounted-mcp.js +71 -2
- package/dist/core/own-property-receipt.d.ts +13 -0
- package/dist/core/own-property-receipt.js +3 -1
- package/dist/core/parent-spec-seat.d.ts +2 -2
- package/dist/core/permission-rule-model.d.ts +58 -9
- package/dist/core/permission-rule-model.js +81 -7
- package/dist/core/permission-rule-org.d.ts +163 -33
- package/dist/core/permission-rule-org.js +205 -71
- package/dist/core/permission-rules.d.ts +7 -1
- package/dist/core/permission-rules.js +37 -8
- package/dist/core/retention.js +7 -2
- package/dist/core/retired-keys.d.ts +8 -2
- package/dist/core/retired-keys.js +12 -1
- package/dist/core/roles.js +60 -10
- package/dist/core/rule-lane-reads.js +1 -1
- package/dist/core/runner/contracts.d.ts +1 -0
- package/dist/core/runner/gate-exit.js +4 -3
- package/dist/core/runner/mcp-redial.d.ts +52 -10
- package/dist/core/runner/mcp-redial.js +38 -9
- package/dist/core/runner/permission-rule-lanes.d.ts +5 -2
- package/dist/core/runner/permission-rule-lanes.js +22 -10
- package/dist/core/runner/person-path-rows.d.ts +3 -1
- package/dist/core/runner/person-path-rows.js +2 -2
- package/dist/core/runner/prepare-config-doors.d.ts +48 -2
- package/dist/core/runner/prepare-config-doors.js +161 -145
- package/dist/core/runner/prepare-defer-classify.js +4 -7
- package/dist/core/runner/prepare-delegation-surface.d.ts +2 -2
- package/dist/core/runner/prepare-delegation-surface.js +7 -5
- package/dist/core/runner/prepare-hands-readface.d.ts +1 -1
- package/dist/core/runner/prepare-hands-readface.js +2 -1
- package/dist/core/runner/prepare-inherited-gate.js +2 -2
- package/dist/core/runner/prepare-listings.d.ts +1 -1
- package/dist/core/runner/prepare-listings.js +4 -2
- package/dist/core/runner/prepare-memory-engine-session.d.ts +0 -6
- package/dist/core/runner/prepare-memory-engine-session.js +19 -6
- package/dist/core/runner/prepare-memory.d.ts +3 -2
- package/dist/core/runner/prepare-memory.js +6 -2
- package/dist/core/runner/prepare-offload-wrappers.d.ts +4 -4
- package/dist/core/runner/prepare-offload-wrappers.js +2 -1
- package/dist/core/runner/prepare-policy-chain.d.ts +1 -1
- package/dist/core/runner/prepare-policy-chain.js +12 -12
- package/dist/core/runner/prepare-project-context.d.ts +1 -1
- package/dist/core/runner/prepare-project-context.js +6 -4
- package/dist/core/runner/prepare-prompt-assembly.d.ts +1 -1
- package/dist/core/runner/prepare-prompt-assembly.js +20 -16
- package/dist/core/runner/prepare-prompt-inputs.d.ts +12 -6
- package/dist/core/runner/prepare-prompt-inputs.js +6 -3
- package/dist/core/runner/prepare-protocol-tools.d.ts +7 -5
- package/dist/core/runner/prepare-protocol-tools.js +19 -12
- package/dist/core/runner/prepare-question-face.d.ts +4 -2
- package/dist/core/runner/prepare-question-face.js +4 -3
- package/dist/core/runner/prepare-task.js +10 -10
- package/dist/core/runner/prepare-wiring-manifest.d.ts +8 -3
- package/dist/core/runner/prepare-wiring-manifest.js +8 -5
- package/dist/core/runner/resume-admission.d.ts +4 -1
- package/dist/core/runner/resume-admission.js +7 -5
- package/dist/core/runner/resume-internals-and-config.d.ts +3 -3
- package/dist/core/runner/resume-internals-and-config.js +3 -8
- package/dist/core/runner/retired-runner-deps.d.ts +5 -6
- package/dist/core/runner/retired-runner-deps.js +1 -4
- package/dist/core/runner/run-leg.js +42 -12
- package/dist/core/runner/run-recovery-lanes.js +5 -3
- package/dist/core/runner/run-terminal-adoption.js +6 -5
- package/dist/core/runner/run-turn-boundary.js +9 -3
- package/dist/core/runner/runtask.js +1 -1
- package/dist/core/runner/skills-seat.d.ts +15 -0
- package/dist/core/runner/skills-seat.js +57 -0
- package/dist/core/runner/sub-agent-deny-lists.d.ts +13 -11
- package/dist/core/runner/sub-agent-deny-lists.js +7 -5
- package/dist/core/runner/synthetic-tools.d.ts +5 -2
- package/dist/core/runner/synthetic-tools.js +2 -12
- package/dist/core/runner-deps.d.ts +29 -14
- package/dist/core/session-policy-store.d.ts +19 -0
- package/dist/core/session-policy-store.js +22 -2
- package/dist/core/store-contracts/mailbox-store-contract.js +13 -0
- package/dist/core/task-event.d.ts +38 -2
- package/dist/core/task-notification.js +2 -2
- package/dist/core/task-spec.d.ts +1 -1
- package/dist/core/tool-policy.d.ts +3 -0
- package/dist/core/tool-policy.js +10 -4
- package/dist/core/types.d.ts +2 -2
- package/dist/core/types.js +1 -1
- package/dist/core/untrusted-text.d.ts +16 -0
- package/dist/core/untrusted-text.js +7 -2
- package/dist/core/user-attachment.d.ts +13 -2
- package/dist/core/user-attachment.js +47 -41
- package/dist/core/wiring-manifest.d.ts +4 -2
- package/dist/engine/harness/agent-harness.js +2 -1
- package/dist/engine/harness/types.d.ts +3 -0
- package/dist/engine/loop/agent-loop.d.ts +12 -1
- package/dist/engine/loop/agent-loop.js +17 -5
- package/dist/engine/loop/types.d.ts +7 -1
- package/dist/index.d.ts +15 -9
- package/dist/index.js +12 -6
- package/dist/internal/harness.d.ts +1 -0
- package/dist/internal/harness.js +1 -0
- package/dist/orchestration/goal.d.ts +24 -1
- package/dist/orchestration/goal.js +3 -2
- package/dist/prompt-assembly/artifact-store.d.ts +44 -9
- package/dist/prompt-assembly/artifact-store.js +38 -12
- package/dist/prompt-assembly/artifact.d.ts +12 -11
- package/dist/prompt-assembly/artifact.js +52 -21
- package/dist/prompt-assembly/assemble.d.ts +2 -0
- package/dist/prompt-assembly/assemble.js +2 -1
- package/dist/prompt-assembly/catalog/index.js +2 -1
- package/dist/prompt-assembly/catalog/memory.d.ts +13 -0
- package/dist/prompt-assembly/catalog/memory.js +6 -0
- package/dist/prompt-assembly/catalog/schema.d.ts +16 -2
- package/dist/prompt-assembly/composer.d.ts +2 -0
- package/dist/prompt-assembly/composer.js +1 -1
- package/dist/prompt-assembly/overlay.d.ts +21 -11
- package/dist/prompt-assembly/overlay.js +55 -17
- package/dist/prompt-assembly/select.d.ts +21 -6
- package/dist/prompt-assembly/select.js +39 -2
- package/dist/prompts/default.d.ts +0 -11
- package/dist/prompts/default.js +0 -3
- package/dist/stores/file/permission-rule-store.d.ts +1 -1
- package/dist/stores/file/permission-rule-store.js +2 -1
- package/dist/tools/artifact/artifact-tool.js +4 -3
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +65 -5
- package/wire-changes/core@7.53.0.json +1946 -0
|
@@ -7,6 +7,19 @@ import { type ModSeat, type ModTier } from "./events.js";
|
|
|
7
7
|
/** The host's Proxy probe (this folder cannot recognise a Proxy on its own): with one, a handler's Proxy is refused
|
|
8
8
|
* before any of its traps runs; without one, it is read like any object. */
|
|
9
9
|
export type ProxyProbe = (value: object) => boolean;
|
|
10
|
+
/**
|
|
11
|
+
* The one depth the bus holds a handler's values to: how many container levels a value may have below a payload member
|
|
12
|
+
* or an answer's top (1 = the member itself). Every value a handler gives the bus — what it hands to `next`, a `$`
|
|
13
|
+
* call's arguments, its answer — is received in a mode bounded by it (a shared reference measured again where it sits
|
|
14
|
+
* each time it is met), so a value nested deeper is refused by the first walk that meets it before that
|
|
15
|
+
* walk goes any deeper. Every walk keeps its own stack, so neither the platform nor the caller's stack depth decides.
|
|
16
|
+
* The pinned-key comparison is held to the same depth. A container is one level wherever it is met, so the verdict
|
|
17
|
+
* does not depend on member order for a value without a cycle; through a cycle, depth is measured on the walk's way (a
|
|
18
|
+
* container still being walked counts as one level where it is met again). The engine's own event is received at any
|
|
19
|
+
* depth, and its objects — handed back anywhere in what a handler hands on, answers or passes to a `$` call — are taken
|
|
20
|
+
* as themselves, never walked: one of its containers is one level where it sits, whatever it holds.
|
|
21
|
+
*/
|
|
22
|
+
export declare const MODS_VALUE_DEPTH = 1000;
|
|
10
23
|
/** Why a handler did not answer for itself: it threw, it ran past its budget, it broke the site's contract, or it was
|
|
11
24
|
* not run because the dispatch re-entered a frame it is part of (its `.catch` answers for it — CC 296 form, (cli296.js:242947) "hasCatch"). */
|
|
12
25
|
export declare const MOD_FAILURE_CAUSES: readonly ["threw", "timeout", "violation", "reentry"];
|
|
@@ -35,8 +48,50 @@ export declare const NEXT_IN_FLIGHT: Readonly<{
|
|
|
35
48
|
export type ModAnswerCheck = (answer: unknown, e: ModEventPayload, by: ModAnswerer, below: readonly unknown[]) => string | undefined;
|
|
36
49
|
/** A matcher: top-level fields of `e` that must equal these values exactly. */
|
|
37
50
|
export type ModMatcher = Readonly<Record<string, string | number | boolean>>;
|
|
38
|
-
/**
|
|
39
|
-
|
|
51
|
+
/** Why a pinned key of what a handler handed on is not taken: it holds another value, or it is a copy the comparison
|
|
52
|
+
* could not walk to the end (`unproven` says why) — refused all the same, since only a copy proven the same is taken. */
|
|
53
|
+
export interface PinnedKeyBreak {
|
|
54
|
+
readonly key: string;
|
|
55
|
+
readonly unproven?: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The first pinned key `next` did not hand on as the engine's fact, or undefined. A pinned value is compared by value
|
|
59
|
+
* ({@link sameModValue}): the engine's own fact handed on as is, or a copy of it, is not a change.
|
|
60
|
+
*/
|
|
61
|
+
export declare function pinnedKeyChanged(pinned: readonly string[], received: ModEventPayload, passed: ModEventPayload): PinnedKeyBreak | undefined;
|
|
62
|
+
/** {@link engineObjects} of a dispatch's own event, found the first time it is asked and the same set every time after:
|
|
63
|
+
* the event is frozen, so one finding serves every receipt of the dispatch. */
|
|
64
|
+
export declare function engineObjectsOnce(held: ModEventPayload): () => ReadonlySet<object>;
|
|
65
|
+
/**
|
|
66
|
+
* What the next handler reads when a handler hands `passed` to `next` (not the dispatch's own e): `passed` received
|
|
67
|
+
* whole in the mode held to {@link MODS_VALUE_DEPTH} (every object of the dispatch's own e in it — `engines`, found once
|
|
68
|
+
* per dispatch by {@link engineObjectsOnce} — kept as itself), then {@link pinnedHandOn}. A value nested past the depth
|
|
69
|
+
* is refused by the receipt, before any deeper walk — under a pinned key in the comparison's own words (too deep to
|
|
70
|
+
* compare), under any other member as the payload holding it.
|
|
71
|
+
*/
|
|
72
|
+
export declare function handedOn(pinned: readonly string[], held: ModEventPayload, passed: unknown, engines: ReadonlySet<object>, isProxy?: ProxyProbe): {
|
|
73
|
+
readonly payload: ModEventPayload;
|
|
74
|
+
} | {
|
|
75
|
+
readonly violation: string;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* What the next handler reads when a handler hands on `passed` (already received whole): the payload with every
|
|
79
|
+
* pinned key the engine's own member — the same object `held` carries, or no member where `held` has none — so a
|
|
80
|
+
* handler below a copy-forwarder reads the engine's fact, not the copy's shape (a member that is `undefined`, a
|
|
81
|
+
* member order, a −0 the comparison does not count). A pinned key the copy did not hand on as the engine's fact
|
|
82
|
+
* ({@link pinnedKeyChanged}) breaks the site instead. The comparison decides only whether to refuse; what travels down
|
|
83
|
+
* for a pinned key is the engine's member, always. The payload keeps the shape it was received in: a reference inside
|
|
84
|
+
* it to the payload itself is a reference to what is handed on (a cycle stays a cycle), and one to any object inside
|
|
85
|
+
* what the handler handed on under a pinned key — the copy itself, a member of it, an element of one of its lists, at
|
|
86
|
+
* any depth — is a reference to the engine's object it was proven the same as (a shared reference stays shared; an
|
|
87
|
+
* object of the copy standing for two of the engine's goes to the one the comparison met first). `engines`: every
|
|
88
|
+
* object of `held` (found here when not given).
|
|
89
|
+
*/
|
|
90
|
+
export declare function pinnedHandOn(pinned: readonly string[], held: ModEventPayload, passed: ModEventPayload, engines?: ReadonlySet<object>): {
|
|
91
|
+
readonly payload: ModEventPayload;
|
|
92
|
+
} | {
|
|
93
|
+
readonly violation: string;
|
|
94
|
+
};
|
|
40
95
|
/** Why a handler's answer breaks the site, or undefined. No answer at all is never an answer. */
|
|
41
96
|
export declare function answerViolation(answer: unknown, check: ModAnswerCheck | undefined, e: ModEventPayload, by: ModAnswerer, below: readonly unknown[]): string | undefined;
|
|
42
97
|
/**
|
|
@@ -52,14 +107,18 @@ export declare function methodAnswerViolation(answer: unknown, _e?: ModEventPayl
|
|
|
52
107
|
export declare function matcherViolation(m: unknown): string | undefined;
|
|
53
108
|
/** Whether every matcher field equals `e`'s own top-level field exactly. */
|
|
54
109
|
export declare function matcherMatches(m: ModMatcher | undefined, e: ModEventPayload): boolean;
|
|
55
|
-
/**
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
110
|
+
/** A record a handler gives the bus other than through `next` — a `$` call's arguments, and a method's `enter` shaping
|
|
111
|
+
* of them — received held to {@link MODS_VALUE_DEPTH}; an object of `held` ({@link engineObjectsOnce} of what the bus
|
|
112
|
+
* already holds: the dispatch the handler runs in, or the call's received arguments) is kept as itself, never walked. */
|
|
113
|
+
export declare function receivePayload(v: unknown, isProxy?: ProxyProbe, held?: ReadonlySet<object>): {
|
|
114
|
+
readonly payload: ModEventPayload;
|
|
115
|
+
} | {
|
|
116
|
+
readonly refusal: string;
|
|
117
|
+
};
|
|
118
|
+
/** The engine's own event at a dispatch's entry, received whole at any depth (one the receipt cannot copy whole —
|
|
119
|
+
* reading it threw where none of its getters runs, or it holds more objects than one receipt can index — is refused,
|
|
120
|
+
* never handed on shorter). */
|
|
121
|
+
export declare function receiveEvent(e: unknown): {
|
|
63
122
|
readonly payload: ModEventPayload;
|
|
64
123
|
} | {
|
|
65
124
|
readonly refusal: string;
|
|
@@ -70,15 +129,21 @@ export declare function receivePayload(v: unknown, held?: ModEventPayload, isPro
|
|
|
70
129
|
* copied once and frozen; an answer already frozen (an engine sentinel) or not a plain container is itself.
|
|
71
130
|
*/
|
|
72
131
|
export declare function answerUpward(v: unknown): unknown;
|
|
73
|
-
/** A handler's answer, received by the same receipt
|
|
74
|
-
|
|
132
|
+
/** A handler's answer, received by the same receipt held to {@link MODS_VALUE_DEPTH} (an answer need not be a record; a
|
|
133
|
+
* primitive is itself); an object of the dispatch's own event in it (`engines`, {@link engineObjectsOnce}) is kept as
|
|
134
|
+
* itself, never walked. */
|
|
135
|
+
export declare function receiveAnswer(answer: unknown, engines: ReadonlySet<object>, isProxy?: ProxyProbe): {
|
|
75
136
|
readonly answer: unknown;
|
|
76
137
|
} | {
|
|
77
138
|
readonly refusal: string;
|
|
78
139
|
};
|
|
79
140
|
/**
|
|
80
|
-
* A copy for an observe handler
|
|
81
|
-
*
|
|
82
|
-
*
|
|
141
|
+
* A copy for an observe handler, made by the one receipt (its own stack, so no depth of the event decides whether an
|
|
142
|
+
* observer runs — the event it observes was received at any depth too): every data container (a plain object, an
|
|
143
|
+
* ordinary array) detached at any depth; then every other object the copy holds — a tool result's `Map`, `Date` or
|
|
144
|
+
* typed array — detached by a structured clone of that object alone (one clone per object, so a shared one stays shared),
|
|
145
|
+
* and one the clone refuses (a function, a handle, a class instance holding one) handed as is. The engine's own event
|
|
146
|
+
* holds data properties only, so the copy is whole; a receipt that could not make it (a Proxy whose trap throws, on a bus
|
|
147
|
+
* given no probe) is the observer's failure, reported like any other.
|
|
83
148
|
*/
|
|
84
149
|
export declare function detachedCopy(e: ModEventPayload): Record<string, unknown>;
|
|
@@ -1,12 +1,194 @@
|
|
|
1
1
|
import { describe } from "./events.js";
|
|
2
2
|
import { describeFault, isPlainRecord, MODS_PAYLOAD_MODE, receive } from "./receive.js";
|
|
3
|
+
export const MODS_VALUE_DEPTH = 1_000;
|
|
4
|
+
const HANDED_MODE = Object.freeze({ ...MODS_PAYLOAD_MODE, depth: MODS_VALUE_DEPTH + 1, past: "refuse" });
|
|
3
5
|
function payloadMode(isProxy) {
|
|
4
|
-
return isProxy === undefined ?
|
|
6
|
+
return isProxy === undefined ? HANDED_MODE : Object.freeze({ ...HANDED_MODE, isProxy });
|
|
7
|
+
}
|
|
8
|
+
const TOO_DEEP_TO_COMPARE = `too deep to compare (nested past ${MODS_VALUE_DEPTH} levels)`;
|
|
9
|
+
function faultClause(fault) {
|
|
10
|
+
if (fault.kind !== "too-deep")
|
|
11
|
+
return describeFault(fault);
|
|
12
|
+
return `a value nested past ${MODS_VALUE_DEPTH} levels${fault.path.length > 0 ? ` under "${fault.path[0]}"` : ""}`;
|
|
5
13
|
}
|
|
6
14
|
export const MOD_FAILURE_CAUSES = Object.freeze(["threw", "timeout", "violation", "reentry"]);
|
|
7
15
|
export const NEXT_IN_FLIGHT = Object.freeze({ inFlight: true });
|
|
16
|
+
const TOO_DEEP = Object.freeze({ tooDeep: true });
|
|
17
|
+
const OPEN = "open";
|
|
18
|
+
function sameModValue(a0, b0, paired, depth0, homes) {
|
|
19
|
+
const stack = [];
|
|
20
|
+
const named = (r) => Object.keys(r).filter((k) => r[k] !== undefined);
|
|
21
|
+
const meet = (a, b, depth) => {
|
|
22
|
+
if (a === b || (Number.isNaN(a) && Number.isNaN(b)))
|
|
23
|
+
return 0;
|
|
24
|
+
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null)
|
|
25
|
+
return false;
|
|
26
|
+
let row = paired.get(a);
|
|
27
|
+
const met = row?.get(b);
|
|
28
|
+
if (met !== undefined) {
|
|
29
|
+
const height = met === OPEN ? 1 : met;
|
|
30
|
+
if (depth + height - 1 > MODS_VALUE_DEPTH)
|
|
31
|
+
throw TOO_DEEP;
|
|
32
|
+
return height;
|
|
33
|
+
}
|
|
34
|
+
if (depth > MODS_VALUE_DEPTH)
|
|
35
|
+
throw TOO_DEEP;
|
|
36
|
+
if (row === undefined)
|
|
37
|
+
paired.set(a, (row = new Map()));
|
|
38
|
+
row.set(b, OPEN);
|
|
39
|
+
if (!homes.has(b))
|
|
40
|
+
homes.set(b, a);
|
|
41
|
+
if (Array.isArray(a) || Array.isArray(b)) {
|
|
42
|
+
if (!Array.isArray(a) || !Array.isArray(b) || Object.getPrototypeOf(a) !== Array.prototype || Object.getPrototypeOf(b) !== Array.prototype || a.length !== b.length)
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
else if (!isPlainRecord(a) || !isPlainRecord(b))
|
|
46
|
+
return false;
|
|
47
|
+
const ra = a;
|
|
48
|
+
const rb = b;
|
|
49
|
+
const names = named(ra);
|
|
50
|
+
if (names.length !== named(rb).length)
|
|
51
|
+
return false;
|
|
52
|
+
stack.push({ a: ra, b: rb, row, names, depth, next: 0, height: 1 });
|
|
53
|
+
return undefined;
|
|
54
|
+
};
|
|
55
|
+
const top = meet(a0, b0, depth0);
|
|
56
|
+
if (top !== undefined)
|
|
57
|
+
return top;
|
|
58
|
+
for (;;) {
|
|
59
|
+
const f = stack[stack.length - 1];
|
|
60
|
+
if (f.next < f.names.length) {
|
|
61
|
+
const k = f.names[f.next++];
|
|
62
|
+
if (!Object.hasOwn(f.b, k))
|
|
63
|
+
return false;
|
|
64
|
+
const below = meet(f.a[k], f.b[k], f.depth + 1);
|
|
65
|
+
if (below === false)
|
|
66
|
+
return false;
|
|
67
|
+
if (below !== undefined)
|
|
68
|
+
f.height = Math.max(f.height, below + 1);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
f.row.set(f.b, f.height);
|
|
72
|
+
stack.pop();
|
|
73
|
+
const holder = stack[stack.length - 1];
|
|
74
|
+
if (holder === undefined)
|
|
75
|
+
return f.height;
|
|
76
|
+
holder.height = Math.max(holder.height, f.height + 1);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
8
79
|
export function pinnedKeyChanged(pinned, received, passed) {
|
|
9
|
-
|
|
80
|
+
const compared = comparePinned(pinned, received, passed);
|
|
81
|
+
return "broke" in compared ? compared.broke : undefined;
|
|
82
|
+
}
|
|
83
|
+
function comparePinned(pinned, received, passed) {
|
|
84
|
+
const paired = new Map();
|
|
85
|
+
const homes = new Map();
|
|
86
|
+
for (const key of pinned) {
|
|
87
|
+
try {
|
|
88
|
+
if (sameModValue(received[key], passed[key], paired, 1, homes) === false)
|
|
89
|
+
return { broke: { key } };
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
return { broke: { key, unproven: err === TOO_DEEP ? TOO_DEEP_TO_COMPARE : "the comparison could not walk it to the end" } };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return { homes };
|
|
96
|
+
}
|
|
97
|
+
function engineObjects(held) {
|
|
98
|
+
const found = new Set();
|
|
99
|
+
const stack = Object.values(held);
|
|
100
|
+
while (stack.length > 0) {
|
|
101
|
+
const v = stack.pop();
|
|
102
|
+
if (typeof v !== "object" || v === null || found.has(v) || !Object.isFrozen(v))
|
|
103
|
+
continue;
|
|
104
|
+
if (!isPlainRecord(v) && !(Array.isArray(v) && Object.getPrototypeOf(v) === Array.prototype))
|
|
105
|
+
continue;
|
|
106
|
+
found.add(v);
|
|
107
|
+
for (const k of Object.keys(v))
|
|
108
|
+
stack.push(v[k]);
|
|
109
|
+
}
|
|
110
|
+
return found;
|
|
111
|
+
}
|
|
112
|
+
export function engineObjectsOnce(held) {
|
|
113
|
+
let found;
|
|
114
|
+
return () => (found ??= engineObjects(held));
|
|
115
|
+
}
|
|
116
|
+
const unprovenCopy = (key, why) => `next() handed on a copy of the pinned key "${key}" that is ${why}; a copy is taken only when proven the same`;
|
|
117
|
+
export function handedOn(pinned, held, passed, engines, isProxy) {
|
|
118
|
+
const received = receiveRecord(passed, payloadMode(isProxy), engines);
|
|
119
|
+
if ("refusal" in received) {
|
|
120
|
+
const key = received.fault?.kind === "too-deep" ? received.fault.path[0] : undefined;
|
|
121
|
+
return { violation: key !== undefined && pinned.includes(key) ? unprovenCopy(key, TOO_DEEP_TO_COMPARE) : `next() takes the event object: ${received.refusal}` };
|
|
122
|
+
}
|
|
123
|
+
return pinnedHandOn(pinned, held, received.payload, engines);
|
|
124
|
+
}
|
|
125
|
+
export function pinnedHandOn(pinned, held, passed, engines) {
|
|
126
|
+
const compared = comparePinned(pinned, held, passed);
|
|
127
|
+
if ("broke" in compared) {
|
|
128
|
+
return { violation: compared.broke.unproven === undefined ? `next() changed the pinned key "${compared.broke.key}"` : unprovenCopy(compared.broke.key, compared.broke.unproven) };
|
|
129
|
+
}
|
|
130
|
+
if (pinned.every((k) => Object.hasOwn(passed, k) === Object.hasOwn(held, k) && Object.is(passed[k], held[k])))
|
|
131
|
+
return { payload: passed };
|
|
132
|
+
return { payload: rehomed(pinned, held, passed, compared.homes, engines ?? engineObjects(held)) };
|
|
133
|
+
}
|
|
134
|
+
function rehomed(pinned, held, passed, homes, engines) {
|
|
135
|
+
const swap = new Map();
|
|
136
|
+
for (const [copy, home] of homes)
|
|
137
|
+
if (copy !== passed && !engines.has(copy))
|
|
138
|
+
swap.set(copy, home);
|
|
139
|
+
const isContainer = (v) => typeof v === "object" && v !== null && !engines.has(v) && !swap.has(v) && (isPlainRecord(v) || (Array.isArray(v) && Object.getPrototypeOf(v) === Array.prototype));
|
|
140
|
+
const holders = new Map();
|
|
141
|
+
const walked = new Set([passed]);
|
|
142
|
+
const stack = [passed];
|
|
143
|
+
while (stack.length > 0) {
|
|
144
|
+
const node = stack.pop();
|
|
145
|
+
for (const k of Object.keys(node)) {
|
|
146
|
+
if (node === passed && pinned.includes(k))
|
|
147
|
+
continue;
|
|
148
|
+
const v = node[k];
|
|
149
|
+
if (v !== passed && !swap.has(v) && !isContainer(v))
|
|
150
|
+
continue;
|
|
151
|
+
const by = holders.get(v);
|
|
152
|
+
if (by === undefined)
|
|
153
|
+
holders.set(v, [node]);
|
|
154
|
+
else
|
|
155
|
+
by.push(node);
|
|
156
|
+
if (isContainer(v) && !walked.has(v)) {
|
|
157
|
+
walked.add(v);
|
|
158
|
+
stack.push(v);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const twins = new Map([[passed, {}]]);
|
|
163
|
+
const reach = [passed, ...swap.keys()];
|
|
164
|
+
while (reach.length > 0) {
|
|
165
|
+
for (const h of holders.get(reach.pop()) ?? []) {
|
|
166
|
+
if (twins.has(h))
|
|
167
|
+
continue;
|
|
168
|
+
twins.set(h, Array.isArray(h) ? [] : {});
|
|
169
|
+
reach.push(h);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const put = (to, k, v) => void Object.defineProperty(to, k, { value: v, enumerable: true, writable: true, configurable: true });
|
|
173
|
+
const moved = (v) => (typeof v !== "object" || v === null ? v : swap.has(v) ? swap.get(v) : (twins.get(v) ?? v));
|
|
174
|
+
for (const [from, to] of twins) {
|
|
175
|
+
const r = from;
|
|
176
|
+
for (const k of Object.keys(r)) {
|
|
177
|
+
if (from !== passed || !pinned.includes(k))
|
|
178
|
+
put(to, k, moved(r[k]));
|
|
179
|
+
else if (Object.hasOwn(held, k))
|
|
180
|
+
put(to, k, held[k]);
|
|
181
|
+
}
|
|
182
|
+
if (from === passed)
|
|
183
|
+
for (const k of pinned)
|
|
184
|
+
if (Object.hasOwn(held, k) && !Object.hasOwn(to, k))
|
|
185
|
+
put(to, k, held[k]);
|
|
186
|
+
if (Array.isArray(from) && Array.isArray(to))
|
|
187
|
+
to.length = from.length;
|
|
188
|
+
}
|
|
189
|
+
for (const to of twins.values())
|
|
190
|
+
Object.freeze(to);
|
|
191
|
+
return twins.get(passed);
|
|
10
192
|
}
|
|
11
193
|
export function answerViolation(answer, check, e, by, below) {
|
|
12
194
|
if (answer === undefined)
|
|
@@ -49,13 +231,21 @@ export function matcherMatches(m, e) {
|
|
|
49
231
|
return true;
|
|
50
232
|
return Object.entries(m).every(([k, v]) => Object.prototype.hasOwnProperty.call(e, k) && e[k] === v);
|
|
51
233
|
}
|
|
52
|
-
|
|
53
|
-
if (isProxy !== undefined && typeof v === "object" && v !== null && isProxy(v))
|
|
234
|
+
function receiveRecord(v, mode, held) {
|
|
235
|
+
if (mode.isProxy !== undefined && typeof v === "object" && v !== null && mode.isProxy(v))
|
|
54
236
|
return { refusal: "the payload is a Proxy (refused before any of its traps runs)" };
|
|
55
237
|
if (!isPlainRecord(v))
|
|
56
238
|
return { refusal: `an event payload is a plain object, not ${describe(v)}` };
|
|
57
|
-
const r = receive(v,
|
|
58
|
-
return r.ok ? { payload: Object.freeze(r.value) } : { refusal: `the payload holds ${
|
|
239
|
+
const r = receive(v, mode, held);
|
|
240
|
+
return r.ok ? { payload: Object.freeze(r.value) } : { refusal: `the payload holds ${faultClause(r.fault)}`, fault: r.fault };
|
|
241
|
+
}
|
|
242
|
+
export function receivePayload(v, isProxy, held) {
|
|
243
|
+
const r = receiveRecord(v, payloadMode(isProxy), held);
|
|
244
|
+
return "refusal" in r ? { refusal: r.refusal } : r;
|
|
245
|
+
}
|
|
246
|
+
export function receiveEvent(e) {
|
|
247
|
+
const r = receiveRecord(e, MODS_PAYLOAD_MODE);
|
|
248
|
+
return "refusal" in r ? { refusal: r.refusal } : r;
|
|
59
249
|
}
|
|
60
250
|
export function answerUpward(v) {
|
|
61
251
|
if (typeof v !== "object" || v === null || Object.isFrozen(v))
|
|
@@ -64,41 +254,43 @@ export function answerUpward(v) {
|
|
|
64
254
|
return Object.freeze([...v]);
|
|
65
255
|
return isPlainRecord(v) ? Object.freeze({ ...v }) : v;
|
|
66
256
|
}
|
|
67
|
-
export function receiveAnswer(answer, isProxy) {
|
|
68
|
-
const r = receive(answer, payloadMode(isProxy));
|
|
69
|
-
return r.ok ? { answer: r.value } : { refusal: `answered ${
|
|
257
|
+
export function receiveAnswer(answer, engines, isProxy) {
|
|
258
|
+
const r = receive(answer, payloadMode(isProxy), engines);
|
|
259
|
+
return r.ok ? { answer: r.value } : { refusal: `answered ${faultClause(r.fault)}` };
|
|
70
260
|
}
|
|
261
|
+
const DETACHED_MODE = Object.freeze({ accessors: "refuse", depth: Infinity, others: "as-is" });
|
|
71
262
|
export function detachedCopy(e) {
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
263
|
+
const r = receive(e, DETACHED_MODE);
|
|
264
|
+
if (!r.ok)
|
|
265
|
+
throw new Error(`the observer's copy of the event could not be made: ${describeFault(r.fault)}`);
|
|
266
|
+
const copy = r.value;
|
|
267
|
+
const clones = new Map();
|
|
268
|
+
const walked = new Set([copy]);
|
|
269
|
+
const stack = [copy];
|
|
270
|
+
while (stack.length > 0) {
|
|
271
|
+
const node = stack.pop();
|
|
272
|
+
for (const k of Object.keys(node)) {
|
|
273
|
+
const v = node[k];
|
|
274
|
+
if (typeof v !== "object" || v === null)
|
|
275
|
+
continue;
|
|
276
|
+
if (isPlainRecord(v) || (Array.isArray(v) && Object.getPrototypeOf(v) === Array.prototype)) {
|
|
277
|
+
if (!walked.has(v)) {
|
|
278
|
+
walked.add(v);
|
|
279
|
+
stack.push(v);
|
|
280
|
+
}
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
if (!clones.has(v)) {
|
|
284
|
+
let own = v;
|
|
285
|
+
try {
|
|
286
|
+
own = structuredClone(v);
|
|
287
|
+
}
|
|
288
|
+
catch {
|
|
289
|
+
}
|
|
290
|
+
clones.set(v, own);
|
|
291
|
+
}
|
|
292
|
+
Object.defineProperty(node, k, { value: clones.get(v), enumerable: true, writable: true, configurable: true });
|
|
293
|
+
}
|
|
96
294
|
}
|
|
97
|
-
|
|
98
|
-
return v;
|
|
99
|
-
const obj = {};
|
|
100
|
-
seen.set(v, obj);
|
|
101
|
-
for (const [k, x] of Object.entries(v))
|
|
102
|
-
Object.defineProperty(obj, k, { value: detachedValue(x, seen), enumerable: true, writable: true, configurable: true });
|
|
103
|
-
return obj;
|
|
295
|
+
return copy;
|
|
104
296
|
}
|
|
@@ -32,12 +32,6 @@ export declare function agentIdOf(identity: HookInvocationIdentity | undefined):
|
|
|
32
32
|
* leg's kind reads `"resume"` whoever it runs as.
|
|
33
33
|
*/
|
|
34
34
|
export declare function stopEventOf(identity: Pick<HookInvocationIdentity, "isDelegatedChild"> | undefined): "classic.Stop" | "classic.SubagentStop";
|
|
35
|
-
/**
|
|
36
|
-
* The args as an observation carries them: the kernel's detached copy (a structured clone, or a shallow copy for a
|
|
37
|
-
* graph the clone refuses), so an observer editing what it was handed cannot move the live args later frames and audit
|
|
38
|
-
* records share. A non-object value (immutable) is handed as is.
|
|
39
|
-
*/
|
|
40
|
-
export declare function detachedArgsOf(args: unknown): unknown;
|
|
41
35
|
/**
|
|
42
36
|
* The args as a judging handler receives them: the gate pass's own immutable value ({@link ownArgs} — the value itself when
|
|
43
37
|
* the gate already took it, which is every call the gate raises an event over), so the bytes a handler judges are the bytes
|
|
@@ -8,7 +8,6 @@ import { askApproverIdentity, describeThrown, ownArgs } from "../tool-policy.js"
|
|
|
8
8
|
import { admitMods, expandModPattern } from "./kernel/index.js";
|
|
9
9
|
import { validateOverlay } from "../../prompt-assembly/overlay.js";
|
|
10
10
|
import { modsInvalid } from "./kernel/registration.js";
|
|
11
|
-
import { detachedCopy } from "./kernel/site-rules.js";
|
|
12
11
|
import { isPlainRecord } from "./kernel/receive.js";
|
|
13
12
|
import { engineMethodBottoms } from "./dollar.js";
|
|
14
13
|
import { modSeatsOf, modsReportToOnError, registrationRefusedNotice } from "./host.js";
|
|
@@ -22,12 +21,6 @@ export function agentIdOf(identity) {
|
|
|
22
21
|
export function stopEventOf(identity) {
|
|
23
22
|
return identity?.isDelegatedChild === true ? "classic.SubagentStop" : "classic.Stop";
|
|
24
23
|
}
|
|
25
|
-
export function detachedArgsOf(args) {
|
|
26
|
-
return isRecord(args) ? detachedCopy(args) : args;
|
|
27
|
-
}
|
|
28
|
-
function isRecord(v) {
|
|
29
|
-
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
30
|
-
}
|
|
31
24
|
export function judgedInputOf(args) {
|
|
32
25
|
const owned = ownArgs(args);
|
|
33
26
|
return owned.ok ? owned.value : args;
|
|
@@ -10,9 +10,58 @@
|
|
|
10
10
|
import type { McpServerSpec } from "./mcp-server-spec.js";
|
|
11
11
|
import type { ToolContentOrigin } from "./tool-spec.js";
|
|
12
12
|
import type { McpConnectionPool } from "./mcp-connection-pool.js";
|
|
13
|
+
import type { McpInstructionsEntry } from "./prompt-section-seat.js";
|
|
13
14
|
/** The two names a server's `allowTools` carries to let the cross-server resource readers reach its resources (a server whose allowlist omits one is left out of that reader). */
|
|
14
15
|
export declare const MCP_RESOURCE_LIST_ALLOW = "list_resources";
|
|
15
16
|
export declare const MCP_RESOURCE_READ_ALLOW = "read_resource";
|
|
17
|
+
/** The canonical names of the resource tools (the trio: list-all / read-one / list-under-a-directory). They belong to no one server: each aggregates the resources of every connected server that advertises them. */
|
|
18
|
+
export declare const LIST_MCP_RESOURCES = "ListMcpResourcesTool";
|
|
19
|
+
export declare const READ_MCP_RESOURCE = "ReadMcpResourceTool";
|
|
20
|
+
export declare const READ_MCP_RESOURCE_DIR = "ReadMcpResourceDirTool";
|
|
21
|
+
/** Does the valve (`leaves`: its one predicate) leave at least one of the cross-server resource tools? While it does, a connected server may contribute to them whatever it lists. */
|
|
22
|
+
export declare function resourceFacesLeft(leaves: (tool: {
|
|
23
|
+
readonly name: string;
|
|
24
|
+
}) => boolean): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Are a server's instructions about something the run holds? Yes when the run's roster (`held`) holds a tool of the server's prefix
|
|
27
|
+
* domain the valve leaves, or a cross-server resource tool the valve leaves (the aggregates exist only if some connected server
|
|
28
|
+
* advertised resources, and which one is not recorded, so a held face keeps the instructions of every server); a server whose own
|
|
29
|
+
* listing (`listed` — any superset of it) has no tool at all (instructions only) is taught while any resource face is left. Read off
|
|
30
|
+
* the roster, a tool the deployment's `toolFaces` overlay refused counts as what it is — not held. A server the run holds nothing of
|
|
31
|
+
* is not taught: its instructions describe tools the model will not hold.
|
|
32
|
+
*
|
|
33
|
+
* The one answer to "should the model be taught them": the initial instructions block and the delta lane's adds after a roster change read
|
|
34
|
+
* it. Whether the model HOLDS them is the ledger's ({@link instructionsTold}), which the disconnect line reads.
|
|
35
|
+
*/
|
|
36
|
+
export declare function instructionsTaught(leaves: (tool: {
|
|
37
|
+
readonly name: string;
|
|
38
|
+
readonly aliases?: readonly string[];
|
|
39
|
+
}) => boolean, serverName: string, held: ReadonlyArray<{
|
|
40
|
+
readonly name: string;
|
|
41
|
+
readonly aliases?: readonly string[];
|
|
42
|
+
}>, listed: ReadonlyArray<{
|
|
43
|
+
readonly name: string;
|
|
44
|
+
}>): boolean;
|
|
45
|
+
/** A materialization's instructions delta lane (`MaterializedMcp.instructionsDelta`): what the run drains at its next boundary. */
|
|
46
|
+
export interface InstructionsLane {
|
|
47
|
+
pendingAdds: McpInstructionsEntry[];
|
|
48
|
+
pendingRemovals: string[];
|
|
49
|
+
}
|
|
50
|
+
/** Are this server's instructions in the model's context now? */
|
|
51
|
+
export declare function instructionsTold(lane: InstructionsLane, server: string): boolean;
|
|
52
|
+
/** A dial's default: the server's instructions are taught (a materialization alone takes every entry it returns as taught, until a run states its block). */
|
|
53
|
+
export declare function toldOnDial(lane: InstructionsLane, server: string): void;
|
|
54
|
+
/** The run's start: the stable block is what the model is told. A removal already queued for a server outside the block names instructions the model
|
|
55
|
+
* never held, so it is withdrawn; a server inside the block with a removal queued is not in context (the frame will retract it). */
|
|
56
|
+
export declare function toldAtStart(lane: InstructionsLane, servers: ReadonlySet<string>): void;
|
|
57
|
+
/** Take this server's unread adds off the lane; a first copy that never reached the model leaves the ledger with it. */
|
|
58
|
+
export declare function withdrawInstructionAdds(lane: InstructionsLane, server: string): void;
|
|
59
|
+
/** Queue this server's current text (superseding an unread copy). In context already ⇒ stays so; otherwise a first copy, queued. */
|
|
60
|
+
export declare function tellInstructions(lane: InstructionsLane, entry: McpInstructionsEntry): void;
|
|
61
|
+
/** The server's connection is gone: unread adds are withdrawn, and the model is told its instructions no longer apply only if it holds them. */
|
|
62
|
+
export declare function retractInstructions(lane: InstructionsLane, server: string): void;
|
|
63
|
+
/** A re-dial that connected: a retraction still unread never reached the model, so it is withdrawn and the text the model holds stands. */
|
|
64
|
+
export declare function unretractInstructions(lane: InstructionsLane, server: string): void;
|
|
16
65
|
/** One declared MCP server and its mounted tools. */
|
|
17
66
|
export interface MountedMcpServer {
|
|
18
67
|
readonly server: McpServerSpec;
|
|
@@ -33,6 +82,14 @@ interface RosterEntry {
|
|
|
33
82
|
readonly name: string;
|
|
34
83
|
readonly mcpRemoteName?: string;
|
|
35
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* The names among `names` that belong to the declared server `serverName`: those under its prefix domain (`mcp__<server>__`), which
|
|
87
|
+
* is the roster's own definition of a server's tools (the live roster swaps a server's tools by it). Handed a roster's names, it is
|
|
88
|
+
* the ONE answer to "how many tools of this server does the run hold" — the re-dial's receipt and notice, the content-class
|
|
89
|
+
* declaration line, the wiring manifest's per-server count and {@link mountedMcpOf} all read it, so no two of them can count
|
|
90
|
+
* differently. Handed a server's own listing it answers what the server offers, which is not a mount count.
|
|
91
|
+
*/
|
|
92
|
+
export declare function toolNamesOfServer(names: Iterable<string>, serverName: string): string[];
|
|
36
93
|
/**
|
|
37
94
|
* Read the run's MCP surface off its roster. `declared` is the run's frozen server declarations; `aggregateNames` the names of the
|
|
38
95
|
* tools its materialization minted that no server owns. A tool is a server's when its wire name sits under the server's prefix
|
package/dist/core/mounted-mcp.js
CHANGED
|
@@ -2,10 +2,79 @@ import { mintNamespacePrefix } from "./protocol-naming.js";
|
|
|
2
2
|
import { MCP_NAMESPACE } from "./protocol-table.js";
|
|
3
3
|
export const MCP_RESOURCE_LIST_ALLOW = "list_resources";
|
|
4
4
|
export const MCP_RESOURCE_READ_ALLOW = "read_resource";
|
|
5
|
+
export const LIST_MCP_RESOURCES = "ListMcpResourcesTool";
|
|
6
|
+
export const READ_MCP_RESOURCE = "ReadMcpResourceTool";
|
|
7
|
+
export const READ_MCP_RESOURCE_DIR = "ReadMcpResourceDirTool";
|
|
8
|
+
const MCP_RESOURCE_FACES = [LIST_MCP_RESOURCES, READ_MCP_RESOURCE, READ_MCP_RESOURCE_DIR];
|
|
9
|
+
export function resourceFacesLeft(leaves) {
|
|
10
|
+
return MCP_RESOURCE_FACES.some((name) => leaves({ name }));
|
|
11
|
+
}
|
|
12
|
+
export function instructionsTaught(leaves, serverName, held, listed) {
|
|
13
|
+
const own = new Set(toolNamesOfServer(held.map((t) => t.name), serverName));
|
|
14
|
+
return held.some((t) => (own.has(t.name) || MCP_RESOURCE_FACES.includes(t.name)) && leaves(t)) || (toolNamesOfServer(listed.map((t) => t.name), serverName).length === 0 && resourceFacesLeft(leaves));
|
|
15
|
+
}
|
|
16
|
+
const ledgers = new WeakMap();
|
|
17
|
+
function ledgerOf(lane) {
|
|
18
|
+
let ledger = ledgers.get(lane);
|
|
19
|
+
if (ledger === undefined)
|
|
20
|
+
ledgers.set(lane, (ledger = new Map()));
|
|
21
|
+
return ledger;
|
|
22
|
+
}
|
|
23
|
+
const queuedFor = (lane, server) => lane.pendingAdds.some((e) => e.server === server);
|
|
24
|
+
export function instructionsTold(lane, server) {
|
|
25
|
+
const state = ledgerOf(lane).get(server);
|
|
26
|
+
return state === "context" || (state === "queued" && !queuedFor(lane, server));
|
|
27
|
+
}
|
|
28
|
+
export function toldOnDial(lane, server) {
|
|
29
|
+
ledgerOf(lane).set(server, "context");
|
|
30
|
+
}
|
|
31
|
+
export function toldAtStart(lane, servers) {
|
|
32
|
+
const ledger = ledgerOf(lane);
|
|
33
|
+
ledger.clear();
|
|
34
|
+
for (let i = lane.pendingRemovals.length - 1; i >= 0; i--)
|
|
35
|
+
if (!servers.has(lane.pendingRemovals[i]))
|
|
36
|
+
lane.pendingRemovals.splice(i, 1);
|
|
37
|
+
for (const server of servers)
|
|
38
|
+
if (!lane.pendingRemovals.includes(server))
|
|
39
|
+
ledger.set(server, "context");
|
|
40
|
+
}
|
|
41
|
+
export function withdrawInstructionAdds(lane, server) {
|
|
42
|
+
const told = instructionsTold(lane, server);
|
|
43
|
+
for (let i = lane.pendingAdds.length - 1; i >= 0; i--)
|
|
44
|
+
if (lane.pendingAdds[i].server === server)
|
|
45
|
+
lane.pendingAdds.splice(i, 1);
|
|
46
|
+
if (!told)
|
|
47
|
+
ledgerOf(lane).delete(server);
|
|
48
|
+
}
|
|
49
|
+
export function tellInstructions(lane, entry) {
|
|
50
|
+
const told = instructionsTold(lane, entry.server);
|
|
51
|
+
withdrawInstructionAdds(lane, entry.server);
|
|
52
|
+
lane.pendingAdds.push(entry);
|
|
53
|
+
ledgerOf(lane).set(entry.server, told ? "context" : "queued");
|
|
54
|
+
}
|
|
55
|
+
export function retractInstructions(lane, server) {
|
|
56
|
+
const told = instructionsTold(lane, server);
|
|
57
|
+
withdrawInstructionAdds(lane, server);
|
|
58
|
+
if (told && !lane.pendingRemovals.includes(server))
|
|
59
|
+
lane.pendingRemovals.push(server);
|
|
60
|
+
ledgerOf(lane).delete(server);
|
|
61
|
+
}
|
|
62
|
+
export function unretractInstructions(lane, server) {
|
|
63
|
+
if (!lane.pendingRemovals.includes(server))
|
|
64
|
+
return;
|
|
65
|
+
for (let i = lane.pendingRemovals.length - 1; i >= 0; i--)
|
|
66
|
+
if (lane.pendingRemovals[i] === server)
|
|
67
|
+
lane.pendingRemovals.splice(i, 1);
|
|
68
|
+
ledgerOf(lane).set(server, "context");
|
|
69
|
+
}
|
|
70
|
+
export function toolNamesOfServer(names, serverName) {
|
|
71
|
+
const prefix = mintNamespacePrefix(MCP_NAMESPACE, serverName);
|
|
72
|
+
return [...names].filter((name) => name.startsWith(prefix));
|
|
73
|
+
}
|
|
5
74
|
export function mountedMcpOf(input) {
|
|
6
75
|
const servers = (input.declared ?? []).map((server) => {
|
|
7
|
-
const
|
|
8
|
-
const tools = input.roster.flatMap((t) => (t.name
|
|
76
|
+
const owned = new Set(toolNamesOfServer(input.roster.map((t) => t.name), server.name));
|
|
77
|
+
const tools = input.roster.flatMap((t) => (owned.has(t.name) && typeof t.mcpRemoteName === "string" ? [{ name: t.name, remoteName: t.mcpRemoteName }] : []));
|
|
9
78
|
return { server, tools };
|
|
10
79
|
});
|
|
11
80
|
const aggregate = input.roster.filter((t) => input.aggregateNames.has(t.name)).map((t) => t.name);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ReceiptMode } from "./mods/kernel/receive.js";
|
|
1
2
|
/** How a refusal names the object being received. */
|
|
2
3
|
export interface OwnPropertyReceiptWords {
|
|
3
4
|
/** The object, e.g. `RunnerDeps`. */
|
|
@@ -14,5 +15,17 @@ export declare function receiptRefusal(message: string): Error & {
|
|
|
14
15
|
/** The receipt's first look, before ANY reflection on the object (a door that must look at the caller's object before
|
|
15
16
|
* the receipt — a retired-name door reading its prototype chain — calls this first): a Proxy is refused. */
|
|
16
17
|
export declare function refuseProxy(given: object, words: OwnPropertyReceiptWords): void;
|
|
18
|
+
/** The configuration receipt's mode of the one receipt: the top record read, each getter once, its members as given (a declared list's
|
|
19
|
+
* own read too: the list itself, each element once, the elements as given). */
|
|
20
|
+
export declare const CONFIG_RECEIPT_MODE: ReceiptMode;
|
|
21
|
+
/**
|
|
22
|
+
* The declaration receipt's mode of the one receipt — a declaration the engine judges and then holds (an MCP server's or an A2A peer's
|
|
23
|
+
* entry, a `toolAxes` record, a lock declaration) received as plain data held to the engine's one depth for a caller's value,
|
|
24
|
+
* {@link MODS_VALUE_DEPTH} levels of records and lists below the declaration itself (the bound a mods handler's answer is held to): every
|
|
25
|
+
* own string-keyed member read once off its captured descriptor (a getter called once, enumerable or not), every level copied, anything
|
|
26
|
+
* that is not data refused (a Proxy at any level, a function, a bigint, an object of another prototype, a structure that contains
|
|
27
|
+
* itself, a container nested deeper — a shared one measured where it sits each time it is met), every copied container frozen.
|
|
28
|
+
*/
|
|
29
|
+
export declare const DECLARATION_RECEIPT_MODE: ReceiptMode;
|
|
17
30
|
/** Read `given` by the receipt law (module note): the plain copy, every own member taken once from its captured descriptor. */
|
|
18
31
|
export declare function receiveOwnProperties<T extends object>(given: T, words: OwnPropertyReceiptWords): T;
|