@sema-agent/server 7.132.0 → 7.133.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 +266 -0
- package/README.md +8 -9
- package/README.zh-CN.md +7 -6
- package/USAGE.md +174 -55
- package/deploy/sema-up/README.md +19 -1
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -2
- package/deploy/sema-up/chart/templates/server.yaml +5 -2
- package/deploy/sema-up/stack/compose.yaml +3 -0
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +4 -2
- package/dist/adoption/plan.d.ts +3 -2
- package/dist/adoption/plan.js +7 -5
- package/dist/adoption/runner.js +3 -10
- package/dist/adoption/sql.d.ts +3 -2
- package/dist/adoption/sql.js +3 -5
- package/dist/adoption/wire.d.ts +4 -1
- package/dist/adoption/wire.js +1 -0
- package/dist/approval-ask-audit-store.d.ts +31 -13
- package/dist/approval-ask-audit-store.js +272 -74
- package/dist/approval-ask-machine.d.ts +15 -0
- package/dist/approval-ask-machine.js +6 -0
- package/dist/approval-ask-retention.d.ts +136 -0
- package/dist/approval-ask-retention.js +102 -0
- package/dist/approval-card.d.ts +79 -19
- package/dist/approval-card.js +44 -13
- package/dist/approval-deny-reasons.d.ts +1 -1
- package/dist/approval.d.ts +9 -0
- package/dist/approval.js +24 -3
- package/dist/audit.d.ts +27 -10
- package/dist/audit.js +12 -16
- package/dist/bake-runner/main.js +3 -2
- package/dist/boot/deferred-sandbox-path-env.js +1 -1
- package/dist/boot/execution-env.js +9 -7
- package/dist/boot/execution-lane.js +11 -0
- package/dist/boot/leader.js +2 -0
- package/dist/boot/memory-boundary.js +2 -2
- package/dist/boot/memory-consolidation.d.ts +5 -4
- package/dist/boot/memory-consolidation.js +7 -6
- package/dist/boot/org-delivery.d.ts +28 -0
- package/dist/boot/org-delivery.js +20 -0
- package/dist/boot/reapers.d.ts +3 -0
- package/dist/boot/reapers.js +21 -1
- package/dist/boot/resolve-spec.d.ts +3 -0
- package/dist/boot/resolve-spec.js +60 -81
- package/dist/boot/runner-deps.js +1 -0
- package/dist/boot/session-faces.d.ts +1 -0
- package/dist/boot/session-faces.js +4 -2
- package/dist/boot/stage-02-web-admin-pull.js +4 -1
- package/dist/boot/stage-06-runners.d.ts +2 -0
- package/dist/boot/stage-06-runners.js +6 -3
- package/dist/boot/stage-07-capability-layer.d.ts +2 -0
- package/dist/boot/stage-07-capability-layer.js +24 -3
- package/dist/boot/stage-08-reapers.d.ts +2 -0
- package/dist/boot/stage-08-reapers.js +2 -2
- package/dist/boot/stage-09-leader.d.ts +3 -0
- package/dist/boot/stage-10-http-server.d.ts +3 -0
- package/dist/boot/stage-10-http-server.js +5 -6
- package/dist/boot/stores.js +2 -2
- package/dist/boot/web-admin.d.ts +4 -0
- package/dist/boot/web-admin.js +151 -63
- package/dist/boot/workflow-orchestration.d.ts +2 -0
- package/dist/boot/workflow-orchestration.js +2 -1
- package/dist/brain.js +8 -3
- package/dist/breaker-key.d.ts +6 -0
- package/dist/breaker-key.js +29 -0
- package/dist/caller-text-echo.d.ts +9 -6
- package/dist/caller-text-echo.js +8 -11
- package/dist/capabilities/center-plugins.d.ts +7 -0
- package/dist/capabilities/center-plugins.js +1 -1
- package/dist/capabilities/composite-members.d.ts +1 -1
- package/dist/capabilities/composite-members.js +1 -1
- package/dist/capabilities/execution-lane.js +2 -2
- package/dist/capabilities/hands-lane.d.ts +21 -0
- package/dist/capabilities/hands-lane.js +10 -0
- package/dist/capabilities/mcp-probe.d.ts +36 -4
- package/dist/capabilities/mcp-probe.js +27 -4
- package/dist/capabilities/scenarios.d.ts +63 -7
- package/dist/capabilities/scenarios.js +39 -7
- package/dist/capability-facts.d.ts +34 -4
- package/dist/capability-facts.js +28 -2
- package/dist/center-config-tier.d.ts +69 -0
- package/dist/center-config-tier.js +42 -0
- package/dist/checkpoint-identity.d.ts +16 -0
- package/dist/checkpoint-identity.js +19 -0
- package/dist/config-catalog.d.ts +17 -10
- package/dist/config-catalog.js +43 -28
- package/dist/config-d-migration.d.ts +3 -1
- package/dist/config-d-migration.js +2 -2
- package/dist/config-dir-trust.d.ts +114 -0
- package/dist/config-dir-trust.js +388 -0
- package/dist/config-invariants.d.ts +18 -5
- package/dist/config-invariants.js +35 -3
- package/dist/config-provider.d.ts +6 -1
- package/dist/config-provider.js +6 -2
- package/dist/config-types.d.ts +71 -14
- package/dist/config-types.js +8 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.js +121 -59
- package/dist/delegated-session-owner.d.ts +185 -0
- package/dist/delegated-session-owner.js +119 -0
- package/dist/device-protocol.d.ts +5 -3
- package/dist/device-protocol.js +1 -1
- package/dist/device-ws-hub.js +21 -2
- package/dist/device-ws-protocol.d.ts +70 -6
- package/dist/device-ws-protocol.js +50 -23
- package/dist/elicitation.js +3 -2
- package/dist/entry-problems.d.ts +34 -0
- package/dist/entry-problems.js +14 -0
- package/dist/execution-lane-caps.d.ts +49 -10
- package/dist/execution-lane-caps.js +43 -4
- package/dist/field-conflict.d.ts +43 -0
- package/dist/field-conflict.js +20 -0
- package/dist/fleet/fleet-bus.d.ts +80 -6
- package/dist/fleet/fleet-bus.js +41 -9
- package/dist/hooks/classic-stations.d.ts +10 -5
- package/dist/hooks/classic-stations.js +4 -4
- package/dist/hooks/command-spawn.d.ts +57 -0
- package/dist/hooks/command-spawn.js +139 -0
- package/dist/hooks/hook-llm.js +2 -2
- package/dist/hooks/hook-runner.d.ts +127 -25
- package/dist/hooks/hook-runner.js +668 -287
- package/dist/hooks/hook-source.d.ts +44 -0
- package/dist/hooks/hook-source.js +40 -0
- package/dist/http/active-run-conflict.d.ts +5 -13
- package/dist/http/active-run-conflict.js +17 -27
- package/dist/http/admission.js +103 -60
- package/dist/http/approval-sweeps.js +55 -18
- package/dist/http/caller-trust.d.ts +77 -0
- package/dist/http/caller-trust.js +143 -0
- package/dist/http/checkpoint-ctx.d.ts +16 -16
- package/dist/http/checkpoint-ctx.js +13 -10
- package/dist/http/claimed-run.d.ts +4 -3
- package/dist/http/device-placement.d.ts +2 -4
- package/dist/http/device-placement.js +2 -1
- package/dist/http/dispatch.js +10 -4
- package/dist/http/durable-run-leg.d.ts +4 -32
- package/dist/http/durable-run-leg.js +34 -10
- package/dist/http/owner-access.d.ts +56 -0
- package/dist/http/owner-access.js +42 -0
- package/dist/http/principal-gate.d.ts +48 -23
- package/dist/http/principal-gate.js +39 -12
- package/dist/http/readiness.d.ts +11 -5
- package/dist/http/readiness.js +10 -3
- package/dist/http/request-guards.d.ts +16 -23
- package/dist/http/request-guards.js +30 -15
- package/dist/http/resume-ctx-read.d.ts +2 -5
- package/dist/http/resume-ctx-read.js +7 -4
- package/dist/http/resume-legs.d.ts +3 -4
- package/dist/http/resume-legs.js +126 -69
- package/dist/http/retired-service-deps.d.ts +43 -0
- package/dist/http/retired-service-deps.js +18 -0
- package/dist/http/route-ctx.d.ts +44 -28
- package/dist/http/route-ctx.js +4 -0
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/a2a-serve.js +3 -4
- package/dist/http/routes/admin-config-refresh.js +1 -1
- package/dist/http/routes/admin-drain.js +1 -1
- package/dist/http/routes/admin-memory-optout.js +5 -1
- package/dist/http/routes/adoption.js +2 -9
- package/dist/http/routes/approvals-assistant.js +49 -48
- package/dist/http/routes/background.js +3 -2
- package/dist/http/routes/capabilities.js +20 -4
- package/dist/http/routes/config-catalog.d.ts +3 -3
- package/dist/http/routes/config-catalog.js +1 -1
- package/dist/http/routes/devices.js +3 -17
- package/dist/http/routes/diagnostics.js +5 -1
- package/dist/http/routes/images.js +6 -7
- package/dist/http/routes/leader.js +1 -8
- package/dist/http/routes/mcp-reconnect.d.ts +1 -1
- package/dist/http/routes/mcp-reconnect.js +3 -2
- package/dist/http/routes/memory-bundle.js +1 -1
- package/dist/http/routes/memory-compliance.js +1 -1
- package/dist/http/routes/memory-consolidation.js +1 -1
- package/dist/http/routes/memory-origin.js +1 -1
- package/dist/http/routes/memory-policy.d.ts +1 -1
- package/dist/http/routes/memory-policy.js +3 -2
- package/dist/http/routes/notify-wake.js +8 -21
- package/dist/http/routes/observability.js +2 -2
- package/dist/http/routes/principal-inbox.d.ts +39 -0
- package/dist/http/routes/principal-inbox.js +76 -0
- package/dist/http/routes/retention-ops.js +2 -9
- package/dist/http/routes/rules.js +5 -18
- package/dist/http/routes/runs.d.ts +5 -0
- package/dist/http/routes/runs.js +33 -106
- package/dist/http/routes/session-sync.js +15 -28
- package/dist/http/routes/sessions.js +30 -40
- package/dist/http/routes/side-query.js +6 -4
- package/dist/http/routes/tasks.js +50 -14
- package/dist/http/routes/workflows.d.ts +351 -0
- package/dist/http/routes/workflows.js +153 -119
- package/dist/http/send.d.ts +24 -3
- package/dist/http/send.js +14 -2
- package/dist/http/server.d.ts +17 -18
- package/dist/http/server.js +15 -13
- package/dist/http/stored-body-replay.js +17 -4
- package/dist/http/submit-ctx.js +4 -3
- package/dist/http/submit-replay.d.ts +4 -3
- package/dist/http/submit-replay.js +5 -4
- package/dist/http/wire-types.d.ts +10 -7
- package/dist/index.d.ts +1 -1
- package/dist/index.js +0 -1
- package/dist/lane-home-probe.d.ts +78 -9
- package/dist/lane-home-probe.js +78 -12
- package/dist/leader/endpoint.d.ts +4 -1
- package/dist/leader/endpoint.js +11 -10
- package/dist/limit-refusal.d.ts +17 -5
- package/dist/limit-refusal.js +4 -1
- package/dist/mcp-assertion-header.d.ts +31 -10
- package/dist/mcp-assertion-header.js +10 -3
- package/dist/mcp-tool-faces.js +1 -3
- package/dist/memory-project-layer.d.ts +37 -0
- package/dist/memory-project-layer.js +46 -0
- package/dist/memory-scope.d.ts +23 -16
- package/dist/memory-scope.js +24 -8
- package/dist/memory-sync-client.d.ts +27 -13
- package/dist/memory-sync-client.js +107 -18
- package/dist/model-entry-refusal.d.ts +9 -1
- package/dist/model-entry-refusal.js +6 -1
- package/dist/model-plane-face.d.ts +51 -0
- package/dist/model-plane-face.js +24 -0
- package/dist/model-provider.d.ts +5 -0
- package/dist/model-provider.js +4 -2
- package/dist/model-route-endpoint.d.ts +8 -11
- package/dist/model-route-endpoint.js +4 -7
- package/dist/model-route-env.d.ts +22 -0
- package/dist/model-route-env.js +2 -0
- package/dist/model-route-gap.d.ts +60 -30
- package/dist/model-route-gap.js +21 -15
- package/dist/observability/corrupt-read-seat.d.ts +7 -0
- package/dist/observability/corrupt-read-seat.js +9 -0
- package/dist/observability/err-text.d.ts +6 -0
- package/dist/observability/err-text.js +18 -4
- package/dist/observability/fail-open.d.ts +35 -9
- package/dist/observability/fail-open.js +35 -9
- package/dist/observability/metrics.js +1 -0
- package/dist/observability/prompt-manifest.d.ts +3 -17
- package/dist/observability/prompt-manifest.js +45 -42
- package/dist/observability/tool-trace.js +9 -9
- package/dist/operator-ask.d.ts +10 -0
- package/dist/operator-ask.js +3 -0
- package/dist/orchestration/workflow-agent-session-index.d.ts +12 -12
- package/dist/orchestration/workflow-agent-session-index.js +9 -13
- package/dist/orchestration/workflow-completion-inbox.d.ts +42 -15
- package/dist/orchestration/workflow-completion-inbox.js +13 -0
- package/dist/orchestration/workflow-notify-journal.d.ts +13 -32
- package/dist/orchestration/workflow-notify-journal.js +27 -34
- package/dist/orchestration/workflow-park-decision.d.ts +89 -0
- package/dist/orchestration/workflow-park-decision.js +118 -0
- package/dist/org-delivery-gate.d.ts +81 -0
- package/dist/org-delivery-gate.js +59 -0
- package/dist/panel-tool-names.d.ts +23 -0
- package/dist/panel-tool-names.js +8 -0
- package/dist/parked-decide.d.ts +39 -6
- package/dist/parked-decide.js +98 -51
- package/dist/parked-revive-surface.d.ts +9 -2
- package/dist/parked-revive-surface.js +11 -8
- package/dist/permission-rule-list.d.ts +1 -1
- package/dist/permission-rule-list.js +2 -2
- package/dist/plugins/approval-ask-store-file.d.ts +16 -1
- package/dist/plugins/approval-ask-store-file.js +21 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +18 -1
- package/dist/plugins/approval-ask-store-memory.js +34 -2
- package/dist/plugins/approval-ask-store-sql.d.ts +25 -0
- package/dist/plugins/approval-ask-store-sql.js +37 -1
- package/dist/plugins/blob-backend.d.ts +38 -25
- package/dist/plugins/blob-backend.js +29 -19
- package/dist/plugins/breaker-state-sql.d.ts +2 -2
- package/dist/plugins/breaker-state-sql.js +4 -4
- package/dist/plugins/caching-session-store.d.ts +3 -0
- package/dist/plugins/caching-session-store.js +3 -0
- package/dist/plugins/checkpoint-store-sql.d.ts +14 -0
- package/dist/plugins/checkpoint-store-sql.js +20 -2
- package/dist/plugins/file-history-store-sql.d.ts +5 -2
- package/dist/plugins/file-history-store-sql.js +3 -1
- package/dist/plugins/file-run-store.d.ts +5 -13
- package/dist/plugins/file-run-store.js +9 -0
- package/dist/plugins/fork-routing-session-store.d.ts +9 -1
- package/dist/plugins/fork-routing-session-store.js +12 -1
- package/dist/plugins/host-platform.d.ts +2 -0
- package/dist/plugins/host-platform.js +2 -1
- package/dist/plugins/local-checkpoint-store.d.ts +2 -0
- package/dist/plugins/local-checkpoint-store.js +6 -1
- package/dist/plugins/local-session-store.d.ts +1 -1
- package/dist/plugins/local-session-window.d.ts +39 -0
- package/dist/plugins/local-session-window.js +54 -0
- package/dist/plugins/mailbox-recipient-lifecycle.d.ts +3 -2
- package/dist/plugins/mailbox-store-sql.d.ts +30 -48
- package/dist/plugins/mailbox-store-sql.js +77 -52
- package/dist/plugins/memory-embedder-fingerprint.js +2 -1
- package/dist/plugins/memory-run-store.d.ts +5 -13
- package/dist/plugins/memory-run-store.js +8 -0
- package/dist/plugins/one-time-migrations.d.ts +110 -5
- package/dist/plugins/one-time-migrations.js +320 -8
- package/dist/plugins/org-delivery-quota-store.d.ts +123 -0
- package/dist/plugins/org-delivery-quota-store.js +228 -0
- package/dist/plugins/pg-pool.js +39 -7
- package/dist/plugins/pg-session-storage.d.ts +17 -4
- package/dist/plugins/pg-session-storage.js +29 -6
- package/dist/plugins/remote-env-adb.d.ts +6 -12
- package/dist/plugins/remote-env-adb.js +12 -2
- package/dist/plugins/remote-env-k8s.d.ts +8 -12
- package/dist/plugins/remote-env-k8s.js +23 -5
- package/dist/plugins/remote-env-local-docker.d.ts +10 -15
- package/dist/plugins/remote-env-local-docker.js +12 -9
- package/dist/plugins/remote-env-ssh.d.ts +10 -16
- package/dist/plugins/remote-env-ssh.js +17 -11
- package/dist/plugins/run-store-sql.d.ts +16 -14
- package/dist/plugins/run-store-sql.js +22 -2
- package/dist/plugins/schema-indexes.js +2 -0
- package/dist/plugins/send-user-file.js +2 -2
- package/dist/plugins/session-epoch-anchor.d.ts +32 -6
- package/dist/plugins/session-epoch-anchor.js +2 -3
- package/dist/plugins/session-store.d.ts +18 -8
- package/dist/plugins/session-store.js +15 -4
- package/dist/plugins/sql-driver.d.ts +74 -11
- package/dist/plugins/sql-driver.js +210 -12
- package/dist/plugins/sql-errors.d.ts +23 -0
- package/dist/plugins/sql-errors.js +21 -0
- package/dist/plugins/store-backend.d.ts +36 -1
- package/dist/plugins/store-backend.js +40 -14
- package/dist/plugins/store-contracts.d.ts +42 -0
- package/dist/plugins/store-contracts.js +1 -0
- package/dist/plugins/tidb-pool.d.ts +6 -1
- package/dist/plugins/tidb-pool.js +44 -10
- package/dist/plugins/tidb-session-storage.d.ts +3 -2
- package/dist/plugins/tidb-session-storage.js +2 -2
- package/dist/plugins/tidb-session-store.d.ts +24 -4
- package/dist/plugins/tidb-session-store.js +28 -4
- package/dist/plugins/workflow-journal-store-sql.d.ts +73 -19
- package/dist/plugins/workflow-journal-store-sql.js +19 -6
- package/dist/plugins/workflow-run-store-sql.d.ts +30 -8
- package/dist/plugins/workflow-run-store-sql.js +50 -9
- package/dist/posture-source.d.ts +18 -10
- package/dist/posture-source.js +4 -1
- package/dist/project-identity.d.ts +45 -6
- package/dist/project-identity.js +162 -8
- package/dist/project-layer-key.d.ts +28 -0
- package/dist/project-layer-key.js +29 -0
- package/dist/question.js +3 -2
- package/dist/read-deny-entry.d.ts +25 -0
- package/dist/read-deny-entry.js +12 -0
- package/dist/read-face-posture.d.ts +37 -11
- package/dist/read-face-posture.js +32 -3
- package/dist/request-key-closure.d.ts +7 -0
- package/dist/request-key-closure.js +9 -1
- package/dist/request-value-closure.d.ts +5 -0
- package/dist/request-value-closure.js +11 -3
- package/dist/rule-entry-list.d.ts +26 -2
- package/dist/rule-entry-list.js +72 -12
- package/dist/rules-consent.js +3 -4
- package/dist/run-acceptance.d.ts +19 -3
- package/dist/run-acceptance.js +13 -1
- package/dist/run-local.js +36 -6
- package/dist/runs.d.ts +10 -9
- package/dist/runs.js +21 -3
- package/dist/runtime-caps-resolver.d.ts +16 -6
- package/dist/runtime-caps-resolver.js +18 -5
- package/dist/sandbox-pkg-source.d.ts +19 -1
- package/dist/sandbox-pkg-source.js +29 -7
- package/dist/security.d.ts +87 -9
- package/dist/security.js +52 -9
- package/dist/session-error-wire.d.ts +19 -2
- package/dist/session-error-wire.js +5 -1
- package/dist/session-titled-frame.d.ts +33 -0
- package/dist/session-titled-frame.js +4 -0
- package/dist/session-titler.d.ts +9 -1
- package/dist/session-titler.js +15 -4
- package/dist/spec-fields.js +21 -2
- package/dist/sql-engine-posture.d.ts +3 -1
- package/dist/task-cwd.d.ts +1 -1
- package/dist/task-mcp.d.ts +3 -3
- package/dist/task-mcp.js +7 -66
- package/dist/task-settings.d.ts +89 -88
- package/dist/task-settings.js +71 -63
- package/dist/text-bidi.d.ts +0 -4
- package/dist/text-bidi.js +1 -3
- package/dist/tighten-only-seats.d.ts +150 -0
- package/dist/tighten-only-seats.js +196 -0
- package/dist/tool-approval.d.ts +303 -87
- package/dist/tool-approval.js +623 -239
- package/dist/trace/core-keyset-guard.d.ts +104 -22
- package/dist/trace/exit-seat.d.ts +28 -0
- package/dist/trace/exit-seat.js +76 -0
- package/dist/trace/ledger-events.d.ts +3 -2
- package/dist/trace/project.d.ts +80 -12
- package/dist/trace/project.js +41 -28
- package/dist/trace/projection-table.d.ts +100 -0
- package/dist/trace/projection-table.js +130 -0
- package/dist/trace/redact.d.ts +54 -0
- package/dist/trace/redact.js +778 -152
- package/dist/trace/self-minted-wire.d.ts +345 -1
- package/dist/trace/self-minted-wire.js +117 -1
- package/dist/trace/wire-projection-faces.d.ts +298 -2
- package/dist/trace/wire-projection-faces.js +154 -13
- package/dist/url-refusal.js +2 -0
- package/dist/web-admin-client/apply-effective.d.ts +12 -0
- package/dist/web-admin-client/apply-effective.js +56 -5
- package/dist/web-admin-client/facade.d.ts +1 -1
- package/dist/web-admin-client/facade.js +1 -1
- package/dist/web-admin-client/read-face.js +5 -9
- package/dist/web-admin-client/skills-mcp.js +4 -5
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +57 -9
- package/package.json +7 -3
package/dist/security.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { IncomingMessage } from "node:http";
|
|
2
|
-
import { type SessionStore, type SessionTreeEntry } from "@sema-agent/core";
|
|
2
|
+
import { type SessionPlacementRecord, type SessionStore, type SessionTreeEntry } from "@sema-agent/core";
|
|
3
3
|
import type { ServiceConfig } from "./config-types.js";
|
|
4
4
|
import type { TaskRequestBody } from "./http/wire-types.js";
|
|
5
5
|
import type { StagingHandle } from "./session-sync-kernel.js";
|
|
6
6
|
import type { SessionFace, SessionFaceReader } from "./session-incarnation.js";
|
|
7
7
|
import type { SessionRowPatch } from "./session-row.js";
|
|
8
|
+
import { type OwnerlessClaim } from "./delegated-session-owner.js";
|
|
8
9
|
/** One row of the session-list projection (CC /resume picker) — the durable session abstraction's enumeration
|
|
9
10
|
* output (§0.5). Mirrors {@link RunStore}'s shipped `SessionSummary` shape so the wire response is unchanged. */
|
|
10
11
|
export interface SessionListItem {
|
|
@@ -51,6 +52,54 @@ export interface SessionListItem {
|
|
|
51
52
|
* 不含读面,也不含 `POST /v1/tasks` 那条提交腿 —— 它有自己的同族门(别重复拦,双拦会让错误归因变糊)。
|
|
52
53
|
*/
|
|
53
54
|
export declare function isDestructiveSessionWrite(method: string, url: string): boolean;
|
|
55
|
+
declare const principalBrand: unique symbol;
|
|
56
|
+
declare const durableOwnerKeyBrand: unique symbol;
|
|
57
|
+
/**
|
|
58
|
+
* 🔴 **两个 owner 不是同一个东西**(S-487 RH-3,类型事实):
|
|
59
|
+
* · {@link Principal} —— **这次请求**验过的调用方身份。铸点闭集:`http/principal-gate.ts` 的 `gatedPrincipal`(验身份的那一只),以及属主存取器
|
|
60
|
+
* (`http/owner-access.ts`)里一只「上游已验」的适配口(调用方身份经一只纯串结构转手过来的腿 —— 第二期随那只结构带品牌而删);
|
|
61
|
+
* · {@link DurableOwnerKey} —— **行上 / 存储键里**落下的属主(run 行、会话行的 `owner` 列)。铸点闭集:属主存取器读行处与 {@link sessionOwnerCellOf}。
|
|
62
|
+
* 两者互不可赋、裸 `string` 两者都不可赋;「这个调用方读得到这一行吗」的判官(`runOwnerReadable`)签名两参各带一个品牌,对调即编译红。
|
|
63
|
+
* 铸点按文件计数钉在 `test/owner-gate-single-owner.test.ts` 的品牌铸点普查格里:多一处铸点 = 门红。
|
|
64
|
+
*/
|
|
65
|
+
export type Principal = string & {
|
|
66
|
+
readonly [principalBrand]: true;
|
|
67
|
+
};
|
|
68
|
+
export type DurableOwnerKey = string & {
|
|
69
|
+
readonly [durableOwnerKeyBrand]: true;
|
|
70
|
+
};
|
|
71
|
+
/** {@link Principal} 的铸造口(只在铸点闭集里调,见上)。 */
|
|
72
|
+
export declare function mintPrincipal(verified: string): Principal;
|
|
73
|
+
/** {@link DurableOwnerKey} 的铸造口(只在铸点闭集里调,见上)。 */
|
|
74
|
+
export declare function mintDurableOwnerKey(persisted: string): DurableOwnerKey;
|
|
75
|
+
/**
|
|
76
|
+
* 会话行属主门读的那一格(S-1770):有主的行只有属主;**无主的行**另带「它是不是委派子代的 placed 行」(店的 `placementOf` 答,{@link sessionOwnerCellOf} 读;
|
|
77
|
+
* 不实现 placement 的店没有 placed 行)。`placed` 只在无主时存在 —— 有主的行属主门不看它。
|
|
78
|
+
*/
|
|
79
|
+
export type SessionOwnerCell = {
|
|
80
|
+
readonly owner: DurableOwnerKey;
|
|
81
|
+
} | {
|
|
82
|
+
readonly owner: null;
|
|
83
|
+
readonly placed: boolean;
|
|
84
|
+
};
|
|
85
|
+
/** 会话行属主门的调用方:验过的主体(`gatedPrincipal`)+ 它是不是 **fleet 调用方**(dev-open 部署上的任何调用方,或出示了这台部署的 service 凭据、
|
|
86
|
+
* 不报主体的调用方)。唯一铸点 `http/principal-gate.ts` 的 `sessionCallerOf`。 */
|
|
87
|
+
export interface SessionCaller {
|
|
88
|
+
readonly principal: Principal | undefined;
|
|
89
|
+
readonly fleet: boolean;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* 🔴 **会话行属主门上「无主行放行」臂的唯一判据**(S-1770 读面律;会话面谓词 `sessionOwnerReadable`、fork / 删除的存量互认臂 {@link legacyUnownedSessionOk}、
|
|
93
|
+
* 审批豁免面、notify 面的无主臂都经它,不各写一份):
|
|
94
|
+
* · 无主的**普通**会话行 ⇒ 成立(各臂照它自己的其余条件);
|
|
95
|
+
* · 无主的 **placed** 行(委派子代:属主 = 委派树根的属主,`delegated-session-owner.ts`)⇒ 只对 **fleet 调用方**成立({@link SessionCaller}:dev-open 部署上的任何调用方,
|
|
96
|
+
* 或出示了 service 凭据、不报主体的调用方 —— 只配 token 的单用户部署、BFF 的系统调用)。任何具名主体(含经 BFF 代发的)与没有 service 凭据的无身份调用方都不成立:
|
|
97
|
+
* 这一行要么属于一棵无身份调用方的树,要么属主还没定下(升级前写下、回填还没判出 / 判断时来源还没有属主)—— 后者把它当公共行,就是把别人那棵树的子代转录交给拿到 id 的人。
|
|
98
|
+
* · 有主的行 ⇒ 不在本臂。
|
|
99
|
+
*/
|
|
100
|
+
export declare function ownerlessRowOpen(cell: SessionOwnerCell, caller: SessionCaller): boolean;
|
|
101
|
+
/** 读一只会话行的 {@link SessionOwnerCell}:无主时问一次店的 `placementOf`(既有读口;店不交它 = 不实现 placement = 没有 placed 行)。`owner` = 调用点那一读。 */
|
|
102
|
+
export declare function sessionOwnerCellOf(store: Pick<OwnerAwareSessionStore, "placementOf"> | undefined, sessionId: string, owner: string | null): Promise<SessionOwnerCell>;
|
|
54
103
|
/** [ref] 窄互认第二臂的租户键字面量 —— 单机形下 core 写侧 `spec.principal ?? "default"` 铸出的那一个,
|
|
55
104
|
* 也是壳 [ref]G1 翻面后随请求带的那一个。**不是哨兵**([ref] 措辞):它是单机形的真租户键。 */
|
|
56
105
|
export declare const LEGACY_UNOWNED_AMNESTY_TENANT = "default";
|
|
@@ -66,7 +115,7 @@ export declare const LEGACY_UNOWNED_AMNESTY_TENANT = "default";
|
|
|
66
115
|
*
|
|
67
116
|
* 🔒 **三条件缺一不放行**(与第一臂同源,不是兼容臂):
|
|
68
117
|
* ① 单机形 `!requirePrincipal` —— 多租部署本臂**死路**(header 必到、键必具名);
|
|
69
|
-
* ② 存量行恰为无主 `owner === null
|
|
118
|
+
* ② 存量行恰为无主 `owner === null`、且不是委派子代的 placed 行(无主臂的唯一判据 {@link ownerlessRowOpen})—— 任何具名 owner 的行不受影响;
|
|
70
119
|
* ③ 调用方恰为 `default` 主 —— 非 default 的具名主对无主行仍走原门(404 / deleted:false)。
|
|
71
120
|
* 反向风险有界:①限定的单机形本就单用户,把无主行判给 default 主不产生跨租外泄。
|
|
72
121
|
*
|
|
@@ -87,10 +136,10 @@ export declare const LEGACY_UNOWNED_AMNESTY_TENANT = "default";
|
|
|
87
136
|
* 写面族超出裁定射程 —— 要做另立一次表态,不在本臂里顺手带过。
|
|
88
137
|
*
|
|
89
138
|
* @param requirePrincipal `config.requirePrincipal`(条件①)
|
|
90
|
-
* @param
|
|
91
|
-
* @param
|
|
139
|
+
* @param caller 调用方(条件③ 读它验过的主体;fleet-wide 面不经本臂)
|
|
140
|
+
* @param cell 存量行那一格(条件②:无主,且经无主臂的唯一判据 {@link ownerlessRowOpen} —— 无主的委派子代 placed 行不在本臂,S-1770)
|
|
92
141
|
*/
|
|
93
|
-
export declare function legacyUnownedSessionOk(requirePrincipal: boolean,
|
|
142
|
+
export declare function legacyUnownedSessionOk(requirePrincipal: boolean, caller: SessionCaller, cell: SessionOwnerCell): boolean;
|
|
94
143
|
/**
|
|
95
144
|
* {@link legacyUnownedSessionOk} 的**条件①③**半支 —— 只判「这个部署形 × 这个调用方」是否落在窄臂辖域内。
|
|
96
145
|
*
|
|
@@ -106,6 +155,13 @@ export type OwnerAwareSessionStore = SessionStore & {
|
|
|
106
155
|
* 是 `src/session-incarnation.ts`。只关心属主的消费点照旧读 `ownerOf`;判「这还是不是同一位住客」的读它。 */
|
|
107
156
|
sessionFaceOf?: SessionFaceReader;
|
|
108
157
|
register?: (sessionId: string, owner: string | null) => Promise<void>;
|
|
158
|
+
/** S-1770 委派继承律的**认领口** —— 只在记录委派树的店上(SQL 两店,只命中 placed 行;local 店没有):判断时读到的那一位住客仍是无主的 placed 行 ⇒ 写 `owner`,
|
|
159
|
+
* 返回是否写成(只 CAS 子行自己)。唯一调用方 = 停驻挂点的 `settleDelegatedOwner`(`delegated-session-owner.ts`;M23 走同一句 SQL);规则写在那个模块。 */
|
|
160
|
+
claimOwnerless?: OwnerlessClaim;
|
|
161
|
+
/** [ref] placed 分区的元组读口(店的既有读口,一行 PK 读;`undefined` = 普通会话或无此行)。店不交它 = 不实现 placement = 没有 placed 行(local 店)。两个读者:
|
|
162
|
+
* ① 会话面的属主门只在属主为 NULL 时读它一次(无主的 placed 行不是公共行,`http/principal-gate.ts` 的 `sessionOwnerCellOf`);
|
|
163
|
+
* ② 会话视图读它投影体顶层 `agent` 键(`audit.ts` 的 `sessionAgentOf`,只在视图读上付):店没有这一面 ⇒ 键缺席,读面不凭别处另铸子代身份。 */
|
|
164
|
+
placementOf?: (sessionId: string) => Promise<SessionPlacementRecord | undefined>;
|
|
109
165
|
/** E16 — enumerate the caller's sessions (owner-filtered on the session store's OWN owner column).
|
|
110
166
|
* `includeUnowned` = [ref] 窄互认第二臂的**第三条件**(`owner IS NULL`)的 SQL 承载位:置真时
|
|
111
167
|
* 谓词放宽为 `owner = ? OR owner IS NULL`。只在 `owner` 在场时有意义(路由已判①③);`owner` 缺席
|
|
@@ -269,24 +325,39 @@ export declare function createAuthorizer(config: ServiceConfig, sessionStore: Ow
|
|
|
269
325
|
* SendUserFile ledger scope + the /v1/sendfile-links fleet-wide default; the resource-suspend isolation
|
|
270
326
|
* key), `"_leader"` merges with the leader durable-approval owner scope (a tenant so named could list/
|
|
271
327
|
* decide internal leader approvals), `"_leader-…"` with the leader resource-suspend scope family, and
|
|
272
|
-
* `"__none__"` with the missing-principal placeholder
|
|
328
|
+
* `"__none__"` with the missing-principal read placeholder of the approval queue faces (≤ 7.132.x replicas).
|
|
273
329
|
* - length > 190 is REJECTED: every scope/owner column the principal lands in VERBATIM is VARCHAR(190)
|
|
274
330
|
* (sendfile_link.scope, approval.owner/scope, memory-engine scope, rate-limit keys, …) — an over-long
|
|
275
331
|
* principal would truncate/500 at the INSERT and split one identity into two.
|
|
276
332
|
* Throws a typed 400 `HttpError` (the HTTP layer maps it); the message names the rule (a reserved identifier /
|
|
277
333
|
* the length cap), never a secret and never the internal scope's semantics. */
|
|
278
334
|
export declare const PRINCIPAL_MAX_LENGTH = 190;
|
|
335
|
+
/**
|
|
336
|
+
* 一个被受理的主体串最多占多少个 UTF-8 字节 —— 按**字节**计宽的身份列(TiDB `VARBINARY(n)`)的列宽**唯一来源**(派生,不手抄第二个数)。
|
|
337
|
+
* {@link PRINCIPAL_MAX_LENGTH} 数的是 UTF-16 码元(`string.length`),一个码元最坏落 3 个 UTF-8 字节:BMP 字符 3 字节;代理对 4 字节 / 2 码元;
|
|
338
|
+
* 孤代理按 U+FFFD 编,3 字节。按**字符**计宽的列(`VARCHAR(n)`:TiDB utf8mb4 / PG 都数码点)直接用 {@link PRINCIPAL_MAX_LENGTH} —— 码点数 ≤ 码元数。
|
|
339
|
+
*/
|
|
340
|
+
export declare const PRINCIPAL_MAX_UTF8_BYTES: number;
|
|
279
341
|
/** 修1 — the SINGLE registry of internal sentinel/scope identifiers a tenant principal must never equal.
|
|
280
342
|
* 🔴 新增内部 sentinel scope 必须在此登记(精确值加 RESERVED_PRINCIPALS,前缀族加
|
|
281
343
|
* RESERVED_PRINCIPAL_PREFIXES),否则 assertPrincipalShape 会放行同名租户 = 与内部 scope 行合流的超范围面。
|
|
282
344
|
* Current entries (where each is minted): `"_"` = single-user/anonymous sentinel (checkpoint/sendfile/
|
|
283
|
-
* resource-suspend scope family); `"__none__"` = missing-principal placeholder
|
|
284
|
-
* (
|
|
345
|
+
* resource-suspend scope family); `"__none__"` = the missing-principal read placeholder of the approval
|
|
346
|
+
* queue faces up to 7.132.x (7.133.0 reads the anonymous group `"_"` instead; still reserved because a 7.132.x replica in the same
|
|
347
|
+
* rolling upgrade lists that scope for anonymous callers, so a tenant by that name would merge with them there); `"_leader"` = leader durable-approval scope
|
|
285
348
|
* (src/leader/wire.ts); prefix `"_leader-"` = the leader resource-suspend scope family
|
|
286
|
-
* (`_leader-resource-<workerId>`, src/leader/wire.ts)
|
|
349
|
+
* (`_leader-resource-<workerId>`, src/leader/wire.ts); prefix `"_orphan:"` = the owner written on a delegated session whose
|
|
350
|
+
* delegation ancestors are gone (`_orphan:<sessionId>`, src/delegated-session-owner.ts) — a caller allowed to authenticate as it
|
|
351
|
+
* would read that transcript. NB the `_leader-` prefix REQUIRES the hyphen — a tenant named
|
|
287
352
|
* `_leaderX` collides with nothing internal and stays valid (boundary pinned by test). */
|
|
288
353
|
export declare const RESERVED_PRINCIPALS: readonly string[];
|
|
289
354
|
export declare const RESERVED_PRINCIPAL_PREFIXES: readonly string[];
|
|
355
|
+
/** The principal-shape rule as a VERDICT (the one judge; {@link assertPrincipalShape} is its throwing reader). `undefined` = a
|
|
356
|
+
* principal may carry this string; otherwise which rule it breaks. A reader that only needs "can this string be anyone?" (the
|
|
357
|
+
* organization delivery gate's recipient: a string that breaks the rule is nobody, refused with the same bytes as an unknown
|
|
358
|
+
* principal) reads the verdict instead of catching the throw. */
|
|
359
|
+
export type PrincipalShapeProblem = "reserved" | "too_long";
|
|
360
|
+
export declare function principalShapeProblem(principal: string): PrincipalShapeProblem | undefined;
|
|
290
361
|
export declare function assertPrincipalShape(principal: string): void;
|
|
291
362
|
/** The checkpoint `scope` column's single-user/anonymous sentinel — the same "_" documented above
|
|
292
363
|
* ({@link RESERVED_PRINCIPALS}) as the checkpoint/sendfile/resource-suspend scope family's shared value.
|
|
@@ -321,6 +392,10 @@ export declare const encodeCheckpointScope: (principal: string | null | undefine
|
|
|
321
392
|
/** Decode a checkpoint `scope` column value back to a principal — {@link CHECKPOINT_PUBLIC_SCOPE} maps to
|
|
322
393
|
* `undefined` (no principal), everything else passes through verbatim. */
|
|
323
394
|
export declare const decodeCheckpointScope: (scope: string) => string | undefined;
|
|
395
|
+
/** A checkpoint `scope` value read as the **owner column** of the rows it governs (run rows, live / crash asks): {@link CHECKPOINT_PUBLIC_SCOPE}
|
|
396
|
+
* ⇒ `null` (the null-owner rows: tasks submitted without a principal), everything else verbatim. The one translation from the approval faces'
|
|
397
|
+
* scope to an owner filter — stores filter on the owner column and never recognize `"_"` themselves. */
|
|
398
|
+
export declare const ownerOfCheckpointScope: (scope: string) => string | null;
|
|
324
399
|
/** Read the authenticated principal from the trusted header. Never from the body. */
|
|
325
400
|
export declare function principalFrom(req: IncomingMessage, config: ServiceConfig): string | undefined;
|
|
326
401
|
/** Header carrying the crypto-verified principal JWT on a direct-door worker (the issuer signs it; the worker only
|
|
@@ -342,5 +417,8 @@ export declare function setSsoPrincipal(req: IncomingMessage, principal: string)
|
|
|
342
417
|
export declare function ssoVerifiedPrincipal(req: IncomingMessage): string | undefined;
|
|
343
418
|
export declare function setSsoScope(req: IncomingMessage, scope: string): void;
|
|
344
419
|
export declare function ssoVerifiedScope(req: IncomingMessage): string | undefined;
|
|
420
|
+
export declare function setSsoRole(req: IncomingMessage, role: string): void;
|
|
421
|
+
export declare function ssoVerifiedRole(req: IncomingMessage): string | undefined;
|
|
345
422
|
export declare function verifiedPrincipal(req: IncomingMessage, config: ServiceConfig): string | undefined;
|
|
423
|
+
export {};
|
|
346
424
|
//# sourceMappingURL=security.d.ts.map
|
package/dist/security.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { uuidv7, PROJECT_ID_REGEX } from "@sema-agent/core";
|
|
2
2
|
import { memoryScopeFor } from "./memory-scope.js";
|
|
3
3
|
import { verifyPrincipalJwt } from "./principal-jwt.js";
|
|
4
|
+
import { fieldConflictFacts } from "./field-conflict.js";
|
|
5
|
+
import { ORPHAN_SESSION_OWNER_PREFIX } from "./delegated-session-owner.js";
|
|
4
6
|
export function isDestructiveSessionWrite(method, url) {
|
|
5
7
|
if (method === "DELETE")
|
|
6
8
|
return /^\/v1\/sessions\/[^/]+$/.test(url);
|
|
@@ -10,9 +12,26 @@ export function isDestructiveSessionWrite(method, url) {
|
|
|
10
12
|
return /^\/v1\/sessions\/[^/]+\/(sync\/import|fork|memory\/erase)$/.test(url);
|
|
11
13
|
return false;
|
|
12
14
|
}
|
|
15
|
+
export function mintPrincipal(verified) {
|
|
16
|
+
return verified;
|
|
17
|
+
}
|
|
18
|
+
export function mintDurableOwnerKey(persisted) {
|
|
19
|
+
return persisted;
|
|
20
|
+
}
|
|
21
|
+
export function ownerlessRowOpen(cell, caller) {
|
|
22
|
+
if (cell.owner !== null)
|
|
23
|
+
return false;
|
|
24
|
+
return !cell.placed || caller.fleet;
|
|
25
|
+
}
|
|
26
|
+
export async function sessionOwnerCellOf(store, sessionId, owner) {
|
|
27
|
+
if (owner !== null)
|
|
28
|
+
return { owner: mintDurableOwnerKey(owner) };
|
|
29
|
+
const placementOf = store?.placementOf;
|
|
30
|
+
return { owner: null, placed: placementOf !== undefined && (await placementOf.call(store, sessionId)) !== undefined };
|
|
31
|
+
}
|
|
13
32
|
export const LEGACY_UNOWNED_AMNESTY_TENANT = "default";
|
|
14
|
-
export function legacyUnownedSessionOk(requirePrincipal,
|
|
15
|
-
return
|
|
33
|
+
export function legacyUnownedSessionOk(requirePrincipal, caller, cell) {
|
|
34
|
+
return legacyUnownedAmnestyOpen(requirePrincipal, caller.principal ?? null) && ownerlessRowOpen(cell, caller);
|
|
16
35
|
}
|
|
17
36
|
export function legacyUnownedAmnestyOpen(requirePrincipal, gateOwner) {
|
|
18
37
|
return !requirePrincipal && gateOwner === LEGACY_UNOWNED_AMNESTY_TENANT;
|
|
@@ -98,7 +117,7 @@ export function createAuthorizer(config, sessionStore) {
|
|
|
98
117
|
}
|
|
99
118
|
else {
|
|
100
119
|
if (requireExisting) {
|
|
101
|
-
throw createCodedHttpError(422, "request.field_conflict", "requireExistingSession requires a sessionId — there is no existing session to resume");
|
|
120
|
+
throw createCodedHttpError(422, "request.field_conflict", "requireExistingSession requires a sessionId — there is no existing session to resume", fieldConflictFacts("existing_session", ["requireExistingSession", "sessionId"]));
|
|
102
121
|
}
|
|
103
122
|
sessionId = uuidv7();
|
|
104
123
|
if (register)
|
|
@@ -108,14 +127,29 @@ export function createAuthorizer(config, sessionStore) {
|
|
|
108
127
|
};
|
|
109
128
|
}
|
|
110
129
|
export const PRINCIPAL_MAX_LENGTH = 190;
|
|
130
|
+
export const PRINCIPAL_MAX_UTF8_BYTES = PRINCIPAL_MAX_LENGTH * 3;
|
|
111
131
|
export const RESERVED_PRINCIPALS = ["_", "__none__", "_leader"];
|
|
112
|
-
export const RESERVED_PRINCIPAL_PREFIXES = ["_leader-"];
|
|
132
|
+
export const RESERVED_PRINCIPAL_PREFIXES = ["_leader-", ORPHAN_SESSION_OWNER_PREFIX];
|
|
133
|
+
export function principalShapeProblem(principal) {
|
|
134
|
+
if (RESERVED_PRINCIPALS.includes(principal) || RESERVED_PRINCIPAL_PREFIXES.some((p) => principal.startsWith(p)))
|
|
135
|
+
return "reserved";
|
|
136
|
+
if (principal.length > PRINCIPAL_MAX_LENGTH)
|
|
137
|
+
return "too_long";
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
113
140
|
export function assertPrincipalShape(principal) {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
141
|
+
const problem = principalShapeProblem(principal);
|
|
142
|
+
switch (problem) {
|
|
143
|
+
case undefined:
|
|
144
|
+
return;
|
|
145
|
+
case "reserved":
|
|
146
|
+
throw new HttpError(400, `principal ${JSON.stringify(principal)} is reserved (an internal scope sentinel) — authenticate with a real tenant identifier`, { code: "principal_reserved" });
|
|
147
|
+
case "too_long":
|
|
148
|
+
throw new HttpError(400, `principal exceeds ${PRINCIPAL_MAX_LENGTH} characters (the scope-column width every store pins, e.g. sendfile_link.scope VARCHAR(190)); got ${principal.length}`, { code: "principal_too_long" });
|
|
149
|
+
default: {
|
|
150
|
+
const unknownProblem = problem;
|
|
151
|
+
throw new Error(`assertPrincipalShape: unknown problem ${String(unknownProblem)}`);
|
|
152
|
+
}
|
|
119
153
|
}
|
|
120
154
|
}
|
|
121
155
|
export const CHECKPOINT_PUBLIC_SCOPE = "_";
|
|
@@ -125,6 +159,7 @@ export function backgroundScopesForCheckpointScope(scope) {
|
|
|
125
159
|
}
|
|
126
160
|
export const encodeCheckpointScope = (principal) => principal ?? CHECKPOINT_PUBLIC_SCOPE;
|
|
127
161
|
export const decodeCheckpointScope = (scope) => (scope === CHECKPOINT_PUBLIC_SCOPE ? undefined : scope);
|
|
162
|
+
export const ownerOfCheckpointScope = (scope) => decodeCheckpointScope(scope) ?? null;
|
|
128
163
|
export function principalFrom(req, config) {
|
|
129
164
|
if (!config.principalHeader)
|
|
130
165
|
return undefined;
|
|
@@ -153,6 +188,14 @@ export function ssoVerifiedScope(req) {
|
|
|
153
188
|
const v = req[SSO_SCOPE];
|
|
154
189
|
return typeof v === "string" && v.length > 0 ? v : undefined;
|
|
155
190
|
}
|
|
191
|
+
const SSO_ROLES = new WeakMap();
|
|
192
|
+
export function setSsoRole(req, role) {
|
|
193
|
+
SSO_ROLES.set(req, role);
|
|
194
|
+
}
|
|
195
|
+
export function ssoVerifiedRole(req) {
|
|
196
|
+
const v = SSO_ROLES.get(req);
|
|
197
|
+
return v !== undefined && v.length > 0 ? v : undefined;
|
|
198
|
+
}
|
|
156
199
|
export function verifiedPrincipal(req, config) {
|
|
157
200
|
const sso = ssoVerifiedPrincipal(req);
|
|
158
201
|
if (sso) {
|
|
@@ -27,8 +27,18 @@
|
|
|
27
27
|
* `open` 面留白(#1077 形,见上)。
|
|
28
28
|
* · `not_found` —— 留白:每一面各有自己的「不存在」答法(404 `not_found.session` / 同步口的 `resume.session_not_found` /
|
|
29
29
|
* 列表里的缺席),码位各不相同,不由本表统一。
|
|
30
|
-
* · `
|
|
31
|
-
*
|
|
30
|
+
* · `placement_refused` —— `import` 面 **409 `conflict.session_placed`**(机读位 `detail.placement_kind`,固定句);`open` 面留白。
|
|
31
|
+
* 同一个词在两面上说的不是同一件事:import 面只有「会话同步往一只**分区会话**(委派子代的转录)上写」一个来源
|
|
32
|
+
* (SQL 两店的整段换装 / 暂存提交门:目标 id 的 `placement_kind` 在场 ⇒ 不适用),调用方没做错格式、是**目标**不收这种写;
|
|
33
|
+
* open 面上同一个词还含「声明了分区的创建撞上了分区外 / 异组的行」两形(core `TtlSessionStore.assertPlacementAdmission` 的后两条),
|
|
34
|
+
* 那不是「目标是分区会话」。而 run 终局上它是引擎词汇(`terminal.code`),原样随 failed 体走 —— 若在这里分诊成 409,
|
|
35
|
+
* 体上的 `errorCode` 仍是引擎词 `placement_refused`,一个状态两个名字。所以 open 面留白,`invalid_session` 是同形先例。
|
|
36
|
+
* 409 的语义:目标会话**状态**不收这种写(重试同一个 id 同一结果;换一个会话 id 推)—— 与 `conflict.session_ownerless` / `conflict.session_children_alive` 同族。
|
|
37
|
+
* `detail.placement_kind` 是**常量**,不是从错误里读的:core 的 `SessionError` 只带 `code` 与句子,不带种类;今天分区种类闭集只有
|
|
38
|
+
* `"subagent"` 一个词,所以常量就是事实。core 给 `SessionPlacementRecord["kind"]` 加第二个词 ⇒ 下面的守卫编译红,由人裁定种类从哪儿读
|
|
39
|
+
* (请求 core 把种类放进错误,而不是在这里解析句子)。
|
|
40
|
+
* · `invalid_entry` / `invalid_fork_target` —— 留白:本仓今天没有一条 wire 口把它们作为自己的
|
|
41
|
+
* 应答(它们在 core 的追加 / 分叉面上抛,落进各站点既有的处置或通用 500)。给它们起名是另一件事、另一张票。
|
|
32
42
|
* · `storage` / `conflict` / `unknown` —— 留白:`conflict` 是 run 的写撞上真并发写,落成那条 run 的 `failed` 终局
|
|
33
43
|
* (`terminal.code: "conflict"`),提交腿不另作处置;`storage` / `unknown` 是故障类,通用 500 就是它们今天的应答。
|
|
34
44
|
*
|
|
@@ -50,9 +60,16 @@ export interface SessionErrorWire {
|
|
|
50
60
|
* 常量锚格),本批逐字不改。
|
|
51
61
|
*/
|
|
52
62
|
readonly sentence?: string;
|
|
63
|
+
/** 机读事实(体顶层的 `detail` 键;缺席 = 体里不带这个键)。只有 import 面的 `placement_refused` 用它:`{ placement_kind }`。 */
|
|
64
|
+
readonly detail?: Readonly<Record<string, string>>;
|
|
53
65
|
}
|
|
54
66
|
/** import 面 `invalid_session` 的固定句(修前 session-sync 暂存导入腿那一行的原文)。 */
|
|
55
67
|
export declare const STAGED_IMPORT_INVALID_SENTENCE = "staged session log failed validation";
|
|
68
|
+
/**
|
|
69
|
+
* import 面 `placement_refused` 的固定句:wire 上不发引擎原句 —— 两家 SQL 店的原句不同(措辞各自铸),都点名会话 id 与引擎内部词
|
|
70
|
+
* (「placement partition」「delegation transcript」);固定句只说调用方能做什么(冻结在 `test/api-error-text-freeze.test.ts` 的常量锚格)。
|
|
71
|
+
*/
|
|
72
|
+
export declare const PLACED_SESSION_SENTENCE = "this session holds a delegated agent's transcript, so session sync cannot overwrite it; sync into a different session id";
|
|
56
73
|
export declare function sessionErrorHttp(code: SessionErrorCode, face: SessionErrorFace): SessionErrorWire | undefined;
|
|
57
74
|
export declare function isSessionErrorCode(code: string): code is SessionErrorCode;
|
|
58
75
|
//# sourceMappingURL=session-error-wire.d.ts.map
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
export const STAGED_IMPORT_INVALID_SENTENCE = "staged session log failed validation";
|
|
2
|
+
export const PLACED_SESSION_SENTENCE = "this session holds a delegated agent's transcript, so session sync cannot overwrite it; sync into a different session id";
|
|
3
|
+
const PLACEMENT_KIND = "subagent";
|
|
2
4
|
const CORRUPT_SESSION = { status: 500, errorCode: "corrupt_session" };
|
|
3
5
|
const INVALID_ENTRIES = { status: 422, errorCode: "invalid_entries", sentence: STAGED_IMPORT_INVALID_SENTENCE };
|
|
6
|
+
const SESSION_PLACED = { status: 409, errorCode: "conflict.session_placed", sentence: PLACED_SESSION_SENTENCE, detail: { placement_kind: PLACEMENT_KIND } };
|
|
4
7
|
export function sessionErrorHttp(code, face) {
|
|
5
8
|
switch (code) {
|
|
6
9
|
case "corrupt_session":
|
|
7
10
|
return CORRUPT_SESSION;
|
|
8
11
|
case "invalid_session":
|
|
9
12
|
return face === "import" ? INVALID_ENTRIES : undefined;
|
|
13
|
+
case "placement_refused":
|
|
14
|
+
return face === "import" ? SESSION_PLACED : undefined;
|
|
10
15
|
case "not_found":
|
|
11
16
|
case "invalid_entry":
|
|
12
17
|
case "invalid_fork_target":
|
|
13
|
-
case "placement_refused":
|
|
14
18
|
case "storage":
|
|
15
19
|
case "conflict":
|
|
16
20
|
case "unknown":
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* **会话标题帧 `session_titled`** —— 标题器把标题写进会话行**之后**,在**这条 run 的活流**上自铸的一帧(契约 §4a-ttl)。
|
|
3
|
+
*
|
|
4
|
+
* ## 为什么有这一帧
|
|
5
|
+
* 标题器是 fire-and-forget:run 被引擎受理之后才起、在 run 跑的同时生成,写成时那条 run 的流往往还开着。此前写成只落行
|
|
6
|
+
* (`setTitleIfNull`)+ 一行运维日志 —— wire 上零通知,端上(桌面 / web 座位)只能在首轮之后有界轮询读会话行。
|
|
7
|
+
* 这一帧把「标题写成了」交给已经在 tail 这条流的人,轮询可以删。
|
|
8
|
+
*
|
|
9
|
+
* ## 律(一条)
|
|
10
|
+
* **只活不存**:会话行是标题的唯一真源,本帧只是「行刚刚变了」的活通知 —— 不落账本(`GET /v1/runs/:id/events` 回放读不出它)、
|
|
11
|
+
* 不进任何重放面;冷启动 / 多窗口 / 断线重连读会话行(`GET /v1/sessions` 的列表行 `title`;`/v1/sessions/:id/head` 只带 `leafId`,不是标题的读面)。因此:
|
|
12
|
+
* · 读者 = **这条 run 的流读者**,与会话行的读权同一(流是提交这条 run 的人开的,会话行归同一个人);
|
|
13
|
+
* · 只有持活流的腿才收得到(今天 = `POST /v1/tasks/stream`);同步 JSON 腿 / durable 后台腿没有活流 ⇒ 这一帧结构上不存在,读行;
|
|
14
|
+
* · 流已经走到终帧(`done`)或连接已断 ⇒ 丢弃(终帧是流的最后一帧);
|
|
15
|
+
* · `PATCH /v1/sessions/:id` 的改名 / 置顶不经标题器 ⇒ 不发(调用方自知);用户清空标题后下一次提交由标题器重填,那一次重填照发(例外:本进程里此前为这个会话生成失败 / 回空过 —— 标题器不再为它重试,直到进程重启)。
|
|
16
|
+
*
|
|
17
|
+
* ## 谁铸
|
|
18
|
+
* 唯一铸点 = {@link buildSessionTitledFrame},唯一调用方 = `session-titler.ts`(落行成功的那一支,实参 = 落进行里的**同一个**标题 ——
|
|
19
|
+
* 已脱敏、已清洗;帧上的标题与行上的标题是一个值,不从模型原文另铸)。键集登记在 `trace/self-minted-wire.ts` 的 `sessionTitledFrameKey`
|
|
20
|
+
* (成员集 `satisfies Record<keyof SessionTitledFrame, …>`:加一个键而登记没跟 ⇒ tsc 红)。
|
|
21
|
+
*
|
|
22
|
+
* 帧上没有 `eventId` ⇒ SSE 不发 `id:` 行(契约 §0.6「无锚不发行」):它不是引擎的内容帧,没有续流位置可言。
|
|
23
|
+
*/
|
|
24
|
+
/** 标题帧的形 —— 键集就是这个接口的键(登记表按 `keyof` 绑定)。 */
|
|
25
|
+
export interface SessionTitledFrame {
|
|
26
|
+
readonly type: "session_titled";
|
|
27
|
+
readonly sessionId: string;
|
|
28
|
+
/** 落进会话行的那个标题(已过标题器的脱敏与清洗,≤ `TITLE_MAX_CHARS` 个字符)。 */
|
|
29
|
+
readonly title: string;
|
|
30
|
+
}
|
|
31
|
+
/** 唯一铸点:纯数据,无行为。 */
|
|
32
|
+
export declare function buildSessionTitledFrame(sessionId: string, title: string): SessionTitledFrame;
|
|
33
|
+
//# sourceMappingURL=session-titled-frame.d.ts.map
|
package/dist/session-titler.d.ts
CHANGED
|
@@ -13,6 +13,11 @@
|
|
|
13
13
|
* cheap-model one-liner via the deployment's hookLlm face (summarize role → MODEL_CHEAP_ID when configured, else the
|
|
14
14
|
* main model; bounded + timed out).
|
|
15
15
|
*
|
|
16
|
+
* WRITE-AFTER NOTICE: the title that lands is announced to the run that triggered it — `maybeTitle`'s `onTitled` hands the
|
|
17
|
+
* seat (`run-acceptance.ts`) the one `session_titled` frame (`session-titled-frame.ts`, contract §4a-ttl) built from the
|
|
18
|
+
* SAME string the row now holds; the seat forwards it to the live stream when the leg has one. Live-only: the row is the
|
|
19
|
+
* truth, nothing else stores the frame.
|
|
20
|
+
*
|
|
16
21
|
* FAILURE POSTURE: everything is best-effort — a generation/store failure logs and leaves title null (the
|
|
17
22
|
* list falls back to objectivePreview). The fail-open tag it leaves names the CAUSE FAMILY (one tag, one family):
|
|
18
23
|
* the llm face's failure CODE picks it (`failOpenTagFor`), never the error's wording. An in-process pending set dedupes concurrent submits on the same
|
|
@@ -20,6 +25,7 @@
|
|
|
20
25
|
* call at worst, and exactly one title lands).
|
|
21
26
|
*/
|
|
22
27
|
import type { HookLlmFailureCode } from "./hooks/hook-runner.js";
|
|
28
|
+
import { type SessionTitledFrame } from "./session-titled-frame.js";
|
|
23
29
|
export interface SessionTitlerDeps {
|
|
24
30
|
/** Secret scrub applied to the RAW llm text before sanitize/persist (workflow audit 2026-07-13: the
|
|
25
31
|
* objective may carry a pasted secret and the model can echo it into the title — titles are persisted,
|
|
@@ -58,7 +64,9 @@ export interface SessionTitlerDeps {
|
|
|
58
64
|
export interface SessionTitler {
|
|
59
65
|
/** Fire-and-forget: maybe generate + persist a title for this session. Never throws, never blocks the caller. */
|
|
60
66
|
/** `model`([ref]②)= 本 turn 真实驱动的模型——带上则标题 hook 同链路,不再裸落 env 缺省。 */
|
|
61
|
-
|
|
67
|
+
/** `onTitled` = 这一次调用**自己**把标题写成之后(`setTitleIfNull` 落行)交出的活通知(`session_titled` 帧,契约 §4a-ttl):只在落行的那一支调用恰一次 ——
|
|
68
|
+
* 已有标题 / 竞态输了 / 模型失败 / 空标题 / 这个会话已有一次在飞的调用,都不调。回调同步执行、**不许抛**;抛了也不影响已落行的标题(见下 `frame_failed`)。 */
|
|
69
|
+
maybeTitle(sessionId: string, objective: string, model?: string, onTitled?: (frame: SessionTitledFrame) => void): void;
|
|
62
70
|
}
|
|
63
71
|
export declare const TITLE_MAX_CHARS = 80;
|
|
64
72
|
/** Single line, control chars stripped, hard cap; surrounding quotes (a common LLM tic) trimmed. */
|
package/dist/session-titler.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { stripControlAndBidi } from "@sema-agent/settings-schema";
|
|
2
2
|
import { recordFailOpen } from "./observability/fail-open.js";
|
|
3
3
|
import { redactSecrets } from "./trace/redact.js";
|
|
4
4
|
import { userAuthoredText } from "./user-authored-text.js";
|
|
5
|
+
import { buildSessionTitledFrame } from "./session-titled-frame.js";
|
|
5
6
|
export const TITLE_MAX_CHARS = 80;
|
|
6
7
|
const OBJECTIVE_SNIPPET_CHARS = 600;
|
|
7
8
|
const LLM_TIMEOUT_MS = 15_000;
|
|
@@ -29,7 +30,7 @@ function failOpenTagFor(code) {
|
|
|
29
30
|
}
|
|
30
31
|
}
|
|
31
32
|
export function sanitizeTitle(raw) {
|
|
32
|
-
const oneLine = raw.replace(/[\r\n]+/g, " ")
|
|
33
|
+
const oneLine = stripControlAndBidi(raw.replace(/[\r\n]+/g, " ")).trim();
|
|
33
34
|
const unquoted = oneLine.replace(/^["'「『]+/, "").replace(/["'」』]+$/, "").trim();
|
|
34
35
|
return unquoted.length > TITLE_MAX_CHARS ? `${unquoted.slice(0, TITLE_MAX_CHARS - 1)}…` : unquoted;
|
|
35
36
|
}
|
|
@@ -45,8 +46,9 @@ export function buildTitlePrompt(objective) {
|
|
|
45
46
|
}
|
|
46
47
|
export function createSessionTitler(deps) {
|
|
47
48
|
const seen = new Set();
|
|
49
|
+
const redactedError = (error) => redactSecrets(error);
|
|
48
50
|
const logFailure = (sessionId, error, code) => {
|
|
49
|
-
const safe =
|
|
51
|
+
const safe = redactedError(error);
|
|
50
52
|
deps.logger?.debug?.("session_title_failed", { sessionId, error: safe.slice(0, 200) });
|
|
51
53
|
recordFailOpen(failOpenTagFor(code), safe.slice(0, FAIL_CAUSE_KEY_CHARS));
|
|
52
54
|
};
|
|
@@ -55,7 +57,7 @@ export function createSessionTitler(deps) {
|
|
|
55
57
|
.then((state) => ({ state, unreadable: false }))
|
|
56
58
|
.catch(() => ({ state: continueWord, unreadable: true }));
|
|
57
59
|
return {
|
|
58
|
-
maybeTitle(sessionId, objective, model) {
|
|
60
|
+
maybeTitle(sessionId, objective, model, onTitled) {
|
|
59
61
|
if (!sessionId || !userAuthoredText(objective))
|
|
60
62
|
return;
|
|
61
63
|
if (seen.has(sessionId))
|
|
@@ -104,6 +106,15 @@ export function createSessionTitler(deps) {
|
|
|
104
106
|
seen.delete(sessionId);
|
|
105
107
|
deps.metrics?.inc("session_title_total", { outcome: "set" });
|
|
106
108
|
deps.logger?.info?.("session_titled", { sessionId, titleChars: title.length });
|
|
109
|
+
if (onTitled) {
|
|
110
|
+
try {
|
|
111
|
+
onTitled(buildSessionTitledFrame(sessionId, title));
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
deps.metrics?.inc("session_title_total", { outcome: "frame_failed" });
|
|
115
|
+
deps.logger?.warn?.("session_titled_frame_failed", { sessionId, error: redactedError(String(e)).slice(0, 200) });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
107
118
|
})().catch((e) => {
|
|
108
119
|
deps.metrics?.inc("session_title_total", { outcome: "error" });
|
|
109
120
|
logFailure(sessionId, String(e));
|
package/dist/spec-fields.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isThinkingLevel } from "@sema-agent/core";
|
|
2
2
|
import { taskWallClockSec } from "./task-workflow.js";
|
|
3
|
-
import { isAbsoluteHostPath } from "@sema-agent/settings-schema";
|
|
3
|
+
import { ABSOLUTE_HOST_PATH_MAX, isAbsoluteHostPath } from "@sema-agent/settings-schema";
|
|
4
4
|
import { ruleEntryListShapeOk, skillToolListsOverCap } from "./rule-entry-list.js";
|
|
5
5
|
import { describeLimit, limitFacts, limitRefusal } from "./limit-refusal.js";
|
|
6
6
|
import { quotedCallerText } from "./caller-text-echo.js";
|
|
@@ -110,6 +110,23 @@ const skillOk = (s) => {
|
|
|
110
110
|
}
|
|
111
111
|
return true;
|
|
112
112
|
};
|
|
113
|
+
const skillsLimit = (v) => {
|
|
114
|
+
if (!Array.isArray(v))
|
|
115
|
+
return undefined;
|
|
116
|
+
const j = v.findIndex((s) => !skillOk(s));
|
|
117
|
+
const s = j < 0 ? undefined : v[j];
|
|
118
|
+
if (!plainObject(s))
|
|
119
|
+
return undefined;
|
|
120
|
+
const content = s["content"];
|
|
121
|
+
const baseDir = s["baseDir"];
|
|
122
|
+
if (typeof content === "string" && content.length > MAX_AGENT_SKILL_CONTENT_CHARS) {
|
|
123
|
+
return { sub: `[${j}].content`, measure: "characters", count: content.length, cap: MAX_AGENT_SKILL_CONTENT_CHARS, keepShapeSentence: true };
|
|
124
|
+
}
|
|
125
|
+
if (typeof baseDir === "string" && baseDir.length > ABSOLUTE_HOST_PATH_MAX) {
|
|
126
|
+
return { sub: `[${j}].baseDir`, measure: "characters", count: baseDir.length, cap: ABSOLUTE_HOST_PATH_MAX, keepShapeSentence: true };
|
|
127
|
+
}
|
|
128
|
+
return undefined;
|
|
129
|
+
};
|
|
113
130
|
const memoryOk = (v) => {
|
|
114
131
|
if (!plainObject(v))
|
|
115
132
|
return false;
|
|
@@ -140,6 +157,7 @@ const TASK_AGENT_FIELD_SHAPES = {
|
|
|
140
157
|
skills: {
|
|
141
158
|
desc: "an array of { name, description, content } skill objects (optional allowedTools/disallowedTools/files/baseDir; allowedTools/disallowedTools are arrays of strings; files entries need { path, content }; baseDir must be an absolute path with no \"..\" segment) — no count cap; the engine renders the listing within its own byte budget",
|
|
142
159
|
ok: (v) => Array.isArray(v) && v.every(skillOk),
|
|
160
|
+
limit: skillsLimit,
|
|
143
161
|
},
|
|
144
162
|
background: { desc: "a boolean", ok: (v) => typeof v === "boolean" },
|
|
145
163
|
isolation: { desc: '"worktree"', ok: (v) => v === "worktree" },
|
|
@@ -180,7 +198,8 @@ export function taskAgentIssue(item) {
|
|
|
180
198
|
if (hit === undefined)
|
|
181
199
|
return { message: `agent.${k} must be ${shape.desc}` };
|
|
182
200
|
const rel = `${k}${hit.sub}`;
|
|
183
|
-
|
|
201
|
+
const limit = { rel, measure: hit.measure, count: hit.count, cap: hit.cap };
|
|
202
|
+
return hit.keepShapeSentence === true ? { message: `agent.${k} must be ${shape.desc}`, limit } : { message: describeLimit(`agent.${rel}`, hit.measure, hit.count, hit.cap), limit };
|
|
184
203
|
}
|
|
185
204
|
return null;
|
|
186
205
|
}
|
|
@@ -60,7 +60,9 @@ export interface SqlEngineCapability {
|
|
|
60
60
|
}
|
|
61
61
|
/**
|
|
62
62
|
* Boot 期建立引擎事实:借一条池连接(初始化随之跑),再原样归还。返回本池的**引擎读口**(驱动本身:方言 + 活的 `facts`)—— 事实由
|
|
63
|
-
* 驱动持有,重连后它会被下一次初始化刷新,快照会说谎;方言与事实同出这一只,写入要装进的墙(`sqlWallsOf`)
|
|
63
|
+
* 驱动持有,重连后它会被下一次初始化刷新,快照会说谎;方言与事实同出这一只,写入要装进的墙(`sqlWallsOf`)只读它。读到的是**最近一次初始化的那条连接**的事实:隔离级 / 事务模式每条连接
|
|
64
|
+
* 同钉同验,所以就是池的事实;包墙 `maxPacketBytes` 是会话值、随连接不同,这里只是那一条连接的读数(池见过的最新读数 —— 只在有连接初始化时才更新,DBA 调了全局值之后、下一条连接初始化之前它仍是旧值;
|
|
65
|
+
* 运维读面与提交受理口的提前一跑读它),终判读将要执行写入的那条连接自己的读数(`sql-driver.ts` `connectJudged`)。
|
|
64
66
|
*
|
|
65
67
|
* 抛出 = 拒启:连接初始化拒绝了这个后端(TiDB 乐观模式设不成悲观、隔离级复核不符、服务器太旧读不出
|
|
66
68
|
* `@@transaction_isolation`)。这条错**刻意不吞** —— 本仓所有 `FOR UPDATE` 判据都以它为前提。
|
package/dist/task-cwd.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export declare function cwdHonored(config: {
|
|
|
34
34
|
}): boolean;
|
|
35
35
|
/**
|
|
36
36
|
* S-377 —— 「**工具跑的那台机器**就是本进程这台吗」。回答的是一个**文件系统同一性**问题,不是权限问题:
|
|
37
|
-
* server 盘上的一条绝对路径(出厂 `SKILLS_DIR`
|
|
37
|
+
* server 盘上的一条绝对路径(出厂 `SKILLS_DIR` 下、或中心 plugin 缓存里某个技能自己的目录)对模型的工具**有没有意义**。
|
|
38
38
|
*
|
|
39
39
|
* 判据 = 能力表两位的合取 {@link handsOnWorkerFilePlane}(`coreRemoteExecutionEnv ∧ hostFilePlane`,都读表,
|
|
40
40
|
* 本函数不手写任何车道词):
|
package/dist/task-mcp.d.ts
CHANGED
|
@@ -159,12 +159,12 @@ export interface RequestMcpRefusal {
|
|
|
159
159
|
* ③ **身份头的键组合**(`principalHeader` 与 `assertionHeader` 同设 / `assertionHeader` 非串)⇒ {@link requestEntryIdentityRefusal}(同设那一句对契约包解析期原句逐字)。
|
|
160
160
|
* ④ **受理键的值** ⇒ 逐键问判官表 {@link ENTRY_KEY_JUDGES},`400 request.field_invalid`,拒句点名 `mcpServers[i].<键路径>`、server 名与**该键判官的原因句**({@link entryFieldRefusal})。
|
|
161
161
|
* 判官**就是读器用的那一只**,不是第二份:`toolAxes` = 引擎根导出的 `readMcpToolAxes`;`toolFaces` = `readMcpToolFaces`;`contentOrigin` = `isContentOriginWord`;`source` = `isMcpSourceLabel`;
|
|
162
|
-
* `name` = `isUsableWireName`;`allowTools` / `transport.args` = {@link isStringArray};`transport.env` / `headers` = {@link
|
|
163
|
-
* `transport` 的硬字段(`kind` / `command` / `url`)与软字段(`args` / `env` / `headers` / `principalHeader`)= {@link
|
|
162
|
+
* `name` = `isUsableWireName`;`allowTools` / `transport.args` = {@link isStringArray};`transport.env` / `headers` = 契约包读器 {@link readRequestMcpTransport} 的纯数据记录读法;`elicitation` = {@link isElicitationFlag};
|
|
163
|
+
* `transport` 的硬字段(`kind` / `command` / `url`)与软字段(`args` / `env` / `headers` / `principalHeader`)= {@link readRequestMcpTransport}(读器投影 transport 的那一只函数,门读它报的 `lost`;读器在契约包,本仓只据 `lost[0]` 拒、据 `lost` 在重放腿逐处点名)。
|
|
164
164
|
* 判官只在引擎里、包根没给读口的键(今天只有 `startupTimeoutMs`)不在这里判,原样过境、由引擎在拨号时按 server 拒(不写第二份判据;到货读口即换)。
|
|
165
165
|
* 于是判官受理的条目,读器({@link normalizeServer})交回的就是申报本身(只差判官自己的合法归一:空容器 / `skillScopeEligible:false` 折成缺席、`toolAxes` 取引擎的拷贝)——
|
|
166
166
|
* 探测口拨的那一份因此就是提交腿会挂的那一份,不另比一遍(另比就是第二只回答者)。唯一按门分的后果是「声明了 `assertionHeader`」这一个事实(引擎尚无座,
|
|
167
|
-
* 承载、不发送):新提交照挂 + 运维 info,探测口整条拒 —— 判据是同一只谓词 `
|
|
167
|
+
* 承载、不发送):新提交照挂 + 运维 info,探测口整条拒 —— 判据是同一只谓词 `specWithholdsMcpAssertionHeader`(开关 `MCP_ASSERTION_HEADER_SENT` 假时「声明了」即「被扣下」),不是第二份判法(见 `readMcpProbeBody`)。
|
|
168
168
|
*
|
|
169
169
|
* ## 射程
|
|
170
170
|
* 纯值域、与租户车道无关(一个写坏的请求在哪条车道上都是写坏的;多租户腿本来就忽略整只数组,告诉调用方「你写错了」只多不少)。
|