@sema-agent/server 7.131.0 → 7.132.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/MIGRATION.md +309 -0
- package/README.md +5 -1
- package/README.zh-CN.md +3 -1
- package/USAGE.md +163 -54
- package/dist/approval-card.d.ts +3 -1
- package/dist/approval-card.js +2 -3
- package/dist/audit.d.ts +7 -10
- package/dist/auth-bridge.d.ts +4 -0
- package/dist/auth-bridge.js +10 -11
- package/dist/boot/deployment-mods.d.ts +31 -0
- package/dist/boot/deployment-mods.js +26 -0
- package/dist/boot/execution-env.d.ts +1 -1
- package/dist/boot/execution-env.js +19 -6
- package/dist/boot/memory-boundary.d.ts +2 -2
- package/dist/boot/read-deny-anchor-audit.d.ts +17 -0
- package/dist/boot/read-deny-anchor-audit.js +36 -0
- package/dist/boot/resolve-spec.d.ts +1 -5
- package/dist/boot/resolve-spec.js +19 -47
- package/dist/boot/runner-deps.d.ts +19 -8
- package/dist/boot/runner-deps.js +14 -2
- package/dist/boot/session-faces.d.ts +1 -7
- package/dist/boot/stage-03-store-backend.d.ts +1 -1
- package/dist/boot/stage-03-store-backend.js +2 -2
- package/dist/boot/stage-04-stores.d.ts +1 -1
- package/dist/boot/stage-05-execution-env.d.ts +4 -4
- package/dist/boot/stage-05-execution-env.js +7 -10
- package/dist/boot/stage-06-runners.d.ts +2 -2
- package/dist/boot/stage-06-runners.js +5 -4
- package/dist/boot/stage-07-capability-layer.d.ts +2 -2
- package/dist/boot/stage-07-capability-layer.js +3 -3
- package/dist/boot/stage-08-reapers.d.ts +2 -2
- package/dist/boot/stage-09-leader.d.ts +3 -9
- package/dist/boot/stage-10-http-server.d.ts +3 -9
- package/dist/boot/stage-10-http-server.js +6 -7
- package/dist/boot/stores.d.ts +1 -1
- package/dist/boot/stores.js +5 -6
- package/dist/boot/web-admin.d.ts +0 -3
- package/dist/boot/web-admin.js +35 -35
- package/dist/brain.js +17 -22
- package/dist/budget.js +5 -4
- package/dist/caller-text-echo.d.ts +20 -0
- package/dist/caller-text-echo.js +24 -0
- package/dist/capabilities/brand-identity.d.ts +26 -0
- package/dist/capabilities/brand-identity.js +27 -0
- package/dist/capabilities/center-plugins.js +1 -1
- package/dist/capabilities/center-prompts.d.ts +32 -59
- package/dist/capabilities/center-prompts.js +18 -32
- package/dist/capabilities/engine-capabilities.js +2 -1
- package/dist/capabilities/hands-lane.d.ts +9 -6
- package/dist/capabilities/hands-lane.js +1 -1
- package/dist/capabilities/mcp-probe.d.ts +14 -1
- package/dist/capabilities/mcp-probe.js +22 -133
- package/dist/capabilities/scenarios.d.ts +34 -40
- package/dist/capabilities/scenarios.js +16 -33
- package/dist/capabilities/skills.d.ts +19 -4
- package/dist/capabilities/skills.js +30 -10
- package/dist/config-catalog.js +6 -6
- package/dist/config-lkg.d.ts +9 -9
- package/dist/config-lkg.js +20 -4
- package/dist/config-provider.d.ts +3 -1
- package/dist/config-provider.js +12 -4
- package/dist/config-types.d.ts +7 -9
- package/dist/config.js +17 -4
- package/dist/device-ws-protocol.d.ts +1 -1
- package/dist/device-ws-protocol.js +1 -0
- package/dist/env-name-allowlist-knobs.d.ts +12 -2
- package/dist/env-name-allowlist-knobs.js +5 -4
- package/dist/exec-bounds.d.ts +15 -3
- package/dist/exec-bounds.js +4 -0
- package/dist/execution-lane-caps.d.ts +9 -2
- package/dist/execution-lane-caps.js +11 -0
- package/dist/hooks/classic-stations.d.ts +86 -0
- package/dist/hooks/classic-stations.js +27 -0
- package/dist/hooks/hook-llm.d.ts +8 -5
- package/dist/hooks/hook-llm.js +78 -35
- package/dist/hooks/hook-runner.d.ts +232 -80
- package/dist/hooks/hook-runner.js +218 -312
- package/dist/http/admission.d.ts +8 -2
- package/dist/http/admission.js +101 -57
- package/dist/http/approval-sweeps.js +57 -16
- package/dist/http/checkpoint-ctx.d.ts +25 -8
- package/dist/http/checkpoint-ctx.js +11 -7
- package/dist/http/claimed-run.d.ts +13 -0
- package/dist/http/claimed-run.js +15 -0
- package/dist/http/device-placement.js +5 -10
- package/dist/http/dispatch.d.ts +0 -4
- package/dist/http/dispatch.js +5 -9
- package/dist/http/durable-run-leg.d.ts +2 -1
- package/dist/http/durable-run-leg.js +5 -3
- package/dist/http/health-self-report.d.ts +7 -5
- package/dist/http/health-self-report.js +4 -18
- package/dist/http/principal-gate.d.ts +23 -6
- package/dist/http/principal-gate.js +24 -5
- package/dist/http/refusal-body.d.ts +21 -0
- package/dist/http/refusal-body.js +4 -0
- package/dist/http/request-guards.d.ts +27 -0
- package/dist/http/request-guards.js +24 -3
- package/dist/http/resume-legs.d.ts +25 -0
- package/dist/http/resume-legs.js +43 -22
- package/dist/http/routes/capabilities.js +1 -1
- package/dist/http/routes/diagnostics.js +1 -1
- package/dist/http/routes/rules.js +2 -2
- package/dist/http/routes/runs.js +7 -7
- package/dist/http/routes/session-sync.js +4 -2
- package/dist/http/routes/sessions.js +1 -1
- package/dist/http/routes/shared-memory.js +2 -13
- package/dist/http/routes/side-query.js +2 -3
- package/dist/http/routes/tasks.js +19 -9
- package/dist/http/send.d.ts +9 -7
- package/dist/http/send.js +7 -2
- package/dist/http/server.d.ts +21 -11
- package/dist/http/server.js +28 -2
- package/dist/http/submit-ctx.d.ts +25 -0
- package/dist/http/submit-ctx.js +39 -0
- package/dist/http/wire-types.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lane-home-probe.d.ts +43 -0
- package/dist/lane-home-probe.js +35 -0
- package/dist/limit-refusal.d.ts +47 -0
- package/dist/limit-refusal.js +12 -0
- package/dist/main.js +1 -1
- package/dist/mcp-assertion-header.d.ts +1 -9
- package/dist/mcp-assertion-header.js +0 -6
- package/dist/mcp-tool-faces.d.ts +5 -0
- package/dist/mcp-tool-faces.js +5 -1
- package/dist/memory-scope.d.ts +1 -1
- package/dist/model-provider.d.ts +39 -12
- package/dist/model-provider.js +19 -2
- package/dist/model-route-endpoint.d.ts +1 -1
- package/dist/model-route-endpoint.js +5 -5
- package/dist/observability/cost-taxonomy.d.ts +7 -7
- package/dist/observability/fail-open.d.ts +42 -6
- package/dist/observability/fail-open.js +42 -6
- package/dist/observability/metrics.js +3 -1
- package/dist/observability/prompt-manifest.d.ts +47 -82
- package/dist/observability/prompt-manifest.js +119 -17
- package/dist/observability/run-terminal.js +14 -6
- package/dist/observability/secret-env-scrub.d.ts +13 -1
- package/dist/observability/secret-env-scrub.js +13 -1
- package/dist/observability/tool-trace.d.ts +16 -21
- package/dist/observability/tool-trace.js +51 -42
- package/dist/per-task-image.d.ts +7 -1
- package/dist/per-task-image.js +3 -3
- package/dist/plain-string-record.d.ts +25 -0
- package/dist/plain-string-record.js +32 -0
- package/dist/plugins/blob-backend.d.ts +68 -13
- package/dist/plugins/blob-backend.js +53 -10
- package/dist/plugins/checkpoint-store-sql.d.ts +14 -4
- package/dist/plugins/checkpoint-store-sql.js +39 -26
- package/dist/plugins/k8s-bg-scripts.d.ts +11 -0
- package/dist/plugins/k8s-bg-scripts.js +22 -0
- package/dist/plugins/local-checkpoint-store.js +5 -2
- package/dist/plugins/local-session-store.js +1 -1
- package/dist/plugins/one-time-migrations.d.ts +137 -90
- package/dist/plugins/one-time-migrations.js +356 -207
- package/dist/plugins/permission-rule-store-sql.d.ts +13 -7
- package/dist/plugins/permission-rule-store-sql.js +4 -18
- package/dist/plugins/pg-session-storage.d.ts +4 -5
- package/dist/plugins/pg-session-storage.js +7 -17
- package/dist/plugins/remote-env-adb.d.ts +6 -0
- package/dist/plugins/remote-env-adb.js +9 -4
- package/dist/plugins/remote-env-device.js +3 -0
- package/dist/plugins/remote-env-e2b.d.ts +1 -1
- package/dist/plugins/remote-env-e2b.js +21 -9
- package/dist/plugins/remote-env-host.d.ts +9 -9
- package/dist/plugins/remote-env-host.js +10 -32
- package/dist/plugins/remote-env-k8s.d.ts +95 -26
- package/dist/plugins/remote-env-k8s.js +265 -90
- package/dist/plugins/remote-env-local-docker.d.ts +20 -1
- package/dist/plugins/remote-env-local-docker.js +77 -9
- package/dist/plugins/remote-env-ssh.d.ts +15 -0
- package/dist/plugins/remote-env-ssh.js +109 -3
- package/dist/plugins/remote-shell.d.ts +0 -1
- package/dist/plugins/remote-shell.js +1 -2
- package/dist/plugins/retention-store-sql.js +6 -2
- package/dist/plugins/schema-consistency.d.ts +54 -0
- package/dist/plugins/schema-consistency.js +52 -0
- package/dist/plugins/session-epoch-anchor.d.ts +13 -0
- package/dist/plugins/session-epoch-anchor.js +23 -0
- package/dist/plugins/shared-memory-store-sql.d.ts +9 -3
- package/dist/plugins/shared-memory-store-sql.js +5 -16
- package/dist/plugins/sql-driver.d.ts +141 -0
- package/dist/plugins/sql-driver.js +115 -1
- package/dist/plugins/sql-errors.d.ts +41 -0
- package/dist/plugins/sql-errors.js +36 -0
- package/dist/plugins/store-backend.js +2 -1
- package/dist/plugins/tidb-session-storage.d.ts +7 -11
- package/dist/plugins/tidb-session-storage.js +6 -16
- package/dist/plugins/tidb-session-store.js +1 -1
- package/dist/prompts-domain-validate.d.ts +17 -61
- package/dist/prompts-domain-validate.js +9 -119
- package/dist/request-key-closure.d.ts +2 -2
- package/dist/request-key-closure.js +2 -4
- package/dist/rule-entry-list.d.ts +12 -9
- package/dist/rule-entry-list.js +37 -21
- package/dist/run-local.js +19 -19
- package/dist/runs.d.ts +6 -0
- package/dist/runs.js +16 -0
- package/dist/server-secret-env.d.ts +44 -18
- package/dist/server-secret-env.js +49 -8
- package/dist/session-incarnation.d.ts +15 -5
- package/dist/session-incarnation.js +16 -9
- package/dist/session-titler.js +12 -2
- package/dist/spec-fields.d.ts +28 -16
- package/dist/spec-fields.js +46 -53
- package/dist/sql-engine-posture.d.ts +29 -4
- package/dist/sql-engine-posture.js +36 -1
- package/dist/stored-request-tool-axes-m19.d.ts +19 -4
- package/dist/stored-request-tool-axes-m19.js +30 -2
- package/dist/task-a2a.d.ts +9 -1
- package/dist/task-a2a.js +73 -47
- package/dist/task-mcp.d.ts +46 -58
- package/dist/task-mcp.js +99 -65
- package/dist/task-settings.d.ts +7 -21
- package/dist/task-settings.js +7 -36
- package/dist/text-bidi.d.ts +3 -46
- package/dist/text-bidi.js +3 -3
- package/dist/tool-approval.d.ts +1 -1
- package/dist/trace/core-keyset-guard.d.ts +24 -4
- package/dist/trace/engine-notice-wire.d.ts +11 -3
- package/dist/trace/engine-notice-wire.js +8 -1
- package/dist/trace/ledger-events.d.ts +3 -1
- package/dist/trace/ledger-sink.js +4 -1
- package/dist/trace/model-segment.js +1 -1
- package/dist/trace/project.d.ts +19 -6
- package/dist/trace/project.js +57 -22
- package/dist/trace/wire-projection-faces.d.ts +79 -1
- package/dist/trace/wire-projection-faces.js +22 -0
- package/dist/web-admin-client/candidate-gate.d.ts +6 -6
- package/dist/web-admin-client/candidate-gate.js +3 -3
- package/dist/web-admin-client/http-client.js +0 -6
- package/dist/web-admin-client/read-warnings.d.ts +13 -0
- package/dist/web-admin-client/read-warnings.js +10 -0
- package/dist/web-admin-client/skills-mcp.d.ts +3 -0
- package/dist/web-admin-client/skills-mcp.js +9 -6
- package/dist/web-admin-client/types.d.ts +2 -3
- package/dist/workspace-cache.d.ts +35 -0
- package/dist/workspace-cache.js +36 -0
- package/dist/workspace-space.d.ts +3 -2
- package/dist/workspace-space.js +2 -0
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +8 -1
- package/package.json +4 -4
- package/scripts/drain-check-local.mjs +34 -1
- package/scripts/drain-check.mysql.sql +30 -2
- package/scripts/drain-check.pg.sql +29 -2
- package/dist/capabilities/memory-notice.d.ts +0 -138
- package/dist/capabilities/memory-notice.js +0 -64
- package/dist/capabilities/prompt.d.ts +0 -17
- package/dist/capabilities/prompt.js +0 -6
- package/dist/mcp-content-origin.d.ts +0 -34
- package/dist/mcp-content-origin.js +0 -10
- package/dist/tool-axis-words.d.ts +0 -27
- package/dist/tool-axis-words.js +0 -9
- package/dist/wire-name-bound.d.ts +0 -14
- package/dist/wire-name-bound.js +0 -13
package/dist/task-mcp.js
CHANGED
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
import { mcpInjectionDroppedNotice, readMcpToolAxes, resolveComplianceDenies } from "@sema-agent/core";
|
|
2
|
-
import {
|
|
2
|
+
import { MCP_CONTENT_ORIGINS, describeNotStringArray, describeValueShape, isContentOriginWord, isStringArray, isUsableWireName, readMcpIdentityHeaders, } from "@sema-agent/settings-schema";
|
|
3
|
+
import { describeBadContentOrigin, describeBadWireName } from "./caller-text-echo.js";
|
|
3
4
|
import { HttpError, createCodedHttpError } from "./security.js";
|
|
4
5
|
import { GOVERNANCE_HTTP_STATUS } from "./governance-http-status.js";
|
|
5
|
-
import { CONTENT_ORIGIN_WORDS, describeBadContentOrigin, isContentOriginWord } from "./mcp-content-origin.js";
|
|
6
6
|
import { MCP_SOURCE_LABEL_MAX, isMcpSourceLabel, readMcpSourceLabel } from "./mcp-source-label.js";
|
|
7
|
-
import { declaresMcpAssertionHeader, describeMcpAssertionHeaderNotAString, describeMcpIdentityHeadersConflict, mcpIdentityHeadersIssue, noteMcpAssertionHeaderIgnored, noteMcpAssertionHeaderNotSent,
|
|
8
|
-
import { echoKeyName } from "./request-key-closure.js";
|
|
7
|
+
import { declaresMcpAssertionHeader, describeMcpAssertionHeaderNotAString, describeMcpIdentityHeadersConflict, mcpIdentityHeadersIssue, noteMcpAssertionHeaderIgnored, noteMcpAssertionHeaderNotSent, toCoreMcpServerSpec } from "./mcp-assertion-header.js";
|
|
8
|
+
import { MAX_KEY_ECHO, echoKeyName, keyClosureClause, scanKeyClosure } from "./request-key-closure.js";
|
|
9
9
|
import { CONTROL_AND_BIDI_STRIP_RE } from "./text-bidi.js";
|
|
10
10
|
import { readMcpToolFaces } from "./mcp-tool-faces.js";
|
|
11
|
+
import { readPlainStringRecord } from "./plain-string-record.js";
|
|
11
12
|
export const MAX_REQUEST_MCP_SERVERS = 32;
|
|
12
13
|
export const MAX_REQUEST_MCP_DROP_NAMES = MAX_REQUEST_MCP_SERVERS;
|
|
13
|
-
export const MCP_SERVER_ENTRY_KEYS = ["allowTools", "contentOrigin", "elicitation", "name", "source", "toolAxes", "toolFaces", "transport"];
|
|
14
|
+
export const MCP_SERVER_ENTRY_KEYS = ["allowTools", "contentOrigin", "elicitation", "name", "source", "startupTimeoutMs", "toolAxes", "toolFaces", "transport"];
|
|
14
15
|
export const STDIO_MCP_TRANSPORT_KEYS = ["args", "command", "env", "kind"];
|
|
15
16
|
export const HTTP_MCP_TRANSPORT_KEYS = ["assertionHeader", "headers", "kind", "principalHeader", "url"];
|
|
16
|
-
export const MCP_ENTRY_EMPTY_RECORD_KEYS = ["toolAxes", "toolFaces"];
|
|
17
|
-
export const MCP_ENTRY_EMPTY_ARRAY_KEYS = ["allowTools"];
|
|
18
|
-
export const MCP_TRANSPORT_EMPTY_RECORD_KEYS = ["env", "headers"];
|
|
19
|
-
export const MCP_TRANSPORT_EMPTY_ARRAY_KEYS = ["args"];
|
|
20
17
|
export function mcpInjectionHonored(config) {
|
|
21
18
|
if (config.lockedConfigKeys?.includes("mcp") === true)
|
|
22
19
|
return false;
|
|
@@ -24,57 +21,31 @@ export function mcpInjectionHonored(config) {
|
|
|
24
21
|
return false;
|
|
25
22
|
return config.requirePrincipal !== true;
|
|
26
23
|
}
|
|
27
|
-
function isStringRecord(v) {
|
|
28
|
-
return !!v && typeof v === "object" && !Array.isArray(v) && Object.values(v).every((x) => typeof x === "string");
|
|
29
|
-
}
|
|
30
24
|
function isRecord(v) {
|
|
31
25
|
return v !== null && typeof v === "object" && !Array.isArray(v);
|
|
32
26
|
}
|
|
33
|
-
function isStringArray(v) {
|
|
34
|
-
return Array.isArray(v) && v.every((a) => typeof a === "string");
|
|
35
|
-
}
|
|
36
27
|
function isElicitationFlag(v) {
|
|
37
28
|
return typeof v === "boolean";
|
|
38
29
|
}
|
|
39
|
-
function describeShape(v) {
|
|
40
|
-
if (v === undefined)
|
|
41
|
-
return "nothing (the key is absent)";
|
|
42
|
-
if (v === null)
|
|
43
|
-
return "null";
|
|
44
|
-
if (Array.isArray(v))
|
|
45
|
-
return "an array";
|
|
46
|
-
if (typeof v === "string")
|
|
47
|
-
return v.length === 0 ? "an empty string" : `a string of ${v.length} characters`;
|
|
48
|
-
if (typeof v === "object")
|
|
49
|
-
return "an object";
|
|
50
|
-
return `a ${typeof v}`;
|
|
51
|
-
}
|
|
52
|
-
function describeNotStringArray(v) {
|
|
53
|
-
return Array.isArray(v) ? "an array with a non-string element" : describeShape(v);
|
|
54
|
-
}
|
|
55
|
-
function describeNotStringRecord(v) {
|
|
56
|
-
return isRecord(v) ? "an object with a non-string value" : describeShape(v);
|
|
57
|
-
}
|
|
58
30
|
const transportBad = (path, reason) => ({ ok: false, issue: { path, reason } });
|
|
59
31
|
function readRequestTransport(t) {
|
|
60
32
|
if (!t || typeof t !== "object")
|
|
61
|
-
return transportBad("transport", `must be an object with a "kind" of "stdio" or "http" — got ${
|
|
33
|
+
return transportBad("transport", `must be an object with a "kind" of "stdio" or "http" — got ${describeValueShape(t)}`);
|
|
62
34
|
const tr = t;
|
|
63
35
|
const lost = [];
|
|
64
36
|
if (tr.kind === "stdio") {
|
|
65
37
|
if (typeof tr.command !== "string" || tr.command.length === 0)
|
|
66
|
-
return transportBad("transport.command", `must be a non-empty string (the command to run) — got ${
|
|
38
|
+
return transportBad("transport.command", `must be a non-empty string (the command to run) — got ${describeValueShape(tr.command)}`);
|
|
67
39
|
if (tr.args !== undefined && !isStringArray(tr.args))
|
|
68
40
|
lost.push({ path: "transport.args", reason: `must be an array of strings — got ${describeNotStringArray(tr.args)}` });
|
|
69
|
-
|
|
70
|
-
lost.push({ path: "transport.env", reason: `must be an object of string values — got ${describeNotStringRecord(tr.env)}` });
|
|
41
|
+
const env = readTransportRecord("transport.env", tr.env, lost);
|
|
71
42
|
return {
|
|
72
43
|
ok: true,
|
|
73
44
|
transport: {
|
|
74
45
|
kind: "stdio",
|
|
75
46
|
command: tr.command,
|
|
76
47
|
...(isStringArray(tr.args) ? { args: tr.args } : {}),
|
|
77
|
-
...(
|
|
48
|
+
...(env !== undefined ? { env } : {}),
|
|
78
49
|
},
|
|
79
50
|
lost,
|
|
80
51
|
};
|
|
@@ -83,23 +54,34 @@ function readRequestTransport(t) {
|
|
|
83
54
|
if (typeof tr.url !== "string" || !/^https?:\/\//i.test(tr.url))
|
|
84
55
|
return transportBad("transport.url", "must be an absolute http(s) URL (put credentials in transport.headers, never in the URL)");
|
|
85
56
|
const ids = readMcpIdentityHeaders(tr);
|
|
86
|
-
|
|
87
|
-
lost.push({ path: "transport.headers", reason: `must be an object of string values — got ${describeNotStringRecord(tr.headers)}` });
|
|
57
|
+
const headers = readTransportRecord("transport.headers", tr.headers, lost);
|
|
88
58
|
if (tr.principalHeader !== undefined && ids.principalHeader === undefined) {
|
|
89
|
-
lost.push({ path: "transport.principalHeader", reason: `must be a string (the HTTP header NAME the end-user principal is injected into) — got ${
|
|
59
|
+
lost.push({ path: "transport.principalHeader", reason: `must be a string (the HTTP header NAME the end-user principal is injected into) — got ${describeValueShape(tr.principalHeader)}` });
|
|
90
60
|
}
|
|
91
61
|
return {
|
|
92
62
|
ok: true,
|
|
93
63
|
transport: {
|
|
94
64
|
kind: "http",
|
|
95
65
|
url: tr.url,
|
|
96
|
-
...(
|
|
66
|
+
...(headers !== undefined ? { headers } : {}),
|
|
97
67
|
...ids,
|
|
98
68
|
},
|
|
99
69
|
lost,
|
|
100
70
|
};
|
|
101
71
|
}
|
|
102
|
-
return transportBad("transport.kind", `must be "stdio" or "http" — got ${
|
|
72
|
+
return transportBad("transport.kind", `must be "stdio" or "http" — got ${describeValueShape(tr.kind)}`);
|
|
73
|
+
}
|
|
74
|
+
function readTransportRecord(path, raw, lost) {
|
|
75
|
+
if (raw === undefined)
|
|
76
|
+
return undefined;
|
|
77
|
+
const read = readPlainStringRecord(raw);
|
|
78
|
+
if (!read.ok) {
|
|
79
|
+
lost.push({ path, reason: `must be a plain object of string values — ${read.member === undefined ? read.fault : `its member "${echoKeyName("", read.member)}" ${read.fault}`}` });
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
for (const m of read.stripped)
|
|
83
|
+
lost.push({ path: echoKeyName(`${path}.`, m.name), reason: m.fault });
|
|
84
|
+
return read.record;
|
|
103
85
|
}
|
|
104
86
|
const bad = (field) => ({ ok: false, field });
|
|
105
87
|
const MALFORMED_NAME = "<malformed>";
|
|
@@ -129,7 +111,7 @@ function normalizeServer(e, noteBadOrigin, storedToolAxes) {
|
|
|
129
111
|
let judged = axes;
|
|
130
112
|
let toolAxesReread;
|
|
131
113
|
if (!axes.ok && storedToolAxes !== undefined) {
|
|
132
|
-
const again = readMcpToolAxes(storedToolAxes(o.toolAxes));
|
|
114
|
+
const again = readMcpToolAxes(storedToolAxes.mcp(o.toolAxes));
|
|
133
115
|
if (again.ok) {
|
|
134
116
|
judged = again;
|
|
135
117
|
toolAxesReread = axes.problem.replace(CONTROL_AND_BIDI_STRIP_RE, "");
|
|
@@ -146,12 +128,14 @@ function normalizeServer(e, noteBadOrigin, storedToolAxes) {
|
|
|
146
128
|
noteBadOrigin(spec.name, o.contentOrigin);
|
|
147
129
|
}
|
|
148
130
|
Object.assign(spec, readMcpSourceLabel(spec.name, o.source));
|
|
131
|
+
if (o.startupTimeoutMs !== undefined)
|
|
132
|
+
spec.startupTimeoutMs = o.startupTimeoutMs;
|
|
149
133
|
const faces = readMcpToolFaces(o.toolFaces);
|
|
150
134
|
if (!faces.ok)
|
|
151
135
|
return bad("toolFaces");
|
|
152
136
|
if (faces.faces !== undefined)
|
|
153
137
|
spec.toolFaces = faces.faces;
|
|
154
|
-
return { ok: true, spec, ...(toolAxesReread !== undefined ? { toolAxesReread } : {}) };
|
|
138
|
+
return { ok: true, spec, ...(toolAxesReread !== undefined ? { toolAxesReread } : {}), transportLost: read.lost };
|
|
155
139
|
}
|
|
156
140
|
export function validateRequestMcp(raw) {
|
|
157
141
|
if (raw !== undefined && raw !== null && !Array.isArray(raw))
|
|
@@ -164,19 +148,22 @@ function validateRequestMcpEntries(raw, storedToolAxes) {
|
|
|
164
148
|
const dropped = [];
|
|
165
149
|
const badContentOrigin = [];
|
|
166
150
|
const toolAxesReread = [];
|
|
151
|
+
const transportLost = [];
|
|
167
152
|
for (const e of raw.slice(0, MAX_REQUEST_MCP_SERVERS)) {
|
|
168
153
|
const v = normalizeServer(e, (server, value) => badContentOrigin.push({ server, value: describeBadContentOrigin(value) }), storedToolAxes);
|
|
169
154
|
if (v.ok) {
|
|
170
155
|
ok.push(v.spec);
|
|
171
156
|
if (v.toolAxesReread !== undefined)
|
|
172
157
|
toolAxesReread.push({ server: v.spec.name, problem: v.toolAxesReread });
|
|
158
|
+
if (v.transportLost.length > 0)
|
|
159
|
+
transportLost.push({ server: v.spec.name, lost: v.transportLost.map((i) => i.path) });
|
|
173
160
|
}
|
|
174
161
|
else
|
|
175
162
|
dropped.push({ server: declaredName(e), reason: "malformed_entry", field: v.field });
|
|
176
163
|
}
|
|
177
164
|
for (const e of raw.slice(MAX_REQUEST_MCP_SERVERS, MAX_REQUEST_MCP_SERVERS + MAX_REQUEST_MCP_DROP_NAMES))
|
|
178
165
|
dropped.push({ server: declaredName(e), reason: "over_cap" });
|
|
179
|
-
return { ok, dropped, droppedTotal: Math.max(0, raw.length - ok.length), badContentOrigin, toolAxesReread };
|
|
166
|
+
return { ok, dropped, droppedTotal: Math.max(0, raw.length - ok.length), badContentOrigin, toolAxesReread, transportLost };
|
|
180
167
|
}
|
|
181
168
|
export function assertRequestMcpUnlocked(bodyMcp, lockedKeys) {
|
|
182
169
|
if (!lockedKeys.has("mcp"))
|
|
@@ -195,7 +182,7 @@ export function requestEntryIdentityIssue(entry) {
|
|
|
195
182
|
return undefined;
|
|
196
183
|
return mcpIdentityHeadersIssue(t);
|
|
197
184
|
}
|
|
198
|
-
|
|
185
|
+
function requestEntryIdentityRefusal(entry, at) {
|
|
199
186
|
const issue = requestEntryIdentityIssue(entry);
|
|
200
187
|
if (issue === undefined || !isRecord(entry))
|
|
201
188
|
return undefined;
|
|
@@ -205,14 +192,44 @@ export function requestEntryIdentityRefusal(entry, at) {
|
|
|
205
192
|
const value = isRecord(transport) ? transport.assertionHeader : undefined;
|
|
206
193
|
return entryFieldRefusal(entry, at, { path: "transport.assertionHeader", reason: describeMcpAssertionHeaderNotAString(value) });
|
|
207
194
|
}
|
|
208
|
-
export function
|
|
209
|
-
if (
|
|
210
|
-
return;
|
|
211
|
-
|
|
212
|
-
|
|
195
|
+
export function requestMcpDeclarationRefusal(list) {
|
|
196
|
+
if (list === undefined || list === null)
|
|
197
|
+
return undefined;
|
|
198
|
+
if (!Array.isArray(list))
|
|
199
|
+
return listRefusal(`mcpServers is ${describeValueShape(list)}, not an array of MCP server declarations`);
|
|
200
|
+
if (list.length > MAX_REQUEST_MCP_SERVERS)
|
|
201
|
+
return listRefusal(`mcpServers carries ${list.length} declarations, above this deployment's ceiling of ${MAX_REQUEST_MCP_SERVERS}`);
|
|
202
|
+
for (let i = 0; i < list.length; i++) {
|
|
203
|
+
const refusal = requestEntryRefusal(list[i], `mcpServers[${i}]`);
|
|
213
204
|
if (refusal !== undefined)
|
|
214
|
-
|
|
205
|
+
return refusal;
|
|
215
206
|
}
|
|
207
|
+
return undefined;
|
|
208
|
+
}
|
|
209
|
+
export function assertRequestMcpEntries(bodyMcp) {
|
|
210
|
+
const refusal = requestMcpDeclarationRefusal(bodyMcp);
|
|
211
|
+
if (refusal !== undefined)
|
|
212
|
+
throw createCodedHttpError(400, refusal.errorCode, refusal.message, refusal.unknownKeys === undefined ? undefined : { unknownKeys: [...refusal.unknownKeys] });
|
|
213
|
+
}
|
|
214
|
+
const LIST_REFUSAL_TAIL = "The request is refused rather than acting on part of the list: declarations that silently did not apply would read as in effect to whoever sent them. " +
|
|
215
|
+
"Fix the list (an empty list declares none).";
|
|
216
|
+
function listRefusal(head) {
|
|
217
|
+
return { errorCode: "request.field_invalid", message: `${head}. ${LIST_REFUSAL_TAIL}` };
|
|
218
|
+
}
|
|
219
|
+
const ENTRY_KEY_SET = new Set(MCP_SERVER_ENTRY_KEYS);
|
|
220
|
+
const STDIO_TRANSPORT_KEY_SET = new Set(STDIO_MCP_TRANSPORT_KEYS);
|
|
221
|
+
const HTTP_TRANSPORT_KEY_SET = new Set(HTTP_MCP_TRANSPORT_KEYS);
|
|
222
|
+
const NO_TOLERATED_KEYS = new Set();
|
|
223
|
+
function entryUnknownKeys(entry, at) {
|
|
224
|
+
const buckets = { unknown: [], unsupported: [] };
|
|
225
|
+
scanKeyClosure(entry, `${at}.`, ENTRY_KEY_SET, NO_TOLERATED_KEYS, buckets);
|
|
226
|
+
const t = entry.transport;
|
|
227
|
+
if (isRecord(t)) {
|
|
228
|
+
const keys = t.kind === "stdio" ? STDIO_TRANSPORT_KEY_SET : t.kind === "http" ? HTTP_TRANSPORT_KEY_SET : undefined;
|
|
229
|
+
if (keys !== undefined)
|
|
230
|
+
scanKeyClosure(t, `${at}.transport.`, keys, NO_TOLERATED_KEYS, buckets);
|
|
231
|
+
}
|
|
232
|
+
return buckets.unknown.sort();
|
|
216
233
|
}
|
|
217
234
|
const ENTRY_KEY_JUDGES = {
|
|
218
235
|
allowTools: (o) => o.allowTools === undefined || isStringArray(o.allowTools)
|
|
@@ -222,14 +239,15 @@ const ENTRY_KEY_JUDGES = {
|
|
|
222
239
|
? undefined
|
|
223
240
|
: {
|
|
224
241
|
path: "contentOrigin",
|
|
225
|
-
reason: `must be one of ${
|
|
242
|
+
reason: `must be one of ${MCP_CONTENT_ORIGINS.map((w) => `"${w}"`).join(" | ")} — got ${describeBadContentOrigin(o.contentOrigin)}` +
|
|
226
243
|
` (omit the key for the default: this server's tools classify as external content)`,
|
|
227
244
|
},
|
|
228
|
-
elicitation: (o) => (o.elicitation === undefined || isElicitationFlag(o.elicitation) ? undefined : { path: "elicitation", reason: `must be a boolean — got ${
|
|
245
|
+
elicitation: (o) => (o.elicitation === undefined || isElicitationFlag(o.elicitation) ? undefined : { path: "elicitation", reason: `must be a boolean — got ${describeValueShape(o.elicitation)}` }),
|
|
229
246
|
name: (o) => (isUsableWireName(o.name) ? undefined : { path: "name", reason: `must be a non-empty string within the wire-name length bound — got ${describeBadWireName(o.name)}` }),
|
|
230
247
|
source: (o) => o.source === undefined || isMcpSourceLabel(o.source)
|
|
231
248
|
? undefined
|
|
232
|
-
: { path: "source", reason: `must be a non-empty string of at most ${MCP_SOURCE_LABEL_MAX} characters (a display label) — got ${
|
|
249
|
+
: { path: "source", reason: `must be a non-empty string of at most ${MCP_SOURCE_LABEL_MAX} characters (a display label) — got ${describeValueShape(o.source)}` },
|
|
250
|
+
startupTimeoutMs: () => undefined,
|
|
233
251
|
toolAxes: (o) => {
|
|
234
252
|
const read = readMcpToolAxes(o.toolAxes);
|
|
235
253
|
return read.ok ? undefined : { path: "toolAxes", reason: read.problem };
|
|
@@ -254,7 +272,17 @@ function entryFieldRefusal(entry, at, issue) {
|
|
|
254
272
|
}
|
|
255
273
|
function requestEntryRefusal(entry, at) {
|
|
256
274
|
if (!isRecord(entry))
|
|
257
|
-
return
|
|
275
|
+
return listRefusal(`${at} is ${describeValueShape(entry)}, not an MCP server declaration (an object)`);
|
|
276
|
+
const unknownKeys = entryUnknownKeys(entry, at);
|
|
277
|
+
if (unknownKeys.length > 0) {
|
|
278
|
+
return {
|
|
279
|
+
errorCode: "request.body_shape",
|
|
280
|
+
message: `body: unrecognized key(s) on an MCP declaration — refused rather than dropped, because a dropped key reads as "in effect" to the caller. ` +
|
|
281
|
+
`${keyClosureClause(unknownKeys, "unknown (not an mcpServers[] key — check the spelling)")}. ` +
|
|
282
|
+
`Accepted per entry: ${[...MCP_SERVER_ENTRY_KEYS].sort().join(",")} (transport.kind "stdio": ${[...STDIO_MCP_TRANSPORT_KEYS].sort().join(",")}; "http": ${[...HTTP_MCP_TRANSPORT_KEYS].sort().join(",")})`,
|
|
283
|
+
unknownKeys: unknownKeys.slice(0, MAX_KEY_ECHO),
|
|
284
|
+
};
|
|
285
|
+
}
|
|
258
286
|
const identity = requestEntryIdentityRefusal(entry, at);
|
|
259
287
|
if (identity !== undefined)
|
|
260
288
|
return identity;
|
|
@@ -265,12 +293,6 @@ function requestEntryRefusal(entry, at) {
|
|
|
265
293
|
}
|
|
266
294
|
return undefined;
|
|
267
295
|
}
|
|
268
|
-
export function requestEntryToolAxesRefusal(entry, at) {
|
|
269
|
-
if (!isRecord(entry))
|
|
270
|
-
return undefined;
|
|
271
|
-
const issue = ENTRY_KEY_JUDGES.toolAxes(entry);
|
|
272
|
-
return issue === undefined ? undefined : entryFieldRefusal(entry, at, issue);
|
|
273
|
-
}
|
|
274
296
|
export function deploymentClosedMcpNames(baseline, reservedNames) {
|
|
275
297
|
return new Set([...(baseline ?? []).map((s) => s.name), ...reservedNames]);
|
|
276
298
|
}
|
|
@@ -311,7 +333,7 @@ function classifyHonored(baseline, entries, config, logger, storedToolAxes) {
|
|
|
311
333
|
if (v.badContentOrigin.length > 0) {
|
|
312
334
|
logger?.warn("mcp_content_class_dropped", {
|
|
313
335
|
entries: v.badContentOrigin,
|
|
314
|
-
allowed:
|
|
336
|
+
allowed: MCP_CONTENT_ORIGINS,
|
|
315
337
|
note: "declaration DROPPED — these servers keep the pre-378 default (external content, session gets marked); the servers themselves still mount",
|
|
316
338
|
});
|
|
317
339
|
}
|
|
@@ -337,6 +359,18 @@ function classifyHonored(baseline, entries, config, logger, storedToolAxes) {
|
|
|
337
359
|
note: "this replayed request was stored before the upgrade and its toolAxes declaration does not pass the engine's reader; while one-time migration M19 is open it is read the way the pre-upgrade server read it (members that did not fit are dropped, a declaration that is not an object counts as none) and the server stays mounted — once the window closes the same request leaves this server unmounted",
|
|
338
360
|
});
|
|
339
361
|
}
|
|
362
|
+
for (const t of v.transportLost) {
|
|
363
|
+
if (!mounted.has(t.server))
|
|
364
|
+
continue;
|
|
365
|
+
logger?.warn("mcp_transport_members_dropped", {
|
|
366
|
+
server: t.server,
|
|
367
|
+
lost: t.lost.slice(0, MAX_KEY_ECHO),
|
|
368
|
+
...(t.lost.length > MAX_KEY_ECHO ? { lostTotal: t.lost.length } : {}),
|
|
369
|
+
note: "this replayed request carries parts of this server's transport declaration that cannot be handed to the engine — an env / headers record that is not a plain object of string values (left out whole, as the pre-upgrade server read it), " +
|
|
370
|
+
"a member named \"__proto__\" in env / headers (only that member is left out: the engine refuses the name), args that are not a list of strings, a principalHeader that is not a string; " +
|
|
371
|
+
"the server mounts with the rest. A new submission with the same entry is refused (400)",
|
|
372
|
+
});
|
|
373
|
+
}
|
|
340
374
|
return {
|
|
341
375
|
mcp: mergeRequestMcp(baseline, v.ok.map(toCoreMcpServerSpec), reservedNames),
|
|
342
376
|
drops: [...v.dropped, ...blocked.map((server) => ({ server, reason: "name_reserved_by_deployment" }))],
|
package/dist/task-settings.d.ts
CHANGED
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
* - (`hooks` NO LONGER deferred either — 轴B #2 注释保鲜:applied 形已接线(本文件 hooks 分片 +
|
|
48
48
|
* main.ts 单用户闸),仅 malformed 才报 deferred;旧「需要 remote hook-runner」是接线前拍照。)
|
|
49
49
|
*/
|
|
50
|
-
import { type PathRuleBases, type ExecutionEnv, type TaskSpec, type ThinkingLevel, type ToolPolicy, type
|
|
50
|
+
import { type PathRuleBases, type ExecutionEnv, type TaskSpec, type ThinkingLevel, type ToolPolicy, type PermissionMode } from "@sema-agent/core";
|
|
51
51
|
import { type KeyClosureIssue } from "./request-key-closure.js";
|
|
52
52
|
import { type RunnableHooksConfig } from "./hooks/hook-runner.js";
|
|
53
53
|
import type { StoredHooksRereadM20 } from "./stored-request-hooks-m20.js";
|
|
@@ -216,7 +216,7 @@ export interface ParsedTaskSettings {
|
|
|
216
216
|
ultracode?: boolean;
|
|
217
217
|
/** hooks hook-runner(阶段一):经 `parseHooksConfig`(契约包分类器 + 服务侧上限 + 本仓会跑的条目类型)判过的 hooks 配置。像 shellEnv 一样
|
|
218
218
|
* 这里只 PARSE;应用点(main.ts resolveSpec)按单用户闸(`requirePrincipal !== true`)决定翻不翻成
|
|
219
|
-
*
|
|
219
|
+
* 任务座 `TaskSpec.mods` 上的一张注册 `settings.hooks`——多租户 lane 收到只警告忽略(hook 命令跑在 worker host = class ② 能力授予)。 */
|
|
220
220
|
hooks?: RunnableHooksConfig;
|
|
221
221
|
/** [ref](7.77.0)—— CC settings 同名键:上下文窗口里**留给技能清单**的比例((0,1];CC 默认 0.01 = 1%)。
|
|
222
222
|
* 超预算时引擎把描述裁短、再不够退成 name-only(`cli259.js` 的清单渲染算法),**从不**拒掉一条技能 ——
|
|
@@ -324,7 +324,7 @@ export declare function taskSettingsKeyIssue(raw: unknown): KeyClosureIssue | nu
|
|
|
324
324
|
* 🔒 **`settings.hooks` 会不会被采纳** —— 全仓**唯一**的车道谓词(S-995,主会话裁):hook 命令跑在 WORKER HOST([ref] class ② 能力授予),所以只有单用户车道
|
|
325
325
|
* (`requirePrincipal !== true`,与 scheduler / backgroundShell / lspHost / MCP 注入同一姿势)采纳;多租户车道收到 hooks **整只忽略**(`task_hooks_ignored`),绝不执行。
|
|
326
326
|
* 三处读它,谁也不许内联 `requirePrincipal`(各写各的 = 迟早漂):
|
|
327
|
-
* · `boot/resolve-spec.ts` —— 装配:不采纳 ⇒
|
|
327
|
+
* · `boot/resolve-spec.ts` —— 装配:不采纳 ⇒ 不铸 `TaskSpec.mods` 的 `settings.hooks` 注册 + 一条 `task_hooks_ignored`;
|
|
328
328
|
* · `http/routes/capabilities.ts` —— 能力位 `taskSettings.hooks`(「says yes ⟺ route works」);
|
|
329
329
|
* · `http/admission.ts` —— fresh 受理面的「别名 matcher 永不命中」判据的**求值深度**:采纳 ⇒ `"regex"`(运行期同一只匹配函数,带资源闸);不采纳 ⇒ `"literal"`
|
|
330
330
|
* (7.112.0 的字面判:零调用方正则执行 —— 受理面是所有车道,租户不能借一只灾难回溯的 matcher 占满事件循环)。
|
|
@@ -350,24 +350,10 @@ export declare function parseTaskSettings(raw: unknown, seats?: ParseTaskSetting
|
|
|
350
350
|
* value must not become active prompt content after rollout (context exhaustion / spend hole). Over-cap ⇒ dropped +
|
|
351
351
|
* warned — the rider was inert pre-upgrade, so dropping preserves the stored task's prior behavior; a 4xx here would
|
|
352
352
|
* permanently brick that task's resume instead (same defensive posture as parseTaskSettings' outputStyle drop).
|
|
353
|
-
* Cap value = the submit gate's (16384; MAX_SETTINGS_OUTPUT_STYLE_CHARS — both land in the same spec field).
|
|
354
|
-
|
|
355
|
-
*
|
|
356
|
-
|
|
357
|
-
* there. Shared predicate for the submit 400 gate, the resolveSpec resume mirror, and the center-declaration
|
|
358
|
-
* probe — one definition so the three gates can't drift. */
|
|
359
|
-
export declare function hasConstitutionAnchors(text: unknown): boolean;
|
|
360
|
-
/** codex R9 (provider-aware append-less detection): mirrors core's ACTUAL pass-through triggers instead of a raw
|
|
361
|
-
* body-text heuristic — the assembler's migration guard probes (a) `stableBlocks` identity declarations and
|
|
362
|
-
* (b) `stableSystem` OUTPUT for the three anchors; a plain `userSystemPrompt` under the DEFAULT provider (no
|
|
363
|
-
* scenario provider) never triggers it and `core/role.append` is retained, so an anchored systemPrompt there
|
|
364
|
-
* must NOT block/strip a rider (R9 false-positive: unbranded default / scan rejected valid combos). Probing
|
|
365
|
-
* calls the provider hooks with a minimal ctx — server providers (and centerPromptProvider) are pure functions
|
|
366
|
-
* of ctx, and the same hooks run again inside core's assembly; a hook throw = conservative false (core will
|
|
367
|
-
* fail the task loudly on its own). `replaceAll` owns the whole prompt(legacy free-form `system()` 腿已随 core 2.0.0 删除)
|
|
368
|
-
* (REPLACE_ALL_EXCLUDED strips role.append) → append-less true. */
|
|
369
|
-
export declare function providerDropsAppend(provider: PromptProvider | undefined, userSystemPrompt: string | undefined): boolean;
|
|
370
|
-
export declare function acceptAppendSystemPrompt(v: unknown, warn?: (detail: string) => void, packDropsAppend?: boolean): string | undefined;
|
|
353
|
+
* Cap value = the submit gate's (16384; MAX_SETTINGS_OUTPUT_STYLE_CHARS — both land in the same spec field).
|
|
354
|
+
* A well-formed rider always mounts: the engine (core 7.52.0) lands it in its own task-append band whatever the role
|
|
355
|
+
* text is — there is no "already-assembled" pass-through arm left that could drop it. */
|
|
356
|
+
export declare function acceptAppendSystemPrompt(v: unknown, warn?: (detail: string) => void): string | undefined;
|
|
371
357
|
/** [ref]②/codex F2 — what the workflow ask leg needs from the deployment, on EVERY lane. It is name-keyed and
|
|
372
358
|
* fs-independent, so it never had the lane split {@link FsWriteGateWiring} carried (that split is itself gone
|
|
373
359
|
* since [ref] — the sandbox lanes wire a gate of their own shape instead of no gate). */
|
package/dist/task-settings.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { combinePolicies, createFsWriteGatePolicy, parseRuleText, resolveReasoningProfile, rankOf, isThinkingLevel,
|
|
1
|
+
import { combinePolicies, createFsWriteGatePolicy, parseRuleText, resolveReasoningProfile, rankOf, isThinkingLevel, RUN_WORKFLOW_TOOL_NAME, PERMISSION_MODES, isPermissionMode, ruleToolGrammarOf, } from "@sema-agent/core";
|
|
2
2
|
import { unmatchableToolNamesRefusal } from "./config.js";
|
|
3
3
|
import { MAX_PERMISSION_RULES_PER_LIST, createRuleListPolicy } from "./permission-rule-list.js";
|
|
4
4
|
import { allowLayerEntryCountIssue, describeAllowLayerOverCap, ruleEntryListShapeOk } from "./rule-entry-list.js";
|
|
5
|
+
import { limitRefusal } from "./limit-refusal.js";
|
|
5
6
|
import { tightenGoverned } from "./governance-overrides.js";
|
|
6
7
|
import { MAX_KEY_ECHO, keyClosureClause, scanKeyClosure } from "./request-key-closure.js";
|
|
7
8
|
import { parseHooksConfig } from "./hooks/hook-runner.js";
|
|
@@ -93,8 +94,9 @@ function bucketIssueMessage(f, rule) {
|
|
|
93
94
|
case "over_cap":
|
|
94
95
|
switch (rule) {
|
|
95
96
|
case "rule_policy":
|
|
96
|
-
return (
|
|
97
|
-
|
|
97
|
+
return limitRefusal(f.field, "entries", f.count, f.cap, {
|
|
98
|
+
tail: "Refused rather than truncated: a truncated list silently drops the rules past the cap, and a dropped deny / ask rule is a tightening that never happened. Merge rules into broader patterns or trim the list",
|
|
99
|
+
}).message;
|
|
98
100
|
case "allow_layer":
|
|
99
101
|
return describeAllowLayerOverCap(f.field, f.count);
|
|
100
102
|
}
|
|
@@ -138,7 +140,7 @@ export function settingsPermissionBucketIssue(perms) {
|
|
|
138
140
|
case "allow_layer": {
|
|
139
141
|
const over = allowLayerEntryCountIssue(field, v);
|
|
140
142
|
if (over !== undefined)
|
|
141
|
-
fields = { field, reason: "over_cap", count: over.count, cap: over.cap };
|
|
143
|
+
fields = { field, reason: "over_cap", count: over.facts.count, cap: over.facts.cap };
|
|
142
144
|
else if (!ruleEntryListShapeOk(v))
|
|
143
145
|
fields = { field, reason: "bad_entry", index: v.findIndex((x) => typeof x !== "string") };
|
|
144
146
|
break;
|
|
@@ -262,34 +264,7 @@ export function parseTaskSettings(raw, seats = {}) {
|
|
|
262
264
|
out.skillListingMaxDescChars = maxDesc;
|
|
263
265
|
return { settings: Object.keys(out).length > 0 ? out : undefined, deferred, ...(hooksReread !== undefined ? { hooksReread } : {}) };
|
|
264
266
|
}
|
|
265
|
-
export function
|
|
266
|
-
return typeof text === "string" && text.includes(CYBER_RISK) && text.includes(URL_SAFETY) && text.includes(HARNESS_SECTION_ANCHOR);
|
|
267
|
-
}
|
|
268
|
-
export function providerDropsAppend(provider, userSystemPrompt) {
|
|
269
|
-
if (!provider)
|
|
270
|
-
return false;
|
|
271
|
-
if (provider.replaceAll === true)
|
|
272
|
-
return true;
|
|
273
|
-
const ctx = { userSystemPrompt, tools: [], memoryEnabled: false, consolidationEnabled: false };
|
|
274
|
-
if (provider.stableBlocks) {
|
|
275
|
-
try {
|
|
276
|
-
return provider.stableBlocks(ctx).some((d) => d.slot === "identity" && hasConstitutionAnchors(d.text));
|
|
277
|
-
}
|
|
278
|
-
catch {
|
|
279
|
-
return false;
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
if (provider.stableSystem) {
|
|
283
|
-
try {
|
|
284
|
-
return hasConstitutionAnchors(provider.stableSystem(ctx));
|
|
285
|
-
}
|
|
286
|
-
catch {
|
|
287
|
-
return false;
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
return false;
|
|
291
|
-
}
|
|
292
|
-
export function acceptAppendSystemPrompt(v, warn, packDropsAppend) {
|
|
267
|
+
export function acceptAppendSystemPrompt(v, warn) {
|
|
293
268
|
if (v === undefined)
|
|
294
269
|
return undefined;
|
|
295
270
|
if (typeof v !== "string" || v.length === 0) {
|
|
@@ -300,10 +275,6 @@ export function acceptAppendSystemPrompt(v, warn, packDropsAppend) {
|
|
|
300
275
|
warn?.(`appendSystemPrompt dropped: ${v.length} chars exceeds the ${MAX_SETTINGS_OUTPUT_STYLE_CHARS} cap (pre-cap stored body on a resume leg?)`);
|
|
301
276
|
return undefined;
|
|
302
277
|
}
|
|
303
|
-
if (packDropsAppend === true) {
|
|
304
|
-
warn?.("appendSystemPrompt dropped: the effective prompt pack cannot mount the append rider (assembled-identity/stableSystem pass-through, replaceAll, or legacy provider — no core/role.append section)");
|
|
305
|
-
return undefined;
|
|
306
|
-
}
|
|
307
278
|
return v;
|
|
308
279
|
}
|
|
309
280
|
const RULE_SOURCE_BY_BEHAVIOR = { ask: "settings.permissions.ask", deny: "settings.permissions.deny" };
|
package/dist/text-bidi.d.ts
CHANGED
|
@@ -1,50 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* ## 为什么有这个文件
|
|
5
|
-
* 同一条字符类此前在本仓有两份逐字手抄(`session-titler.ts` 的 `sanitizeTitle`、
|
|
6
|
-
* `plugins/send-user-file.ts` 的 `sanitizeSendFileName`),第三份还要给审批卡的 bidi **在场检测**用。
|
|
7
|
-
* 这是一条安全语义上的词表(它划定「人眼看到的顺序可能不是字节顺序」那一族码点),三份手抄必然漂移 ——
|
|
8
|
-
* 单一属主的纪律与 `APPROVAL_GATE_KINDS` 同源(CLAUDE.md 硬条款:词表是闭集,不许散落副本)。
|
|
9
|
-
*
|
|
10
|
-
* ## 两条类刻意分开(**别合并**)
|
|
11
|
-
* · {@link BIDI_CONTROL_CHARS} —— **只有** bidi 一族(LRM/RLM、嵌入与覆写、隔离符)。它是**检测**用的:
|
|
12
|
-
* 问的是「这串文本里有没有能让人眼读到与执行顺序不同的东西」。C0 控制符不属于这一问 —— 一条 Bash
|
|
13
|
-
* 命令里出现换行、一段 diff 里出现制表符都是**正常**的,把它们算进来会让检测位恒为真、从而毫无判别力。
|
|
14
|
-
* · {@link CONTROL_AND_BIDI_CHARS} —— bidi ∪ C0/DEL,**清洗**用的(标题、文件名这类要落一行的短串)。
|
|
15
|
-
* 清洗面比检测面宽是对的:那两处要的是「只留可打印的一行」。
|
|
16
|
-
*
|
|
17
|
-
* ## 案锚
|
|
18
|
-
* Trojan Source([ref]②;`docs/DISEASE-SHAPES.md` 的不可见字符条):字面控制符让**人审与机器门看到
|
|
19
|
-
* 两份不同的文本**。审批卡是本仓唯一一处「把模型写的命令交给人眼判断」的面,所以它需要的是**披露**
|
|
20
|
-
* (告诉壳「这串里有 bidi」),不是清洗 —— 清洗会改掉即将被执行的那串字节,让卡上显示的与真正跑的不是
|
|
21
|
-
* 同一个东西,那比不披露更坏。
|
|
22
|
-
*/
|
|
23
|
-
/**
|
|
24
|
-
* bidi 一族的字符类**内容**(不含方括号,便于拼进更大的类)。
|
|
25
|
-
*
|
|
26
|
-
* 逐字 = Unicode 的 `Bidi_Control=Yes` **全集**(12 个码点),不是「常见的那几个」:
|
|
27
|
-
* · U+061C = ALM(Arabic Letter Mark);U+200E/200F = LRM/RLM;
|
|
28
|
-
* · U+202A-202E = 嵌入/覆写族(含 RLO);U+2066-2069 = 隔离符族。
|
|
29
|
-
*
|
|
30
|
-
* 🔴 **U+061C 是 codex 交叉复审 [medium] 验真后补的**:首版漏了它 —— 而漏一个码点在**检测**面上不是
|
|
31
|
-
* 「覆盖率差一点」,是一条完整的跳过路(只用 ALM 构造的输入让在场位缺席,壳于是照常按干净渲染)。
|
|
32
|
-
* 交叉锚:core 自己的 `APPROVER_REFUSED_CHARS_RE`(`dist/core/tool-policy.js`)同样含 `\\u061c`。
|
|
33
|
-
*
|
|
34
|
-
* ⚠️ 与 core 那只**更宽**的集合的差额如实登记(刻意,不是漏):core 还含 C1(`\\u0080-\\u009f`)与
|
|
35
|
-
* U+2028/U+2029(行/段分隔符)。那两族**不是 bidi**(不影响阅读方向),属于「不可打印 / 换行伪装」的
|
|
36
|
-
* 另一问;本类是 bidi 专用,混进来会让 {@link hasBidiControls} 的语义从「方向可能骗你」滑成「有奇怪
|
|
37
|
-
* 字符」。清洗面要不要跟着加宽是另一件(见 {@link CONTROL_AND_BIDI_CHARS} 的注)。
|
|
38
|
-
*/
|
|
39
|
-
export declare const BIDI_CONTROL_CHARS = "\\u061c\\u200e\\u200f\\u202a-\\u202e\\u2066-\\u2069";
|
|
40
|
-
/** bidi ∪ C0/DEL —— **清洗**面用(见文件头注:清洗面比检测面宽是刻意的)。
|
|
41
|
-
* ⚠️ 仍**不含** C1(`-`)与 U+2028/U+2029:加宽是行为变更、要各自的判据支撑,不搭本批的车
|
|
42
|
-
* (登记在此,别当成漏)。两处存量消费方(标题、文件名)较其手抄前身**多剥一枚 U+061C**
|
|
43
|
-
* (经 {@link BIDI_CONTROL_CHARS} 内插带入)—— 对本清洗类是有意收紧,merge-rescan 745 验真后
|
|
44
|
-
* 钉在两消费方各自的测试里;除此之外与手抄前身逐字同集。 */
|
|
45
|
-
export declare const CONTROL_AND_BIDI_CHARS = "\\u0000-\\u001f\\u007f\\u061c\\u200e\\u200f\\u202a-\\u202e\\u2066-\\u2069";
|
|
1
|
+
/** bidi ∪ C0/DEL —— **清洗**面用(见文件头注:清洗面比检测面宽是刻意的)。bidi 半场内插 core 的类,C0/DEL 半场是本仓清洗面自己的。 */
|
|
2
|
+
export declare const CONTROL_AND_BIDI_CHARS = "\\u0000-\\u001f\\u007f\\u061C\\u200E\\u200F\\u202A-\\u202E\\u2066-\\u2069";
|
|
46
3
|
/** 清洗用的全局正则(`String.replace` 会在返回前把 `lastIndex` 归零,故模块级常量可安全复用)。 */
|
|
47
4
|
export declare const CONTROL_AND_BIDI_STRIP_RE: RegExp;
|
|
48
|
-
/** 这串文本里**有没有** bidi
|
|
5
|
+
/** 这串文本里**有没有** bidi 控制符(判官 = core 的 {@link carriesBidiControls})。纯谓词:不改一个字节、不做任何清洗(理由见文件头注)。 */
|
|
49
6
|
export declare function hasBidiControls(text: string): boolean;
|
|
50
7
|
//# sourceMappingURL=text-bidi.d.ts.map
|
package/dist/text-bidi.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import { BIDI_CONTROL_CHARS, carriesBidiControls } from "@sema-agent/core";
|
|
2
2
|
export const CONTROL_AND_BIDI_CHARS = `\\u0000-\\u001f\\u007f${BIDI_CONTROL_CHARS}`;
|
|
3
3
|
export const CONTROL_AND_BIDI_STRIP_RE = new RegExp(`[${CONTROL_AND_BIDI_CHARS}]`, "g");
|
|
4
|
-
const
|
|
4
|
+
const WHOLE_TEXT_SCAN = { maxNodes: 1, maxChars: Number.MAX_SAFE_INTEGER };
|
|
5
5
|
export function hasBidiControls(text) {
|
|
6
|
-
return
|
|
6
|
+
return carriesBidiControls(text, WHOLE_TEXT_SCAN);
|
|
7
7
|
}
|
|
8
8
|
//# sourceMappingURL=text-bidi.js.map
|
package/dist/tool-approval.d.ts
CHANGED
|
@@ -509,7 +509,7 @@ export interface ToolApprovalFrame {
|
|
|
509
509
|
readRootCandidate?: ReadRootGrantCandidate;
|
|
510
510
|
/**
|
|
511
511
|
* **E-14**([ref]② Trojan Source 族;**ADDITIVE**,`"tool_approval"` only)—— 这只 ask 的**工具输入**
|
|
512
|
-
* (`AskRequest.args`)里含 bidi 控制符(LRM/RLM
|
|
512
|
+
* (`AskRequest.args`)里含 bidi 控制符(LRM/RLM、嵌入/覆写、隔离符;字符类与在场谓词的属主是 core 的 `BIDI_CONTROL_CHARS` / `carriesBidiControls`,经 `text-bidi.ts` 的 `hasBidiControls` 取)。
|
|
513
513
|
*
|
|
514
514
|
* 🔴 **真才带,缺席绝不编 `false`**(与 `governanceForced`/`requiresRealApproval` 同形)。缺席的含义是
|
|
515
515
|
* 「没扫到」——它同时覆盖「真的没有」与「args 序列化不了(循环引用)所以扫不了」两形,消费端**禁**把
|
|
@@ -50,7 +50,7 @@ type _GuardAskReverse = AssertAllKeysHandled<Exclude<AskProjected | AskExcluded,
|
|
|
50
50
|
type AskFrameServerMinted = "type" | "approvalId" | "argsOmitted" | "outcome" | "governanceForced" | "expiresAtMs" | "expiresInMs" | "serverNowMs" | "parked" | "cause" | "inputHasBidi" | "rememberRefused";
|
|
51
51
|
type _GuardAskFrame = AssertAllKeysHandled<Exclude<keyof ToolApprovalFrame, AskProjected | AskFrameServerMinted>>;
|
|
52
52
|
type _GuardAskFrameReverse = AssertAllKeysHandled<Exclude<AskProjected | AskFrameServerMinted, keyof ToolApprovalFrame>>;
|
|
53
|
-
type TaskEventHandled = "text_delta" | "reasoning_delta" | "tool_start" | "tool_end" | "turn_end" | "compacted" | "diagnostics" | "message_committed" | "status" | "task_notification" | "task_progress" | "steering_injected" | "workspace_changed" | "done" | "context_usage" | "compaction_outcome" | "human_input" | "wiring_manifest" | "text_end" | "tool_roster_delta" | "tool_progress" | "tool_disclosure" | "task_started";
|
|
53
|
+
type TaskEventHandled = "text_delta" | "reasoning_delta" | "tool_start" | "tool_end" | "turn_end" | "compacted" | "diagnostics" | "message_committed" | "status" | "task_notification" | "task_progress" | "steering_injected" | "workspace_changed" | "done" | "context_usage" | "compaction_outcome" | "human_input" | "wiring_manifest" | "text_end" | "tool_roster_delta" | "tool_progress" | "tool_disclosure" | "task_started" | "compaction_started";
|
|
54
54
|
type _GuardTaskEvent = AssertAllKeysHandled<Exclude<TaskEvent["type"], TaskEventHandled>>;
|
|
55
55
|
type _GuardTaskEventReverse = AssertAllKeysHandled<Exclude<TaskEventHandled, TaskEvent["type"]>>;
|
|
56
56
|
type MailboxProjected = "seq" | "from" | "content" | "sentAt" | "hopChain" | "peerMeta";
|
|
@@ -59,7 +59,7 @@ type _GuardMailboxReverse = AssertAllKeysHandled<Exclude<MailboxProjected, keyof
|
|
|
59
59
|
type MailboxAppendProjected = "from" | "content" | "sentAt" | "hopChain" | "peerMeta";
|
|
60
60
|
type _GuardMailboxAppend = AssertAllKeysHandled<Exclude<keyof MailboxAppendMessage, MailboxAppendProjected>>;
|
|
61
61
|
type _GuardMailboxAppendReverse = AssertAllKeysHandled<Exclude<MailboxAppendProjected, keyof MailboxAppendMessage>>;
|
|
62
|
-
type WiringSectionProjected = "schemaVersion" | "leg" | "ask" | "question" | "interaction" | "elicit" | "parkLane" | "session" | "fleet" | "permissionRules" | "modelGate" | "autoMode" | "mcp" | "tools" | "
|
|
62
|
+
type WiringSectionProjected = "schemaVersion" | "leg" | "ask" | "question" | "interaction" | "elicit" | "parkLane" | "session" | "fleet" | "permissionRules" | "modelGate" | "autoMode" | "mcp" | "tools" | "mods" | "lsp" | "hands" | "writeProtection" | "teamRole" | "fileHistory";
|
|
63
63
|
type WiringSectionExcluded = (typeof import("./wire-projection-faces.js").WIRE_PROJECTION_FACES)["wiring_manifest_tenant"]["excluded"][number];
|
|
64
64
|
type _GuardWiringSections = AssertAllKeysHandled<Exclude<keyof WiringManifest, WiringSectionProjected | WiringSectionExcluded>>;
|
|
65
65
|
type _GuardWiringSectionsReverse = AssertAllKeysHandled<Exclude<WiringSectionProjected | WiringSectionExcluded, keyof WiringManifest>>;
|
|
@@ -67,6 +67,16 @@ type WiringSection<K extends keyof WiringManifest> = NonNullable<WiringManifest[
|
|
|
67
67
|
type WiringLegHandled = "kind";
|
|
68
68
|
type _GuardWiringLeg = AssertAllKeysHandled<Exclude<keyof WiringSection<"leg">, WiringLegHandled>>;
|
|
69
69
|
type _GuardWiringLegReverse = AssertAllKeysHandled<Exclude<WiringLegHandled, keyof WiringSection<"leg">>>;
|
|
70
|
+
type WiringModRowKeys = WiringSection<"mods">[number] extends infer R ? (R extends unknown ? keyof R : never) : never;
|
|
71
|
+
type WiringModRowHandled = "name" | "seat" | "tier" | "events" | "observe" | "skipped" | "refusedBy" | "reason";
|
|
72
|
+
type _GuardWiringModRow = AssertAllKeysHandled<Exclude<WiringModRowKeys, WiringModRowHandled>>;
|
|
73
|
+
type _GuardWiringModRowReverse = AssertAllKeysHandled<Exclude<WiringModRowHandled, WiringModRowKeys>>;
|
|
74
|
+
type WiringModSkipKeys = keyof NonNullable<Extract<WiringSection<"mods">[number], {
|
|
75
|
+
events: unknown;
|
|
76
|
+
}>["skipped"]>[number];
|
|
77
|
+
type WiringModSkipHandled = "registration" | "cause" | "reason";
|
|
78
|
+
type _GuardWiringModSkip = AssertAllKeysHandled<Exclude<WiringModSkipKeys, WiringModSkipHandled>>;
|
|
79
|
+
type _GuardWiringModSkipReverse = AssertAllKeysHandled<Exclude<WiringModSkipHandled, WiringModSkipKeys>>;
|
|
70
80
|
type WiringAskHandled = "form" | "provenance" | "effective";
|
|
71
81
|
type _GuardWiringAsk = AssertAllKeysHandled<Exclude<keyof WiringSection<"ask">, WiringAskHandled>>;
|
|
72
82
|
type _GuardWiringAskReverse = AssertAllKeysHandled<Exclude<WiringAskHandled, keyof WiringSection<"ask">>>;
|
|
@@ -136,6 +146,11 @@ type _GuardPermissionTraceReverse = AssertAllKeysHandled<Exclude<PermissionTrace
|
|
|
136
146
|
/** `T` 非 `never` 时收敛到 `never`(空集 ⇒ 残留 `"EMPTY"` ⇒ tsc 红)。 */
|
|
137
147
|
type AssertNonEmpty<T> = [T] extends [never] ? "EMPTY" : never;
|
|
138
148
|
type _GuardPermissionTraceNonEmpty = AssertAllKeysHandled<AssertNonEmpty<PermissionTraceKind>>;
|
|
149
|
+
type PromptAssembledFrame = Extract<TraceEvent, {
|
|
150
|
+
kind: "prompt.assembled";
|
|
151
|
+
}>;
|
|
152
|
+
type PromptManifestNotOnRow = (typeof import("./wire-projection-faces.js").WIRE_PROJECTION_FACES)["prompt_manifest"]["excluded"][number];
|
|
153
|
+
type _GuardPromptManifestNotOnRowReverse = AssertAllKeysHandled<Exclude<PromptManifestNotOnRow, keyof PromptAssembledFrame>>;
|
|
139
154
|
type SummaryProjected = "sessionId" | "scope" | "createdAt" | "gateKind" | "severity" | "spentMicroUsd" | "deadline" | "hasBidiControls" | "requiresRealApproval" | "denialLimitFallback" | "origin" | "mandated" | "mandate" | "boundGrantDigest" | "boundGrants" | "classifierNoRuling" | "boundGrantAbsence";
|
|
140
155
|
type SummaryExcluded = "token" | "toolInput" | "toolName" | "toolCallId" | "preview" | "principal" | "sourceTaskId" | "approvalCard" | "restoreMode" | "checkpointId" | "previewWithheld" | "authoredBy";
|
|
141
156
|
type _GuardInboxSummary = AssertAllKeysHandled<Exclude<keyof CheckpointSummary, SummaryProjected | SummaryExcluded>>;
|
|
@@ -148,9 +163,9 @@ type ParkArmQueueExcluded = "kind" | "args" | "batchToolCallIds" | "completedCal
|
|
|
148
163
|
type _GuardParkArmQueue = AssertAllKeysHandled<Exclude<ParkArmKeys, ParkArmQueueProjected | ParkArmQueueExcluded>>;
|
|
149
164
|
type _GuardParkArmQueueReverse = AssertAllKeysHandled<Exclude<ParkArmQueueProjected | ParkArmQueueExcluded, ParkArmKeys>>;
|
|
150
165
|
type _NoDoubleBookParkArmQueue = AssertAllKeysHandled<Extract<ParkArmQueueProjected, ParkArmQueueExcluded>>;
|
|
151
|
-
type TaskSpecWired = "objective" | "principal" | "images" | "sessionId" | "requireExistingSession" | "oneShot" | "clientContext" | "resumeAt" | "resumeAtMode" | "model" | "compactionModel" | "thinking" | "systemPrompt" | "appendSystemPrompt" | "
|
|
166
|
+
type TaskSpecWired = "objective" | "principal" | "images" | "sessionId" | "requireExistingSession" | "oneShot" | "clientContext" | "resumeAt" | "resumeAtMode" | "model" | "compactionModel" | "thinking" | "systemPrompt" | "appendSystemPrompt" | "promptRole" | "promptBinding" | "memory" | "suggestNextPrompts" | "restoreFiles" | "acceptPartialRestore" | "rewindFilesTo" | "tools" | "excludeTools" | "deferTools" | "toolMaterializeStrategy" | "promptProfile" | "toolPolicy" | "onAsk" | "onQuestion" | "mods" | "durableApproval" | "resourceSuspend" | "resilience" | "finalVerification" | "checkpointStore" | "handsReadOnly" | "memoryPersistenceCapable" | "additionalDirectories" | "additionalReadDirectories" | "enablePlanMode" | "interactiveTools" | "enableFork" | "shellGate" | "approvalReach" | "writeFace" | "mcp" | "a2a" | "skills" | "backgroundScope" | "envFacts" | "limits" | "configOverrides" | "forwardSubagentEvents" | "retainSubagentSessions" | "retainBackgroundProcesses" | "outputSchema" | "outputRetries" | "compaction" | "attachments" | "selfOrchestration" | "getApiKeyAndHeaders" | "interactionPosture" | "agents" | "permissionMode" | "taskId" | "signal" | "preemptSignal" | "maxSuspends" | "skillListingBudgetFraction" | "skillListingMaxDescChars" | "excludeAllTools" | "fileHistory" | "userInvokedSkills" | "outputStyle" | "allowedTools" | "allowTools" | "userAttachments";
|
|
152
167
|
/** 导出:请求体键闭集门(`request-key-closure.ts`)据它锁「本仓记为未接线的引擎座,提交口不许受理」—— 两处分类只能同向。 */
|
|
153
|
-
export type TaskSpecUnwired = "actor" | "roles" | "lspManager" | "tracer" | "readFace" | "readDenyPatterns" | "interactiveQuestionFallback" | "alwaysLoadTools" | "restoreGatedTools" | "deferSelfResolve" | "basePolicyForResumeEdit" | "lspDiagnostics" | "streamingToolExecution" | "toolResultThresholdChars" | "peerPresence" | "writeProtectedAdditions" | "complianceAdditionalDenies" | "modelRole" | "enableBlockedReport";
|
|
168
|
+
export type TaskSpecUnwired = "actor" | "roles" | "lspManager" | "tracer" | "readFace" | "readDenyPatterns" | "interactiveQuestionFallback" | "alwaysLoadTools" | "restoreGatedTools" | "deferSelfResolve" | "basePolicyForResumeEdit" | "lspDiagnostics" | "streamingToolExecution" | "toolResultThresholdChars" | "peerPresence" | "writeProtectedAdditions" | "complianceAdditionalDenies" | "modelRole" | "enableBlockedReport" | "promptForm";
|
|
154
169
|
type _GuardTaskSpec = AssertAllKeysHandled<Exclude<keyof TaskSpec, TaskSpecWired | TaskSpecUnwired>>;
|
|
155
170
|
type _GuardTaskSpecReverse = AssertAllKeysHandled<Exclude<TaskSpecWired | TaskSpecUnwired, keyof TaskSpec>>;
|
|
156
171
|
type TaskResultForwarded = "taskId" | "runId" | "sessionId" | "terminal" | "model" | "effectiveReasoning" | "result" | "salvagedOutput" | "remoteEnvFailures" | "apiFailure" | "retryAfterMs" | "degraded" | "structuredOutput" | "rewindNotes" | "haltedOnUserRejection" | "haltedByUser" | "strandedHumanAnswers" | "pendingApproval" | "approvalWaitedMs" | "effectiveReadFace" | "effectiveReadDenyPatterns" | "effectiveWriteFace" | "effectiveMemoryScopes" | "stats" | "editedFiles" | "responseModel" | "compaction";
|
|
@@ -294,6 +309,10 @@ export type CoreKeysetGuards = [
|
|
|
294
309
|
_GuardWiringFleetReverse,
|
|
295
310
|
_GuardSubagentTranscriptTierWords,
|
|
296
311
|
_GuardSubagentTranscriptTierWordsReverse,
|
|
312
|
+
_GuardWiringModRow,
|
|
313
|
+
_GuardWiringModRowReverse,
|
|
314
|
+
_GuardWiringModSkip,
|
|
315
|
+
_GuardWiringModSkipReverse,
|
|
297
316
|
_GuardWiringMcp,
|
|
298
317
|
_GuardWiringMcpReverse,
|
|
299
318
|
_GuardWiringRules,
|
|
@@ -306,6 +325,7 @@ export type CoreKeysetGuards = [
|
|
|
306
325
|
_GuardWiringGovernanceReverse,
|
|
307
326
|
_GuardPermissionTrace,
|
|
308
327
|
_GuardPermissionTraceReverse,
|
|
328
|
+
_GuardPromptManifestNotOnRowReverse,
|
|
309
329
|
_GuardPermissionTraceNonEmpty,
|
|
310
330
|
_GuardInboxSummary,
|
|
311
331
|
_GuardInboxSummaryReverse,
|