@sema-agent/server 7.131.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 +575 -0
- package/README.md +12 -9
- package/README.zh-CN.md +9 -6
- package/USAGE.md +326 -98
- 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 +82 -20
- package/dist/approval-card.js +46 -16
- 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 +33 -19
- package/dist/audit.js +12 -16
- package/dist/auth-bridge.d.ts +4 -0
- package/dist/auth-bridge.js +10 -11
- package/dist/bake-runner/main.js +3 -2
- package/dist/boot/deferred-sandbox-path-env.js +1 -1
- package/dist/boot/deployment-mods.d.ts +31 -0
- package/dist/boot/deployment-mods.js +26 -0
- package/dist/boot/execution-env.d.ts +1 -1
- package/dist/boot/execution-env.js +27 -12
- package/dist/boot/execution-lane.js +11 -0
- package/dist/boot/leader.js +2 -0
- package/dist/boot/memory-boundary.d.ts +2 -2
- 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/read-deny-anchor-audit.d.ts +17 -0
- package/dist/boot/read-deny-anchor-audit.js +36 -0
- package/dist/boot/reapers.d.ts +3 -0
- package/dist/boot/reapers.js +21 -1
- package/dist/boot/resolve-spec.d.ts +4 -5
- package/dist/boot/resolve-spec.js +74 -123
- package/dist/boot/runner-deps.d.ts +19 -8
- package/dist/boot/runner-deps.js +15 -2
- package/dist/boot/session-faces.d.ts +2 -7
- package/dist/boot/session-faces.js +4 -2
- package/dist/boot/stage-02-web-admin-pull.js +4 -1
- package/dist/boot/stage-03-store-backend.d.ts +1 -1
- package/dist/boot/stage-03-store-backend.js +2 -2
- package/dist/boot/stage-04-stores.d.ts +1 -1
- package/dist/boot/stage-05-execution-env.d.ts +4 -4
- package/dist/boot/stage-05-execution-env.js +7 -10
- package/dist/boot/stage-06-runners.d.ts +4 -2
- package/dist/boot/stage-06-runners.js +11 -7
- package/dist/boot/stage-07-capability-layer.d.ts +4 -2
- package/dist/boot/stage-07-capability-layer.js +27 -6
- package/dist/boot/stage-08-reapers.d.ts +4 -2
- package/dist/boot/stage-08-reapers.js +2 -2
- package/dist/boot/stage-09-leader.d.ts +6 -9
- package/dist/boot/stage-10-http-server.d.ts +6 -9
- package/dist/boot/stage-10-http-server.js +7 -9
- package/dist/boot/stores.d.ts +1 -1
- package/dist/boot/stores.js +7 -8
- package/dist/boot/web-admin.d.ts +4 -3
- package/dist/boot/web-admin.js +186 -98
- package/dist/boot/workflow-orchestration.d.ts +2 -0
- package/dist/boot/workflow-orchestration.js +2 -1
- package/dist/brain.js +25 -25
- package/dist/breaker-key.d.ts +6 -0
- package/dist/breaker-key.js +29 -0
- package/dist/budget.js +5 -4
- package/dist/caller-text-echo.d.ts +23 -0
- package/dist/caller-text-echo.js +21 -0
- package/dist/capabilities/brand-identity.d.ts +26 -0
- package/dist/capabilities/brand-identity.js +27 -0
- package/dist/capabilities/center-plugins.d.ts +7 -0
- package/dist/capabilities/center-plugins.js +1 -1
- package/dist/capabilities/center-prompts.d.ts +32 -59
- package/dist/capabilities/center-prompts.js +18 -32
- package/dist/capabilities/composite-members.d.ts +1 -1
- package/dist/capabilities/composite-members.js +1 -1
- package/dist/capabilities/engine-capabilities.js +2 -1
- package/dist/capabilities/execution-lane.js +2 -2
- package/dist/capabilities/hands-lane.d.ts +30 -6
- package/dist/capabilities/hands-lane.js +11 -1
- package/dist/capabilities/mcp-probe.d.ts +48 -3
- package/dist/capabilities/mcp-probe.js +47 -135
- package/dist/capabilities/scenarios.d.ts +95 -45
- package/dist/capabilities/scenarios.js +53 -38
- package/dist/capabilities/skills.d.ts +19 -4
- package/dist/capabilities/skills.js +30 -10
- 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 +47 -32
- 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-lkg.d.ts +9 -9
- package/dist/config-lkg.js +20 -4
- package/dist/config-provider.d.ts +9 -2
- package/dist/config-provider.js +18 -6
- package/dist/config-types.d.ts +75 -20
- package/dist/config-types.js +8 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.js +137 -62
- 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 -22
- package/dist/elicitation.js +3 -2
- package/dist/entry-problems.d.ts +34 -0
- package/dist/entry-problems.js +14 -0
- package/dist/env-name-allowlist-knobs.d.ts +12 -2
- package/dist/env-name-allowlist-knobs.js +5 -4
- package/dist/exec-bounds.d.ts +15 -3
- package/dist/exec-bounds.js +4 -0
- package/dist/execution-lane-caps.d.ts +56 -10
- package/dist/execution-lane-caps.js +50 -0
- 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 +91 -0
- package/dist/hooks/classic-stations.js +27 -0
- package/dist/hooks/command-spawn.d.ts +57 -0
- package/dist/hooks/command-spawn.js +139 -0
- package/dist/hooks/hook-llm.d.ts +8 -5
- package/dist/hooks/hook-llm.js +79 -36
- package/dist/hooks/hook-runner.d.ts +349 -95
- package/dist/hooks/hook-runner.js +855 -568
- 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.d.ts +8 -2
- package/dist/http/admission.js +188 -101
- package/dist/http/approval-sweeps.js +99 -21
- package/dist/http/caller-trust.d.ts +77 -0
- package/dist/http/caller-trust.js +143 -0
- package/dist/http/checkpoint-ctx.d.ts +41 -24
- package/dist/http/checkpoint-ctx.js +23 -16
- package/dist/http/claimed-run.d.ts +14 -0
- package/dist/http/claimed-run.js +15 -0
- package/dist/http/device-placement.d.ts +2 -4
- package/dist/http/device-placement.js +7 -11
- package/dist/http/dispatch.d.ts +0 -4
- package/dist/http/dispatch.js +15 -13
- package/dist/http/durable-run-leg.d.ts +6 -33
- package/dist/http/durable-run-leg.js +36 -10
- package/dist/http/health-self-report.d.ts +7 -5
- package/dist/http/health-self-report.js +4 -18
- package/dist/http/owner-access.d.ts +56 -0
- package/dist/http/owner-access.js +42 -0
- package/dist/http/principal-gate.d.ts +70 -28
- package/dist/http/principal-gate.js +61 -15
- package/dist/http/readiness.d.ts +11 -5
- package/dist/http/readiness.js +10 -3
- package/dist/http/refusal-body.d.ts +21 -0
- package/dist/http/refusal-body.js +4 -0
- package/dist/http/request-guards.d.ts +43 -23
- package/dist/http/request-guards.js +53 -17
- 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 +28 -4
- package/dist/http/resume-legs.js +169 -91
- 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 +21 -5
- 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 +6 -2
- 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 +34 -107
- package/dist/http/routes/session-sync.js +15 -26
- package/dist/http/routes/sessions.js +30 -40
- package/dist/http/routes/shared-memory.js +2 -13
- package/dist/http/routes/side-query.js +8 -7
- package/dist/http/routes/tasks.js +67 -21
- package/dist/http/routes/workflows.d.ts +351 -0
- package/dist/http/routes/workflows.js +153 -119
- package/dist/http/send.d.ts +33 -10
- package/dist/http/send.js +21 -4
- package/dist/http/server.d.ts +27 -18
- package/dist/http/server.js +34 -6
- package/dist/http/stored-body-replay.js +17 -4
- package/dist/http/submit-ctx.d.ts +25 -0
- package/dist/http/submit-ctx.js +40 -0
- package/dist/http/submit-replay.d.ts +4 -3
- package/dist/http/submit-replay.js +5 -4
- package/dist/http/wire-types.d.ts +11 -8
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -2
- package/dist/lane-home-probe.d.ts +112 -0
- package/dist/lane-home-probe.js +101 -0
- package/dist/leader/endpoint.d.ts +4 -1
- package/dist/leader/endpoint.js +11 -10
- package/dist/limit-refusal.d.ts +59 -0
- package/dist/limit-refusal.js +15 -0
- package/dist/main.js +1 -1
- package/dist/mcp-assertion-header.d.ts +32 -19
- package/dist/mcp-assertion-header.js +10 -9
- package/dist/mcp-tool-faces.d.ts +5 -0
- package/dist/mcp-tool-faces.js +6 -4
- package/dist/memory-project-layer.d.ts +37 -0
- package/dist/memory-project-layer.js +46 -0
- package/dist/memory-scope.d.ts +24 -17
- 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 +44 -12
- package/dist/model-provider.js +21 -2
- package/dist/model-route-endpoint.d.ts +9 -12
- package/dist/model-route-endpoint.js +8 -11
- 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/cost-taxonomy.d.ts +7 -7
- package/dist/observability/err-text.d.ts +6 -0
- package/dist/observability/err-text.js +18 -4
- package/dist/observability/fail-open.d.ts +76 -14
- package/dist/observability/fail-open.js +76 -14
- package/dist/observability/metrics.js +4 -1
- package/dist/observability/prompt-manifest.d.ts +33 -82
- package/dist/observability/prompt-manifest.js +122 -17
- package/dist/observability/run-terminal.js +14 -6
- package/dist/observability/secret-env-scrub.d.ts +13 -1
- package/dist/observability/secret-env-scrub.js +13 -1
- package/dist/observability/tool-trace.d.ts +16 -21
- package/dist/observability/tool-trace.js +58 -49
- 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/per-task-image.d.ts +7 -1
- package/dist/per-task-image.js +3 -3
- package/dist/permission-rule-list.d.ts +1 -1
- package/dist/permission-rule-list.js +2 -2
- package/dist/plain-string-record.d.ts +25 -0
- package/dist/plain-string-record.js +32 -0
- 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 +83 -15
- package/dist/plugins/blob-backend.js +68 -15
- 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 +28 -4
- package/dist/plugins/checkpoint-store-sql.js +59 -28
- 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/k8s-bg-scripts.d.ts +11 -0
- package/dist/plugins/k8s-bg-scripts.js +22 -0
- package/dist/plugins/local-checkpoint-store.d.ts +2 -0
- package/dist/plugins/local-checkpoint-store.js +11 -3
- package/dist/plugins/local-session-store.d.ts +1 -1
- package/dist/plugins/local-session-store.js +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 +245 -93
- package/dist/plugins/one-time-migrations.js +668 -207
- package/dist/plugins/org-delivery-quota-store.d.ts +123 -0
- package/dist/plugins/org-delivery-quota-store.js +228 -0
- package/dist/plugins/permission-rule-store-sql.d.ts +13 -7
- package/dist/plugins/permission-rule-store-sql.js +4 -18
- package/dist/plugins/pg-pool.js +39 -7
- package/dist/plugins/pg-session-storage.d.ts +20 -8
- package/dist/plugins/pg-session-storage.js +34 -21
- package/dist/plugins/remote-env-adb.d.ts +12 -12
- package/dist/plugins/remote-env-adb.js +21 -6
- package/dist/plugins/remote-env-device.js +3 -0
- package/dist/plugins/remote-env-e2b.d.ts +1 -1
- package/dist/plugins/remote-env-e2b.js +21 -9
- package/dist/plugins/remote-env-host.d.ts +9 -9
- package/dist/plugins/remote-env-host.js +10 -32
- package/dist/plugins/remote-env-k8s.d.ts +103 -38
- package/dist/plugins/remote-env-k8s.js +288 -95
- package/dist/plugins/remote-env-local-docker.d.ts +27 -13
- package/dist/plugins/remote-env-local-docker.js +82 -11
- package/dist/plugins/remote-env-ssh.d.ts +21 -12
- package/dist/plugins/remote-env-ssh.js +117 -5
- package/dist/plugins/remote-shell.d.ts +0 -1
- package/dist/plugins/remote-shell.js +1 -2
- package/dist/plugins/retention-store-sql.js +6 -2
- package/dist/plugins/run-store-sql.d.ts +16 -14
- package/dist/plugins/run-store-sql.js +22 -2
- package/dist/plugins/schema-consistency.d.ts +54 -0
- package/dist/plugins/schema-consistency.js +52 -0
- 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 +39 -0
- package/dist/plugins/session-epoch-anchor.js +22 -0
- package/dist/plugins/session-store.d.ts +18 -8
- package/dist/plugins/session-store.js +15 -4
- package/dist/plugins/shared-memory-store-sql.d.ts +9 -3
- package/dist/plugins/shared-memory-store-sql.js +5 -16
- package/dist/plugins/sql-driver.d.ts +205 -1
- package/dist/plugins/sql-driver.js +325 -13
- package/dist/plugins/sql-errors.d.ts +64 -0
- package/dist/plugins/sql-errors.js +57 -0
- package/dist/plugins/store-backend.d.ts +36 -1
- package/dist/plugins/store-backend.js +42 -15
- 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 +8 -11
- package/dist/plugins/tidb-session-storage.js +6 -16
- package/dist/plugins/tidb-session-store.d.ts +24 -4
- package/dist/plugins/tidb-session-store.js +29 -5
- 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/prompts-domain-validate.d.ts +17 -61
- package/dist/prompts-domain-validate.js +9 -119
- 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 +9 -2
- package/dist/request-key-closure.js +11 -5
- package/dist/request-value-closure.d.ts +5 -0
- package/dist/request-value-closure.js +11 -3
- package/dist/rule-entry-list.d.ts +38 -11
- package/dist/rule-entry-list.js +106 -30
- 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 +54 -24
- package/dist/runs.d.ts +15 -8
- package/dist/runs.js +35 -1
- 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/server-secret-env.d.ts +44 -18
- package/dist/server-secret-env.js +49 -8
- package/dist/session-error-wire.d.ts +19 -2
- package/dist/session-error-wire.js +5 -1
- package/dist/session-incarnation.d.ts +15 -5
- package/dist/session-incarnation.js +16 -9
- 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 +27 -6
- package/dist/spec-fields.d.ts +28 -16
- package/dist/spec-fields.js +66 -54
- package/dist/sql-engine-posture.d.ts +31 -4
- package/dist/sql-engine-posture.js +36 -1
- package/dist/stored-request-tool-axes-m19.d.ts +19 -4
- package/dist/stored-request-tool-axes-m19.js +30 -2
- package/dist/task-a2a.d.ts +9 -1
- package/dist/task-a2a.js +73 -47
- package/dist/task-cwd.d.ts +1 -1
- package/dist/task-mcp.d.ts +46 -58
- package/dist/task-mcp.js +82 -107
- package/dist/task-settings.d.ts +95 -108
- package/dist/task-settings.js +77 -98
- package/dist/text-bidi.d.ts +1 -48
- package/dist/text-bidi.js +3 -5
- package/dist/tighten-only-seats.d.ts +150 -0
- package/dist/tighten-only-seats.js +196 -0
- package/dist/tool-approval.d.ts +304 -88
- package/dist/tool-approval.js +623 -239
- package/dist/trace/core-keyset-guard.d.ts +122 -20
- package/dist/trace/engine-notice-wire.d.ts +11 -3
- package/dist/trace/engine-notice-wire.js +8 -1
- package/dist/trace/exit-seat.d.ts +28 -0
- package/dist/trace/exit-seat.js +76 -0
- package/dist/trace/ledger-events.d.ts +6 -3
- package/dist/trace/ledger-sink.js +4 -1
- package/dist/trace/model-segment.js +1 -1
- package/dist/trace/project.d.ts +98 -17
- package/dist/trace/project.js +98 -50
- 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 +377 -3
- package/dist/trace/wire-projection-faces.js +164 -1
- 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/candidate-gate.d.ts +6 -6
- package/dist/web-admin-client/candidate-gate.js +3 -3
- package/dist/web-admin-client/facade.d.ts +1 -1
- package/dist/web-admin-client/facade.js +1 -1
- package/dist/web-admin-client/http-client.js +0 -6
- package/dist/web-admin-client/read-face.js +5 -9
- package/dist/web-admin-client/read-warnings.d.ts +13 -0
- package/dist/web-admin-client/read-warnings.js +10 -0
- package/dist/web-admin-client/skills-mcp.d.ts +3 -0
- package/dist/web-admin-client/skills-mcp.js +11 -9
- package/dist/web-admin-client/types.d.ts +2 -3
- package/dist/workspace-cache.d.ts +35 -0
- package/dist/workspace-cache.js +36 -0
- package/dist/workspace-space.d.ts +3 -2
- package/dist/workspace-space.js +2 -0
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +65 -10
- package/package.json +8 -4
- package/scripts/drain-check-local.mjs +34 -1
- package/scripts/drain-check.mysql.sql +30 -2
- package/scripts/drain-check.pg.sql +29 -2
- package/dist/capabilities/memory-notice.d.ts +0 -138
- package/dist/capabilities/memory-notice.js +0 -64
- package/dist/capabilities/prompt.d.ts +0 -17
- package/dist/capabilities/prompt.js +0 -6
- package/dist/mcp-content-origin.d.ts +0 -34
- package/dist/mcp-content-origin.js +0 -10
- package/dist/tool-axis-words.d.ts +0 -27
- package/dist/tool-axis-words.js +0 -9
- package/dist/wire-name-bound.d.ts +0 -14
- package/dist/wire-name-bound.js +0 -13
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { type WebFetchConfig, type BackgroundAgentStore, type CheckpointStore, type
|
|
1
|
+
import { type WebFetchConfig, type BackgroundAgentStore, type CheckpointStore, type Runner, type SkillSpec, type TaskListStore, type TaskSpec, type ToolSpec, type WebSearchConfig, USER_ATTACHMENT_SEAT } from "@sema-agent/core";
|
|
2
2
|
import type { Logger } from "../observability/logger.js";
|
|
3
3
|
import { type SubagentExtraToolSet } from "./builtin-tools.js";
|
|
4
4
|
import { type RepoReadClient } from "./repo-tools.js";
|
|
5
5
|
import { type LoadedSkill } from "./skills.js";
|
|
6
|
-
import type
|
|
6
|
+
import { type ScenarioHands } from "./hands-lane.js";
|
|
7
|
+
import type { DelegationRootWitness } from "../delegated-session-owner.js";
|
|
7
8
|
/**
|
|
8
9
|
* Scenario routing — a deployment serves many scenarios from one image. Each request's `scenario`
|
|
9
|
-
* selects a pre-wired capability bundle: tools (incl. subagent roster) +
|
|
10
|
-
*
|
|
10
|
+
* selects a pre-wired capability bundle: tools (incl. subagent roster) + its prompt seats + skills.
|
|
11
|
+
* Heavy bits (HTTP clients, skill files) are startup singletons; per task we only bind
|
|
11
12
|
* coordinates and build cheap closures, so there is no per-request "assembly" cost.
|
|
12
13
|
*/
|
|
13
14
|
export interface ScenarioRequest {
|
|
@@ -26,12 +27,45 @@ export interface ScenarioBundle {
|
|
|
26
27
|
* `scan` 声明 clone-free 四件、实际拿到全量可写手)。
|
|
27
28
|
*/
|
|
28
29
|
hands: ScenarioHands;
|
|
29
|
-
|
|
30
|
+
/**
|
|
31
|
+
* S-1376:本场景从 roster 里**真卸载**的工具名(`TaskSpec.excludeTools`:per-scenario 的 roster 移除,schema 不进 `tools[]`;不是策略 deny)。缺席 = 不卸。
|
|
32
|
+
* 经 {@link buildExcludeToolsSeat} 与调用方自己的 `excludeTools` 取并后写进 `TaskSpec`(HTTP 腿与 run-local 腿同一只写点)—— 场景只能多卸,调用方也只能多卸。
|
|
33
|
+
* 与 `hands` 正交:`hands: "none"` 是整只手不挂(scan / code-review),本键是挂手之后卸掉其中一部分(cowork 卸编码类工具、留文件读)。
|
|
34
|
+
*/
|
|
35
|
+
excludeTools?: readonly string[];
|
|
36
|
+
/** 本场景对提示的贡献(缺席 = 不贡献:引擎目录的缺省角色)。经 {@link buildPromptSeats} 写进 `TaskSpec`,这是场景到提示的唯一通道。 */
|
|
37
|
+
prompt?: ScenarioPrompt;
|
|
30
38
|
/** [ref] 场景解释层定死的终验开关(core TaskSpec.finalVerification):bench 实测产品默认请求与
|
|
31
39
|
* bench 态差距三件之一。[ref] 起无场景定死(autonomous 退役)——纯 caller 显式旋钮;spec 组装处 OR 折入(场景只会
|
|
32
40
|
* 多加一轮收官验证,绝不收窄 caller 意图),壳/caller 不感知。 */
|
|
33
41
|
finalVerification?: true;
|
|
34
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* 一个场景对提示的贡献 —— 只有两个座,都是 `TaskSpec` 上的任务类座位:
|
|
45
|
+
* · `role`:选目录里的哪一种角色基底(`TaskSpec.promptRole`;缺席 = 引擎缺省 `general`);
|
|
46
|
+
* · `roleText`:场景自己的角色文本,写在调用方 `systemPrompt` 之前一起进 `TaskSpec.systemPrompt`(它整替选中的角色基底)。
|
|
47
|
+
* 两者都**不许**是引擎目录的文本(抄目录文本 = 第二份文本;逐字含锁定段的角色文本引擎在 prepare 拒 `prompt.assembled_role_refused`)。
|
|
48
|
+
* 宪法、行为段、记忆段、追加段的落位全归引擎。
|
|
49
|
+
*/
|
|
50
|
+
export interface ScenarioPrompt {
|
|
51
|
+
readonly role?: NonNullable<TaskSpec["promptRole"]>;
|
|
52
|
+
readonly roleText?: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* 一次请求写进 `TaskSpec` 的提示座 —— **`promptBinding` 的唯一写点**,HTTP 腿(`resolveSpec`)与 `run-local` 同用这一只:
|
|
56
|
+
* · `promptBinding` = 场景名,恒写:它是引擎提示选择器的一维,每一类 overlay(中心 artifact / 部署注册 / 任务)的 `when.binding` 都读它 ——
|
|
57
|
+
* 不写 ⇒ 每条 `anyOf` 恒假、每条 `noneOf` 恒真,按场景定向的中心段与部署的品牌行全部失效。场景名过了场景门的文法
|
|
58
|
+
* (`SCENARIO_NAME_RE`,≤ 32 个 ASCII 字)⇒ 恒在引擎 binding 文法之内(非空白、≤ `PROMPT_BINDING_MAX_CHARS` 码点);委派子代经父 spec 座继承它。
|
|
59
|
+
* · `promptRole` = 场景的角色选择器(缺席 = 引擎缺省 `general`);
|
|
60
|
+
* · `systemPrompt` = 角色文本(场景自己的在前、调用方 `systemPrompt` 在后,`\n\n` 相连;空串不占位;两者都缺席 ⇒ 键不写,调用方给的空串原样交引擎)。
|
|
61
|
+
*/
|
|
62
|
+
export declare function buildPromptSeats(scenarioName: string, prompt: ScenarioPrompt | undefined, callerSystemPrompt: string | undefined): Pick<TaskSpec, "promptBinding" | "promptRole" | "systemPrompt">;
|
|
63
|
+
/**
|
|
64
|
+
* 一次请求写进 `TaskSpec` 的**工具卸载座** —— `excludeTools` 的唯一写点,HTTP 腿(`resolveSpec`)与 `run-local` 同用这一只(同 {@link buildPromptSeats}):
|
|
65
|
+
* 场景自己的卸载名单在前,调用方请求体里的 `excludeTools` 接在后(两边都只会**多卸**,调用方拿不回场景卸掉的)。
|
|
66
|
+
* 场景没有卸载名单 ⇒ 调用方的名单**逐字原样**(不去重、不重排;缺席 ⇒ 键不写),这是 cowork 之前所有场景的字节形。
|
|
67
|
+
*/
|
|
68
|
+
export declare function buildExcludeToolsSeat(scenarioExcludes: readonly string[] | undefined, callerExcludes: readonly string[] | undefined): Pick<TaskSpec, "excludeTools">;
|
|
35
69
|
/**
|
|
36
70
|
* [ref]:场景工厂的**服务端事实**上下文 —— 与 `req`(= 调用方请求体,不可信)分开的第三个入参。
|
|
37
71
|
* 这里的每一位都由鉴权信道解析,调用方无法自报;新增位一律走本接口,绝不往 `req` 上加。
|
|
@@ -43,11 +77,19 @@ export interface ScenarioContext {
|
|
|
43
77
|
* 等于让一个租户读另一个租户的清单(同 spec 组装处那条「sessionId comes from `auth`, NEVER the
|
|
44
78
|
* body」的逐字纪律)。
|
|
45
79
|
*
|
|
46
|
-
* 缺席 = 这条调用形本来就没有会话(`parked-revive-surface.ts`
|
|
80
|
+
* 缺席 = 这条调用形本来就没有会话(`parked-revive-surface.ts` 对不交座的行、boot 期那一次 Agent 工具探针、
|
|
47
81
|
* `builtinScenarioDetails` 的工具名探针)。此时会话级设施退化为 per-call 实例 —— 不为它发明
|
|
48
82
|
* 一个假 session。
|
|
49
83
|
*/
|
|
50
84
|
sessionId?: string;
|
|
85
|
+
/**
|
|
86
|
+
* S-1770 / S-1808:**委派树根的见证**(停驻挂点的属主来源)—— 根会话 id + 调用方判断那一刻读到的根行住客(`delegated-session-owner.ts` 的 `DelegationRootWitness`)。
|
|
87
|
+
* 由**每一个**接了停驻挂点的取用方显式交出(一条读法,没有回落):请求腿 = 本请求经鉴权解析的会话与受理时那一读(`boot/resolve-spec.ts`);`/decide` 赎回面 = 行上的
|
|
88
|
+
* `rootSessionId` 与赎回腿 claim 前后两读的那一位住客(`parked-revive-surface.ts`,交不交座都交)。它**只**喂停驻挂点,不挂任何会话级设施(那是 {@link sessionId} 的事,
|
|
89
|
+
* 判据是「这只 bundle 是不是在那只会话上取用的」,与属主来源是两个独立判据)。缺席 = 没有根可交(boot 期探针、run-local、行上没有根)⇒ 律给哨兵。
|
|
90
|
+
* 挂点在停驻那一刻再读一次根行:住客不是见证的那一位(删了、同 id 被重新登记)⇒ 停驻否决 —— 不按新住客晋升或认领。
|
|
91
|
+
*/
|
|
92
|
+
delegationRoot?: DelegationRootWitness;
|
|
51
93
|
}
|
|
52
94
|
export type Scenario = (req: ScenarioRequest, principal?: string, ctx?: ScenarioContext) => ScenarioBundle;
|
|
53
95
|
export interface ScenarioDeps {
|
|
@@ -61,6 +103,11 @@ export interface ScenarioDeps {
|
|
|
61
103
|
* default roster — core says a multi-tenant deployment MUST allowlist hosts (an injected/untrusted tenant model
|
|
62
104
|
* could exfil via an arbitrary public URL; the SSRF floor only blocks internal). Single-user TOC keeps WebFetch. */
|
|
63
105
|
requirePrincipal?: boolean;
|
|
106
|
+
/**
|
|
107
|
+
* S-1652:这台部署的执行车道**有没有手**(`laneWiresExecutionEnv`;`REMOTE_EXEC` 未设 = `in-process` = 没有)。场景详情读面据它与场景自己的 `hands` 表态一起答
|
|
108
|
+
* 「这个场景的 run 有没有工作区」({@link runHasWorkspace}),进而给出附件可受理供给集。**缺席按没有手读**(宁少说不多说:不广告一个会撞 400 的 `path`)。
|
|
109
|
+
*/
|
|
110
|
+
handsLane?: boolean;
|
|
64
111
|
/** Deployment-injected WebSearch backend (Brave/Tavily/SearXNG via `WEB_SEARCH_PROVIDER`). When set,
|
|
65
112
|
* `assembleCodeTools` mounts the WebSearch tool; absent ⇒ not assembled (core ships no search backend). */
|
|
66
113
|
webSearch?: WebSearchConfig;
|
|
@@ -70,14 +117,6 @@ export interface ScenarioDeps {
|
|
|
70
117
|
* 字节形,core 落「summarization unavailable」诚实兜底)。 */
|
|
71
118
|
webFetchSummarize?: NonNullable<NonNullable<WebFetchConfig["summarize"]>>;
|
|
72
119
|
logger?: Logger;
|
|
73
|
-
/**
|
|
74
|
-
* When true, the `default` scenario carries the Sema product identity (see {@link semaIdentityProvider}).
|
|
75
|
-
* Set by the local/TOC deployment (CONFIG_PROVIDER=local / run-local) so the local engine answers "who
|
|
76
|
-
* are you" as Sema instead of the model's hallucinated identity. Business scenarios (code-review)
|
|
77
|
-
* keep their own prompts; cloud (CONFIG_PROVIDER≠local) leaves the default scenario neutral unless turned
|
|
78
|
-
* on, so integrators that inject their own persona are unaffected.
|
|
79
|
-
*/
|
|
80
|
-
brandIdentity?: boolean;
|
|
81
120
|
/**
|
|
82
121
|
* core 1.287 `SubagentToolOptions.extraTools` seam wire-through — per-SPAWN dynamic tool injection into the
|
|
83
122
|
* delegated (Agent-tool) child roster. Deployment-injected per-task tools (today: SendUserFile — its instance is
|
|
@@ -112,7 +151,12 @@ export interface ScenarioDeps {
|
|
|
112
151
|
* 后续按需再做)。
|
|
113
152
|
*/
|
|
114
153
|
checkpointStore?: CheckpointStore;
|
|
115
|
-
|
|
154
|
+
/**
|
|
155
|
+
* S-1770:比 core 挂点多一个参数 —— `root` = **委派树根的见证,由取用这只 bundle 的调用方交出**({@link ScenarioContext.delegationRoot};缺席 = 没有根可交)。
|
|
156
|
+
* core 的挂点只给子代 id,停驻写下 / 定夺的宿主行属主却要按委派继承律取委派树根的属主;场景工厂把见证绑进交给 core 的那只闭包,同一棵树里任何深度的后台子代
|
|
157
|
+
* 停驻都经它(子代沿用父的委派工具实例)。
|
|
158
|
+
*/
|
|
159
|
+
ensureChildSessionDurable?: (sessionId: string, root: DelegationRootWitness | undefined) => Promise<void>;
|
|
116
160
|
/**
|
|
117
161
|
* [ref]([ref] F2 症状 → [ref] 定谳):**会话级**任务清单店解析器,属主 =
|
|
118
162
|
* `boot/task-list-lane.ts` 的 {@link import("../boot/task-list-lane.js").createTaskListLane}
|
|
@@ -126,8 +170,9 @@ export interface ScenarioDeps {
|
|
|
126
170
|
taskListStoreFor?: (sessionId: string) => TaskListStore;
|
|
127
171
|
}
|
|
128
172
|
/**
|
|
129
|
-
* Sema product identity
|
|
130
|
-
*
|
|
173
|
+
* Sema product identity — the brand line of the `default` / `code` scenarios on a branded deployment (local / TOC). It is not a
|
|
174
|
+
* scenario seat: it is one deployment-class overlay (`capabilities/brand-identity.ts`, minted by `createDeploymentMods`) whose
|
|
175
|
+
* `when.binding` names the two scenarios. Honest about the substrate (the engine runs whichever model
|
|
131
176
|
* the operator configured — not Claude/Anthropic), so the agent never inherits the model's training-time
|
|
132
177
|
* "I am Claude" hallucination.
|
|
133
178
|
*
|
|
@@ -138,34 +183,10 @@ export interface ScenarioDeps {
|
|
|
138
183
|
* that maker's misstate its own substrate. Same for
|
|
139
184
|
* the gateway protocol (the brain stack serves Anthropic-compatible routes too — routing brain +
|
|
140
185
|
* createAnthropicBrain — so "OpenAI-compatible gateway" would be the same class of lie). Neutral wording
|
|
141
|
-
* (
|
|
142
|
-
* seam and reads poorly for ugly preset ids). The anti-"I am Claude" design is kept — only the baked
|
|
186
|
+
* (interpolating the model id reads poorly for ugly preset ids). The anti-"I am Claude" design is kept — only the baked
|
|
143
187
|
* substrate facts are removed.
|
|
144
188
|
*/
|
|
145
189
|
export { SEMA_IDENTITY } from "./prompts/identity.js";
|
|
146
|
-
/**
|
|
147
|
-
* Prompt provider for the branded `default` scenario: SEMA_IDENTITY on top of the ROLE base — the
|
|
148
|
-
* task's own `body.systemPrompt`, or core's {@link DEFAULT_SYSTEM_PROMPT} when none. Core 1.243
|
|
149
|
-
* (提示词主权批) appends the constitution structurally AFTER this role layer (harness
|
|
150
|
-
* safety blocks + modes + memory guidance + the prefix-cache-safe `<user_memory>` tail), so identity
|
|
151
|
-
* cannot displace the safety blocks. The pre-1.243 form (identity + `defaultPromptProvider.stableSystem`,
|
|
152
|
-
* i.e. an ALREADY-assembled prompt) would now trip the migration guard (anchor-detect → pass-through +
|
|
153
|
-
* `onError(phase:"prompt-constitution")`) — this role-only form is the guard-free contract.
|
|
154
|
-
*/
|
|
155
|
-
export declare function semaIdentityProvider(): PromptProvider;
|
|
156
|
-
/**
|
|
157
|
-
* `code` 场景的提示词提供者([ref] 造,[ref] clay 裁定改名 autonomous→code):role 基底 = core
|
|
158
|
-
* {@link CODE_SYSTEM_PROMPT}(core 1.298 [ref] 改名批正名,旧名 FULL_BODY_SYSTEM_PROMPT=恒等
|
|
159
|
-
* 别名过渡窗;CODE_AGENT persona + AUTONOMY_SELF_AUDIT + ANTI_VERBOSITY +
|
|
160
|
-
* TOOL_PARAM_JSON;[ref] 谱系定论 = CC 生产编码提示词的蒸馏去牌版,底本随 CC 版本对表 cc-anchors,
|
|
161
|
-
* 非自研)——与 bench 的请求组装完全同源,引用 core 常量随版本走,绝不复制字符串(tb bench 实测:
|
|
162
|
-
* 产品默认请求与同引擎 bench 态的差距根因就在这三件 persona/自检/终验)。品牌层与
|
|
163
|
-
* {@link semaIdentityProvider} 同构:brandIdentity 开时 SEMA_IDENTITY 叠在 role 基底之上;任务自带
|
|
164
|
-
* systemPrompt 按同一优先序赢过基底(role 合成规则与 default 场景一致)。宪法由 core 1.243 在 role
|
|
165
|
-
* 层之后结构化追加——此处只产 role-only 形态(guard-free 契约,同 semaIdentityProvider 注释)。
|
|
166
|
-
* 无 systemPrompt 且无品牌时原样返回 core 常量(测试以引用比对锁 bench 同源,不做字符串快照)。
|
|
167
|
-
*/
|
|
168
|
-
export declare function codePromptProvider(brand: boolean): PromptProvider;
|
|
169
190
|
export declare function buildScenarios(deps: ScenarioDeps): Record<string, Scenario>;
|
|
170
191
|
/**
|
|
171
192
|
* Resolve the scenario bundle for a name. `undefined` = no preference ⇒ the built-in `default`; any OTHER name must be
|
|
@@ -195,18 +216,47 @@ export interface ScenarioDetail {
|
|
|
195
216
|
available: boolean;
|
|
196
217
|
/** 机读原因键;仅 `available:false` 时在场(缺席=没有理由)。消费方按键分支,禁匹配英文文案。 */
|
|
197
218
|
unavailableReason?: ScenarioUnavailableReason;
|
|
219
|
+
/**
|
|
220
|
+
* S-1652:**这个场景在本部署上受理的附件供给**(顶层能力位 `userAttachments.supplies` 的子集,保持席位序;键恒在场,不是 `null`)。
|
|
221
|
+
* 顶层能力位说的是引擎席位**能承载**的三种供给(常量);`path` 读的是这一 run 的工作区,只有「场景挂手 ∧ 部署的执行车道有手」的 run 才有
|
|
222
|
+
* (判官 {@link runHasWorkspace}),其余整条 `path` 条目由引擎 prepare 拒 `config.user_attachment_invalid` —— 宿主发之前读这一格,不靠撞 400。
|
|
223
|
+
* `content_text` / `content_image` 与工作区无关,恒在。
|
|
224
|
+
*/
|
|
225
|
+
attachmentSupplies: UserAttachmentSupplyWord[];
|
|
198
226
|
}
|
|
227
|
+
/** 引擎附件席位的供给词(`USER_ATTACHMENT_SEAT.supplies` 的成员;取型,不手抄)。 */
|
|
228
|
+
export type UserAttachmentSupplyWord = (typeof USER_ATTACHMENT_SEAT)["supplies"][number];
|
|
229
|
+
/**
|
|
230
|
+
* 场景详情上的附件供给集 = 席位供给里去掉「这一 run 没有工作区时受理不了」的 `path`。**判据只有 {@link runHasWorkspace} 一只**:
|
|
231
|
+
* 内建与 center 两条产线共用本函数,引擎 prepare 的拒与本读面说的是同一个判决(同源钉在 `test/user-attachments.test.ts` ⑦b)。
|
|
232
|
+
*/
|
|
233
|
+
export declare function attachmentSuppliesFor(hands: ScenarioHands, handsLane: boolean): UserAttachmentSupplyWord[];
|
|
199
234
|
/** 内建四场景详情。default/code 工厂对良性请求无副作用可真调(拿真实工具名单);code-review/scan 是
|
|
200
235
|
* fail-loud 语义(缺 GIT_API 配置/principal 即 throw)→ 探针失败落静态表兜底(表↔工厂一致性由测试锁:
|
|
201
236
|
* 测试喂 fake deps 真调工厂对账工具名)。enabled 对内建恒 true(约定②)。 */
|
|
202
237
|
/** 内建场景名的闭集(`GET /v1/capabilities.scenarios` 与场景详情口的内建成员)。{@link builtinScenarioDetails} 的返回型按它键控 ⇒ 加 / 删一个内建场景而
|
|
203
238
|
* 这里没跟 = 编译红;wire 变更清单的自铸登记表(`trace/self-minted-wire.ts` 的 `builtinScenario`)同按它 `satisfies`。 */
|
|
204
|
-
export declare const BUILTIN_SCENARIO_NAMES: readonly ["code", "default", "code-review", "scan"];
|
|
239
|
+
export declare const BUILTIN_SCENARIO_NAMES: readonly ["code", "default", "code-review", "scan", "cowork"];
|
|
205
240
|
export type BuiltinScenarioName = (typeof BUILTIN_SCENARIO_NAMES)[number];
|
|
206
|
-
|
|
241
|
+
/**
|
|
242
|
+
* 内建场景对手带工具面的表态 —— **全仓唯一声明处**:各场景工厂产出的 bundle 的 `hands` 与场景详情读面的 `attachmentSupplies` 都读这张表,
|
|
243
|
+
* 不在三个工厂里各写一份字面量再靠对表格拴住。按 {@link BuiltinScenarioName} 键控 ⇒ 加 / 删一个内建场景而这里没跟 = 编译红。
|
|
244
|
+
*/
|
|
245
|
+
export declare const BUILTIN_SCENARIO_HANDS: {
|
|
246
|
+
readonly code: "full";
|
|
247
|
+
readonly default: "full";
|
|
248
|
+
readonly "code-review": "none";
|
|
249
|
+
readonly scan: "none";
|
|
250
|
+
readonly cowork: "full";
|
|
251
|
+
};
|
|
252
|
+
/**
|
|
253
|
+
* `branded` = 这台部署是不是品牌部署 —— 部署座挂品牌行读的同一只判官(`brand-identity.ts` `isBrandedDeployment`)交进来;没有默认值:每个调用点说出这件事实。
|
|
254
|
+
* 品牌部署上,品牌行 `when.binding` 那张表里的场景(`BRAND_IDENTITY_SCENARIOS`)的 `promptSummary` 点名 Sema 产品身份 —— 读面说的就是模型收到的。
|
|
255
|
+
*/
|
|
256
|
+
export declare function builtinScenarioDetails(scenarios: Record<string, Scenario>, deps: Pick<ScenarioDeps, "repoClient" | "handsLane">, branded: boolean): Record<string, ScenarioDetail>;
|
|
207
257
|
/** center 条目详情(有效性判定与 centerScenarios 完全同款:无效条目既不进 overlay 也不进详情——
|
|
208
258
|
* 保证约定①「详情显示的来源=运行实际用的定义」永不错位)。 */
|
|
209
|
-
export declare function centerScenarioDetails(specs: CenterScenarioSpec[] | undefined, builtinNames: string[], deps: Pick<ScenarioDeps, "repoClient">): Record<string, ScenarioDetail>;
|
|
259
|
+
export declare function centerScenarioDetails(specs: CenterScenarioSpec[] | undefined, builtinNames: string[], deps: Pick<ScenarioDeps, "repoClient" | "handsLane">): Record<string, ScenarioDetail>;
|
|
210
260
|
export interface CenterScenarioSpec {
|
|
211
261
|
name: string;
|
|
212
262
|
toolset: string;
|
|
@@ -1,31 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { USER_ATTACHMENT_SEAT, WEB_FETCH_TOOL_NAME, assembleCodeTools, defaultTaskRegistry } from "@sema-agent/core";
|
|
2
2
|
import { HttpError, createCodedHttpError } from "../security.js";
|
|
3
3
|
import { createSubagentExtraTools, extraToolsErrorFields, nowTool } from "./builtin-tools.js";
|
|
4
4
|
import { parseRepo, repoToolsFor } from "./repo-tools.js";
|
|
5
5
|
import { NOW_TOOL_NAME, REPO_PULL_DIFF_TOOL_NAME, REPO_READ_FILE_TOOL_NAME, REPO_TREE_TOOL_NAME } from "./host-tool-names.js";
|
|
6
|
-
import { stablePrompt } from "./prompt.js";
|
|
7
6
|
import { createWebSearchBackend, judgeRequestWebSearch } from "../plugins/web-search.js";
|
|
8
7
|
import { skillsForScenario } from "./skills.js";
|
|
9
|
-
|
|
10
|
-
import {
|
|
11
|
-
export function
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
],
|
|
16
|
-
};
|
|
8
|
+
import { OFFICE_EXCLUDED_TOOL_NAMES, runHasWorkspace } from "./hands-lane.js";
|
|
9
|
+
import { BRAND_IDENTITY_SCENARIOS } from "./brand-identity.js";
|
|
10
|
+
export function buildPromptSeats(scenarioName, prompt, callerSystemPrompt) {
|
|
11
|
+
const parts = [prompt?.roleText, callerSystemPrompt].filter((t) => typeof t === "string" && t.length > 0);
|
|
12
|
+
const systemPrompt = parts.length > 0 ? parts.join("\n\n") : callerSystemPrompt;
|
|
13
|
+
return { promptBinding: scenarioName, ...(prompt?.role !== undefined ? { promptRole: prompt.role } : {}), ...(systemPrompt !== undefined ? { systemPrompt } : {}) };
|
|
17
14
|
}
|
|
18
|
-
export function
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
return {
|
|
24
|
-
stableBlocks: (ctx) => [
|
|
25
|
-
{ id: "sema/identity", slot: "identity", text: `${SEMA_IDENTITY}\n\n${roleBase(ctx)}` },
|
|
26
|
-
],
|
|
27
|
-
};
|
|
15
|
+
export function buildExcludeToolsSeat(scenarioExcludes, callerExcludes) {
|
|
16
|
+
if (scenarioExcludes === undefined || scenarioExcludes.length === 0)
|
|
17
|
+
return callerExcludes !== undefined ? { excludeTools: [...callerExcludes] } : {};
|
|
18
|
+
const own = new Set(scenarioExcludes);
|
|
19
|
+
return { excludeTools: [...scenarioExcludes, ...(callerExcludes ?? []).filter((n) => !own.has(n))] };
|
|
28
20
|
}
|
|
21
|
+
export { SEMA_IDENTITY } from "./prompts/identity.js";
|
|
29
22
|
function requestWebSearchBackend(verdict, deployment, logger) {
|
|
30
23
|
switch (verdict.kind) {
|
|
31
24
|
case "absent":
|
|
@@ -45,6 +38,8 @@ export function buildScenarios(deps) {
|
|
|
45
38
|
const webSearch = requestWebSearchBackend(deps.requirePrincipal !== true
|
|
46
39
|
? judgeRequestWebSearch(req?.settings?.webSearch)
|
|
47
40
|
: { kind: "absent" }, deps.webSearch, deps.logger);
|
|
41
|
+
const ensureChildSessionDurable = deps.ensureChildSessionDurable;
|
|
42
|
+
const delegationRoot = ctx?.delegationRoot;
|
|
48
43
|
return {
|
|
49
44
|
tools: [
|
|
50
45
|
nowTool(),
|
|
@@ -63,7 +58,7 @@ export function buildScenarios(deps) {
|
|
|
63
58
|
scope: "default",
|
|
64
59
|
...(deps.backgroundAgentStore ? { agentStore: deps.backgroundAgentStore } : {}),
|
|
65
60
|
...(deps.checkpointStore ? { checkpointStore: deps.checkpointStore } : {}),
|
|
66
|
-
...(
|
|
61
|
+
...(ensureChildSessionDurable !== undefined ? { ensureChildSessionDurable: (childSessionId) => ensureChildSessionDurable(childSessionId, delegationRoot) } : {}),
|
|
67
62
|
},
|
|
68
63
|
...createSubagentExtraTools(deps.subagentExtraTools),
|
|
69
64
|
...(deps.logger
|
|
@@ -73,16 +68,16 @@ export function buildScenarios(deps) {
|
|
|
73
68
|
...(webSearch ? { webSearch } : {}),
|
|
74
69
|
}).filter((t) => t.name !== WEB_FETCH_TOOL_NAME || deps.requirePrincipal !== true),
|
|
75
70
|
],
|
|
76
|
-
hands:
|
|
71
|
+
hands: BUILTIN_SCENARIO_HANDS.default,
|
|
77
72
|
skills: skillsForScenario(deps.skills, "default"),
|
|
78
|
-
...(deps.brandIdentity ? { promptProvider: semaIdentityProvider() } : {}),
|
|
79
73
|
};
|
|
80
74
|
};
|
|
81
75
|
return {
|
|
82
76
|
default: defaultScenario,
|
|
83
77
|
code: (req, principal, ctx) => ({
|
|
84
78
|
...defaultScenario(req, principal, ctx),
|
|
85
|
-
|
|
79
|
+
hands: BUILTIN_SCENARIO_HANDS.code,
|
|
80
|
+
prompt: { role: "code" },
|
|
86
81
|
}),
|
|
87
82
|
"code-review": (req) => codeReview(deps, req),
|
|
88
83
|
scan: (req) => {
|
|
@@ -92,10 +87,17 @@ export function buildScenarios(deps) {
|
|
|
92
87
|
}
|
|
93
88
|
return {
|
|
94
89
|
tools: [...repoToolsFor(repoClient, parseRepo(req.repo)), nowTool()],
|
|
95
|
-
hands:
|
|
90
|
+
hands: BUILTIN_SCENARIO_HANDS.scan,
|
|
96
91
|
skills: skillsForScenario(deps.skills, "scan"),
|
|
97
92
|
};
|
|
98
93
|
},
|
|
94
|
+
cowork: (req, principal, ctx) => ({
|
|
95
|
+
...defaultScenario(req, principal, ctx),
|
|
96
|
+
hands: BUILTIN_SCENARIO_HANDS.cowork,
|
|
97
|
+
skills: skillsForScenario(deps.skills, "cowork"),
|
|
98
|
+
excludeTools: OFFICE_EXCLUDED_TOOL_NAMES,
|
|
99
|
+
prompt: { role: "cowork" },
|
|
100
|
+
}),
|
|
99
101
|
};
|
|
100
102
|
}
|
|
101
103
|
export function selectScenario(scenarios, name) {
|
|
@@ -106,12 +108,23 @@ export function selectScenario(scenarios, name) {
|
|
|
106
108
|
throw new Error(`scenario "${name}" is not registered — resolve a request's scenario through gateScenarioRequest, which only returns registered names`);
|
|
107
109
|
return picked;
|
|
108
110
|
}
|
|
111
|
+
export function attachmentSuppliesFor(hands, handsLane) {
|
|
112
|
+
const workspace = runHasWorkspace(hands, handsLane);
|
|
113
|
+
return USER_ATTACHMENT_SEAT.supplies.filter((supply) => workspace || supply !== "path");
|
|
114
|
+
}
|
|
109
115
|
function availabilityFields(deps, toolset) {
|
|
110
116
|
const verdict = scenarioAvailability(deps, toolset);
|
|
111
117
|
return verdict.available ? { available: true } : { available: false, unavailableReason: verdict.reason };
|
|
112
118
|
}
|
|
113
|
-
export const BUILTIN_SCENARIO_NAMES = ["code", "default", "code-review", "scan"];
|
|
114
|
-
export
|
|
119
|
+
export const BUILTIN_SCENARIO_NAMES = ["code", "default", "code-review", "scan", "cowork"];
|
|
120
|
+
export const BUILTIN_SCENARIO_HANDS = {
|
|
121
|
+
code: "full",
|
|
122
|
+
default: "full",
|
|
123
|
+
"code-review": "none",
|
|
124
|
+
scan: "none",
|
|
125
|
+
cowork: "full",
|
|
126
|
+
};
|
|
127
|
+
export function builtinScenarioDetails(scenarios, deps, branded) {
|
|
115
128
|
const probe = (name, req, principal, fallback) => {
|
|
116
129
|
try {
|
|
117
130
|
return ((Object.hasOwn(scenarios, name) ? scenarios[name] : undefined)?.(req, principal)?.tools ?? []).map((t) => t.name);
|
|
@@ -124,14 +137,15 @@ export function builtinScenarioDetails(scenarios, deps) {
|
|
|
124
137
|
const mk = (name, summary, toolset, tools, promptSummary) => ({
|
|
125
138
|
name, source: "builtin", builtin: true, summary, toolset, tools, promptSummary, enabled: true,
|
|
126
139
|
...availabilityFields(deps, toolset),
|
|
140
|
+
attachmentSupplies: attachmentSuppliesFor(BUILTIN_SCENARIO_HANDS[name], deps.handsLane === true),
|
|
127
141
|
});
|
|
142
|
+
const brandedScenario = (name) => branded && BRAND_IDENTITY_SCENARIOS.includes(name);
|
|
128
143
|
const details = {
|
|
129
|
-
code: mk("code", "编码主场景([891] 出厂缺省;CC 编码 persona 蒸馏版,default 全量工具面;终验旋钮独立)", "full-body", probe("code", {}, undefined, [NOW_TOOL_NAME]),
|
|
130
|
-
|
|
131
|
-
: "core 编码完全体提示词(CODE_AGENT persona+自治自检;CC 血统对表)"),
|
|
132
|
-
default: mk("default", "通用/助理场景(域中性 persona,CC agent loop 全量工具面;[891] 起非出厂缺省,显式可选)", "full-body", probe("default", {}, undefined, [NOW_TOOL_NAME]), deps.brandIdentity ? "Sema 产品身份 + core 默认宪法(结构层由引擎合成)" : "core 默认宪法(中性,无场景附加 persona)"),
|
|
144
|
+
code: mk("code", "编码主场景([891] 出厂缺省;CC 编码 persona 蒸馏版,default 全量工具面;终验旋钮独立)", "full-body", probe("code", {}, undefined, [NOW_TOOL_NAME]), `${brandedScenario("code") ? "Sema 产品身份 + " : ""}core 编码完全体提示词(CODE_AGENT persona+自治自检;CC 血统对表)`),
|
|
145
|
+
default: mk("default", "通用/助理场景(域中性 persona,CC agent loop 全量工具面;[891] 起非出厂缺省,显式可选)", "full-body", probe("default", {}, undefined, [NOW_TOOL_NAME]), brandedScenario("default") ? "Sema 产品身份 + core 默认宪法(结构层由引擎合成)" : "core 默认宪法(中性,无场景附加 persona)"),
|
|
133
146
|
"code-review": mk("code-review", "代码评审(clone-free 只读仓库工具)", "repo-readonly", probe("code-review", { repo: "probe/probe" }, undefined, REPO_TOOLS), "评审员提示词(产出契约)"),
|
|
134
147
|
scan: mk("scan", "中性只读仓库扫描(输出契约由 objective+skills 决定)", "repo-readonly", probe("scan", { repo: "probe/probe" }, undefined, REPO_TOOLS), "无场景附加提示词(objective+center skills 拥有输出契约)"),
|
|
148
|
+
cowork: mk("cowork", "办公向场景(default 的工具面去编码类工具:文件读 / 浏览 / 连接器挂载;Cowork 角色基底)", "office", probe("cowork", {}, undefined, [NOW_TOOL_NAME]), "core Cowork 角色基底(promptRole: cowork;办公向,不带编码 persona)"),
|
|
135
149
|
};
|
|
136
150
|
return details;
|
|
137
151
|
}
|
|
@@ -142,7 +156,8 @@ export function centerScenarioDetails(specs, builtinNames, deps) {
|
|
|
142
156
|
continue;
|
|
143
157
|
if (typeof spec.name !== "string" || !SCENARIO_NAME_RE.test(spec.name))
|
|
144
158
|
continue;
|
|
145
|
-
|
|
159
|
+
const toolset = Object.hasOwn(TOOLSETS, spec.toolset) ? TOOLSETS[spec.toolset] : undefined;
|
|
160
|
+
if (!toolset)
|
|
146
161
|
continue;
|
|
147
162
|
out[spec.name] = {
|
|
148
163
|
name: spec.name,
|
|
@@ -154,6 +169,7 @@ export function centerScenarioDetails(specs, builtinNames, deps) {
|
|
|
154
169
|
promptSummary: "",
|
|
155
170
|
enabled: true,
|
|
156
171
|
...availabilityFields(deps, spec.toolset),
|
|
172
|
+
attachmentSupplies: attachmentSuppliesFor(toolset.hands, deps.handsLane === true),
|
|
157
173
|
};
|
|
158
174
|
}
|
|
159
175
|
return out;
|
|
@@ -229,14 +245,13 @@ function codeReview(deps, req) {
|
|
|
229
245
|
const coords = parseRepo(req.repo);
|
|
230
246
|
const repoTools = repoToolsFor(repoClient, coords);
|
|
231
247
|
const skills = skillsForScenario(deps.skills, "code-review");
|
|
232
|
-
const hands = "
|
|
233
|
-
return { tools: [...repoTools, nowTool()], hands, skills,
|
|
248
|
+
const hands = BUILTIN_SCENARIO_HANDS["code-review"];
|
|
249
|
+
return { tools: [...repoTools, nowTool()], hands, skills, prompt: { roleText: REVIEWER_ROLE_TEXT } };
|
|
234
250
|
}
|
|
235
|
-
const
|
|
236
|
-
"(blocker / major / minor), each with `path:line`, the problem, and a concrete fix. Cite real code — never invent files or symbols.";
|
|
237
|
-
const directReviewerPrompt = stablePrompt("You are a senior code reviewer. Call repo_tree to map the repository, then repo_read_file to read " +
|
|
251
|
+
const REVIEWER_ROLE_TEXT = "You are a senior code reviewer. Call repo_tree to map the repository, then repo_read_file to read " +
|
|
238
252
|
"the files in scope, then review them yourself. " +
|
|
239
|
-
|
|
253
|
+
"Produce ONE prioritized review: a short summary, then findings grouped by severity " +
|
|
254
|
+
"(blocker / major / minor), each with `path:line`, the problem, and a concrete fix. Cite real code — never invent files or symbols.";
|
|
240
255
|
export function mergeUserSkills(scenarioSkills, userSkills, logger) {
|
|
241
256
|
if (!userSkills || userSkills.length === 0)
|
|
242
257
|
return scenarioSkills;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { SkillSpec } from "@sema-agent/core";
|
|
2
2
|
import type { RemoteExecProvider } from "../execution-lane-caps.js";
|
|
3
|
+
import { type Logger } from "../observability/logger.js";
|
|
3
4
|
/**
|
|
4
5
|
* Built-in skills baked into the image, loaded ONCE at startup (no per-task disk IO). A skill is a
|
|
5
6
|
* Markdown capability (frontmatter + body). core uses **progressive disclosure** (core ≥1.98.0):
|
|
@@ -26,6 +27,10 @@ import type { RemoteExecProvider } from "../execution-lane-caps.js";
|
|
|
26
27
|
* description: when to use it
|
|
27
28
|
* scenarios: code-review, oa # which scenarios get it; omit = all scenarios
|
|
28
29
|
* ---
|
|
30
|
+
*
|
|
31
|
+
* 🔴 **frontmatter 读不了的技能不装,不降成全局技能**(安全轴:`scenarios` 是场景围栏,丢了它技能就对每个场景可见):文件第一行是围栏(`---`,行尾只许空白 / 制表 / CR,
|
|
32
|
+
* 与 CC 2.1.296 的开头正则同判)而块没有收尾 ⇒ {@link parseFrontmatter} 答 `unclosed`,这一个技能被**拒载**并落一行 `skill_refused` warn(点名技能与文件、不带正文);
|
|
33
|
+
* 兄弟技能照装。第一行不是围栏的文件没有 frontmatter,是正当的全局技能。
|
|
29
34
|
*/
|
|
30
35
|
export interface LoadedSkill {
|
|
31
36
|
spec: SkillSpec;
|
|
@@ -52,6 +57,8 @@ export interface LoadSkillsOptions {
|
|
|
52
57
|
* core 的律也明写缺席 ⇒ 结果逐字节与 baseDir 到货之前相同)。两个方向不对称 ⇒ 默认取轻的那边。
|
|
53
58
|
*/
|
|
54
59
|
toolsShareThisFilesystem?: boolean;
|
|
60
|
+
/** 拒载一行 warn 的出口(见文件头注「frontmatter 读不了的技能不装」)。缺席 ⇒ 进程的 JSON 行 logger(`createLogger("warn")`,stderr)—— 拒载没有「安静」的形;装配点传自己的 logger 只为字段与级别跟部署同一份。 */
|
|
61
|
+
logger?: Logger;
|
|
55
62
|
}
|
|
56
63
|
/** `p` 的 realpath 必须落在 `rootReal` 之内(含自身),否则抛。`sep` 边界判定防 `/a/root-evil` 撞
|
|
57
64
|
* `/a/root` 前缀。目标不存在 ⇒ realpath 抛 ENOENT,同样是拒绝(悬空链接不该被读)。
|
|
@@ -70,12 +77,20 @@ export declare function loadDeploymentSkills(config: {
|
|
|
70
77
|
readonly remoteExec?: {
|
|
71
78
|
readonly provider: RemoteExecProvider;
|
|
72
79
|
} | undefined;
|
|
73
|
-
}): LoadedSkill[];
|
|
80
|
+
}, logger?: Logger): LoadedSkill[];
|
|
74
81
|
/** Skills applicable to a scenario: those tagged with it, plus untagged (global) ones.
|
|
75
82
|
* [ref]:alias 窗撤销,单键查询——退役旧名标签不再命中(迁移面在 7.44 发车帖/MIGRATION 记载)。 */
|
|
76
83
|
export declare function skillsForScenario(loaded: LoadedSkill[], scenario: string): SkillSpec[];
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
84
|
+
/** {@link parseFrontmatter} 的三种读数(闭集):`absent` = 第一行不是围栏,没有 frontmatter(正当的全局技能)· `block` = 围栏收好了的块 · `unclosed` = 第一行是围栏而块没收好(读不了 —— 调用方拒载)。 */
|
|
85
|
+
export type FrontmatterRead = {
|
|
86
|
+
readonly kind: "absent";
|
|
87
|
+
readonly body: string;
|
|
88
|
+
} | {
|
|
89
|
+
readonly kind: "block";
|
|
90
|
+
readonly meta: Record<string, string>;
|
|
91
|
+
readonly body: string;
|
|
92
|
+
} | {
|
|
93
|
+
readonly kind: "unclosed";
|
|
80
94
|
};
|
|
95
|
+
export declare function parseFrontmatter(raw: string): FrontmatterRead;
|
|
81
96
|
//# sourceMappingURL=skills.d.ts.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readdirSync, readFileSync, realpathSync, statSync } from "node:fs";
|
|
2
2
|
import { join, resolve, sep } from "node:path";
|
|
3
3
|
import { toolsRunOnThisHost } from "../task-cwd.js";
|
|
4
|
+
import { createLogger } from "../observability/logger.js";
|
|
4
5
|
export function assertConfined(p, rootReal, label = "skill entry") {
|
|
5
6
|
let real;
|
|
6
7
|
try {
|
|
@@ -14,6 +15,7 @@ export function assertConfined(p, rootReal, label = "skill entry") {
|
|
|
14
15
|
}
|
|
15
16
|
}
|
|
16
17
|
export function loadSkills(dir, opts) {
|
|
18
|
+
const logger = opts?.logger ?? createLogger("warn");
|
|
17
19
|
let entries;
|
|
18
20
|
try {
|
|
19
21
|
entries = readdirSync(dir, { withFileTypes: true });
|
|
@@ -41,7 +43,10 @@ export function loadSkills(dir, opts) {
|
|
|
41
43
|
if (confineRoot !== undefined)
|
|
42
44
|
assertConfined(join(dir, entry.name), confineRoot);
|
|
43
45
|
const raw = readFileSync(join(dir, entry.name), "utf8");
|
|
44
|
-
|
|
46
|
+
const source = join(dir, entry.name);
|
|
47
|
+
const parsed = parseSkill(raw, entry.name.replace(/\.md$/, ""), source, logger);
|
|
48
|
+
if (parsed !== undefined)
|
|
49
|
+
push(parsed, source);
|
|
45
50
|
}
|
|
46
51
|
else if (isDirLike(entry, join(dir, entry.name))) {
|
|
47
52
|
const skillDir = join(dir, entry.name);
|
|
@@ -56,7 +61,9 @@ export function loadSkills(dir, opts) {
|
|
|
56
61
|
}
|
|
57
62
|
if (confineRoot !== undefined)
|
|
58
63
|
assertConfined(join(skillDir, "SKILL.md"), confineRoot);
|
|
59
|
-
const skill = parseSkill(raw, entry.name);
|
|
64
|
+
const skill = parseSkill(raw, entry.name, join(skillDir, "SKILL.md"), logger);
|
|
65
|
+
if (skill === undefined)
|
|
66
|
+
continue;
|
|
60
67
|
const files = collectAttachments(skillDir, "", confineRoot);
|
|
61
68
|
if (files.length > 0)
|
|
62
69
|
skill.spec.files = files;
|
|
@@ -67,8 +74,8 @@ export function loadSkills(dir, opts) {
|
|
|
67
74
|
}
|
|
68
75
|
return out;
|
|
69
76
|
}
|
|
70
|
-
export function loadDeploymentSkills(config) {
|
|
71
|
-
return loadSkills(config.skillsDir, { toolsShareThisFilesystem: toolsRunOnThisHost(config) });
|
|
77
|
+
export function loadDeploymentSkills(config, logger) {
|
|
78
|
+
return loadSkills(config.skillsDir, { toolsShareThisFilesystem: toolsRunOnThisHost(config), ...(logger !== undefined ? { logger } : {}) });
|
|
72
79
|
}
|
|
73
80
|
function collectAttachments(skillDir, rel, confineRoot) {
|
|
74
81
|
const files = [];
|
|
@@ -93,8 +100,19 @@ function collectAttachments(skillDir, rel, confineRoot) {
|
|
|
93
100
|
}
|
|
94
101
|
return files;
|
|
95
102
|
}
|
|
96
|
-
function parseSkill(raw, fallbackName) {
|
|
97
|
-
const
|
|
103
|
+
function parseSkill(raw, fallbackName, source, logger) {
|
|
104
|
+
const fm = parseFrontmatter(raw);
|
|
105
|
+
if (fm.kind === "unclosed") {
|
|
106
|
+
logger.warn("skill_refused", {
|
|
107
|
+
skill: fallbackName,
|
|
108
|
+
source,
|
|
109
|
+
reason: "frontmatter_unclosed",
|
|
110
|
+
note: "the file opens a frontmatter fence (`---`) that is never closed, so its `scenarios` restriction cannot be read — this skill is NOT loaded (it is not demoted to a global skill); close the fence or remove the opening line",
|
|
111
|
+
});
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
const meta = fm.kind === "block" ? fm.meta : {};
|
|
115
|
+
const body = fm.body;
|
|
98
116
|
const name = meta.name ?? fallbackName;
|
|
99
117
|
const description = meta.description ?? firstHeading(body) ?? name;
|
|
100
118
|
const scenarios = (meta.scenarios ?? "")
|
|
@@ -106,17 +124,19 @@ function parseSkill(raw, fallbackName) {
|
|
|
106
124
|
export function skillsForScenario(loaded, scenario) {
|
|
107
125
|
return loaded.filter((k) => k.scenarios.length === 0 || k.scenarios.includes(scenario)).map((k) => k.spec);
|
|
108
126
|
}
|
|
127
|
+
const FRONTMATTER_OPENS_RE = /^---[ \t]*\r?(?:\n|$)/;
|
|
128
|
+
const FRONTMATTER_BLOCK_RE = /^---[ \t]*\r?\n(?:---[ \t]*\r?(?:\n|$)|([\s\S]*?)\r?\n---[ \t]*\r?(?:\n|$))([\s\S]*)$/;
|
|
109
129
|
export function parseFrontmatter(raw) {
|
|
110
|
-
const m =
|
|
130
|
+
const m = FRONTMATTER_BLOCK_RE.exec(raw);
|
|
111
131
|
if (!m)
|
|
112
|
-
return {
|
|
132
|
+
return FRONTMATTER_OPENS_RE.test(raw) ? { kind: "unclosed" } : { kind: "absent", body: raw };
|
|
113
133
|
const meta = {};
|
|
114
|
-
for (const line of m[1].split("\n")) {
|
|
134
|
+
for (const line of (m[1] ?? "").split("\n")) {
|
|
115
135
|
const kv = /^([A-Za-z0-9_-]+):\s*(.*)$/.exec(line.trim());
|
|
116
136
|
if (kv)
|
|
117
137
|
meta[kv[1]] = kv[2].trim();
|
|
118
138
|
}
|
|
119
|
-
return { meta, body: m[2] };
|
|
139
|
+
return { kind: "block", meta, body: m[2] };
|
|
120
140
|
}
|
|
121
141
|
function firstHeading(body) {
|
|
122
142
|
for (const line of body.split("\n")) {
|