@sema-agent/server 7.149.0 → 7.150.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 +122 -9
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/USAGE.md +39 -15
- package/dist/approval-card.d.ts +1 -1
- package/dist/approval-gate-currency.d.ts +1 -1
- package/dist/audit.d.ts +1 -1
- package/dist/audit.js +2 -2
- package/dist/background-session-reap.d.ts +1 -1
- package/dist/boot/deferred-sandbox-path-env.d.ts +5 -3
- package/dist/boot/deferred-sandbox-path-env.js +1 -2
- package/dist/boot/parked-revive-gate.d.ts +5 -5
- package/dist/boot/parked-revive-gate.js +2 -3
- package/dist/boot/resolve-spec.d.ts +4 -5
- package/dist/boot/resolve-spec.js +61 -25
- package/dist/boot/retention-lane.d.ts +1 -1
- package/dist/boot/session-faces.js +21 -21
- package/dist/boot/stage-03-store-backend.js +2 -2
- package/dist/boot/stage-06-runners.js +1 -2
- package/dist/boot/stage-07-capability-layer.js +1 -1
- package/dist/boot/stage-10-http-server.d.ts +33 -1
- package/dist/boot/stage-10-http-server.js +9 -4
- package/dist/boot/web-admin.d.ts +1 -1
- package/dist/capability-facts.d.ts +65 -56
- package/dist/capability-facts.js +42 -35
- package/dist/config-catalog.js +1 -1
- package/dist/config-types.d.ts +12 -11
- package/dist/deployment-governance.d.ts +7 -28
- package/dist/deployment-governance.js +1 -14
- package/dist/device-ws-hub.d.ts +1 -0
- package/dist/device-ws-hub.js +64 -28
- package/dist/device-ws-protocol.d.ts +20 -6
- package/dist/device-ws-protocol.js +9 -2
- package/dist/engine-identity.d.ts +7 -1
- package/dist/engine-identity.js +5 -0
- package/dist/field-conflict.d.ts +2 -2
- package/dist/fleet/engine-signal.d.ts +14 -1
- package/dist/fleet/engine-signal.js +5 -1
- package/dist/fleet/fleet-reconciler.d.ts +1 -1
- package/dist/fleet/serving-lease.d.ts +18 -3
- package/dist/fleet/serving-lease.js +81 -35
- package/dist/fleet-client.d.ts +13 -11
- package/dist/fleet-client.js +53 -33
- package/dist/history-anchor.js +1 -1
- package/dist/hitl-delivery.d.ts +1 -3
- package/dist/hitl-delivery.js +1 -1
- package/dist/http/active-run-conflict.d.ts +3 -7
- package/dist/http/active-run-conflict.js +2 -2
- package/dist/http/admission.js +2 -2
- package/dist/http/approval-sweeps.js +2 -1
- package/dist/http/caller-trust.d.ts +2 -2
- package/dist/http/caller-trust.js +3 -3
- package/dist/http/checkpoint-ctx.d.ts +18 -63
- package/dist/http/checkpoint-ctx.js +1 -24
- package/dist/http/claim-heartbeat.d.ts +4 -4
- package/dist/http/claim-heartbeat.js +3 -3
- package/dist/http/dispatch.js +2 -2
- package/dist/http/durable-run-leg.js +4 -4
- package/dist/http/owner-access.d.ts +243 -19
- package/dist/http/owner-access.js +184 -5
- package/dist/http/readiness.d.ts +4 -2
- package/dist/http/resume-ctx-read.js +16 -1
- package/dist/http/resume-legs.js +18 -14
- package/dist/http/route-ctx.d.ts +23 -11
- package/dist/http/routes/a2a-serve.js +15 -14
- package/dist/http/routes/approvals-assistant.d.ts +3 -2
- package/dist/http/routes/approvals-assistant.js +8 -9
- package/dist/http/routes/capabilities.js +4 -3
- package/dist/http/routes/config-catalog.d.ts +1 -1
- package/dist/http/routes/mcp-reconnect.js +2 -2
- package/dist/http/routes/memory-origin.d.ts +1 -1
- package/dist/http/routes/notify-wake.js +2 -3
- package/dist/http/routes/projects.d.ts +1 -0
- package/dist/http/routes/projects.js +5 -3
- package/dist/http/routes/retention-ops.d.ts +1 -1
- package/dist/http/routes/run-permission-mode.d.ts +1 -1
- package/dist/http/routes/run-permission-mode.js +2 -2
- package/dist/http/routes/runs.d.ts +1 -1
- package/dist/http/routes/runs.js +23 -30
- package/dist/http/routes/session-memory-sync.js +4 -5
- package/dist/http/routes/session-sync.js +3 -7
- package/dist/http/routes/sessions.d.ts +1 -1
- package/dist/http/routes/sessions.js +18 -44
- package/dist/http/routes/tasks.js +9 -8
- package/dist/http/routes/trace-usage.js +14 -14
- package/dist/http/routes/workflows.d.ts +1 -0
- package/dist/http/routes/workflows.js +20 -38
- package/dist/http/server.d.ts +8 -4
- package/dist/http/server.js +5 -1
- package/dist/http/stored-body-replay.d.ts +3 -24
- package/dist/http/stored-body-replay.js +2 -12
- package/dist/http/submit-ctx.d.ts +1 -2
- package/dist/http/submit-ctx.js +3 -2
- package/dist/http/submit-replay.d.ts +15 -2
- package/dist/http/submit-replay.js +10 -4
- package/dist/http/wire-types.d.ts +6 -3
- package/dist/leader/endpoint.js +9 -8
- package/dist/leg-facts.d.ts +8 -2
- package/dist/leg-facts.js +1 -0
- package/dist/mcp-authorization-face.d.ts +18 -14
- package/dist/mcp-authorization-face.js +3 -2
- package/dist/memory-store-refusal.d.ts +1 -1
- package/dist/observability/corrupt-read-seat.d.ts +1 -1
- package/dist/observability/fail-open.d.ts +5 -5
- package/dist/observability/fail-open.js +5 -5
- package/dist/observability/logger.d.ts +7 -0
- package/dist/observability/logger.js +3 -1
- package/dist/observability/run-terminal.d.ts +1 -1
- package/dist/owner-faces.d.ts +27 -3
- package/dist/owner-faces.js +2 -0
- package/dist/peer-seat.d.ts +1 -1
- package/dist/peer-seat.js +52 -59
- package/dist/plugins/exec-path-law.d.ts +34 -0
- package/dist/plugins/exec-path-law.js +13 -0
- package/dist/plugins/file-run-store.js +1 -1
- package/dist/plugins/local-checkpoint-store.d.ts +4 -1
- package/dist/plugins/local-checkpoint-store.js +3 -0
- package/dist/plugins/memory-run-store.js +1 -1
- package/dist/plugins/one-time-migrations.d.ts +74 -49
- package/dist/plugins/one-time-migrations.js +134 -69
- package/dist/plugins/pg-pool.js +4 -0
- package/dist/plugins/posix-shell-fs.js +4 -2
- package/dist/plugins/remote-env-adb.js +3 -2
- package/dist/plugins/remote-env-device.js +8 -6
- package/dist/plugins/remote-env-e2b.d.ts +3 -1
- package/dist/plugins/remote-env-e2b.js +11 -8
- package/dist/plugins/remote-env-host.d.ts +1 -1
- package/dist/plugins/remote-env-host.js +20 -11
- package/dist/plugins/remote-env-k8s.js +3 -2
- package/dist/plugins/remote-env-local-docker.js +3 -2
- package/dist/plugins/remote-env-ssh.js +4 -3
- package/dist/plugins/remote-shell.d.ts +3 -1
- package/dist/plugins/remote-shell.js +3 -3
- package/dist/plugins/replica-registration.d.ts +35 -0
- package/dist/plugins/replica-registration.js +48 -0
- package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
- package/dist/plugins/run-store-sql.d.ts +1 -1
- package/dist/plugins/run-store-sql.js +2 -2
- package/dist/plugins/scenario-prefix-switch-m42.d.ts +6 -12
- package/dist/plugins/scenario-prefix-switch-m42.js +7 -5
- package/dist/plugins/schema-consistency.d.ts +7 -5
- package/dist/plugins/schema-consistency.js +29 -16
- package/dist/plugins/schema-drift-sentence.js +1 -1
- package/dist/plugins/serving-requirement.d.ts +49 -0
- package/dist/plugins/serving-requirement.js +53 -0
- package/dist/plugins/stop-then-start-sentence.d.ts +42 -3
- package/dist/plugins/stop-then-start-sentence.js +44 -0
- package/dist/plugins/store-backend.d.ts +1 -1
- package/dist/plugins/store-contracts.d.ts +12 -2
- package/dist/plugins/store-contracts.js +3 -0
- package/dist/plugins/tidb-pool.js +4 -0
- package/dist/process-instance.d.ts +3 -0
- package/dist/process-instance.js +7 -0
- package/dist/project-context.d.ts +66 -0
- package/dist/project-context.js +70 -0
- package/dist/question.d.ts +9 -21
- package/dist/question.js +28 -19
- package/dist/run-cancel-card.d.ts +1 -1
- package/dist/run-cancel-card.js +2 -1
- package/dist/security.d.ts +1 -1
- package/dist/session-agent.d.ts +1 -10
- package/dist/session-agent.js +0 -6
- package/dist/session-incarnation.d.ts +18 -4
- package/dist/session-incarnation.js +4 -1
- package/dist/session-notify-door.d.ts +4 -4
- package/dist/session-notify-door.js +5 -6
- package/dist/session-rules-seat.d.ts +4 -3
- package/dist/session-rules-seat.js +3 -11
- package/dist/session-sync.js +3 -3
- package/dist/stores-sql/checkpoint-store-sql.d.ts +21 -2
- package/dist/stores-sql/checkpoint-store-sql.js +106 -18
- package/dist/stores-sql/retention-store-sql.d.ts +1 -1
- package/dist/task-cwd.d.ts +4 -3
- package/dist/task-settings.d.ts +13 -0
- package/dist/task-settings.js +13 -7
- package/dist/tool-approval.d.ts +7 -6
- package/dist/tool-approval.js +41 -37
- package/dist/trace/engine-notice-wire.d.ts +14 -0
- package/dist/trace/engine-notice-wire.js +18 -1
- package/dist/trace/project.d.ts +4 -3
- package/dist/trace/project.js +3 -2
- package/dist/trace/projection-table.d.ts +33 -2
- package/dist/trace/self-minted-wire.d.ts +150 -17
- package/dist/trace/self-minted-wire.js +54 -16
- package/dist/trace/tool-card.d.ts +3 -0
- package/dist/trace/tool-card.js +24 -0
- package/dist/trace/tool-output-media.d.ts +2 -1
- package/dist/unattended-permission-mode.d.ts +1 -1
- package/dist/web-admin-client/apply-effective.d.ts +1 -1
- package/dist/web-admin-client/effective-keys.d.ts +1 -1
- package/dist/web-admin-client/skills-mcp.d.ts +1 -1
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +57 -29
- package/package.json +2 -2
- package/wire-changes/server@7.150.0.json +335 -0
|
@@ -287,6 +287,31 @@ export const SELF_MINTED_WIRE = {
|
|
|
287
287
|
waiting: { attr: "always within sandboxCapacity", since: "7.148.0" },
|
|
288
288
|
},
|
|
289
289
|
},
|
|
290
|
+
listeningLineKey: {
|
|
291
|
+
at: "stdout 启动协议行 listening(<键> → 在场律)",
|
|
292
|
+
members: {
|
|
293
|
+
port: { attr: "always", since: "1.214.2" },
|
|
294
|
+
bindHost: { attr: "always", since: "1.306.0" },
|
|
295
|
+
bindHostNote: { attr: "present-iff BIND_HOST unset and the bind was narrowed to loopback (unauthenticated write face)", since: "3.15.0" },
|
|
296
|
+
boundAddress: { attr: "always", since: "7.150.0" },
|
|
297
|
+
model: { attr: "always", since: "1.214.2" },
|
|
298
|
+
brain: { attr: "always", since: "1.214.2" },
|
|
299
|
+
breakerState: { attr: "always", since: "1.214.2" },
|
|
300
|
+
session: { attr: "always", since: "1.214.2" },
|
|
301
|
+
memory: { attr: "always", since: "1.214.2" },
|
|
302
|
+
instanceId: { attr: "always", since: "1.214.2" },
|
|
303
|
+
rateLimitPerMin: { attr: "always", since: "1.214.2" },
|
|
304
|
+
rateLimit: { attr: "always", since: "1.214.2" },
|
|
305
|
+
maxPrincipalCostUsd: { attr: "always", since: "1.214.2" },
|
|
306
|
+
costQuota: { attr: "always", since: "1.214.2" },
|
|
307
|
+
toolResultStore: { attr: "always", since: "1.214.2" },
|
|
308
|
+
otel: { attr: "always", since: "1.214.2" },
|
|
309
|
+
perModelKeys: { attr: "always", since: "1.214.2" },
|
|
310
|
+
sealedModelKeys: { attr: "always", since: "1.214.2" },
|
|
311
|
+
sealedPoisonedModels: { attr: "always", since: "1.214.2" },
|
|
312
|
+
workflowRunStore: { attr: "always", since: "1.214.2" },
|
|
313
|
+
},
|
|
314
|
+
},
|
|
290
315
|
healthStoreKey: {
|
|
291
316
|
at: "GET /health store",
|
|
292
317
|
members: {
|
|
@@ -421,6 +446,7 @@ export const SELF_MINTED_WIRE = {
|
|
|
421
446
|
registeredBy: { attr: "always", since: "7.147.0" },
|
|
422
447
|
registeredAt: { attr: "always", since: "7.147.0" },
|
|
423
448
|
archivedAt: { attr: "present-iff archived", since: "7.147.0" },
|
|
449
|
+
contentAttestedAt: { attr: "present-iff the registration carries the configuration center's content attestation (settings-schema 25.1.0; the time the center's write path last admitted the project's goal / notes / contextItems under the publisher role)", since: "7.150.0" },
|
|
424
450
|
},
|
|
425
451
|
},
|
|
426
452
|
projectsListBodyKey: {
|
|
@@ -481,8 +507,19 @@ export const SELF_MINTED_WIRE = {
|
|
|
481
507
|
at: "MCP 授权记录 authorization 的出现面(<面>#<键> → 在场律)",
|
|
482
508
|
members: {
|
|
483
509
|
"wiring_manifest.mcp[]#authorization": { attr: "present-iff errorCode unauthorized", since: "7.138.0" },
|
|
510
|
+
"GET /v1/sessions/:id/mcp#lastLegMcp.mcp[].authorization": { attr: "present-iff errorCode unauthorized", since: "7.138.0" },
|
|
511
|
+
"GET /v1/capabilities/mcp#servers[].authorization": { attr: "present-iff errorCode unauthorized", since: "7.138.0" },
|
|
512
|
+
"POST /v1/capabilities/mcp/probe#servers[].authorization": { attr: "present-iff errorCode unauthorized", since: "7.138.0" },
|
|
484
513
|
"POST /v1/sessions/:id/mcp/reconnect#status.authorization": { attr: "present-iff errorCode unauthorized", since: "7.138.0" },
|
|
485
514
|
"GET /v1/sessions/:id/mcp#servers[].authorization": { attr: "present-iff server unauthorized (this face carries no errorCode)", since: "7.138.0" },
|
|
515
|
+
"GET /v1/sessions/:id#messages[].details.authorization": { attr: "present-iff details.code unauthorized", since: "7.138.0" },
|
|
516
|
+
"SSE tool_end#structured.authorization": { attr: "present-iff structured.code unauthorized and reason in the closed set; members = reason", since: "7.138.0" },
|
|
517
|
+
"GET /v1/runs/:id/events#tool_end.structured.authorization": { attr: "present-iff structured.code unauthorized and reason in the closed set; members = reason", since: "7.138.0" },
|
|
518
|
+
},
|
|
519
|
+
retired: {
|
|
520
|
+
"GET /v1/sessions/:id#messages[].details.authorization.resourceMetadataUrl": { attr: "remote-claimed URL from the endpoint's challenge (deep-scrubbed text)", since: "7.138.0", until: "7.150.0" },
|
|
521
|
+
"SSE tool_end#structured.authorization(reason 以外的成员)": { attr: "card members passed through the text redactor (resourceMetadataUrl, a custom card's own members)", since: "7.138.0", until: "7.150.0" },
|
|
522
|
+
"GET /v1/runs/:id/events#tool_end.structured.authorization(reason 以外的成员)": { attr: "card members passed through the text redactor (resourceMetadataUrl, a custom card's own members)", since: "7.138.0", until: "7.150.0" },
|
|
486
523
|
},
|
|
487
524
|
},
|
|
488
525
|
wiringModProvenance: {
|
|
@@ -505,12 +542,12 @@ export const SELF_MINTED_WIRE = {
|
|
|
505
542
|
cascade_verify: { attr: "-", since: "7.148.0" },
|
|
506
543
|
image_profile: { attr: "-", since: "7.148.0" },
|
|
507
544
|
resume_anchor: { attr: "-", since: "7.148.0" },
|
|
508
|
-
system_prompt_fold: { attr: "
|
|
545
|
+
system_prompt_fold: { attr: "fields in fold order from appendSystemPrompt / projectId (the inherited project brief) / settings.outputStyle; count / cap", since: "7.150.0" },
|
|
509
546
|
file_history_restore: { attr: "-", since: "7.148.0" },
|
|
510
547
|
skills_disabled: { attr: "-", since: "7.148.0" },
|
|
511
548
|
existing_session: { attr: "-", since: "7.148.0" },
|
|
512
549
|
fork_target: { attr: "-", since: "7.148.0" },
|
|
513
|
-
scratchpad_root: { attr: "
|
|
550
|
+
scratchpad_root: { attr: "fields = cwd (sent) or projectId (inherited from the project), then scratchpadDir when the request's own covers it", since: "7.150.0" },
|
|
514
551
|
ask_answer: { attr: "-", since: "7.148.0" },
|
|
515
552
|
policy_person_ask: { attr: "-", since: "7.148.0" },
|
|
516
553
|
plan_edit: { attr: "-", since: "7.148.0" },
|
|
@@ -947,22 +984,22 @@ export const SELF_MINTED_WIRE = {
|
|
|
947
984
|
"POST /v1/approvals/:sessionId/decide|/v1/sessions/:id/wake|/v1/assistant/tasks/:id/resume|/v1/assistant/tasks/:id/plan_review#stored_unread_members(续跑将要跑的那一份体 —— 存量体,重述键在场时盖过重述之后 —— 里有本版读者读不出、而本部署本会采纳的成员:settings.hooks / settings.env / 其余 settings 延后键 / mcpServers[i].transport / a2aPeers[i].headers;认领之前,卡仍待决;体 resume_blocked_by_policy + blockedBy request.field_invalid + field + retriable)": { attr: 409, since: "7.147.0" },
|
|
948
985
|
"POST /v1/runs/:id/steer#stored_unread_members(run 已终态、铸唤醒卡之前;同一只判;不铸卡;体 resume_blocked_by_policy + blockedBy request.field_invalid + field,不带 retriable)": { attr: 409, since: "7.147.0" },
|
|
949
986
|
"POST /v1/approvals/:sessionId/decide|/v1/sessions/:id/wake|/v1/assistant/tasks/:id/resume|/v1/assistant/tasks/:id/plan_review|/v1/runs/:id/steer|/v1/runs/:id/permission-mode#resume_context_read_failed(读这条会话的续跑上下文失败:库断连 / 拒连 / 超时、缺表 / 权限拒、认不出的库错;拒在任何状态改动之前,卡仍待决、终态 steer 不铸卡;体 state.resume_context_unreadable)": { attr: 503, since: "7.148.0" },
|
|
950
|
-
"POST /v1/approvals/:sessionId/decide|/v1/sessions/:id/wake|/v1/assistant/tasks/:id/resume|/v1/assistant/tasks/:id/plan_review#resume_claim_store_fault(认领之前那一次执行席读、认领那一笔 —— markResuming / wake 现建行的 createRun —— 或认领之后提交执行放置那一次店往返失败:库断连 / 拒连 / 超时、缺表 / 权限拒、认不出的库错;认领之后那一形续跑认领的停驻行回到认领之前的停驻词、认领留着,wake 现建的行删掉;卡仍待决;体 state.resume_context_unreadable)": { attr: 503,
|
|
951
|
-
"POST /v1/runs/:id/cancel#parked_card_body_scope_differs(停驻 run 上的取消:这张卡行体里自带的属主格与店的属主格不一致 —— 取消只读店的属主格,结算这张卡、驱 run 终局;体 { taskId, status: failed, errorCode: cancelled, cancelRequested: false, note })": { attr: 202,
|
|
952
|
-
"POST /v1/runs/:id/cancel#parked_card_body_unreadable(停驻 run 上的取消:这张卡的行体读不成检查点 —— 取消只读店的列,结算这张卡、驱 run 终局;体同上)": { attr: 202,
|
|
987
|
+
"POST /v1/approvals/:sessionId/decide|/v1/sessions/:id/wake|/v1/assistant/tasks/:id/resume|/v1/assistant/tasks/:id/plan_review#resume_claim_store_fault(认领之前那一次执行席读、认领那一笔 —— markResuming / wake 现建行的 createRun —— 或认领之后提交执行放置那一次店往返失败:库断连 / 拒连 / 超时、缺表 / 权限拒、认不出的库错;认领之后那一形续跑认领的停驻行回到认领之前的停驻词、认领留着,wake 现建的行删掉;卡仍待决;体 state.resume_context_unreadable)": { attr: 503, since: "7.149.0" },
|
|
988
|
+
"POST /v1/runs/:id/cancel#parked_card_body_scope_differs(停驻 run 上的取消:这张卡行体里自带的属主格与店的属主格不一致 —— 取消只读店的属主格,结算这张卡、驱 run 终局;体 { taskId, status: failed, errorCode: cancelled, cancelRequested: false, note })": { attr: 202, since: "7.149.0" },
|
|
989
|
+
"POST /v1/runs/:id/cancel#parked_card_body_unreadable(停驻 run 上的取消:这张卡的行体读不成检查点 —— 取消只读店的列,结算这张卡、驱 run 终局;体同上)": { attr: 202, since: "7.149.0" },
|
|
953
990
|
"POST /v1/approvals/:sessionId/decide#parked_agent_definition_unavailable(停驻赎回;行上的代理类型不在赎回面委派工具的名册里:逐请求 `agents` 定义 / 停驻后被撤的部署定义 / 名叫 fork 的定义;approve 与 deny 同答;认领回滚、委派工具零调用、卡仍待决;体 decide.agent_definition_unavailable + taskId + rollback)": { attr: 409, since: "7.148.0" },
|
|
954
|
-
"POST /v1/tasks|/v1/tasks/stream|/v1/runs#run_claim_store_fault(新提交:认领之前那一次执行席读,或认领这一段 —— 建行认领 createRun、执行放置、续跑输入的写、起跑之前的认领复核 —— 有一次店往返没答出来:库断连 / 拒连 / 超时、缺表 / 权限拒、认不出的库错;本请求铸的行已删掉 —— 认领与幂等键随行去,同一个自带 taskId 重发即新提交 —— 什么都没起跑;认领之后的流式腿 = 流的终帧;已绑设备的会话上认领之后那一次执行席读同答;体 state.run_store_unavailable)": { attr: 503,
|
|
955
|
-
"POST /v1/approvals/:sessionId/decide|/v1/sessions/:id/wake|/v1/assistant/tasks/:id/resume|/v1/assistant/tasks/:id/plan_review#resume_pre_engine_store_fault(续跑腿提交放行之后、交给引擎之前那一段 —— 排空 workflow 完成的序号基址现读与落账、通告口落账 —— 店往返没答出来;续跑认领的停驻行回到停驻、认领留着,wake 现建的行删掉;卡仍待决;体 state.resume_context_unreadable)": { attr: 503,
|
|
956
|
-
"POST /v1/approvals/:sessionId/decide#workflow_host_turn_claim_store_fault(workflow 决定在宿主会话上起的新一跑:建行认领 / 执行放置 / 续跑输入 / 决定落行 / 起跑之前的认领复核有一次店往返没答出来;决定落行那一笔在 wake 腿上同答;现建的行已删掉,子代的卡仍待决;体 state.resume_context_unreadable)": { attr: 503,
|
|
957
|
-
"POST /v1/approvals/:sessionId/decide#workflow_decision_not_recorded(workflow 决定的投递那一跑在决定落行那一拍已不持宿主会话的认领 —— 心跳停满一窗被收割;决定没落、那一跑没起;与起跑之前认领复核答「没持有」同一只答复:认领在别的 run 上 ⇒ 409 conflict.session_active_run,宿主会话已删 ⇒ 404 resume.session_not_found,否则 409 conflict.claim_lost)": { attr: 409,
|
|
958
|
-
"POST /v1/approvals/:sessionId/decide#parked_redeem_placement_store_fault(停驻子代赎回:认领之前那一次执行席读,或认领之后那一次执行放置的店往返没答出来;认领没有或已回滚,子代仍停着、卡仍待决;体 decide.store_unreachable + taskId)": { attr: 503,
|
|
959
|
-
"POST /v1/approvals/:sessionId/decide|/v1/sessions/:id/wake|/v1/assistant/tasks/:id/resume|/v1/assistant/tasks/:id/plan_review#placement_refused_after_claim(续跑家族、workflow 决定在宿主会话上起的新一跑、停驻子代赎回认领之后提交执行放置读出这条会话此刻不能在本处执行:已放在别的车道 / 写者在别处 / 设备拒;续跑认领的停驻行回到停驻、停驻赎回回滚,卡仍待决,wake 与宿主新一跑现建的行删掉;与认领之前同一只折法、同一只体;体 resume_blocked_by_policy + blockedBy 原码 + 原事实 forkPath / boundLane + retriable)": { attr: 409,
|
|
991
|
+
"POST /v1/tasks|/v1/tasks/stream|/v1/runs#run_claim_store_fault(新提交:认领之前那一次执行席读,或认领这一段 —— 建行认领 createRun、执行放置、续跑输入的写、起跑之前的认领复核 —— 有一次店往返没答出来:库断连 / 拒连 / 超时、缺表 / 权限拒、认不出的库错;本请求铸的行已删掉 —— 认领与幂等键随行去,同一个自带 taskId 重发即新提交 —— 什么都没起跑;认领之后的流式腿 = 流的终帧;已绑设备的会话上认领之后那一次执行席读同答;体 state.run_store_unavailable)": { attr: 503, since: "7.149.0" },
|
|
992
|
+
"POST /v1/approvals/:sessionId/decide|/v1/sessions/:id/wake|/v1/assistant/tasks/:id/resume|/v1/assistant/tasks/:id/plan_review#resume_pre_engine_store_fault(续跑腿提交放行之后、交给引擎之前那一段 —— 排空 workflow 完成的序号基址现读与落账、通告口落账 —— 店往返没答出来;续跑认领的停驻行回到停驻、认领留着,wake 现建的行删掉;卡仍待决;体 state.resume_context_unreadable)": { attr: 503, since: "7.149.0" },
|
|
993
|
+
"POST /v1/approvals/:sessionId/decide#workflow_host_turn_claim_store_fault(workflow 决定在宿主会话上起的新一跑:建行认领 / 执行放置 / 续跑输入 / 决定落行 / 起跑之前的认领复核有一次店往返没答出来;决定落行那一笔在 wake 腿上同答;现建的行已删掉,子代的卡仍待决;体 state.resume_context_unreadable)": { attr: 503, since: "7.149.0" },
|
|
994
|
+
"POST /v1/approvals/:sessionId/decide#workflow_decision_not_recorded(workflow 决定的投递那一跑在决定落行那一拍已不持宿主会话的认领 —— 心跳停满一窗被收割;决定没落、那一跑没起;与起跑之前认领复核答「没持有」同一只答复:认领在别的 run 上 ⇒ 409 conflict.session_active_run,宿主会话已删 ⇒ 404 resume.session_not_found,否则 409 conflict.claim_lost)": { attr: 409, since: "7.149.0" },
|
|
995
|
+
"POST /v1/approvals/:sessionId/decide#parked_redeem_placement_store_fault(停驻子代赎回:认领之前那一次执行席读,或认领之后那一次执行放置的店往返没答出来;认领没有或已回滚,子代仍停着、卡仍待决;体 decide.store_unreachable + taskId)": { attr: 503, since: "7.149.0" },
|
|
996
|
+
"POST /v1/approvals/:sessionId/decide|/v1/sessions/:id/wake|/v1/assistant/tasks/:id/resume|/v1/assistant/tasks/:id/plan_review#placement_refused_after_claim(续跑家族、workflow 决定在宿主会话上起的新一跑、停驻子代赎回认领之后提交执行放置读出这条会话此刻不能在本处执行:已放在别的车道 / 写者在别处 / 设备拒;续跑认领的停驻行回到停驻、停驻赎回回滚,卡仍待决,wake 与宿主新一跑现建的行删掉;与认领之前同一只折法、同一只体;体 resume_blocked_by_policy + blockedBy 原码 + 原事实 forkPath / boundLane + retriable)": { attr: 409, since: "7.149.0" },
|
|
960
997
|
"POST /v1/tasks#park_commit_ended(同步腿停在要批的门上,而停驻提交答出这条 run 没有停住、已收场 —— 停驻写之前已按下取消 / 被失联收割 / 别处终结;卡已作废;体 = 收场那一行的信封,与同键重放同一只:终局行的结果,取消那一形 terminal.code cancelled;行上无结果 ⇒ 回执三键)": { attr: 200, since: "7.149.0" },
|
|
961
998
|
"POST /v1/approvals/:sessionId/decide|/v1/sessions/:id/wake|/v1/assistant/tasks/:id/resume|/v1/assistant/tasks/:id/plan_review#resume_park_ended(续跑腿再停 / 重开时停驻提交答出这条 run 已收场;卡已作废;体 status / errorCode = 收场那一行的,不带 retriable)": { attr: 200, since: "7.149.0" },
|
|
962
999
|
"POST /v1/runs/:id/interrupt#body_with_fields(体带任何顶层键 —— 含早先版本受理的 text;非对象体同答;判在查 run 之前:任何 run 状态、属主、存在与否同一只体;体 request.body_shape + unknownKeys(键全在此)+ unsupportedKeys(恒空))": { attr: 400, since: "7.148.0" },
|
|
963
|
-
"GET /v1/tool-approvals/:id#row_unreadable(有行的问,按 id 读行那一拍店抛 / 超时;本副本自己铸的活卡与起服接管的登记同答;体 not_found.ask,与查无 / 不是你的逐字节同)": { attr: 404,
|
|
964
|
-
"POST /v1/sessions/:id/sync/plan|POST /v1/sessions/:id/sync/import|PUT /v1/sessions/:id/sync/blobs/:hash#foreign_session_deleting(推送三口的门:id 上是别的主体正在删除的会话 —— 删除围栏已立、尚未删净;「被占着」读活行 ∪ 在删行,与对别人的活行同答;本人 / fleet 对自己在删的会话不变,拉取口仍只认活行;体 not_found.session,与对不存在 id 的拉取答复逐字节同)": { attr: 404,
|
|
965
|
-
"POST /v1/sessions/:id/sync/import#idle_id_other_principal_in_flight(第一阶段:id 上还没有会话行,而另一个主体在这只 id 上的第一阶段正在飞;导入租约键 = 落点属主格 + 会话 id,空闲 id 上各占各的;体 = 第一阶段的暂存回执 stagingId;先提交者得,输的那一份在提交前复判答 404 not_found.session,与赢家的提交撞在同一刻时由店的属主 CAS 拒 409 conflict)": { attr: 200,
|
|
1000
|
+
"GET /v1/tool-approvals/:id#row_unreadable(有行的问,按 id 读行那一拍店抛 / 超时;本副本自己铸的活卡与起服接管的登记同答;体 not_found.ask,与查无 / 不是你的逐字节同)": { attr: 404, since: "7.149.0" },
|
|
1001
|
+
"POST /v1/sessions/:id/sync/plan|POST /v1/sessions/:id/sync/import|PUT /v1/sessions/:id/sync/blobs/:hash#foreign_session_deleting(推送三口的门:id 上是别的主体正在删除的会话 —— 删除围栏已立、尚未删净;「被占着」读活行 ∪ 在删行,与对别人的活行同答;本人 / fleet 对自己在删的会话不变,拉取口仍只认活行;体 not_found.session,与对不存在 id 的拉取答复逐字节同)": { attr: 404, since: "7.149.0" },
|
|
1002
|
+
"POST /v1/sessions/:id/sync/import#idle_id_other_principal_in_flight(第一阶段:id 上还没有会话行,而另一个主体在这只 id 上的第一阶段正在飞;导入租约键 = 落点属主格 + 会话 id,空闲 id 上各占各的;体 = 第一阶段的暂存回执 stagingId;先提交者得,输的那一份在提交前复判答 404 not_found.session,与赢家的提交撞在同一刻时由店的属主 CAS 拒 409 conflict)": { attr: 200, since: "7.149.0" },
|
|
966
1003
|
"POST /v1/tasks|/v1/tasks/stream|/v1/runs#a2aPeers_headers_reserved_member(新提交;a2aPeers[i].headers 的成员名是 constructor / prototype —— 与 mcpServers[i].transport.headers / .env 同一张保留成员名表、同一只读法,大小写敏感;体 request.field_invalid + field 成员级路径 a2aPeers[i].headers.<名>;存盘续跑体里同形 ⇒ 续跑家族既有一面 #stored_unread_members 409)": { attr: 400, since: "7.149.0" },
|
|
967
1004
|
},
|
|
968
1005
|
retired: {},
|
|
@@ -1040,7 +1077,7 @@ export const SELF_MINTED_WIRE = {
|
|
|
1040
1077
|
"GET|PUT /v1/sessions/:id/policy#ownerless-placed-session-non-fleet-non-operator": { attr: "404 not_found.session (session not found), same body as a missing session; was 409 conflict.session_ownerless", since: "7.148.0" },
|
|
1041
1078
|
"run / session read faces#deployment-service-credential-no-principal-users-rows": { attr: "200 on GET /v1/runs/:id · /v1/runs/:id/events · /v1/sessions/:id · /head · /events · /memory-status · /execution-placement (unless SERVICE_TOKEN_ACTS_FOR_DEPLOYMENT=false); was 404, or 401 auth.principal_required where a principal is required", since: "7.148.0" },
|
|
1042
1079
|
"GET /v1/runs/:id · /v1/runs/:id/events#dev-open-principal-header-not-owner": { attr: "404 not_found.run, same body as a missing run (a caller that names a principal is that principal on a deployment without an identity boundary too); was 200", since: "7.149.0" },
|
|
1043
|
-
"session faces · list faces · /metrics family#dev-open-principal-header-not-owner": { attr: "each face's missing-row answer, same body as a missing row (404 not_found.session on GET /v1/sessions/:id · /head · /events · /memory-status · /execution-placement · PATCH /v1/sessions/:id · fork · sync reads (manifest · entries · history blob) · memory/erase · background · background/stop · mcp/reconnect · policy · notify; approval exemptions 404 not_found.session (not found); DELETE /v1/sessions/:id 200 {deleted:false}; sync push family (plan · import · blob put) 404 on another owner's session, its existing create answer on a missing id); GET /v1/sessions · /v1/fleet/stream · /v1/agents/roster · /v1/tasks (trace list) · /v1/usage/* · /v1/sendfile-links pinned to the named caller; /metrics* and GET /v1/tasks/source-summary 401 auth.unauthorized (operator sentence; METRICS_TOKEN, when configured, still opens /metrics* and is judged first); a Bearer this deployment cannot verify does not count as naming no principal (no fleet); a caller naming no principal and presenting no unverifiable credential unchanged (fleet); was 200 / fleet-wide (the principal header read as a label)",
|
|
1080
|
+
"session faces · list faces · /metrics family#dev-open-principal-header-not-owner": { attr: "each face's missing-row answer, same body as a missing row (404 not_found.session on GET /v1/sessions/:id · /head · /events · /memory-status · /execution-placement · PATCH /v1/sessions/:id · fork · sync reads (manifest · entries · history blob) · memory/erase · background · background/stop · mcp/reconnect · policy · notify; approval exemptions 404 not_found.session (not found); DELETE /v1/sessions/:id 200 {deleted:false}; sync push family (plan · import · blob put) 404 on another owner's session, its existing create answer on a missing id); GET /v1/sessions · /v1/fleet/stream · /v1/agents/roster · /v1/tasks (trace list) · /v1/usage/* · /v1/sendfile-links pinned to the named caller; /metrics* and GET /v1/tasks/source-summary 401 auth.unauthorized (operator sentence; METRICS_TOKEN, when configured, still opens /metrics* and is judged first); a Bearer this deployment cannot verify does not count as naming no principal (no fleet); a caller naming no principal and presenting no unverifiable credential unchanged (fleet); was 200 / fleet-wide (the principal header read as a label)", since: "7.149.0" },
|
|
1044
1081
|
"owner-only session ports#unreadable-archive-ownerless-session-fleet-or-operator": { attr: "answered as on a readable archive: background · background/stop · notify · mcp/reconnect · execution-placement · approval exemptions list / revoke (the gate skips the placement read only when both hypotheses admit the caller); was 500 corrupt_session", since: "7.148.0" },
|
|
1045
1082
|
"run faces#row-without-owner-cell-no-fleet-no-operator": { attr: "the face's missing-row answer for every caller without a fleet or operator qualification on that face; was: a caller without a principal passed on some faces (absent equals absent)", since: "7.148.0" },
|
|
1046
1083
|
"POST /v1/tool-approvals/:id/respond#ask-not-visible-to-caller(查无 / 不是调用方的 / 行读不出 / 本 worker 没有问账)": { attr: "404 not_found.ask (no such approval ask (never existed, no longer kept, or not yours)), one body for every form, no state facts — the durable decision door's word; was 404 tool_approval.not_pending with cause unknown_or_other_replica (no cause on a worker without an ask ledger)", since: "7.148.0" },
|
|
@@ -1252,12 +1289,13 @@ export const SELF_MINTED_WIRE = {
|
|
|
1252
1289
|
},
|
|
1253
1290
|
},
|
|
1254
1291
|
deviceProtocolRevision: {
|
|
1255
|
-
at: "GET /v1/capabilities deviceExecutor.protocolVersion 与 device WS challenge 帧的修订号(<修订号> →
|
|
1292
|
+
at: "GET /v1/capabilities deviceExecutor.protocolVersion 与 device WS challenge 帧的修订号(<修订号> → 它加进结局码闭集的词;零加词的语义修订 → 变更名)",
|
|
1256
1293
|
members: {
|
|
1257
1294
|
1: { attr: "base", since: "7.51.0" },
|
|
1258
1295
|
2: { attr: "+liveness_no_output", since: "7.133.0" },
|
|
1259
1296
|
3: { attr: "+name_too_long", since: "7.137.0" },
|
|
1260
1297
|
4: { attr: "+symlink_loop", since: "7.143.0" },
|
|
1298
|
+
5: { attr: "paths-unfolded", since: "7.150.0" },
|
|
1261
1299
|
},
|
|
1262
1300
|
},
|
|
1263
1301
|
hookNonBlockingFailureReason: {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { projectMcpAuthorization } from "../mcp-authorization-face.js";
|
|
2
|
+
import { projectToolStructured } from "./tool-output-media.js";
|
|
3
|
+
const TOOL_CARD_RECORDS = {
|
|
4
|
+
unauthorized: { member: "authorization", project: projectMcpAuthorization },
|
|
5
|
+
};
|
|
6
|
+
const isPlainRecord = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
|
|
7
|
+
function recordOf(card) {
|
|
8
|
+
const code = card.code;
|
|
9
|
+
if (typeof code !== "string")
|
|
10
|
+
return undefined;
|
|
11
|
+
const records = TOOL_CARD_RECORDS;
|
|
12
|
+
const record = Object.hasOwn(records, code) ? records[code] : undefined;
|
|
13
|
+
return record !== undefined && Object.hasOwn(card, record.member) ? record : undefined;
|
|
14
|
+
}
|
|
15
|
+
export function projectToolCard(card, redact) {
|
|
16
|
+
const record = isPlainRecord(card) ? recordOf(card) : undefined;
|
|
17
|
+
if (!isPlainRecord(card) || record === undefined)
|
|
18
|
+
return projectToolStructured(card, redact);
|
|
19
|
+
const face = record.project(card[record.member]);
|
|
20
|
+
const rest = projectToolStructured(Object.fromEntries(Object.entries(card).filter(([k]) => k !== record.member)), redact);
|
|
21
|
+
const kept = isPlainRecord(rest) ? rest : {};
|
|
22
|
+
return Object.fromEntries(Object.keys(card).flatMap((k) => (k === record.member ? (face === undefined ? [] : [[k, face]]) : Object.hasOwn(kept, k) ? [[k, kept[k]]] : [])));
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=tool-card.js.map
|
|
@@ -7,7 +7,8 @@ export declare function projectToolOutput(output: unknown): unknown;
|
|
|
7
7
|
* 媒体卡座位的**唯一一只遍历**(与 {@link projectToolOutput} 同律):媒体卡逐成员过 `redact`,`file` 里 `base64` 逐字、其余成员照脱;
|
|
8
8
|
* 其它一切整只过 `redact`。保键序(逐键映射),不改入参。
|
|
9
9
|
*
|
|
10
|
-
* 形判与遍历只此一只,**脱敏器由调用面给**(「什么算该脱」是各面自己的事,「字节座位不过它」是这里的事)
|
|
10
|
+
* 形判与遍历只此一只,**脱敏器由调用面给**(「什么算该脱」是各面自己的事,「字节座位不过它」是这里的事)。调用它的只有工具卡的唯一读者
|
|
11
|
+
* `trace/tool-card.ts` 的 `projectToolCard`(卡上挂着的有处置表的记录先经记录的投影,其余部分交给本遍历),两面经它到这里:
|
|
11
12
|
* · `tool_end` 活面 / 持久面(`toolEndEventData` 经 `trace/project.ts`):凭据脱敏 `redactDeep`;
|
|
12
13
|
* · 会话存档读面(`audit.ts` 的 `toolResult.details` 叶):模型文本段脱敏的深扫(`redactDeepWith(v, redactModelText)`)。
|
|
13
14
|
* `redact` 必须是整值→整值的纯函数(环 / 深度守卫在它里面,遍历不重做);非媒体卡原样交给它,所以非媒体卡的读数就是调用面自己的深扫。
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* ## 为什么是这一形(core §4.6e 推荐形逐条)
|
|
18
18
|
* · **读整体,不读 `askClass`**:一问可以同属几类(探针问与写保护并存、组织裁决与 hook 并存),`askClass` 只是表序第一个;集里任一类
|
|
19
19
|
* 不答 ⇒ 整问不答。
|
|
20
|
-
* · **缺席 = 不答的类**:没盖 `origin` 的站(共享制品读确认,
|
|
20
|
+
* · **缺席 = 不答的类**:没盖 `origin` 的站(共享制品读确认,[ref])、部署自铸的请求、7.37.0 之前 park 的行续跑([ref],续跑不补)
|
|
21
21
|
* 都不带类 ⇒ 不答。
|
|
22
22
|
* · **答集只 `ordinary`**:引擎可放行的类(core `releasableAskClassesFor(face)`,按问的面读 —— 哪些类、哪一面放得行以引擎的表为准,本注不抄名单)里除 `ordinary`
|
|
23
23
|
* 之外的保护类与 `mode`(plan 的写问)留给人;可放行类之外的类(权威为人提的问)恒不答。function approver 的 yes 是「这一次调用的答」—— 它连 `requiresRealApproval`
|
|
@@ -134,7 +134,7 @@ export declare const isNoCenterEffective: (eff: EffectiveConfig) => boolean;
|
|
|
134
134
|
*/
|
|
135
135
|
export declare function collabTemplatesNotExecuted(eff: Pick<EffectiveConfig, "collab">): string[];
|
|
136
136
|
/**
|
|
137
|
-
*
|
|
137
|
+
* [ref] §5 S2([ref])—— center 这份 effective **当前在管**哪些 `ServiceConfig` 键(配置目录端点
|
|
138
138
|
* `GET /v1/config/catalog` 判 `effectiveLane` 的 center 半场)。
|
|
139
139
|
*
|
|
140
140
|
* 判据与各消费腿**同源**,不自铸第二份:
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* 2. 三张登记表(非域白名单 / 不消费表 / 远端专属表)每行**必须带理由**;行的成立性由对账门**双向**钉——登记了
|
|
9
9
|
* 却不成立(死账)与成立了却没登记(半接线)都红,理由失效之日格子自己翻红(墓碑),禁裸豁免。
|
|
10
10
|
* 3. schema 侧的数据(`DOMAINS` / `PORTABLE_DOMAINS` / zod shape)一律由对账门**读 dist**,绝不抄进这里
|
|
11
|
-
* (平行副本病是
|
|
11
|
+
* (平行副本病是 [ref] §0 的病理定性,本文件只登记 server 自己那一侧)。
|
|
12
12
|
*/
|
|
13
13
|
import type { EffectiveConfig } from "./types.js";
|
|
14
14
|
/** EffectiveConfig 的全部顶层键(信封 + 域 + 非域白名单键),类型级绑定见上。 */
|
|
@@ -69,7 +69,7 @@ export declare function resolveMcpServers(mcp: {
|
|
|
69
69
|
* [ref]:alias 窗撤销,单键命中(同 `skillsForScenario`)。 */
|
|
70
70
|
export declare function mcpForScenario(center: CenterMcp | undefined, scenario: string): McpServerSpec[] | undefined;
|
|
71
71
|
/**
|
|
72
|
-
*
|
|
72
|
+
* [ref] §2.1 —— resolve the deployment's A2A peers (the `a2a` domain: `config.d/a2a.json` on the local leg, `/effective.a2a` on the
|
|
73
73
|
* center leg — one declaration seat, both legs read through the contract) into core `A2aServerSpec`s + the scenarios each applies to. Exact sibling of {@link resolveMcpServers}, same three rules:
|
|
74
74
|
* · header-NAME refs → real values from THIS service's env (the secret boundary is unchanged — the center
|
|
75
75
|
* never holds the bearer), registered on `desk` under `rosterLease` (`mintDeclaration`, only for a peer that mounts); the spec carries the minted
|
|
@@ -156,6 +156,10 @@ not above `challenge.protocolVersion` into `hello.protocolVersion` — the same
|
|
|
156
156
|
only the `errorCode` words of that revision (the revision table in §2.1). Nothing is renegotiated after `hello`:
|
|
157
157
|
the revision you declared is the contract for the whole connection. If the highest revision you implement is below
|
|
158
158
|
`DEVICE_MIN_PROTOCOL_VERSION`, the server answers `helloReject: protocol_version_unsupported` (§1.4).
|
|
159
|
+
Revisions are cumulative on the executor's side: an executor that implements revision *N* implements every revision
|
|
160
|
+
below it, so against an older server it declares that server's revision (a revision-5 executor serves a revision-4
|
|
161
|
+
server, whose paths arrive folded — a subset of what revision 5 sends). `DEVICE_MIN_PROTOCOL_VERSION` is the lowest
|
|
162
|
+
revision **this server** accepts, not a floor for your own negotiation.
|
|
159
163
|
|
|
160
164
|
### 1.3 The `hello` signature (byte-exact — do not improvise)
|
|
161
165
|
|
|
@@ -247,7 +251,7 @@ sign exactly these bytes with the device's Ed25519 private key.
|
|
|
247
251
|
|---|---|---|
|
|
248
252
|
| `auth_failed` | deliberately ambiguous: unknown device id, malformed id, malformed epoch, bad signature, or the server's device registry was unreachable | do **not** hammer: back off exponentially. If it never clears, the enrollment is gone — re-enroll. The server will not tell you which of these it was (anti-enumeration) |
|
|
249
253
|
| `revoked` | this device has been revoked. Terminal | stop reconnecting, delete the private key, ask the user to re-enroll (it yields a new `deviceId`) |
|
|
250
|
-
| `protocol_version_unsupported` | your `protocolVersion` is outside the range this server accepts; the frame carries `minProtocolVersion` | upgrade the executor. Never retry-with-a-different-version in a loop |
|
|
254
|
+
| `protocol_version_unsupported` | your `protocolVersion` is outside the range this server accepts; the frame carries `minProtocolVersion` and a one-line `message` that names your revision, the range and — below the floor — the change at the floor revision (§2.1) | upgrade the executor (`message` is fit to show as is). Never retry-with-a-different-version in a loop |
|
|
251
255
|
| `draining` | this replica is shutting down or upgrading and takes no new connections | reconnect with backoff; a replacement replica will accept you |
|
|
252
256
|
| `already_connected` | **the connection lease for this `deviceId` is not available right now**: a previous connection is still considered fresh, the stored lease has not expired yet, or the deployment forbids takeover | retry with bounded backoff — the lease expires on its own (deployment default 45 s, and a previous socket is judged stale after ~3 missed heartbeats). This code does **not** prove another process is alive: a half-open network drop can make your *own* previous connection look fresh. Do not exit permanently on it; do hold a machine-local single-instance lock so you are never racing yourself |
|
|
253
257
|
|
|
@@ -341,8 +345,8 @@ base64 inside JSON fields.
|
|
|
341
345
|
| Constant | Value | Meaning |
|
|
342
346
|
|---|---|---|
|
|
343
347
|
| `DEVICE_WS_PATH` | `/v1/device/ws` | the upgrade path (prefer the `wsPath` from `/v1/capabilities`) |
|
|
344
|
-
| `DEVICE_PROTOCOL_VERSION` | `
|
|
345
|
-
| `DEVICE_MIN_PROTOCOL_VERSION` | `
|
|
348
|
+
| `DEVICE_PROTOCOL_VERSION` | `5` | the protocol revision this server speaks (the highest it accepts) |
|
|
349
|
+
| `DEVICE_MIN_PROTOCOL_VERSION` | `5` | the lowest revision it accepts (the revision table says why); below it (or above the highest), a loud `helloReject` — never a silent downgrade |
|
|
346
350
|
| `DEVICE_HELLO_DOMAIN_TAG` | `sema.device.hello.v1` | the handshake signature domain tag (§1.3) |
|
|
347
351
|
|
|
348
352
|
<!-- closed-set: DEVICE_WS_LIMITS -->
|
|
@@ -357,25 +361,36 @@ base64 inside JSON fields.
|
|
|
357
361
|
Note the asymmetry: the transport cap is 1 MiB, and the 4096-byte pre-auth cap is applied **after** the
|
|
358
362
|
frame has been reassembled. Keep `hello` small; it is not a place for long `supports` prose.
|
|
359
363
|
|
|
364
|
+
`maxFrameBytes` binds the server too: every frame it sends is measured after serialization and is never over the
|
|
365
|
+
cap. An instruction whose frame would be over it is refused before dispatch (you never receive it), and `payload`
|
|
366
|
+
chunks are sliced so that a chunk frame, base64 and envelope included, fits. You can therefore cap the frames you
|
|
367
|
+
accept at `maxFrameBytes`.
|
|
368
|
+
|
|
360
369
|
#### Protocol revisions and the `errorCode` set
|
|
361
370
|
|
|
362
371
|
The protocol revision is the only thing an executor can read *before* it sends `hello` (the `challenge` frame
|
|
363
|
-
carries it), so
|
|
364
|
-
separate list
|
|
365
|
-
|
|
372
|
+
carries it), so everything you must know to be correct on this server is a function of the revision, not a
|
|
373
|
+
separate list: the set of `errorCode` words the server accepts from you, and what the frames it sends you mean.
|
|
374
|
+
The table gives, per revision, the words **added** at that revision and any other change made at it; the word set
|
|
375
|
+
at revision *N* is the union of the rows up to *N*, and the full set at the current revision is the §3.3 table.
|
|
366
376
|
|
|
367
377
|
<!-- closed-set: DEVICE_OUTCOME_ERROR_CODES_BY_REVISION -->
|
|
368
378
|
|
|
369
|
-
| Revision | `errorCode` words added at this revision |
|
|
370
|
-
|
|
371
|
-
| `1` | `aborted`, `already_exists`, `auth_failed`, `callback_error`, `invalid`, `is_directory`, `not_directory`, `not_found`, `not_supported`, `outcome_unknown`, `permission_denied`, `precondition_failed`, `shell_unavailable`, `spawn_error`, `suspended`, `target_unavailable`, `timeout`, `transport_lost`, `unknown` |
|
|
372
|
-
| `2` | `liveness_no_output` |
|
|
373
|
-
| `3` | `name_too_long` |
|
|
374
|
-
| `4` | `symlink_loop` |
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
+
| Revision | `errorCode` words added at this revision | Other change at this revision |
|
|
380
|
+
|---|---|---|
|
|
381
|
+
| `1` | `aborted`, `already_exists`, `auth_failed`, `callback_error`, `invalid`, `is_directory`, `not_directory`, `not_found`, `not_supported`, `outcome_unknown`, `permission_denied`, `precondition_failed`, `shell_unavailable`, `spawn_error`, `suspended`, `target_unavailable`, `timeout`, `transport_lost`, `unknown` | — |
|
|
382
|
+
| `2` | `liveness_no_output` | — |
|
|
383
|
+
| `3` | `name_too_long` | — |
|
|
384
|
+
| `4` | `symlink_loop` | — |
|
|
385
|
+
| `5` | — | every path an instruction carries (`args.path`, `args.paths`, `cwd`) arrives **unfolded** (since server 7.150.0): absolute as written, or anchored at the session's working directory, with `.` / `..` / empty segments kept — the server anchors and never folds. Resolve it as your filesystem does and judge containment on where it resolves (§3.1, §6 item 6). An executor written for revision 4 or below expects folded paths, so this is also the lowest revision the server accepts |
|
|
386
|
+
|
|
387
|
+
Rules: adding a frame or a field is additive and does not raise the revision. Every other change
|
|
388
|
+
raises `DEVICE_PROTOCOL_VERSION` and adds a row here — a word added to a closed set the server *accepts from you*
|
|
389
|
+
(today: the `errorCode` set; second column), or a **semantic change**, a change in what a frame the server sends you
|
|
390
|
+
means (third column): a semantic change raises the revision. A released row never changes. When an executor written for
|
|
391
|
+
an older revision cannot honor the change, the same release raises `DEVICE_MIN_PROTOCOL_VERSION` to the new
|
|
392
|
+
revision, so such an executor is refused once at `hello` (§1.4) instead of failing call by call.
|
|
393
|
+
Declare a revision as §1.2 says and send only the words of that revision: an executor
|
|
379
394
|
that declared revision 1 never sends `liveness_no_output` (the server does not police this per connection — it
|
|
380
395
|
decodes every connection against the current revision's full set — but a word above your declared revision is outside
|
|
381
396
|
your contract). The same sets are importable:
|
|
@@ -407,7 +422,7 @@ zeros, a plus sign, whitespace or a float form are rejected as malformed.
|
|
|
407
422
|
|---|---|---|
|
|
408
423
|
| `challenge` | `nonce` string, `protocolVersion` int | first frame the server sends, immediately on open |
|
|
409
424
|
| `helloAck` | `ok`, `heartbeatIntervalMs`, `maxInflight`, `gen`, `pendingInstructions`, `chunkWatermarks`, `reconnectGraceMs`, `cancelGraceMs`, `chunkGapTimeoutMs`, `executionCeilingGraceMs` | §1.5 |
|
|
410
|
-
| `helloReject` | `code`, `minProtocolVersion?` | §1.4; the socket closes right after |
|
|
425
|
+
| `helloReject` | `code`, `minProtocolVersion?`, `message?` | §1.4; `minProtocolVersion` and `message` appear on `protocol_version_unsupported` only; the socket closes right after |
|
|
411
426
|
| `instruction` | `gen`, `instructionId`, `rootSessionId`, `issuedSeq` int, `kind`, `args`, `cwd?`, `shellEnv?`, `timeoutMs` int | one unit of work (§3). `cwd` appears on `exec` / `execStream` only, and always there (§3.1) |
|
|
412
427
|
| `payload` | `gen`, `instructionId`, `part` (`begin` \| `chunk` \| `commit`), `offset?`, `dataB64?`, `totalLen?`, `sha256?` | the bytes for a write-family instruction (§3.4) |
|
|
413
428
|
| `cancel` | `gen`, `instructionId` | idempotent; answer with a terminal `result` (§5 R11) |
|
|
@@ -480,11 +495,19 @@ silently forgiven: it becomes a gap or a missing terminal, and the instruction e
|
|
|
480
495
|
|
|
481
496
|
### 3.1 The closed set, its arguments, and the success outcome each one owes
|
|
482
497
|
|
|
483
|
-
Every `path` in `args` arrives **already absolute
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
498
|
+
Every `path` in `args` arrives **already absolute** — the server anchored a relative one at the session's
|
|
499
|
+
working directory before sending — and **as written: a `..` or `.` segment, or an empty one, is never folded**
|
|
500
|
+
(revision 5, §2.1). Hand it to your
|
|
501
|
+
filesystem as it is. The kernel resolves `..` component by component, so a `..` that follows a symbolic link
|
|
502
|
+
goes where the link leads (`<root>/bridge/../next` with `bridge -> elsewhere/sub` is `<root>/elsewhere/next`,
|
|
503
|
+
not `<root>/next`) — and that is the file the engine's gates judged: they asked you about this same spelling
|
|
504
|
+
(`exists` / `canonicalPath` / `fileInfo` / `readLink`). `exec` and `execStream` additionally carry `cwd`, which is
|
|
505
|
+
**always present and always absolute** (unfolded the same way): run the command in exactly that directory.
|
|
506
|
+
There is no implicit base to fall back to, so an executor needs no branch for a missing or relative `cwd`.
|
|
507
|
+
Every other kind carries no `cwd` — its paths are already absolute. The paths the server reports back are its
|
|
508
|
+
own spellings, not the ones you return: `fileInfo` reports the path it asked; `listDir` reads only the leaf name
|
|
509
|
+
(last segment) of each entry's `WireFileInfo.path` and reports the entry as `<asked path>/<leaf>`, so a listed
|
|
510
|
+
entry can be asked again as written.
|
|
488
511
|
|
|
489
512
|
<!-- closed-set: DEVICE_INSTRUCTION_KINDS -->
|
|
490
513
|
|
|
@@ -567,8 +590,8 @@ a moment ago. If you omit `created`, the consumer reports the weaker of the two
|
|
|
567
590
|
|
|
568
591
|
`message` is required on the failure arm and is shown to the model — make it specific.
|
|
569
592
|
|
|
570
|
-
This is the full set at the current revision (`
|
|
571
|
-
with, and an executor sends only the words of the revision it declared (§1.2).
|
|
593
|
+
This is the full set at the current revision (`DEVICE_PROTOCOL_VERSION`, §2.1); the revision table in §2.1 says which revision
|
|
594
|
+
each word arrived with, and an executor sends only the words of the revision it declared (§1.2).
|
|
572
595
|
|
|
573
596
|
<!-- closed-set: DEVICE_OUTCOME_ERROR_CODES -->
|
|
574
597
|
|
|
@@ -972,11 +995,16 @@ These two are a real distinction to the caller: `not_started` is safely retryabl
|
|
|
972
995
|
*Honest boundary*: this is a decision-and-audit property, not enforcement against a compromised
|
|
973
996
|
machine. The protocol assumes an honest executor; it protects against races and mistakes, not against
|
|
974
997
|
an executor that lies.
|
|
975
|
-
6. **Respect `workspaceRoot` and resolve nothing yourself.** Paths arrive absolute and
|
|
976
|
-
server has already
|
|
977
|
-
`workspaceRoot` you registered. Do not re-interpret them
|
|
978
|
-
|
|
979
|
-
|
|
998
|
+
6. **Respect `workspaceRoot` and resolve nothing yourself.** Paths arrive absolute and unfolded; the
|
|
999
|
+
server has already anchored them at the session's working directory, falling back to the
|
|
1000
|
+
`workspaceRoot` you registered. Do not re-interpret them: never fold a `..` lexically (with a link before
|
|
1001
|
+
it, the folded spelling names a different file than the one the gates judged), do not expand `~`, do not
|
|
1002
|
+
follow a different base. You **may** enforce your own containment policy on top (refusing paths outside a
|
|
1003
|
+
root you are willing to serve) — judge it on where the path resolves (the real path of its existing part),
|
|
1004
|
+
never on a string prefix of the spelling (`<root>/../etc` starts with `<root>/`); if you refuse, refuse
|
|
1005
|
+
with `permission_denied`. Negative control: with `bridge` a link to `/opt/x/sub` (outside the root),
|
|
1006
|
+
`<root>/bridge/../next` resolves to `/opt/x/next` — the link carried the `..` out of the root, so the
|
|
1007
|
+
answer is `permission_denied` (not `not_found`, not success). What you must never do is silently
|
|
980
1008
|
redirect a path to somewhere else: a write that lands in a different place than the caller adjudicated
|
|
981
1009
|
is the exact failure this lane is built to prevent.
|
|
982
1010
|
7. **Do not cache and replay results.** No answer may be served from a cache keyed by command text, path
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/server",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.150.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",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"dependencies": {
|
|
85
85
|
"@modelcontextprotocol/server": "2.4.0",
|
|
86
86
|
"@sema-agent/core": "7.66.0",
|
|
87
|
-
"@sema-agent/settings-schema": "
|
|
87
|
+
"@sema-agent/settings-schema": "25.1.0",
|
|
88
88
|
"e2b": "2.36.0",
|
|
89
89
|
"libsodium-wrappers": "0.8.4",
|
|
90
90
|
"mysql2": "3.22.6",
|