@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/caller-text-echo.js
CHANGED
|
@@ -1,24 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { CONTROL_AND_BIDI_STRIP_RE } from "./text-bidi.js";
|
|
1
|
+
import { stripControlAndBidi } from "@sema-agent/settings-schema";
|
|
3
2
|
export const CALLER_TEXT_ECHO_MAX_CHARS = 64;
|
|
4
3
|
export function echoCallerText(text, opts) {
|
|
5
4
|
const max = opts?.maxChars ?? CALLER_TEXT_ECHO_MAX_CHARS;
|
|
6
5
|
if (!Number.isInteger(max) || max < 1)
|
|
7
6
|
throw new RangeError(`echoCallerText: maxChars must be a positive integer, got ${String(max)}`);
|
|
8
|
-
const clean = text
|
|
7
|
+
const clean = stripControlAndBidi(text);
|
|
9
8
|
return clean.length > max ? `${clean.slice(0, max)}…` : clean;
|
|
10
9
|
}
|
|
11
10
|
export function quotedCallerText(text) {
|
|
12
11
|
return `"${echoCallerText(text)}"`;
|
|
13
12
|
}
|
|
14
|
-
export function
|
|
15
|
-
|
|
16
|
-
return v === null ? "null" : Array.isArray(v) ? "array" : typeof v;
|
|
17
|
-
if (v.length === 0)
|
|
18
|
-
return "empty";
|
|
19
|
-
return `${quotedCallerText(v)} (${v.length} chars > ${TOOL_WIRE_NAME_MAX_CHARS})`;
|
|
13
|
+
export function clipDataText(s, max) {
|
|
14
|
+
return s.length > max ? `${s.slice(0, max)}…(${s.length})` : s;
|
|
20
15
|
}
|
|
21
|
-
export function
|
|
22
|
-
|
|
16
|
+
export function capText(s, max) {
|
|
17
|
+
if (s === undefined)
|
|
18
|
+
return undefined;
|
|
19
|
+
return s.length > max ? s.slice(0, max) : s;
|
|
23
20
|
}
|
|
24
21
|
//# sourceMappingURL=caller-text-echo.js.map
|
|
@@ -104,6 +104,13 @@ export declare function applyCenterPlugins(baseline: LoadedSkill[], eff: {
|
|
|
104
104
|
}, opts: {
|
|
105
105
|
cacheRoot: string;
|
|
106
106
|
allowHosts: readonly string[];
|
|
107
|
+
/**
|
|
108
|
+
* S-379 —— 「**工具跑的那台机器**的盘就是本进程这台盘吗」,由**组合根**算好传入(`boot/web-admin.ts` 传 `toolsRunOnThisHost(config)`,与出厂自扫
|
|
109
|
+
* `loadDeploymentSkills` 读的是同一只函数 —— 判据属主在 `task-cwd.ts`,这里不第二次判车道、不 import 车道词)。真 ⇒ 目录形 plugin 技能带上自己的
|
|
110
|
+
* 目录(`SkillSpec.baseDir`:`Skill` 结果首行 + `${SKILL_ROOT}` 替换);假 ⇒ 不带(fail-closed:沙箱 / 远端车道上这条路径在工具那边不存在)。
|
|
111
|
+
* 🔴 **必填,不给缺省**:修前这个调用点手上根本没有这一事实,fail-closed 默认把 host 车道也一并挡成「永不带」而没有任何红 —— 必填让「漏传」是编译错。
|
|
112
|
+
*/
|
|
113
|
+
toolsShareThisFilesystem: boolean;
|
|
107
114
|
logger?: Logger;
|
|
108
115
|
/** 测试口:跳过 validate(materialize 只接受已验声明;真 git 腿用本地 bare repo,validate 层的
|
|
109
116
|
* https-only 单独测——两层分开,谁也不掩护谁)。生产恒 false/缺席。 */
|
|
@@ -196,7 +196,7 @@ export async function applyCenterPlugins(baseline, eff, opts) {
|
|
|
196
196
|
}
|
|
197
197
|
if (!rootCheck.dir)
|
|
198
198
|
continue;
|
|
199
|
-
const loaded = loadSkills(rootCheck.dir, { confineTo: liveDir, ...(opts.logger !== undefined ? { logger: opts.logger } : {}) });
|
|
199
|
+
const loaded = loadSkills(rootCheck.dir, { confineTo: liveDir, toolsShareThisFilesystem: opts.toolsShareThisFilesystem, ...(opts.logger !== undefined ? { logger: opts.logger } : {}) });
|
|
200
200
|
for (const skill of loaded) {
|
|
201
201
|
if (taken.has(skill.spec.name)) {
|
|
202
202
|
out.letGo.push({ plugin: v.name, skill: skill.spec.name });
|
|
@@ -45,7 +45,7 @@ export declare const COMPOSITE_CAPABILITY_MEMBERS: {
|
|
|
45
45
|
readonly centerWiring: readonly ["effectivePull", "effectiveRevision", "lease", "leaseHealth", "failMode", "usageReport", "issuer", "worker", "caller"];
|
|
46
46
|
readonly webSearch: readonly ["backend"];
|
|
47
47
|
readonly background: readonly ["listFace", "exitFaces"];
|
|
48
|
-
readonly taskSettings: readonly ["permissions", "permissionMode", "model", "outputStyle", "env", "hooks"];
|
|
48
|
+
readonly taskSettings: readonly ["permissions", "permissionMode", "model", "outputStyle", "env", "hooks", "pluginHooks", "managedHookGroups", "tightenOnlySeats"];
|
|
49
49
|
readonly settings: readonly ["permissions"];
|
|
50
50
|
readonly permissionModeAuto: readonly ["accepted", "classifierSeat", "entitlementSource", "armed", "reason", "model"];
|
|
51
51
|
readonly writeProtection: readonly ["armed", "rows", "replaced"];
|
|
@@ -6,7 +6,7 @@ export const COMPOSITE_CAPABILITY_MEMBERS = {
|
|
|
6
6
|
centerWiring: ["effectivePull", "effectiveRevision", "lease", "leaseHealth", "failMode", "usageReport", "issuer", "worker", "caller"],
|
|
7
7
|
webSearch: ["backend"],
|
|
8
8
|
background: ["listFace", "exitFaces"],
|
|
9
|
-
taskSettings: ["permissions", "permissionMode", "model", "outputStyle", "env", "hooks"],
|
|
9
|
+
taskSettings: ["permissions", "permissionMode", "model", "outputStyle", "env", "hooks", "pluginHooks", "managedHookGroups", "tightenOnlySeats"],
|
|
10
10
|
settings: ["permissions"],
|
|
11
11
|
permissionModeAuto: ["accepted", "classifierSeat", "entitlementSource", "armed", "reason", "model"],
|
|
12
12
|
writeProtection: ["armed", "rows", "replaced"],
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { toolsRunOnThisHost } from "../task-cwd.js";
|
|
2
|
-
import {
|
|
2
|
+
import { executionLaneOf, laneIsolated, laneWiresExecutionEnv } from "../execution-lane-caps.js";
|
|
3
3
|
export function projectExecutionLaneCapability(config) {
|
|
4
4
|
const lane = executionLaneOf(config.remoteExec?.provider);
|
|
5
|
-
const handsWired =
|
|
5
|
+
const handsWired = laneWiresExecutionEnv(lane);
|
|
6
6
|
return {
|
|
7
7
|
provider: lane,
|
|
8
8
|
toolsOnThisHost: toolsRunOnThisHost(config),
|
|
@@ -39,6 +39,14 @@ export interface HandsRunnerPair {
|
|
|
39
39
|
}
|
|
40
40
|
/** 按场景表态取 Runner。**穷举 switch**:`ScenarioHands` 加词而此处不改 = 编译错(无 default 臂)。 */
|
|
41
41
|
export declare function pickHandsRunner(hands: ScenarioHands, pair: HandsRunnerPair): Runner;
|
|
42
|
+
/**
|
|
43
|
+
* 一个场景在一台部署上起的 run **有没有工作区** —— core prepare 的 `handsEnabled`(`ownedEnv || deps.executionEnv`)在本仓的镜像,**唯一一只判官**。
|
|
44
|
+
* 两个条件缺一不可:场景挂手({@link pickHandsRunner} 选有手 Runner,即带 `executionEnvFactory` 的那只)∧ 这台部署的执行车道有手
|
|
45
|
+
* (`execution-lane-caps.ts` 的 `laneWiresExecutionEnv`:`in-process` 车道整台没有 factory)。引擎对 `userAttachments` 里 `path` 条目的拒
|
|
46
|
+
* (`config.user_attachment_invalid`「this run has no workspace」)与场景详情读面的 `attachmentSupplies` 都落在这一只的答案上。
|
|
47
|
+
* **穷举 switch**:`ScenarioHands` 加词而此处不表态 = 编译红(与 {@link pickHandsRunner} 同一条纪律)。
|
|
48
|
+
*/
|
|
49
|
+
export declare function runHasWorkspace(hands: ScenarioHands, laneHasHands: boolean): boolean;
|
|
42
50
|
/**
|
|
43
51
|
* core 手带 band 的工具名**全集** —— 「挂 executionEnvFactory 才出现、不挂就消失」的那一批。
|
|
44
52
|
*
|
|
@@ -78,6 +86,19 @@ export declare const HANDS_BAND_TOOL_NAMES: readonly string[];
|
|
|
78
86
|
*/
|
|
79
87
|
export declare const HANDS_DUAL_USE_TOOL_NAMES: readonly string[];
|
|
80
88
|
export declare const HANDS_EXCLUSIVE_TOOL_NAMES: readonly string[];
|
|
89
|
+
/**
|
|
90
|
+
* S-1376:办公向场景(`cowork`)**保留**的手带工具 —— 文件读三件。办公场景挂手(`hands: "full"`:run 有工作区,附件 `path` 受理,这三件要这只手),
|
|
91
|
+
* 但不带编码类工具;「编码类」的定义是**手独占名单减去这张保留表**({@link OFFICE_EXCLUDED_TOOL_NAMES}),不是另抄一张编码工具名单:
|
|
92
|
+
* core 往 band 里加新的手带工具,办公场景**默认就卸它**(fail-closed),要保留得在这里显式点名并过评审。
|
|
93
|
+
* 保留表里每一项必须是 band 全集的成员(对表钉在 `test/cowork-scenario.test.ts`)。
|
|
94
|
+
*/
|
|
95
|
+
export declare const OFFICE_KEPT_HAND_TOOL_NAMES: readonly string[];
|
|
96
|
+
/**
|
|
97
|
+
* 办公向场景从 roster 里**真卸载**的手带工具名单(`TaskSpec.excludeTools`:per-scenario 的 roster 移除,工具 schema 不进 `tools[]`;不是策略 deny)=
|
|
98
|
+
* 手独占名单({@link HANDS_EXCLUSIVE_TOOL_NAMES},两用件不在内:委派 / workflow 车道要它们)∖ {@link OFFICE_KEPT_HAND_TOOL_NAMES}。
|
|
99
|
+
* 今天 = Edit · Write · NotebookEdit · Bash · RepoMap · LSP · EnterWorktree · ExitWorktree · Monitor。
|
|
100
|
+
*/
|
|
101
|
+
export declare const OFFICE_EXCLUDED_TOOL_NAMES: readonly string[];
|
|
81
102
|
/** 手独占名单的 deny 策略(纵深层)。名单是常量 ⇒ 每次调用产出等价策略,构造成本可忽略。 */
|
|
82
103
|
export declare function handsDenyPolicy(): ToolPolicy;
|
|
83
104
|
/**
|
|
@@ -12,6 +12,14 @@ export function pickHandsRunner(hands, pair) {
|
|
|
12
12
|
return pair.handsless;
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
|
+
export function runHasWorkspace(hands, laneHasHands) {
|
|
16
|
+
switch (hands) {
|
|
17
|
+
case "full":
|
|
18
|
+
return laneHasHands;
|
|
19
|
+
case "none":
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
15
23
|
export const HANDS_BAND_TOOL_NAMES = Object.freeze([
|
|
16
24
|
...handBandEffects().keys(),
|
|
17
25
|
"SendMessage",
|
|
@@ -23,6 +31,8 @@ export const HANDS_BAND_TOOL_NAMES = Object.freeze([
|
|
|
23
31
|
].filter((n, i, all) => judgeRuleToolName(n, TOOL_NAME_ROSTER).kind === "current" && all.indexOf(n) === i));
|
|
24
32
|
export const HANDS_DUAL_USE_TOOL_NAMES = Object.freeze(["TaskOutput", "TaskStop", "SendMessage", "AgentTranscript", "ListAgents"]);
|
|
25
33
|
export const HANDS_EXCLUSIVE_TOOL_NAMES = Object.freeze(HANDS_BAND_TOOL_NAMES.filter((n) => !HANDS_DUAL_USE_TOOL_NAMES.includes(n)));
|
|
34
|
+
export const OFFICE_KEPT_HAND_TOOL_NAMES = Object.freeze(["Read", "Glob", "Grep"]);
|
|
35
|
+
export const OFFICE_EXCLUDED_TOOL_NAMES = Object.freeze(HANDS_EXCLUSIVE_TOOL_NAMES.filter((n) => !OFFICE_KEPT_HAND_TOOL_NAMES.includes(n)));
|
|
26
36
|
export function handsDenyPolicy() {
|
|
27
37
|
return createAllowDenyPolicy({ deny: [...HANDS_EXCLUSIVE_TOOL_NAMES] });
|
|
28
38
|
}
|
|
@@ -134,8 +134,10 @@ export interface McpProbeFaceBody {
|
|
|
134
134
|
/** 这份读数还能复用多久(秒)= {@link MCP_PROBE_CACHE_TTL_MS}。 */
|
|
135
135
|
readonly ttlSec: number;
|
|
136
136
|
/**
|
|
137
|
-
*
|
|
138
|
-
* ({@link projectWiringManifestMcpRows},契约 §G.7)
|
|
137
|
+
* 每一行 = `wiring_manifest.mcp[]` 在 wire 上的那一行 —— **同一只投影**
|
|
138
|
+
* ({@link projectWiringManifestMcpRows},契约 §G.7),不是本面自己挑的一份键 —— **外加本面独有的两个可选键**
|
|
139
|
+
* `toolNames` / `toolNamesTruncated`({@link buildMcpProbeFaceRows};名字的来源只有同一次探测的读数
|
|
140
|
+
* `servers[i].tools`,§G.7 的行与 `wiring_manifest.mcp[]` 上都没有它们)。与入参申报**同序同长**
|
|
139
141
|
* (core `@contract mcp.probe.index_aligned`;下标对齐,不按 name)。
|
|
140
142
|
*
|
|
141
143
|
* 🔴 **`error`(远端原话)因此在本面上同样缺席**,而这**不是**本车的选择:§G.7 第 3 条是一条成文裁定
|
|
@@ -168,10 +170,10 @@ export interface McpProbeRefusal {
|
|
|
168
170
|
* (`source` 写坏的 F 类丢弃)不会在一次被拒的探测上虚记。
|
|
169
171
|
*
|
|
170
172
|
* ## 唯一一处按门分的后果:声明了 `assertionHeader`(引擎尚无断言头座)
|
|
171
|
-
* 事实只有一个、读它的谓词只有一只(`
|
|
173
|
+
* 事实只有一个、读它的谓词只有一只(`specWithholdsMcpAssertionHeader`,读发送开关 `MCP_ASSERTION_HEADER_SENT`):这台 server 声明的断言头本版**承载、不发送**,交给引擎的规格里没有它。
|
|
172
174
|
* 新提交照挂并给运维一行 info(`mcp_assertion_header_not_sent`;settings 面同读法);本面**整条拒** —— 拨出去的不是申报的那一份,一台握手放行、
|
|
173
175
|
* 调用才要断言的对端会被答成 connected,而它的调用会被拒。判据同一只、后果按门分(与重放腿对同一组身份头「降级到升级前读法」同一个姿势);
|
|
174
|
-
*
|
|
176
|
+
* 引擎长出同名座的那天,开关翻真,`toCoreMcpServerSpec` 的剥键与这一拒一起退役(`mcp-assertion-header.ts` 的退役门编译红)。
|
|
175
177
|
*/
|
|
176
178
|
export declare function readMcpProbeBody(raw: unknown): {
|
|
177
179
|
ok: true;
|
|
@@ -234,6 +236,28 @@ export interface McpProbeLocal {
|
|
|
234
236
|
}
|
|
235
237
|
/** 带行为的东西 ⇒ `create*`(工厂命名律:`build*` 出纯数据,`create*` 出活对象)。 */
|
|
236
238
|
export declare function createMcpProbeLocal(): McpProbeLocal;
|
|
239
|
+
/**
|
|
240
|
+
* S-1734 —— 一行的**本面独有**两键:`toolNames` / `toolNamesTruncated`。两条口走同一只 {@link createMcpProbeWalk},
|
|
241
|
+
* 所以这是它们**唯一**的铸点。
|
|
242
|
+
*
|
|
243
|
+
* ## 来源只有一个
|
|
244
|
+
* core 7.52.0 的 `probeMcpServers().servers[i].tools` —— 这台"会挂上"的工具名,形是引擎的命名空间形
|
|
245
|
+
* `mcp__<server>__<tool>`(= 会话面板 `toolNames` 同一只来源,过了 schema 闸与逐台白名单之后的名册,`tools.length` 恒等于该行的 `toolCount`)。
|
|
246
|
+
* server **不拼、不改名、不加前缀**:引擎是什么形,wire 上就是什么形。
|
|
247
|
+
*
|
|
248
|
+
* ## 失败方向(与 `toolCount` 不编 0 同律,逐键独立)
|
|
249
|
+
* · 这一格的 `tools` 缺席 / 非数组 / 带任何非串元素(含稀疏数组的空槽) ⇒ **两个键都缺席**(不编 `[]`:编出来的空名单会被读成「这台没有工具」;
|
|
250
|
+
* 带非串元素的数组整只不要 —— 少一半的名单看着像完整的那一份,而「会撒谎的读面比大的读面更贵」);
|
|
251
|
+
* · 在场的 `[]` 原样保留(core 对没连上的台给 `[]`,`toolCount` 同行为 0 —— 与「写了就在场」同律,不折成缺席);
|
|
252
|
+
* · 超过 {@link import("../panel-tool-names.js").PANEL_MAX_TOOL_NAMES} 只截**表**:`toolNamesTruncated: true`,`toolCount` 仍是 §G.7 投影出的真数。
|
|
253
|
+
*
|
|
254
|
+
* ## 下标对齐是承诺,不是约定
|
|
255
|
+
* `rows` 与 `readings` 按**下标**配(core `@contract mcp.probe.index_aligned`,名字不保证唯一)。读数不是数组、或条数与行数不等 ⇒
|
|
256
|
+
* **抛** {@link McpProbeMisaligned},不发一份会配错的名单 —— 与 {@link createMcpProbeWalk} 对 `rows` 条数的那道断言同一条纪律、同一个具名型
|
|
257
|
+
* (今天结构上不可达,所以是断言而不是兜底路径;一旦发生是服务内部的读数违约,两条口都答 5xx,不归到调用方的申报)。
|
|
258
|
+
* `rows` 一个字都不被改写(不过滤、不排序、不改已有键)。
|
|
259
|
+
*/
|
|
260
|
+
export declare function buildMcpProbeFaceRows(rows: readonly Record<string, unknown>[], readings: unknown): Array<Record<string, unknown>>;
|
|
237
261
|
/**
|
|
238
262
|
* 一次走查。**两只 promise,两件事**(合并树 codex ① [high],亲跑复现后按类修):
|
|
239
263
|
* · `answer` —— **HTTP 应答面**:到本面的期限就 reject {@link McpProbeIncomplete},调用腿据它答 503;
|
|
@@ -254,6 +278,14 @@ export interface McpProbeWalk {
|
|
|
254
278
|
readonly dials: Promise<unknown>;
|
|
255
279
|
}
|
|
256
280
|
export declare function createMcpProbeWalk(specs: readonly McpServerSpec[], principal: string | undefined, now?: () => number): McpProbeWalk;
|
|
281
|
+
/**
|
|
282
|
+
* 下标对齐的**内部断言**没过(行数 ≠ 申报数,或读数条数 ≠ 行数):core 的 `@contract mcp.probe.index_aligned` 在今天结构上保证它不发生,
|
|
283
|
+
* 所以它一旦发生,是**这台服务内部的读数违约**,不是调用方的申报写错 —— 修申报修不好它。**具名型**而不是按文案或按「非 Incomplete 的 reject」分诊:
|
|
284
|
+
* 调用腿据它把 `POST` 也答成 5xx(与 `GET` 同),而不是落进「core 物化拒了这份申报 ⇒ 400 点名调用方」那一臂。
|
|
285
|
+
*/
|
|
286
|
+
export declare class McpProbeMisaligned extends Error {
|
|
287
|
+
constructor(message: string);
|
|
288
|
+
}
|
|
257
289
|
/** 整次走查没在 {@link MCP_PROBE_WALK_TIMEOUT_MS} 内落地。**具名型**而不是一个字符串比较:调用腿要据它
|
|
258
290
|
* 分诊(503 + 退避),而按错误文案分诊是本仓明令不许的形。 */
|
|
259
291
|
export declare class McpProbeIncomplete extends Error {
|
|
@@ -4,8 +4,9 @@ import { createFixedWindowRateLimiter } from "../device-enrollment.js";
|
|
|
4
4
|
import { canonicalJson } from "../canonical-json.js";
|
|
5
5
|
import { keyClosureClause, scanKeyClosure } from "../request-key-closure.js";
|
|
6
6
|
import { requestMcpDeclarationRefusal, validateRequestMcp } from "../task-mcp.js";
|
|
7
|
-
import {
|
|
7
|
+
import { specWithholdsMcpAssertionHeader, toCoreMcpServerSpec } from "../mcp-assertion-header.js";
|
|
8
8
|
import { projectWiringManifestMcpRows } from "../trace/project.js";
|
|
9
|
+
import { buildBoundedToolNames } from "../panel-tool-names.js";
|
|
9
10
|
export const MCP_PROBE_REFUSAL_CODES = [
|
|
10
11
|
"capability.mcp_injection_required",
|
|
11
12
|
"limit.rate_exceeded",
|
|
@@ -70,7 +71,7 @@ export function readMcpProbeBody(raw) {
|
|
|
70
71
|
" so nothing in your body needs changing — if you see it, this deployment has a bug worth reporting"),
|
|
71
72
|
};
|
|
72
73
|
}
|
|
73
|
-
const carried = validated.ok.findIndex(
|
|
74
|
+
const carried = validated.ok.findIndex(specWithholdsMcpAssertionHeader);
|
|
74
75
|
if (carried >= 0) {
|
|
75
76
|
return {
|
|
76
77
|
ok: false,
|
|
@@ -138,6 +139,22 @@ export function createMcpProbeLocal() {
|
|
|
138
139
|
inflight: () => [...cache.values()].filter((v) => v.settledAt === undefined).length,
|
|
139
140
|
};
|
|
140
141
|
}
|
|
142
|
+
export function buildMcpProbeFaceRows(rows, readings) {
|
|
143
|
+
if (!Array.isArray(readings) || readings.length !== rows.length) {
|
|
144
|
+
const got = Array.isArray(readings) ? `${readings.length} readings` : "no reading array";
|
|
145
|
+
throw new McpProbeMisaligned(`mcp probe returned ${got} for the ${rows.length} rows it must align with by index — refusing to publish tool names a consumer would mis-pair`);
|
|
146
|
+
}
|
|
147
|
+
return rows.map((row, i) => {
|
|
148
|
+
const reading = readings[i];
|
|
149
|
+
const tools = typeof reading === "object" && reading !== null ? reading.tools : undefined;
|
|
150
|
+
if (!isStringList(tools))
|
|
151
|
+
return row;
|
|
152
|
+
return { ...row, ...buildBoundedToolNames(tools) };
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
function isStringList(v) {
|
|
156
|
+
return Array.isArray(v) && Array.from(v).every((t) => typeof t === "string");
|
|
157
|
+
}
|
|
141
158
|
export function createMcpProbeWalk(specs, principal, now = Date.now) {
|
|
142
159
|
const bound = buildMcpProbeWalkTimeoutMs(specs.length);
|
|
143
160
|
const controller = new AbortController();
|
|
@@ -160,9 +177,9 @@ export function createMcpProbeWalk(specs, principal, now = Date.now) {
|
|
|
160
177
|
const result = await Promise.race([dials, deadline]);
|
|
161
178
|
const rows = projectWiringManifestMcpRows(result.entries) ?? [];
|
|
162
179
|
if (rows.length !== specs.length) {
|
|
163
|
-
throw new
|
|
180
|
+
throw new McpProbeMisaligned(`mcp probe row count ${rows.length} does not match the ${specs.length} declarations it must align with by index — refusing to publish a list a consumer would mis-pair`);
|
|
164
181
|
}
|
|
165
|
-
return { probedAt: new Date(now()).toISOString(), ttlSec: Math.floor(MCP_PROBE_CACHE_TTL_MS / 1000), servers: rows };
|
|
182
|
+
return { probedAt: new Date(now()).toISOString(), ttlSec: Math.floor(MCP_PROBE_CACHE_TTL_MS / 1000), servers: buildMcpProbeFaceRows(rows, result.servers) };
|
|
166
183
|
}
|
|
167
184
|
finally {
|
|
168
185
|
if (timer !== undefined)
|
|
@@ -172,6 +189,12 @@ export function createMcpProbeWalk(specs, principal, now = Date.now) {
|
|
|
172
189
|
answer.catch(() => undefined);
|
|
173
190
|
return { answer, dials };
|
|
174
191
|
}
|
|
192
|
+
export class McpProbeMisaligned extends Error {
|
|
193
|
+
constructor(message) {
|
|
194
|
+
super(message);
|
|
195
|
+
this.name = "McpProbeMisaligned";
|
|
196
|
+
}
|
|
197
|
+
}
|
|
175
198
|
export class McpProbeIncomplete extends Error {
|
|
176
199
|
boundMs;
|
|
177
200
|
constructor(boundMs) {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { type WebFetchConfig, type BackgroundAgentStore, type CheckpointStore, type Runner, type SkillSpec, type TaskListStore, type TaskSpec, type ToolSpec, type WebSearchConfig } from "@sema-agent/core";
|
|
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
10
|
* selects a pre-wired capability bundle: tools (incl. subagent roster) + its prompt seats + skills.
|
|
@@ -26,6 +27,12 @@ export interface ScenarioBundle {
|
|
|
26
27
|
* `scan` 声明 clone-free 四件、实际拿到全量可写手)。
|
|
27
28
|
*/
|
|
28
29
|
hands: ScenarioHands;
|
|
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[];
|
|
29
36
|
/** 本场景对提示的贡献(缺席 = 不贡献:引擎目录的缺省角色)。经 {@link buildPromptSeats} 写进 `TaskSpec`,这是场景到提示的唯一通道。 */
|
|
30
37
|
prompt?: ScenarioPrompt;
|
|
31
38
|
/** [ref] 场景解释层定死的终验开关(core TaskSpec.finalVerification):bench 实测产品默认请求与
|
|
@@ -53,6 +60,12 @@ export interface ScenarioPrompt {
|
|
|
53
60
|
* · `systemPrompt` = 角色文本(场景自己的在前、调用方 `systemPrompt` 在后,`\n\n` 相连;空串不占位;两者都缺席 ⇒ 键不写,调用方给的空串原样交引擎)。
|
|
54
61
|
*/
|
|
55
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">;
|
|
56
69
|
/**
|
|
57
70
|
* [ref]:场景工厂的**服务端事实**上下文 —— 与 `req`(= 调用方请求体,不可信)分开的第三个入参。
|
|
58
71
|
* 这里的每一位都由鉴权信道解析,调用方无法自报;新增位一律走本接口,绝不往 `req` 上加。
|
|
@@ -64,11 +77,19 @@ export interface ScenarioContext {
|
|
|
64
77
|
* 等于让一个租户读另一个租户的清单(同 spec 组装处那条「sessionId comes from `auth`, NEVER the
|
|
65
78
|
* body」的逐字纪律)。
|
|
66
79
|
*
|
|
67
|
-
* 缺席 = 这条调用形本来就没有会话(`parked-revive-surface.ts`
|
|
80
|
+
* 缺席 = 这条调用形本来就没有会话(`parked-revive-surface.ts` 对不交座的行、boot 期那一次 Agent 工具探针、
|
|
68
81
|
* `builtinScenarioDetails` 的工具名探针)。此时会话级设施退化为 per-call 实例 —— 不为它发明
|
|
69
82
|
* 一个假 session。
|
|
70
83
|
*/
|
|
71
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;
|
|
72
93
|
}
|
|
73
94
|
export type Scenario = (req: ScenarioRequest, principal?: string, ctx?: ScenarioContext) => ScenarioBundle;
|
|
74
95
|
export interface ScenarioDeps {
|
|
@@ -82,6 +103,11 @@ export interface ScenarioDeps {
|
|
|
82
103
|
* default roster — core says a multi-tenant deployment MUST allowlist hosts (an injected/untrusted tenant model
|
|
83
104
|
* could exfil via an arbitrary public URL; the SSRF floor only blocks internal). Single-user TOC keeps WebFetch. */
|
|
84
105
|
requirePrincipal?: boolean;
|
|
106
|
+
/**
|
|
107
|
+
* S-1652:这台部署的执行车道**有没有手**(`laneWiresExecutionEnv`;`REMOTE_EXEC` 未设 = `in-process` = 没有)。场景详情读面据它与场景自己的 `hands` 表态一起答
|
|
108
|
+
* 「这个场景的 run 有没有工作区」({@link runHasWorkspace}),进而给出附件可受理供给集。**缺席按没有手读**(宁少说不多说:不广告一个会撞 400 的 `path`)。
|
|
109
|
+
*/
|
|
110
|
+
handsLane?: boolean;
|
|
85
111
|
/** Deployment-injected WebSearch backend (Brave/Tavily/SearXNG via `WEB_SEARCH_PROVIDER`). When set,
|
|
86
112
|
* `assembleCodeTools` mounts the WebSearch tool; absent ⇒ not assembled (core ships no search backend). */
|
|
87
113
|
webSearch?: WebSearchConfig;
|
|
@@ -125,7 +151,12 @@ export interface ScenarioDeps {
|
|
|
125
151
|
* 后续按需再做)。
|
|
126
152
|
*/
|
|
127
153
|
checkpointStore?: CheckpointStore;
|
|
128
|
-
|
|
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>;
|
|
129
160
|
/**
|
|
130
161
|
* [ref]([ref] F2 症状 → [ref] 定谳):**会话级**任务清单店解析器,属主 =
|
|
131
162
|
* `boot/task-list-lane.ts` 的 {@link import("../boot/task-list-lane.js").createTaskListLane}
|
|
@@ -185,22 +216,47 @@ export interface ScenarioDetail {
|
|
|
185
216
|
available: boolean;
|
|
186
217
|
/** 机读原因键;仅 `available:false` 时在场(缺席=没有理由)。消费方按键分支,禁匹配英文文案。 */
|
|
187
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[];
|
|
188
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[];
|
|
189
234
|
/** 内建四场景详情。default/code 工厂对良性请求无副作用可真调(拿真实工具名单);code-review/scan 是
|
|
190
235
|
* fail-loud 语义(缺 GIT_API 配置/principal 即 throw)→ 探针失败落静态表兜底(表↔工厂一致性由测试锁:
|
|
191
236
|
* 测试喂 fake deps 真调工厂对账工具名)。enabled 对内建恒 true(约定②)。 */
|
|
192
237
|
/** 内建场景名的闭集(`GET /v1/capabilities.scenarios` 与场景详情口的内建成员)。{@link builtinScenarioDetails} 的返回型按它键控 ⇒ 加 / 删一个内建场景而
|
|
193
238
|
* 这里没跟 = 编译红;wire 变更清单的自铸登记表(`trace/self-minted-wire.ts` 的 `builtinScenario`)同按它 `satisfies`。 */
|
|
194
|
-
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"];
|
|
195
240
|
export type BuiltinScenarioName = (typeof BUILTIN_SCENARIO_NAMES)[number];
|
|
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
|
+
};
|
|
196
252
|
/**
|
|
197
253
|
* `branded` = 这台部署是不是品牌部署 —— 部署座挂品牌行读的同一只判官(`brand-identity.ts` `isBrandedDeployment`)交进来;没有默认值:每个调用点说出这件事实。
|
|
198
254
|
* 品牌部署上,品牌行 `when.binding` 那张表里的场景(`BRAND_IDENTITY_SCENARIOS`)的 `promptSummary` 点名 Sema 产品身份 —— 读面说的就是模型收到的。
|
|
199
255
|
*/
|
|
200
|
-
export declare function builtinScenarioDetails(scenarios: Record<string, Scenario>, deps: Pick<ScenarioDeps, "repoClient">, branded: boolean): Record<string, ScenarioDetail>;
|
|
256
|
+
export declare function builtinScenarioDetails(scenarios: Record<string, Scenario>, deps: Pick<ScenarioDeps, "repoClient" | "handsLane">, branded: boolean): Record<string, ScenarioDetail>;
|
|
201
257
|
/** center 条目详情(有效性判定与 centerScenarios 完全同款:无效条目既不进 overlay 也不进详情——
|
|
202
258
|
* 保证约定①「详情显示的来源=运行实际用的定义」永不错位)。 */
|
|
203
|
-
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>;
|
|
204
260
|
export interface CenterScenarioSpec {
|
|
205
261
|
name: string;
|
|
206
262
|
toolset: string;
|
|
@@ -1,16 +1,23 @@
|
|
|
1
|
-
import { WEB_FETCH_TOOL_NAME, assembleCodeTools, defaultTaskRegistry } from "@sema-agent/core";
|
|
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
6
|
import { createWebSearchBackend, judgeRequestWebSearch } from "../plugins/web-search.js";
|
|
7
7
|
import { skillsForScenario } from "./skills.js";
|
|
8
|
+
import { OFFICE_EXCLUDED_TOOL_NAMES, runHasWorkspace } from "./hands-lane.js";
|
|
8
9
|
import { BRAND_IDENTITY_SCENARIOS } from "./brand-identity.js";
|
|
9
10
|
export function buildPromptSeats(scenarioName, prompt, callerSystemPrompt) {
|
|
10
11
|
const parts = [prompt?.roleText, callerSystemPrompt].filter((t) => typeof t === "string" && t.length > 0);
|
|
11
12
|
const systemPrompt = parts.length > 0 ? parts.join("\n\n") : callerSystemPrompt;
|
|
12
13
|
return { promptBinding: scenarioName, ...(prompt?.role !== undefined ? { promptRole: prompt.role } : {}), ...(systemPrompt !== undefined ? { systemPrompt } : {}) };
|
|
13
14
|
}
|
|
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))] };
|
|
20
|
+
}
|
|
14
21
|
export { SEMA_IDENTITY } from "./prompts/identity.js";
|
|
15
22
|
function requestWebSearchBackend(verdict, deployment, logger) {
|
|
16
23
|
switch (verdict.kind) {
|
|
@@ -31,6 +38,8 @@ export function buildScenarios(deps) {
|
|
|
31
38
|
const webSearch = requestWebSearchBackend(deps.requirePrincipal !== true
|
|
32
39
|
? judgeRequestWebSearch(req?.settings?.webSearch)
|
|
33
40
|
: { kind: "absent" }, deps.webSearch, deps.logger);
|
|
41
|
+
const ensureChildSessionDurable = deps.ensureChildSessionDurable;
|
|
42
|
+
const delegationRoot = ctx?.delegationRoot;
|
|
34
43
|
return {
|
|
35
44
|
tools: [
|
|
36
45
|
nowTool(),
|
|
@@ -49,7 +58,7 @@ export function buildScenarios(deps) {
|
|
|
49
58
|
scope: "default",
|
|
50
59
|
...(deps.backgroundAgentStore ? { agentStore: deps.backgroundAgentStore } : {}),
|
|
51
60
|
...(deps.checkpointStore ? { checkpointStore: deps.checkpointStore } : {}),
|
|
52
|
-
...(
|
|
61
|
+
...(ensureChildSessionDurable !== undefined ? { ensureChildSessionDurable: (childSessionId) => ensureChildSessionDurable(childSessionId, delegationRoot) } : {}),
|
|
53
62
|
},
|
|
54
63
|
...createSubagentExtraTools(deps.subagentExtraTools),
|
|
55
64
|
...(deps.logger
|
|
@@ -59,7 +68,7 @@ export function buildScenarios(deps) {
|
|
|
59
68
|
...(webSearch ? { webSearch } : {}),
|
|
60
69
|
}).filter((t) => t.name !== WEB_FETCH_TOOL_NAME || deps.requirePrincipal !== true),
|
|
61
70
|
],
|
|
62
|
-
hands:
|
|
71
|
+
hands: BUILTIN_SCENARIO_HANDS.default,
|
|
63
72
|
skills: skillsForScenario(deps.skills, "default"),
|
|
64
73
|
};
|
|
65
74
|
};
|
|
@@ -67,6 +76,7 @@ export function buildScenarios(deps) {
|
|
|
67
76
|
default: defaultScenario,
|
|
68
77
|
code: (req, principal, ctx) => ({
|
|
69
78
|
...defaultScenario(req, principal, ctx),
|
|
79
|
+
hands: BUILTIN_SCENARIO_HANDS.code,
|
|
70
80
|
prompt: { role: "code" },
|
|
71
81
|
}),
|
|
72
82
|
"code-review": (req) => codeReview(deps, req),
|
|
@@ -77,10 +87,17 @@ export function buildScenarios(deps) {
|
|
|
77
87
|
}
|
|
78
88
|
return {
|
|
79
89
|
tools: [...repoToolsFor(repoClient, parseRepo(req.repo)), nowTool()],
|
|
80
|
-
hands:
|
|
90
|
+
hands: BUILTIN_SCENARIO_HANDS.scan,
|
|
81
91
|
skills: skillsForScenario(deps.skills, "scan"),
|
|
82
92
|
};
|
|
83
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
|
+
}),
|
|
84
101
|
};
|
|
85
102
|
}
|
|
86
103
|
export function selectScenario(scenarios, name) {
|
|
@@ -91,11 +108,22 @@ export function selectScenario(scenarios, name) {
|
|
|
91
108
|
throw new Error(`scenario "${name}" is not registered — resolve a request's scenario through gateScenarioRequest, which only returns registered names`);
|
|
92
109
|
return picked;
|
|
93
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
|
+
}
|
|
94
115
|
function availabilityFields(deps, toolset) {
|
|
95
116
|
const verdict = scenarioAvailability(deps, toolset);
|
|
96
117
|
return verdict.available ? { available: true } : { available: false, unavailableReason: verdict.reason };
|
|
97
118
|
}
|
|
98
|
-
export const BUILTIN_SCENARIO_NAMES = ["code", "default", "code-review", "scan"];
|
|
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
|
+
};
|
|
99
127
|
export function builtinScenarioDetails(scenarios, deps, branded) {
|
|
100
128
|
const probe = (name, req, principal, fallback) => {
|
|
101
129
|
try {
|
|
@@ -109,6 +137,7 @@ export function builtinScenarioDetails(scenarios, deps, branded) {
|
|
|
109
137
|
const mk = (name, summary, toolset, tools, promptSummary) => ({
|
|
110
138
|
name, source: "builtin", builtin: true, summary, toolset, tools, promptSummary, enabled: true,
|
|
111
139
|
...availabilityFields(deps, toolset),
|
|
140
|
+
attachmentSupplies: attachmentSuppliesFor(BUILTIN_SCENARIO_HANDS[name], deps.handsLane === true),
|
|
112
141
|
});
|
|
113
142
|
const brandedScenario = (name) => branded && BRAND_IDENTITY_SCENARIOS.includes(name);
|
|
114
143
|
const details = {
|
|
@@ -116,6 +145,7 @@ export function builtinScenarioDetails(scenarios, deps, branded) {
|
|
|
116
145
|
default: mk("default", "通用/助理场景(域中性 persona,CC agent loop 全量工具面;[891] 起非出厂缺省,显式可选)", "full-body", probe("default", {}, undefined, [NOW_TOOL_NAME]), brandedScenario("default") ? "Sema 产品身份 + core 默认宪法(结构层由引擎合成)" : "core 默认宪法(中性,无场景附加 persona)"),
|
|
117
146
|
"code-review": mk("code-review", "代码评审(clone-free 只读仓库工具)", "repo-readonly", probe("code-review", { repo: "probe/probe" }, undefined, REPO_TOOLS), "评审员提示词(产出契约)"),
|
|
118
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)"),
|
|
119
149
|
};
|
|
120
150
|
return details;
|
|
121
151
|
}
|
|
@@ -126,7 +156,8 @@ export function centerScenarioDetails(specs, builtinNames, deps) {
|
|
|
126
156
|
continue;
|
|
127
157
|
if (typeof spec.name !== "string" || !SCENARIO_NAME_RE.test(spec.name))
|
|
128
158
|
continue;
|
|
129
|
-
|
|
159
|
+
const toolset = Object.hasOwn(TOOLSETS, spec.toolset) ? TOOLSETS[spec.toolset] : undefined;
|
|
160
|
+
if (!toolset)
|
|
130
161
|
continue;
|
|
131
162
|
out[spec.name] = {
|
|
132
163
|
name: spec.name,
|
|
@@ -138,6 +169,7 @@ export function centerScenarioDetails(specs, builtinNames, deps) {
|
|
|
138
169
|
promptSummary: "",
|
|
139
170
|
enabled: true,
|
|
140
171
|
...availabilityFields(deps, spec.toolset),
|
|
172
|
+
attachmentSupplies: attachmentSuppliesFor(toolset.hands, deps.handsLane === true),
|
|
141
173
|
};
|
|
142
174
|
}
|
|
143
175
|
return out;
|
|
@@ -213,7 +245,7 @@ function codeReview(deps, req) {
|
|
|
213
245
|
const coords = parseRepo(req.repo);
|
|
214
246
|
const repoTools = repoToolsFor(repoClient, coords);
|
|
215
247
|
const skills = skillsForScenario(deps.skills, "code-review");
|
|
216
|
-
const hands = "
|
|
248
|
+
const hands = BUILTIN_SCENARIO_HANDS["code-review"];
|
|
217
249
|
return { tools: [...repoTools, nowTool()], hands, skills, prompt: { roleText: REVIEWER_ROLE_TEXT } };
|
|
218
250
|
}
|
|
219
251
|
const REVIEWER_ROLE_TEXT = "You are a senior code reviewer. Call repo_tree to map the repository, then repo_read_file to read " +
|