@sema-agent/server 7.67.0 → 7.69.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/USAGE.md +19 -2
- package/dist/adoption/plan.js +11 -0
- package/dist/approval-card.d.ts +26 -0
- package/dist/approval-card.js +11 -0
- package/dist/approval.js +5 -4
- package/dist/boot/config-center.d.ts +6 -7
- package/dist/boot/config-center.js +31 -8
- package/dist/boot/leader.js +1 -1
- package/dist/boot/resolve-spec.js +1 -1
- package/dist/boot/workflow-orchestration.d.ts +2 -0
- package/dist/boot/workflow-orchestration.js +10 -2
- package/dist/budget.js +1 -1
- package/dist/config-catalog.js +20 -1
- package/dist/config-center/apply-effective.d.ts +8 -1
- package/dist/config-center/apply-effective.js +23 -9
- package/dist/config-center/facade.d.ts +1 -1
- package/dist/config-center/facade.js +1 -1
- package/dist/config-center/read-face.d.ts +30 -1
- package/dist/config-center/read-face.js +33 -15
- package/dist/config-center/restart-signal.js +2 -1
- package/dist/config-center/types.d.ts +20 -5
- package/dist/config-provider.js +1 -0
- package/dist/config-types.d.ts +17 -2
- package/dist/config.d.ts +0 -21
- package/dist/config.js +19 -6
- package/dist/http/route-ctx.d.ts +44 -2
- package/dist/http/routes/approvals-assistant.js +1 -0
- package/dist/http/routes/capabilities.js +1 -0
- package/dist/http/routes/runs.js +1 -1
- package/dist/http/routes/tasks.js +1 -0
- package/dist/http/routes/workflows.js +15 -7
- package/dist/http/server.d.ts +15 -2
- package/dist/http/server.js +74 -45
- package/dist/leader/wire.d.ts +9 -2
- package/dist/leader/wire.js +6 -6
- package/dist/main.js +6 -5
- package/dist/mcp-tool-faces.js +11 -2
- package/dist/model-compat.d.ts +81 -0
- package/dist/model-compat.js +52 -0
- package/dist/observability/fail-open.d.ts +4 -0
- package/dist/observability/fail-open.js +4 -0
- package/dist/operator-ask.d.ts +46 -0
- package/dist/operator-ask.js +4 -0
- package/dist/orchestration/workflow-agent-session-index.d.ts +96 -0
- package/dist/orchestration/workflow-agent-session-index.js +146 -0
- package/dist/orchestration/workflow-journal-entry.d.ts +78 -0
- package/dist/orchestration/workflow-journal-entry.js +20 -0
- package/dist/orchestration/workflow-notify-journal.d.ts +43 -1
- package/dist/orchestration/workflow-notify-journal.js +43 -3
- package/dist/parked-decide.d.ts +115 -5
- package/dist/parked-decide.js +94 -26
- package/dist/plugins/pg-pool.js +8 -0
- package/dist/plugins/store-backend.d.ts +5 -0
- package/dist/plugins/store-backend.js +3 -1
- package/dist/plugins/tidb-pool.js +8 -0
- package/dist/plugins/workflow-journal-store-sql.js +10 -3
- package/dist/plugins/workflow-run-store-sql.d.ts +30 -0
- package/dist/plugins/workflow-run-store-sql.js +40 -0
- package/dist/router/route-orchestration.js +2 -1
- package/dist/run-local.js +1 -1
- package/dist/runs.d.ts +10 -1
- package/dist/runs.js +4 -1
- package/dist/runtime-governance.js +5 -4
- package/dist/task-mcp.d.ts +50 -6
- package/dist/task-mcp.js +71 -35
- package/dist/tool-approval.d.ts +20 -0
- package/dist/tool-approval.js +2 -1
- package/dist/trace/core-keyset-guard.d.ts +3 -3
- package/dist/trace/engine-notice-wire.d.ts +17 -1
- package/dist/trace/engine-notice-wire.js +7 -1
- package/package.json +4 -4
package/dist/task-mcp.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { resolveComplianceDenies } from "@sema-agent/core";
|
|
1
|
+
import { mcpInjectionDroppedNotice, resolveComplianceDenies } from "@sema-agent/core";
|
|
2
2
|
import { HttpError } from "./security.js";
|
|
3
3
|
import { CONTENT_ORIGIN_WORDS, describeBadContentOrigin, isContentOriginWord } from "./mcp-content-origin.js";
|
|
4
4
|
import { readMcpSourceLabel } from "./mcp-source-label.js";
|
|
5
5
|
import { readMcpToolFaces } from "./mcp-tool-faces.js";
|
|
6
6
|
export const MAX_REQUEST_MCP_SERVERS = 32;
|
|
7
|
+
export const MAX_REQUEST_MCP_DROP_NAMES = MAX_REQUEST_MCP_SERVERS;
|
|
7
8
|
export function mcpInjectionHonored(config) {
|
|
8
9
|
if (config.lockedConfigKeys?.includes("mcp") === true)
|
|
9
10
|
return false;
|
|
@@ -14,20 +15,27 @@ export function mcpInjectionHonored(config) {
|
|
|
14
15
|
function isStringRecord(v) {
|
|
15
16
|
return !!v && typeof v === "object" && !Array.isArray(v) && Object.values(v).every((x) => typeof x === "string");
|
|
16
17
|
}
|
|
18
|
+
const bad = (field) => ({ ok: false, field });
|
|
19
|
+
const MALFORMED_NAME = "<malformed>";
|
|
20
|
+
function declaredName(e) {
|
|
21
|
+
return e && typeof e === "object" && typeof e.name === "string" && e.name !== ""
|
|
22
|
+
? String(e.name)
|
|
23
|
+
: MALFORMED_NAME;
|
|
24
|
+
}
|
|
17
25
|
function normalizeServer(e, noteBadOrigin) {
|
|
18
26
|
if (!e || typeof e !== "object")
|
|
19
|
-
return
|
|
27
|
+
return bad("entry");
|
|
20
28
|
const o = e;
|
|
21
29
|
if (typeof o.name !== "string" || o.name.length === 0 || o.name.length > 128)
|
|
22
|
-
return
|
|
30
|
+
return bad("name");
|
|
23
31
|
const t = o.transport;
|
|
24
32
|
if (!t || typeof t !== "object")
|
|
25
|
-
return
|
|
33
|
+
return bad("transport");
|
|
26
34
|
const tr = t;
|
|
27
35
|
let transport;
|
|
28
36
|
if (tr.kind === "stdio") {
|
|
29
37
|
if (typeof tr.command !== "string" || tr.command.length === 0)
|
|
30
|
-
return
|
|
38
|
+
return bad("transport.command");
|
|
31
39
|
transport = {
|
|
32
40
|
kind: "stdio",
|
|
33
41
|
command: tr.command,
|
|
@@ -37,7 +45,7 @@ function normalizeServer(e, noteBadOrigin) {
|
|
|
37
45
|
}
|
|
38
46
|
else if (tr.kind === "http") {
|
|
39
47
|
if (typeof tr.url !== "string" || !/^https?:\/\//i.test(tr.url))
|
|
40
|
-
return
|
|
48
|
+
return bad("transport.url");
|
|
41
49
|
transport = {
|
|
42
50
|
kind: "http",
|
|
43
51
|
url: tr.url,
|
|
@@ -46,12 +54,12 @@ function normalizeServer(e, noteBadOrigin) {
|
|
|
46
54
|
};
|
|
47
55
|
}
|
|
48
56
|
else {
|
|
49
|
-
return
|
|
57
|
+
return bad("transport.kind");
|
|
50
58
|
}
|
|
51
59
|
const spec = { name: o.name, transport };
|
|
52
60
|
if (o.allowTools !== undefined) {
|
|
53
61
|
if (!Array.isArray(o.allowTools) || !o.allowTools.every((a) => typeof a === "string"))
|
|
54
|
-
return
|
|
62
|
+
return bad("allowTools");
|
|
55
63
|
spec.allowTools = o.allowTools;
|
|
56
64
|
}
|
|
57
65
|
if (typeof o.elicitation === "boolean")
|
|
@@ -82,29 +90,32 @@ function normalizeServer(e, noteBadOrigin) {
|
|
|
82
90
|
Object.assign(spec, readMcpSourceLabel(spec.name, o.source));
|
|
83
91
|
const faces = readMcpToolFaces(o.toolFaces);
|
|
84
92
|
if (!faces.ok)
|
|
85
|
-
return
|
|
93
|
+
return bad("toolFaces");
|
|
86
94
|
if (faces.faces !== undefined)
|
|
87
95
|
spec.toolFaces = faces.faces;
|
|
88
|
-
return spec;
|
|
96
|
+
return { ok: true, spec };
|
|
89
97
|
}
|
|
90
98
|
export function validateRequestMcp(raw) {
|
|
91
99
|
if (raw === undefined || raw === null)
|
|
92
|
-
return
|
|
100
|
+
return validateRequestMcpEntries([]);
|
|
93
101
|
if (!Array.isArray(raw))
|
|
94
102
|
return null;
|
|
103
|
+
return validateRequestMcpEntries(raw);
|
|
104
|
+
}
|
|
105
|
+
function validateRequestMcpEntries(raw) {
|
|
95
106
|
const ok = [];
|
|
96
107
|
const dropped = [];
|
|
97
108
|
const badContentOrigin = [];
|
|
98
109
|
for (const e of raw.slice(0, MAX_REQUEST_MCP_SERVERS)) {
|
|
99
110
|
const v = normalizeServer(e, (server, value) => badContentOrigin.push({ server, value: describeBadContentOrigin(value) }));
|
|
100
|
-
if (v)
|
|
101
|
-
ok.push(v);
|
|
111
|
+
if (v.ok)
|
|
112
|
+
ok.push(v.spec);
|
|
102
113
|
else
|
|
103
|
-
dropped.push(
|
|
114
|
+
dropped.push({ server: declaredName(e), reason: "malformed_entry", field: v.field });
|
|
104
115
|
}
|
|
105
|
-
|
|
106
|
-
dropped.push(
|
|
107
|
-
return { ok, dropped, badContentOrigin };
|
|
116
|
+
for (const e of raw.slice(MAX_REQUEST_MCP_SERVERS, MAX_REQUEST_MCP_SERVERS + MAX_REQUEST_MCP_DROP_NAMES))
|
|
117
|
+
dropped.push({ server: declaredName(e), reason: "over_cap" });
|
|
118
|
+
return { ok, dropped, droppedTotal: Math.max(0, raw.length - ok.length), badContentOrigin };
|
|
108
119
|
}
|
|
109
120
|
export function assertRequestMcpUnlocked(bodyMcp, lockedKeys) {
|
|
110
121
|
if (!lockedKeys.has("mcp"))
|
|
@@ -140,21 +151,33 @@ export function mergeRequestMcp(baseline, gated, reservedNames) {
|
|
|
140
151
|
const add = gated.filter((s) => !closed.has(s.name));
|
|
141
152
|
return add.length === 0 ? baseline : [...(baseline ?? []), ...add];
|
|
142
153
|
}
|
|
143
|
-
export function resolveRequestMcp(baseline, bodyMcp, config, logger) {
|
|
154
|
+
export function resolveRequestMcp(baseline, bodyMcp, config, logger, notice) {
|
|
144
155
|
if (bodyMcp === undefined || bodyMcp === null)
|
|
145
156
|
return baseline;
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
if (v === null) {
|
|
157
|
+
const { mcp, drops } = classifyRequestMcp(baseline, bodyMcp, config, logger);
|
|
158
|
+
mintInjectionDropNotices(drops, notice);
|
|
159
|
+
return mcp;
|
|
160
|
+
}
|
|
161
|
+
function classifyRequestMcp(baseline, bodyMcp, config, logger) {
|
|
162
|
+
if (bodyMcp !== undefined && bodyMcp !== null && !Array.isArray(bodyMcp)) {
|
|
153
163
|
logger?.warn("mcp_injection_ignored", { reason: "mcpServers not an array" });
|
|
154
|
-
return baseline;
|
|
164
|
+
return { mcp: baseline, drops: [] };
|
|
155
165
|
}
|
|
156
|
-
|
|
157
|
-
|
|
166
|
+
const entries = Array.isArray(bodyMcp) ? bodyMcp : [];
|
|
167
|
+
const outcome = mcpInjectionHonored(config) ? classifyHonored(baseline, entries, config, logger) : classifyGateClosed(baseline, entries);
|
|
168
|
+
if (outcome.drops.length > 0)
|
|
169
|
+
logger?.warn("mcp_injection_dropped", { dropped: outcome.drops, droppedTotal: outcome.droppedTotal });
|
|
170
|
+
return { mcp: outcome.mcp, drops: outcome.drops };
|
|
171
|
+
}
|
|
172
|
+
function classifyGateClosed(baseline, entries) {
|
|
173
|
+
return {
|
|
174
|
+
mcp: baseline,
|
|
175
|
+
drops: entries.slice(0, MAX_REQUEST_MCP_DROP_NAMES).map((e) => ({ server: declaredName(e), reason: "gate_closed" })),
|
|
176
|
+
droppedTotal: entries.length,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
function classifyHonored(baseline, entries, config, logger) {
|
|
180
|
+
const v = validateRequestMcpEntries(entries);
|
|
158
181
|
if (v.badContentOrigin.length > 0) {
|
|
159
182
|
logger?.warn("mcp_content_class_dropped", {
|
|
160
183
|
entries: v.badContentOrigin,
|
|
@@ -165,13 +188,26 @@ export function resolveRequestMcp(baseline, bodyMcp, config, logger) {
|
|
|
165
188
|
const reservedNames = config.mcpServers?.reservedNames ?? [];
|
|
166
189
|
const closed = deploymentClosedMcpNames(baseline, reservedNames);
|
|
167
190
|
const blocked = v.ok.filter((s) => closed.has(s.name)).map((s) => s.name);
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
191
|
+
return {
|
|
192
|
+
mcp: mergeRequestMcp(baseline, v.ok, reservedNames),
|
|
193
|
+
drops: [...v.dropped, ...blocked.map((server) => ({ server, reason: "name_reserved_by_deployment" }))],
|
|
194
|
+
droppedTotal: v.droppedTotal + blocked.length,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
function mintInjectionDropNotices(drops, notice) {
|
|
198
|
+
if (notice === undefined || drops.length === 0)
|
|
199
|
+
return;
|
|
200
|
+
const sessionId = notice.sessionId;
|
|
201
|
+
if (typeof sessionId !== "string" || sessionId.length === 0)
|
|
202
|
+
return;
|
|
203
|
+
const said = new Set();
|
|
204
|
+
for (const d of drops) {
|
|
205
|
+
if (d.server !== MALFORMED_NAME) {
|
|
206
|
+
if (said.has(d.server))
|
|
207
|
+
continue;
|
|
208
|
+
said.add(d.server);
|
|
209
|
+
}
|
|
210
|
+
notice.emit(mcpInjectionDroppedNotice({ sessionId, server: d.server, reason: d.reason, ...(d.field !== undefined ? { field: d.field } : {}) }));
|
|
174
211
|
}
|
|
175
|
-
return mergeRequestMcp(baseline, v.ok, reservedNames);
|
|
176
212
|
}
|
|
177
213
|
//# sourceMappingURL=task-mcp.js.map
|
package/dist/tool-approval.d.ts
CHANGED
|
@@ -143,6 +143,26 @@ export interface ToolApprovalFrame {
|
|
|
143
143
|
* ask」,治理策略产的与普通策略产的在这一个词上同形 ⇒ 顶替不了(逐字论证见 `governance-ask-marks.ts` 顶注)。
|
|
144
144
|
*/
|
|
145
145
|
origin?: string;
|
|
146
|
+
/**
|
|
147
|
+
* **S-185 / [ref]**(core 7.10.0;**ADDITIVE**,`"tool_approval"` only)—— 这一问**为什么**到了人手上:
|
|
148
|
+
* auto 档的分类器被咨询过、而它**跑不了**。`cause` = core 的闭三词
|
|
149
|
+
* (`AUTO_MODE_UNAVAILABLE_CAUSES` = `error` / `timeout` / `breaker_open`),`AskRequest.classifierUnavailable`
|
|
150
|
+
* 逐字透传。
|
|
151
|
+
*
|
|
152
|
+
* 🔴 **缺席 ≠「分类器好着呢」**:缺席同时覆盖三形 —— 分类器答上了 / 这只 ask 没资格走分类器
|
|
153
|
+
* (`classifierMayAnswer` 的闭表)/ 本部署压根没接分类器。消费端**禁**把缺席读成对分类器健康的断言。
|
|
154
|
+
* 另注:`parse_error`(分类器跑了但答得出格)**不盖这一位** —— 那是另一句话,core 顶注逐字。
|
|
155
|
+
*
|
|
156
|
+
* 🔴 **不枚举词表**(值形是 `{cause: string}` 而不是本仓自铸的联合):词表单一属主在 core,抄一份会把
|
|
157
|
+
* core 加的新词吞成缺席。窄读只判「对象 ∧ `cause` 非空串 ∧ 无多余成员」(`readClassifierUnavailable`,
|
|
158
|
+
* 帧与卡的**唯一**铸造点 ⇒ 两面结构性同值)。
|
|
159
|
+
*
|
|
160
|
+
* 🔴 **echo-only,零消费**:熔断/超时的处置全在 core 的分类器站,server 不许据本键自铸第二套回落判据
|
|
161
|
+
* —— 同 `origin` / `denialLimitFallback` 两条顶注的同一条禁令(同一语义面两个写者)。
|
|
162
|
+
*/
|
|
163
|
+
classifierUnavailable?: {
|
|
164
|
+
cause: string;
|
|
165
|
+
};
|
|
146
166
|
/**
|
|
147
167
|
* **E-14**([ref]② Trojan Source 族;**ADDITIVE**,`"tool_approval"` only)—— 这只 ask 的**工具输入**
|
|
148
168
|
* (`AskRequest.args`)里含 bidi 控制符(LRM/RLM、嵌入/覆写、隔离符;字符类属主 `text-bidi.ts`)。
|
package/dist/tool-approval.js
CHANGED
|
@@ -8,7 +8,7 @@ import { approvalPayloadFingerprint } from "./plugins/approval-payload-fingerpri
|
|
|
8
8
|
import { createLogger } from "./observability/logger.js";
|
|
9
9
|
import { recordFailOpen } from "./observability/fail-open.js";
|
|
10
10
|
import { deriveAskId, deriveBatchId, MAX_DECISION_NOTE_CHARS } from "./approval-ask-machine.js";
|
|
11
|
-
import { ApprovalCardEnvelopeSchema, MAX_RULE_OFFERS, buildApprovalCard, buildApprovalCardEnvelope, buildApprovalRequestFrame, buildRevokeFrame, readDenialLimitFallback, readProbeCause, readRuleEvidence, readRuleOffersAbsence, RuleOfferRawSchema, backfillLegacyBatchMemberKind, screenUncoveredDetailSeat, } from "./approval-card.js";
|
|
11
|
+
import { ApprovalCardEnvelopeSchema, MAX_RULE_OFFERS, buildApprovalCard, buildApprovalCardEnvelope, buildApprovalRequestFrame, buildRevokeFrame, readDenialLimitFallback, readClassifierUnavailable, readProbeCause, readRuleEvidence, readRuleOffersAbsence, RuleOfferRawSchema, backfillLegacyBatchMemberKind, screenUncoveredDetailSeat, } from "./approval-card.js";
|
|
12
12
|
import { projectAskTerminalClaimTruth } from "./plugins/approval-ask-store-sql.js";
|
|
13
13
|
import { governanceAskMarksFor, runWithGovernanceAskScope } from "./governance-ask-marks.js";
|
|
14
14
|
const defaultLogger = createLogger();
|
|
@@ -844,6 +844,7 @@ export class ToolApprovalCoordinator {
|
|
|
844
844
|
...(ruleLaneMaterial !== undefined ? { ruleOffers: ruleLaneMaterial.offers } : {}),
|
|
845
845
|
...((a) => (a !== undefined ? { ruleOffersAbsence: a } : {}))(readRuleOffersAbsence(req)),
|
|
846
846
|
...((f) => (f !== undefined ? { denialLimitFallback: f } : {}))(readDenialLimitFallback(req)),
|
|
847
|
+
...((c) => (c !== undefined ? { classifierUnavailable: c } : {}))(readClassifierUnavailable(req)),
|
|
847
848
|
...((c) => (c !== undefined ? { probeCause: c } : {}))(readProbeCause(req)),
|
|
848
849
|
...((c) => (c !== undefined ? { ruleEvidence: c } : {}))(readRuleEvidence(req)),
|
|
849
850
|
...(bounded.omitted ? { argsOmitted: true } : { args: bounded.args }),
|
|
@@ -28,7 +28,7 @@ type BgNotifExcluded = "kind" | "sessionScoped" | "owner" | "scope" | "descripti
|
|
|
28
28
|
type _GuardBgNotif = AssertAllKeysHandled<Exclude<keyof BackgroundChildEvent, BgNotifProjected | BgNotifExcluded>>;
|
|
29
29
|
type RosterProjected = "name" | "agentId" | "sessionId" | "toolUseId" | "owner" | "scope" | "sessionScoped" | "rootSessionId" | "model" | "modelFallback" | "createdAt";
|
|
30
30
|
type _GuardRoster = AssertAllKeysHandled<Exclude<keyof RosterEntry, RosterProjected>>;
|
|
31
|
-
type AskProjected = "toolName" | "toolCallId" | "args" | "message" | "sourceTaskId" | "fromSubagent" | "sourceAgentName" | "delegation" | "ruleOffers" | "ruleOffersAbsence" | "persistedRuleShadowed" | "probeCause" | "ruleEvidence" | "requiresRealApproval" | "denialLimitFallback" | "origin";
|
|
31
|
+
type AskProjected = "toolName" | "toolCallId" | "args" | "message" | "sourceTaskId" | "fromSubagent" | "sourceAgentName" | "delegation" | "ruleOffers" | "ruleOffersAbsence" | "persistedRuleShadowed" | "probeCause" | "ruleEvidence" | "requiresRealApproval" | "denialLimitFallback" | "origin" | "classifierUnavailable";
|
|
32
32
|
type AskExcluded = "preview" | "principal" | "riskAxes" | "boundInputHash" | "isDelegatedChild" | "probeReason" | "hasBidiControls" | "previewWithheld" | "execCwd";
|
|
33
33
|
type _GuardAsk = AssertAllKeysHandled<Exclude<keyof AskRequest, AskProjected | AskExcluded>>;
|
|
34
34
|
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";
|
|
@@ -38,14 +38,14 @@ type _GuardMailbox = AssertAllKeysHandled<Exclude<keyof MailboxMessage, MailboxP
|
|
|
38
38
|
type MailboxAppendProjected = "from" | "content" | "sentAt" | "hopChain" | "peerMeta";
|
|
39
39
|
type _GuardMailboxAppend = AssertAllKeysHandled<Exclude<keyof MailboxAppendMessage, MailboxAppendProjected>>;
|
|
40
40
|
type PermissionTraceKind = Extract<TraceEvent["kind"], `permission.${string}`>;
|
|
41
|
-
type PermissionTraceProjected = "permission.persisted_rule_allowed" | "permission.rule_store_unreadable";
|
|
41
|
+
type PermissionTraceProjected = "permission.persisted_rule_allowed" | "permission.rule_store_unreadable" | "permission.read_only_allowed";
|
|
42
42
|
type PermissionTraceDropped = "permission.sandbox_admitted" | "permission.rule_sync_resurrected" | "permission.rule_sync_dropped" | "permission.org_snapshot_unavailable";
|
|
43
43
|
type _GuardPermissionTrace = AssertAllKeysHandled<Exclude<PermissionTraceKind, PermissionTraceProjected | PermissionTraceDropped>>;
|
|
44
44
|
type _GuardPermissionTraceReverse = AssertAllKeysHandled<Exclude<PermissionTraceProjected | PermissionTraceDropped, PermissionTraceKind>>;
|
|
45
45
|
/** `T` 非 `never` 时收敛到 `never`(空集 ⇒ 残留 `"EMPTY"` ⇒ tsc 红)。 */
|
|
46
46
|
type AssertNonEmpty<T> = [T] extends [never] ? "EMPTY" : never;
|
|
47
47
|
type _GuardPermissionTraceNonEmpty = AssertAllKeysHandled<AssertNonEmpty<PermissionTraceKind>>;
|
|
48
|
-
type SummaryProjected = "sessionId" | "scope" | "createdAt" | "gateKind" | "severity" | "spentMicroUsd" | "deadline" | "hasBidiControls" | "requiresRealApproval" | "denialLimitFallback" | "origin";
|
|
48
|
+
type SummaryProjected = "sessionId" | "scope" | "createdAt" | "gateKind" | "severity" | "spentMicroUsd" | "deadline" | "hasBidiControls" | "requiresRealApproval" | "denialLimitFallback" | "origin" | "classifierUnavailable";
|
|
49
49
|
type SummaryExcluded = "token" | "toolInput" | "toolName" | "toolCallId" | "preview" | "principal" | "sourceTaskId" | "contentKind" | "restoreMode" | "checkpointId" | "previewWithheld";
|
|
50
50
|
type _GuardInboxSummary = AssertAllKeysHandled<Exclude<keyof CheckpointSummary, SummaryProjected | SummaryExcluded>>;
|
|
51
51
|
type TaskSpecWired = "objective" | "principal" | "images" | "sessionId" | "requireExistingSession" | "oneShot" | "clientContext" | "resumeAt" | "resumeAtMode" | "model" | "compactionModel" | "thinking" | "systemPrompt" | "appendSystemPrompt" | "promptProvider" | "memory" | "suggestNextPrompts" | "restoreFiles" | "acceptPartialRestore" | "rewindFilesTo" | "tools" | "excludeTools" | "deferTools" | "toolMaterializeStrategy" | "promptProfile" | "toolPolicy" | "onAsk" | "onQuestion" | "hooks" | "durableApproval" | "resourceSuspend" | "resilience" | "finalVerification" | "checkpointStore" | "handsReadOnly" | "memoryPersistenceCapable" | "additionalDirectories" | "additionalReadDirectories" | "enablePlanMode" | "interactiveTools" | "enableFork" | "shellGate" | "mcp" | "a2a" | "skills" | "backgroundScope" | "envFacts" | "limits" | "configOverrides" | "forwardSubagentEvents" | "retainSubagentSessions" | "retainBackgroundProcesses" | "outputSchema" | "outputRetries" | "compaction" | "attachments" | "selfOrchestration" | "getApiKeyAndHeaders" | "interactionPosture" | "agents" | "taskId" | "signal" | "preemptSignal" | "modelRole" | "enableBlockedReport" | "maxSuspends" | "autoModeRequested";
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* 同文件 G1 e2e 的全码扇出夹具、以及契约文档附录 D.3 那张表(含**小节标题里的码数** —— 那道门本批
|
|
17
17
|
* 刚立,立完就在下一次加码时自己咬住了)。
|
|
18
18
|
*/
|
|
19
|
-
export declare const ENGINE_NOTICE_WIRE_CODES: readonly ["memory.session_polluted", "memory.harvest_quarantined", "memory.delegation_static_mark_waived", "memory.hold_opened", "memory.hold_released", "memory.hold_disposed", "task.turn_interrupted", "steering.parked_input_blocked", "task.user_steer_undrained", "task.user_followup_undrained", "memory.capture_opted_out", "memory.capture_optout_unpersisted", "task.halt_unconsumed", "task.late_approval", "config.durable_gate_unavailable", "peer.inbound_disposition", "peer.held_settled", "peer.idle_subscription", "classifier.denial_limit"];
|
|
19
|
+
export declare const ENGINE_NOTICE_WIRE_CODES: readonly ["memory.session_polluted", "memory.harvest_quarantined", "memory.delegation_static_mark_waived", "memory.hold_opened", "memory.hold_released", "memory.hold_disposed", "task.turn_interrupted", "steering.parked_input_blocked", "task.user_steer_undrained", "task.user_followup_undrained", "memory.capture_opted_out", "memory.capture_optout_unpersisted", "task.halt_unconsumed", "task.late_approval", "config.durable_gate_unavailable", "peer.inbound_disposition", "peer.held_settled", "peer.idle_subscription", "classifier.denial_limit", "mcp.injection_dropped", "delegation.ask_unresolvable"];
|
|
20
20
|
export type EngineNoticeWireCode = (typeof ENGINE_NOTICE_WIRE_CODES)[number];
|
|
21
21
|
/** 白名单谓词(单点):路由与门都读这一个,不许第二处手抄码串。 */
|
|
22
22
|
export declare function isEngineNoticeWireCode(code: string): code is EngineNoticeWireCode;
|
|
@@ -136,5 +136,21 @@ export declare function registerEngineNoticeLeg(opts: {
|
|
|
136
136
|
live?: EngineNoticeWireSink;
|
|
137
137
|
durable?: EngineNoticeWireSink;
|
|
138
138
|
router?: EngineNoticeRouter;
|
|
139
|
+
/**
|
|
140
|
+
* L-167 —— **腿开张之前**就已经铸好的通告(装配期 `resolveSpec` 的产物,经
|
|
141
|
+
* `PreparedTaskSubmission.engineNotices` 递过来)。注册完口**立刻**经同一只 {@link EngineNoticeRouter.route}
|
|
142
|
+
* 投出:白名单、归属键、消毒、隔离四件判据一个都不绕,**不是**第二条投递机制 —— 只是把 `route()` 挪到
|
|
143
|
+
* 「这条会话已经有口在听」的那一拍。
|
|
144
|
+
*
|
|
145
|
+
* 🔴 为什么不让铸点自己 `route()`:装配(`prepareSpec`)跑在本函数**之前**,那一刻这条会话一只口都没有,
|
|
146
|
+
* `route()` 恒返 0 —— 一条结构上永远投不出去的用户面披露,就是本仓 `task.user_steer_undrained` 陈腐明拒
|
|
147
|
+
* 那一族的病。缺席/空数组 ⇒ 一个字节不投(既有腿逐字不变)。
|
|
148
|
+
*/
|
|
149
|
+
pending?: readonly {
|
|
150
|
+
code: string;
|
|
151
|
+
message: string;
|
|
152
|
+
detail?: Record<string, unknown>;
|
|
153
|
+
sessionId?: unknown;
|
|
154
|
+
}[];
|
|
139
155
|
}): () => void;
|
|
140
156
|
//# sourceMappingURL=engine-notice-wire.d.ts.map
|
|
@@ -20,6 +20,8 @@ export const ENGINE_NOTICE_WIRE_CODES = [
|
|
|
20
20
|
"peer.held_settled",
|
|
21
21
|
"peer.idle_subscription",
|
|
22
22
|
"classifier.denial_limit",
|
|
23
|
+
"mcp.injection_dropped",
|
|
24
|
+
"delegation.ask_unresolvable",
|
|
23
25
|
];
|
|
24
26
|
const WIRE_CODES = new Set(ENGINE_NOTICE_WIRE_CODES);
|
|
25
27
|
export function isEngineNoticeWireCode(code) {
|
|
@@ -150,6 +152,10 @@ export function registerEngineNoticeLeg(opts) {
|
|
|
150
152
|
const sinks = [...(live ? [live] : []), ...(durable ? [durable] : [])];
|
|
151
153
|
if (sinks.length === 0)
|
|
152
154
|
return () => undefined;
|
|
153
|
-
|
|
155
|
+
const router = opts.router ?? defaultEngineNoticeRouter;
|
|
156
|
+
const unregister = router.registerLeg(sessionId, sinks);
|
|
157
|
+
for (const notice of opts.pending ?? [])
|
|
158
|
+
router.route(notice);
|
|
159
|
+
return unregister;
|
|
154
160
|
}
|
|
155
161
|
//# sourceMappingURL=engine-notice-wire.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/server",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.69.0",
|
|
4
4
|
"description": "Sema Server — the server/API implementation layer for Sema, wiring core, registry, model providers, and cloud agent execution. Built on @sema-agent/core.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "BUSL-1.1",
|
|
@@ -54,8 +54,8 @@
|
|
|
54
54
|
"build:binary:run-local:darwin-arm64": "bun build --compile --target=bun-darwin-arm64 src/run-local.ts --outfile dist/run-local-darwin-arm64"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@sema-agent/core": "7.
|
|
58
|
-
"@sema-agent/settings-schema": "1.
|
|
57
|
+
"@sema-agent/core": "7.11.2",
|
|
58
|
+
"@sema-agent/settings-schema": "1.10.0",
|
|
59
59
|
"e2b": "^2.28.0",
|
|
60
60
|
"libsodium-wrappers": "^0.8.4",
|
|
61
61
|
"mysql2": "^3.22.4",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"sharp": "^0.35.3"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
|
-
"@sema-agent/sdk": "8.
|
|
72
|
+
"@sema-agent/sdk": "8.8.0",
|
|
73
73
|
"@types/libsodium-wrappers": "^0.7.14",
|
|
74
74
|
"@types/node": "22.10.2",
|
|
75
75
|
"@types/pg": "^8.20.0",
|