@sema-agent/server 7.43.0 → 7.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/USAGE.md +18 -0
- package/dist/adoption/plan.js +31 -192
- package/dist/adoption/quiesce.js +3 -86
- package/dist/adoption/runner.js +3 -140
- package/dist/adoption/sql.js +0 -74
- package/dist/adoption/wire.js +0 -80
- package/dist/approval-ask-machine.js +0 -75
- package/dist/approval-card.js +0 -323
- package/dist/approval-deny-reasons.js +0 -42
- package/dist/approval-hmac.js +0 -35
- package/dist/approval-reconciler.js +8 -166
- package/dist/approval.js +4 -67
- package/dist/audit.js +1 -44
- package/dist/auth-bridge.js +4 -47
- package/dist/auth-keys.js +0 -23
- package/dist/bake-runner/main.js +4 -65
- package/dist/bake-runner/protocol.js +3 -58
- package/dist/bake-runner/runner.js +5 -91
- package/dist/bench/l8/artifact.js +2 -61
- package/dist/bench/l8/escape.js +0 -25
- package/dist/bench/l8/index.js +0 -14
- package/dist/bench/l8/probes.js +0 -60
- package/dist/bench/l8/run-probes.js +2 -45
- package/dist/bench/s1/arms.js +14 -189
- package/dist/bench/s1/live-deps.js +11 -253
- package/dist/bench/s1/oracle.js +1 -36
- package/dist/bench/s1/repair-oracle-adapter.js +0 -30
- package/dist/bench/s1/reviewer.js +0 -34
- package/dist/bench/s1/row.js +0 -62
- package/dist/bench/s1/run-firm.js +4 -70
- package/dist/bench/s1/runner-ctx.js +0 -40
- package/dist/bench/s1/tasks.js +0 -115
- package/dist/boot/adoption.js +0 -20
- package/dist/boot/budget-tracing.js +3 -55
- package/dist/boot/config-center.js +43 -551
- package/dist/boot/coordinators.js +1 -69
- package/dist/boot/crash-last.js +0 -18
- package/dist/boot/deferred-sandbox-path-env.js +3 -119
- package/dist/boot/execution-env.js +5 -171
- package/dist/boot/governance-seams.js +0 -92
- package/dist/boot/leader.js +0 -69
- package/dist/boot/limit-sync.js +0 -2
- package/dist/boot/memory-boundary.js +3 -91
- package/dist/boot/org-memory.js +1 -25
- package/dist/boot/parked-revive-gate.js +0 -150
- package/dist/boot/permission-rules-audit.js +1 -56
- package/dist/boot/reapers.js +15 -273
- package/dist/boot/resolve-spec.js +9 -768
- package/dist/boot/retention-lane.js +4 -87
- package/dist/boot/runner-deps.js +3 -297
- package/dist/boot/runtime-caps.js +0 -40
- package/dist/boot/session-faces.js +2 -133
- package/dist/boot/shutdown.js +9 -83
- package/dist/boot/side-query-lane.js +2 -137
- package/dist/boot/stores.js +15 -215
- package/dist/boot/task-list-lane.js +0 -18
- package/dist/boot/webfetch-summarize-lane.js +0 -47
- package/dist/boot/workflow-orchestration.js +3 -99
- package/dist/boot-reclaim.js +0 -20
- package/dist/bounded-session-map.js +0 -19
- package/dist/brain.js +2 -139
- package/dist/budget.js +9 -244
- package/dist/capabilities/builtin-tools.js +0 -3
- package/dist/capabilities/center-plugins.js +6 -51
- package/dist/capabilities/center-prompts.js +6 -71
- package/dist/capabilities/code-review-council.js +7 -40
- package/dist/capabilities/collab-workflows.js +1 -44
- package/dist/capabilities/hands-lane.js +0 -65
- package/dist/capabilities/memory-notice.js +0 -70
- package/dist/capabilities/prompt.js +0 -14
- package/dist/capabilities/prompts/code-review.js +0 -14
- package/dist/capabilities/prompts/identity.js +0 -6
- package/dist/capabilities/prompts/team.js +0 -4
- package/dist/capabilities/repo-tools.js +0 -34
- package/dist/capabilities/sandbox-file-send.js +3 -92
- package/dist/capabilities/scenarios.d.ts +0 -1
- package/dist/capabilities/scenarios.js +18 -279
- package/dist/capabilities/select-environment-tool.js +0 -32
- package/dist/capabilities/send-user-file-tool.js +2 -66
- package/dist/capabilities/skills.d.ts +1 -2
- package/dist/capabilities/skills.js +3 -21
- package/dist/capabilities/team.d.ts +3 -11
- package/dist/capabilities/team.js +3 -51
- package/dist/capabilities/tool-defer.js +0 -3
- package/dist/config-center/apply-effective.js +15 -330
- package/dist/config-center/apply-ledger.js +5 -38
- package/dist/config-center/facade.js +0 -41
- package/dist/config-center/hot-keys-registry.js +0 -20
- package/dist/config-center/http-client.js +2 -125
- package/dist/config-center/mcp-revocation.js +2 -34
- package/dist/config-center/read-face.js +0 -59
- package/dist/config-center/restart-signal.js +1 -85
- package/dist/config-center/skills-mcp.d.ts +1 -1
- package/dist/config-center/skills-mcp.js +9 -76
- package/dist/config-center/stage-limits.js +8 -35
- package/dist/config-invariants.js +0 -16
- package/dist/config-lkg.js +0 -42
- package/dist/config-provider.js +3 -186
- package/dist/config-types.js +0 -5
- package/dist/config.js +107 -1145
- package/dist/degenerate-instrument.js +3 -67
- package/dist/deployment-governance.js +0 -124
- package/dist/digest-form.js +0 -12
- package/dist/elicitation.js +3 -86
- package/dist/env-facts.js +7 -75
- package/dist/fleet/fleet-bus.js +34 -507
- package/dist/fleet/fleet-reconciler.js +9 -149
- package/dist/fleet/fleet-terminal-window.js +10 -178
- package/dist/fleet/subagent-tail-bus.js +3 -72
- package/dist/fleet-client.js +10 -70
- package/dist/fleet-lease.js +5 -79
- package/dist/git-api-kind.js +0 -3
- package/dist/governance-ask-marks.js +2 -78
- package/dist/hooks/branch-transcript.js +0 -74
- package/dist/hooks/cc-agent-hook-prompt.js +0 -29
- package/dist/hooks/cc-stop-prompt.js +1 -46
- package/dist/hooks/hook-llm.js +1 -53
- package/dist/hooks/hook-runner.js +20 -414
- package/dist/http/active-run-conflict.js +4 -129
- package/dist/http/cursor-fingerprint.d.ts +5 -0
- package/dist/http/cursor-fingerprint.js +5 -0
- package/dist/http/idempotency.js +0 -37
- package/dist/http/principal-gate.js +3 -40
- package/dist/http/route-ctx.js +0 -9
- package/dist/http/routes/a2a-serve.js +7 -319
- package/dist/http/routes/admin-config-refresh.js +0 -4
- package/dist/http/routes/admin-drain.js +0 -10
- package/dist/http/routes/adoption.js +1 -29
- package/dist/http/routes/agents-roster.js +1 -47
- package/dist/http/routes/approvals-assistant.js +32 -395
- package/dist/http/routes/attachments.js +4 -22
- package/dist/http/routes/capabilities.js +3 -420
- package/dist/http/routes/diagnostics.js +1 -81
- package/dist/http/routes/fleet.js +9 -185
- package/dist/http/routes/images.js +14 -239
- package/dist/http/routes/leader.js +0 -13
- package/dist/http/routes/memory-bundle.js +1 -61
- package/dist/http/routes/memory-policy.js +9 -99
- package/dist/http/routes/notify-wake.js +3 -37
- package/dist/http/routes/observability.js +2 -19
- package/dist/http/routes/retention-ops.js +2 -34
- package/dist/http/routes/rules.js +1 -93
- package/dist/http/routes/runs.js +64 -873
- package/dist/http/routes/session-sync.js +19 -258
- package/dist/http/routes/sessions-list.js +17 -43
- package/dist/http/routes/sessions.js +34 -226
- package/dist/http/routes/shared-memory.js +5 -36
- package/dist/http/routes/side-query.js +1 -87
- package/dist/http/routes/tasks.js +52 -722
- package/dist/http/routes/trace-usage.js +32 -195
- package/dist/http/routes/workflows.js +19 -195
- package/dist/http/run-meta.js +0 -6
- package/dist/http/send.js +0 -32
- package/dist/http/server.js +92 -1597
- package/dist/http/sse-lifecycle.js +2 -13
- package/dist/http/sse-log.js +3 -48
- package/dist/http/tar.js +5 -21
- package/dist/http/verify-rounds.js +0 -5
- package/dist/http/wire-gate.js +0 -9
- package/dist/http/workspace-content.js +0 -10
- package/dist/images/bake-validate.js +1 -70
- package/dist/images/manifest.js +1 -6
- package/dist/index.js +0 -21
- package/dist/key-resolver.js +2 -17
- package/dist/leader/diffout.js +1 -20
- package/dist/leader/diffup.js +0 -47
- package/dist/leader/endpoint.js +2 -57
- package/dist/leader/fanout.js +3 -45
- package/dist/leader/grader-env-factory.js +3 -72
- package/dist/leader/leader.js +5 -156
- package/dist/leader/merge.js +8 -115
- package/dist/leader/planner.js +3 -54
- package/dist/leader/repair-oracle.js +1 -60
- package/dist/leader/repair-wire.js +2 -79
- package/dist/leader/wire.js +8 -307
- package/dist/lsp/e2b-bridge.js +4 -64
- package/dist/lsp/e2b-manager.js +6 -94
- package/dist/lsp/lsp-frames.js +0 -12
- package/dist/lsp/manager.js +4 -96
- package/dist/lsp/ws-transport.js +5 -55
- package/dist/lsp-evict.js +1 -15
- package/dist/main.js +57 -765
- package/dist/memory-bundle-engine.js +0 -55
- package/dist/memory-export.js +0 -4
- package/dist/memory-posture.js +1 -15
- package/dist/memory-scope.js +11 -148
- package/dist/memory-sync-client.js +2 -44
- package/dist/memory-sync.js +1 -80
- package/dist/model-select.js +3 -80
- package/dist/observability/cost-quota.js +1 -17
- package/dist/observability/cost-taxonomy.js +0 -34
- package/dist/observability/fail-open.js +7 -86
- package/dist/observability/logger.js +0 -6
- package/dist/observability/metrics.js +0 -94
- package/dist/observability/otel-exporter.js +3 -13
- package/dist/observability/principal-context.js +0 -9
- package/dist/observability/prompt-manifest.js +1 -37
- package/dist/observability/rate-limit.js +0 -4
- package/dist/observability/secret-env-scrub.js +2 -56
- package/dist/observability/tool-trace.js +1 -70
- package/dist/orchestration/hardened-vm-runner.js +4 -118
- package/dist/orchestration/hardened-vm-worker-runner.js +1 -26
- package/dist/orchestration/hardened-vm-worker.js +0 -27
- package/dist/orchestration/subagent-steer.js +1 -45
- package/dist/orchestration/workflow-agent-steer.js +1 -80
- package/dist/orchestration/workflow-completion-inbox.js +32 -285
- package/dist/orchestration/workflow-notify-journal.js +16 -259
- package/dist/org-memory-admission.js +3 -47
- package/dist/parent-watch.js +2 -48
- package/dist/parked-decide.js +1 -109
- package/dist/per-task-image.js +0 -57
- package/dist/plan-cache-probe.js +3 -27
- package/dist/plugins/adoption-log-sql.js +2 -119
- package/dist/plugins/approval-ask-store-memory.js +3 -38
- package/dist/plugins/approval-ask-store-sql.js +6 -188
- package/dist/plugins/approval-exemption-store.js +2 -28
- package/dist/plugins/background-agent-store-sql.js +4 -105
- package/dist/plugins/background-shell-support.js +14 -122
- package/dist/plugins/blob-backend.js +6 -169
- package/dist/plugins/breaker-state-sql.js +8 -46
- package/dist/plugins/caching-session-store.js +4 -106
- package/dist/plugins/checkpoint-store-sql.js +18 -505
- package/dist/plugins/e2b-orphan-reclaim.js +0 -45
- package/dist/plugins/file-outcome-sink.js +0 -9
- package/dist/plugins/file-resume-anchor-store.js +4 -43
- package/dist/plugins/file-run-store.js +26 -364
- package/dist/plugins/file-snapshot-store-sql.js +10 -181
- package/dist/plugins/fork-routing-session-store.js +8 -111
- package/dist/plugins/host-platform.js +2 -91
- package/dist/plugins/image-bake-store-sql.js +7 -250
- package/dist/plugins/image-index-sql.js +4 -123
- package/dist/plugins/k8s-bg-scripts.js +4 -88
- package/dist/plugins/k8s-exec-protocol.js +0 -41
- package/dist/plugins/leader-run-store-sql.js +0 -101
- package/dist/plugins/local-checkpoint-store.js +8 -128
- package/dist/plugins/local-session-store.js +34 -296
- package/dist/plugins/local-task-attachment-store.js +2 -16
- package/dist/plugins/mailbox-store-sql.js +8 -65
- package/dist/plugins/memory-embedder-fingerprint.js +5 -166
- package/dist/plugins/memory-embedder.js +4 -70
- package/dist/plugins/memory-engine-pg.js +6 -170
- package/dist/plugins/memory-engine-tidb.js +7 -155
- package/dist/plugins/memory-engine-vector-util.js +0 -10
- package/dist/plugins/memory-key-guards.js +0 -34
- package/dist/plugins/memory-origin-law.js +0 -187
- package/dist/plugins/memory-resume-anchor-store.js +0 -17
- package/dist/plugins/memory-run-store.js +12 -89
- package/dist/plugins/memory-session-policy-store.js +0 -17
- package/dist/plugins/memory-sync-store-pg.js +4 -49
- package/dist/plugins/memory-sync-store-tidb.js +3 -35
- package/dist/plugins/outcome-ledger-sql.js +3 -97
- package/dist/plugins/permission-rule-store-file.js +5 -133
- package/dist/plugins/permission-rule-store-sql.d.ts +3 -0
- package/dist/plugins/permission-rule-store-sql.js +50 -307
- package/dist/plugins/pg-cost-quota.js +0 -7
- package/dist/plugins/pg-pool.js +0 -92
- package/dist/plugins/pg-rate-limiter.js +2 -13
- package/dist/plugins/pg-safe-json.js +4 -40
- package/dist/plugins/pg-session-storage.js +25 -189
- package/dist/plugins/posix-shell-fs.js +1 -31
- package/dist/plugins/remote-env-adb.js +12 -101
- package/dist/plugins/remote-env-e2b.js +40 -371
- package/dist/plugins/remote-env-file-error.js +0 -37
- package/dist/plugins/remote-env-host.js +63 -483
- package/dist/plugins/remote-env-k8s.js +32 -326
- package/dist/plugins/remote-env-local-docker.js +24 -157
- package/dist/plugins/remote-env-ssh.js +20 -128
- package/dist/plugins/remote-scratchpad.js +2 -32
- package/dist/plugins/remote-shell.js +1 -32
- package/dist/plugins/resume-anchor-store-sql.js +0 -11
- package/dist/plugins/retention-lane-store-sql.js +0 -108
- package/dist/plugins/retention-store-sql.js +4 -383
- package/dist/plugins/roster-store-sql.js +0 -55
- package/dist/plugins/run-store-sql.js +14 -251
- package/dist/plugins/s3-presign.js +2 -49
- package/dist/plugins/scheduler-support.js +3 -80
- package/dist/plugins/send-file-ledger.js +4 -53
- package/dist/plugins/send-user-file.js +4 -94
- package/dist/plugins/session-placement.js +1 -89
- package/dist/plugins/session-policy-store-sql.js +3 -81
- package/dist/plugins/session-store.js +0 -57
- package/dist/plugins/shared-memory-store-sql.js +4 -167
- package/dist/plugins/sql-driver.js +0 -17
- package/dist/plugins/sql-errors.js +0 -7
- package/dist/plugins/sql-escape.js +0 -8
- package/dist/plugins/sql-row-helpers.js +0 -25
- package/dist/plugins/store-backend.js +42 -222
- package/dist/plugins/store-contracts.js +2 -46
- package/dist/plugins/task-attachment-store.js +3 -49
- package/dist/plugins/task-list-store-sql.js +0 -79
- package/dist/plugins/tidb-cost-quota.js +1 -4
- package/dist/plugins/tidb-pool.js +1 -207
- package/dist/plugins/tidb-rate-limiter.js +3 -9
- package/dist/plugins/tidb-session-storage.js +4 -70
- package/dist/plugins/tidb-session-store.js +19 -341
- package/dist/plugins/tool-result-store-sql.js +4 -179
- package/dist/plugins/usage-window-store-sql.js +0 -8
- package/dist/plugins/web-search.js +10 -132
- package/dist/plugins/workflow-journal-store-sql.js +2 -58
- package/dist/plugins/workflow-run-store-sql.js +6 -91
- package/dist/plugins/worktree-isolation.js +6 -126
- package/dist/plugins/write-behind-counter.js +16 -75
- package/dist/principal-jwt.js +5 -60
- package/dist/project-memory.js +15 -146
- package/dist/prompts-domain-validate.js +1 -51
- package/dist/question.js +2 -111
- package/dist/resource-suspend.js +0 -18
- package/dist/router/route-orchestration.js +0 -77
- package/dist/rules-consent.d.ts +44 -5
- package/dist/rules-consent.js +75 -215
- package/dist/run-local.js +14 -381
- package/dist/runs.js +29 -617
- package/dist/runtime-caps-resolver.js +6 -132
- package/dist/runtime-governance.js +1 -232
- package/dist/sandbox-pkg-source.js +0 -37
- package/dist/sealed-key.js +3 -68
- package/dist/security.js +6 -291
- package/dist/session-leaf-bus.js +0 -32
- package/dist/session-sync-content.js +1 -69
- package/dist/session-sync-kernel.js +3 -60
- package/dist/session-sync.js +3 -66
- package/dist/session-titler.js +7 -41
- package/dist/session-watch.js +9 -73
- package/dist/shared-memory-scope-authorizer.js +0 -18
- package/dist/sighup-idle.js +1 -12
- package/dist/spec-fields.js +4 -143
- package/dist/store-live-probe.js +3 -49
- package/dist/task-a2a.js +1 -126
- package/dist/task-cwd.js +1 -103
- package/dist/task-mcp.js +1 -89
- package/dist/task-settings.js +10 -300
- package/dist/task-workflow.js +8 -75
- package/dist/tool-approval.d.ts +28 -1
- package/dist/tool-approval.js +70 -1430
- package/dist/trace/artifacts.js +5 -20
- package/dist/trace/engine-notice-wire.js +6 -138
- package/dist/trace/ledger-sink.js +7 -96
- package/dist/trace/project.js +4 -448
- package/dist/trace/redact.js +9 -77
- package/dist/turn-activity.js +1 -27
- package/dist/usage-analytics.js +4 -34
- package/dist/wall-clock-jump-guard.js +1 -68
- package/package.json +3 -3
- package/dist/capabilities/scenario-alias.d.ts +0 -27
- package/dist/capabilities/scenario-alias.js +0 -61
|
@@ -8,113 +8,31 @@ import { createDiscussionTools, discussionCoordinatorPrompt, getTeam, teamNames
|
|
|
8
8
|
import { createWebSearchBackend, webSearchConfigFromSettings } from "../plugins/web-search.js";
|
|
9
9
|
import { skillsForScenario } from "./skills.js";
|
|
10
10
|
import { pickHandsRunner } from "./hands-lane.js";
|
|
11
|
-
|
|
12
|
-
// #273 / C-R14:alias 表与两只归一口的**属主**是 `scenario-alias.ts`(零依赖模块,避免
|
|
13
|
-
// scenarios ↔ skills/skills-mcp/center-prompts 的循环 import)。此处再导出一次,保持既有 import 面。
|
|
14
|
-
export { SCENARIO_ALIASES, canonicalScenarioName, scenarioConfigKeys } from "./scenario-alias.js";
|
|
15
|
-
/**
|
|
16
|
-
* Sema product identity, prepended to the core default base for the `default` scenario when
|
|
17
|
-
* {@link ScenarioDeps.brandIdentity} is on. Honest about the substrate (the engine runs whichever model
|
|
18
|
-
* the operator configured — not Claude/Anthropic), so the agent never inherits the model's training-time
|
|
19
|
-
* "I am Claude" hallucination.
|
|
20
|
-
*
|
|
21
|
-
* Live-caught incident (a deployment served by one model family described itself as running on a DIFFERENT
|
|
22
|
-
* vendor's model, because that vendor's name was baked into this text):
|
|
23
|
-
* NOTHING substrate-specific may be hardcoded here — onboard is multi-provider (any OpenAI-/Anthropic-
|
|
24
|
-
* compatible endpoint, self-hosted vLLM included), so a baked maker name makes every deployment that is not
|
|
25
|
-
* that maker's misstate its own substrate. Same for
|
|
26
|
-
* the gateway protocol (the brain stack serves Anthropic-compatible routes too — routing brain +
|
|
27
|
-
* createAnthropicBrain — so "OpenAI-compatible gateway" would be the same class of lie). Neutral wording
|
|
28
|
-
* (zero core-seam need; interpolating the model id would need a `StablePromptContext.model`
|
|
29
|
-
* seam and reads poorly for ugly preset ids). The anti-"I am Claude" design is kept — only the baked
|
|
30
|
-
* substrate facts are removed.
|
|
31
|
-
*/
|
|
32
|
-
export { SEMA_IDENTITY } from "./prompts/identity.js"; // copy moved to the bundle-data layer
|
|
11
|
+
export { SEMA_IDENTITY } from "./prompts/identity.js";
|
|
33
12
|
import { SEMA_IDENTITY } from "./prompts/identity.js";
|
|
34
|
-
/**
|
|
35
|
-
* Prompt provider for the branded `default` scenario: SEMA_IDENTITY on top of the ROLE base — the
|
|
36
|
-
* task's own `body.systemPrompt`, or core's {@link DEFAULT_SYSTEM_PROMPT} when none. Core 1.243
|
|
37
|
-
* (提示词主权批) appends the constitution structurally AFTER this role layer (harness
|
|
38
|
-
* safety blocks + modes + memory guidance + the prefix-cache-safe `<user_memory>` tail), so identity
|
|
39
|
-
* cannot displace the safety blocks. The pre-1.243 form (identity + `defaultPromptProvider.stableSystem`,
|
|
40
|
-
* i.e. an ALREADY-assembled prompt) would now trip the migration guard (anchor-detect → pass-through +
|
|
41
|
-
* `onError(phase:"prompt-constitution")`) — this role-only form is the guard-free contract.
|
|
42
|
-
*/
|
|
43
13
|
export function semaIdentityProvider() {
|
|
44
|
-
// Lens-4 endgame (core 1.310, [1006]②/[1012]): the typed stableBlocks branch now carries core's OWN
|
|
45
|
-
// pass-through guard (M9-family anchor detection on identity declarations → provider-assembled,
|
|
46
|
-
// un-doubled) — the 0c3352f server-side fallback routing for the already-assembled input face is
|
|
47
|
-
// retired; the real-composer parity matrix keeps that face pinned byte-equal against the pre-M14 form.
|
|
48
14
|
return {
|
|
49
|
-
// M14 (core 1.303, 板 [968]): the branded head is a TYPED block — the stable id "sema/identity" gives
|
|
50
|
-
// it a manifest section identity + digest (the G-1 observability gap; IDENTITY-DIGEST-MIGRATION.md
|
|
51
|
-
// route B, this hook is its carrier). identity-slot semantics: the block REPLACES core/role.base at
|
|
52
|
-
// the head position, so it must carry the FULL role layer (identity + role base) — byte-identical to
|
|
53
|
-
// the previous stableSystem string. Finer identity/role digest separation is the catalog-section
|
|
54
|
-
// endgame, not this hook's job.
|
|
55
15
|
stableBlocks: (ctx) => [
|
|
56
16
|
{ id: "sema/identity", slot: "identity", text: `${SEMA_IDENTITY}\n\n${ctx.userSystemPrompt ?? DEFAULT_SYSTEM_PROMPT}` },
|
|
57
17
|
],
|
|
58
18
|
};
|
|
59
19
|
}
|
|
60
|
-
/**
|
|
61
|
-
* `code` 场景的提示词提供者([849] 造,[891] clay 裁定改名 autonomous→code):role 基底 = core
|
|
62
|
-
* {@link CODE_SYSTEM_PROMPT}(core 1.298 [891] 改名批正名,旧名 FULL_BODY_SYSTEM_PROMPT=恒等
|
|
63
|
-
* 别名过渡窗;CODE_AGENT persona + AUTONOMY_SELF_AUDIT + ANTI_VERBOSITY +
|
|
64
|
-
* TOOL_PARAM_JSON;[891] 血缘定论 = CC 生产编码提示词的蒸馏去牌版,底本随 CC 版本对表 cc-anchors,
|
|
65
|
-
* 非自研)——与 bench 的请求组装完全同源,引用 core 常量随版本走,绝不复制字符串(tb bench 实测:
|
|
66
|
-
* 产品默认请求与同引擎 bench 态的差距根因就在这三件 persona/自检/终验)。品牌层与
|
|
67
|
-
* {@link semaIdentityProvider} 同构:brandIdentity 开时 SEMA_IDENTITY 叠在 role 基底之上;任务自带
|
|
68
|
-
* systemPrompt 按同一优先序赢过基底(role 合成规则与 default 场景一致)。宪法由 core 1.243 在 role
|
|
69
|
-
* 层之后结构化追加——此处只产 role-only 形态(guard-free 契约,同 semaIdentityProvider 注释)。
|
|
70
|
-
* 无 systemPrompt 且无品牌时原样返回 core 常量(测试以引用比对锁 bench 同源,不做字符串快照)。
|
|
71
|
-
*/
|
|
72
20
|
export function codePromptProvider(brand) {
|
|
73
|
-
// [1158]/[1161]/[1162] b 案(clay 拍):provider 供给的字节 core 永不改写(provenance 卫,1.329),
|
|
74
|
-
// 所以 known-constant narrowing 够不着 provider 手里的 CODE_SYSTEM_PROMPT——simple 形的「裸底」
|
|
75
|
-
// 由 server 自己按 ctx.promptProfile 选 core 常量(CODE_AGENT_PROMPT=core 1.329 narrowing 的同一
|
|
76
|
-
// 目标常量,引用不复制,[891] 同源铁律)。classic 全链字节等价旧形;行为九段随 pack 走(平形
|
|
77
|
-
// stableSystem/stableBlocks 都不排段;server 从未用 replaceAll)。
|
|
78
21
|
const roleBase = (ctx) => ctx.userSystemPrompt ?? (ctx.promptProfile === "classic" ? CODE_SYSTEM_PROMPT : CODE_AGENT_PROMPT);
|
|
79
|
-
// Unbranded: plain role layer via the string hook — core keeps its own core/role.base section identity,
|
|
80
|
-
// and the reference-equality bench-parity tests keep comparing the exact core constant.
|
|
81
22
|
if (!brand) {
|
|
82
23
|
return { stableSystem: (ctx) => roleBase(ctx) };
|
|
83
24
|
}
|
|
84
|
-
// Branded: same M14 typed form as semaIdentityProvider (identity slot = role-layer replacement with the
|
|
85
|
-
// brand line on top; the base under the brand follows the SAME profile fork — the brand overlay is the
|
|
86
|
-
// legal divergence ([1134] 宪法二类), the base stays core-owned bytes).
|
|
87
25
|
return {
|
|
88
26
|
stableBlocks: (ctx) => [
|
|
89
27
|
{ id: "sema/identity", slot: "identity", text: `${SEMA_IDENTITY}\n\n${roleBase(ctx)}` },
|
|
90
28
|
],
|
|
91
29
|
};
|
|
92
30
|
}
|
|
93
|
-
// [2400] CAPS-OPS-11:autonomousPromptProvider 别名导出已随场景退役删除(真身=codePromptProvider)。
|
|
94
|
-
// 其 `@deprecated` JSDoc 曾残留于此,被 tsc 误挂到下方 buildScenarios(三处调用点全告 deprecated
|
|
95
|
-
// ——TODO-3 立案的「迁移」实为孤儿注释,随删除清账;buildScenarios 本身非退役面)。
|
|
96
|
-
/** #196 唯一取用口:场景按自己的判别位取子任务 Runner。场景体内一律不直接摸 `deps.subRunner` /
|
|
97
|
-
* `deps.handslessSubRunner` —— 两处各挑一次就是漂移的成因,判别位必须是唯一开关。 */
|
|
98
31
|
function subRunnerFor(deps, hands) {
|
|
99
32
|
return pickHandsRunner(hands, { full: deps.subRunner, handsless: deps.handslessSubRunner });
|
|
100
33
|
}
|
|
101
34
|
export function buildScenarios(deps) {
|
|
102
|
-
// The default scenario filters skills by "default" — NOT by req.scenario (which may be an unknown name
|
|
103
|
-
// that fell back here): the bundle must be a coherent "default" set, matching how main.ts resolves an
|
|
104
|
-
// unknown scenario to "default" for tools/prompt/mcp too (council finding — else default-tagged drop).
|
|
105
|
-
// 抽成具名工厂:`code` 直接复用它取 bundle(工具/技能面与 default 恒等由构造保证,不靠两处
|
|
106
|
-
// 各写一份 assembleCodeTools 参数再祈祷不漂移)。
|
|
107
35
|
const defaultScenario = (req, _principal, ctx) => {
|
|
108
|
-
// gap-audit rank-1 BLOCKER: the default agent is the CC agent loop — it MUST have the
|
|
109
|
-
// full-body roster, not just nowTool. core's `assembleCodeTools` (1.161) ships TodoWrite (planning) +
|
|
110
|
-
// the subagent/Task delegation tool (runs on the sub-runner, child ⊆ parent — no escalation) + WebFetch.
|
|
111
|
-
// 🔒 WebFetch is GATED OUT on a multi-tenant deployment (REQUIRE_PRINCIPAL): allowHosts is unset = all PUBLIC,
|
|
112
|
-
// and core says a multi-tenant deployment MUST allowlist (an injected tenant model could exfil via an
|
|
113
|
-
// arbitrary public URL — the SSRF floor only blocks INTERNAL). Single-user TOC keeps it (the user's own box).
|
|
114
|
-
// WebSearch backend resolution: a per-request `body.settings.webSearch` (the user's shell settings) WINS, but
|
|
115
|
-
// ONLY on the single-user host lane (a per-request endpoint/key is a capability config — on multi-tenant a tenant
|
|
116
|
-
// could SSRF via a `searxng` URL pointed at an internal host, so multi-tenant uses ONLY the deployment-env
|
|
117
|
-
// `deps.webSearch`; design/107 axis, mirrors settings.env). Absent both ⇒ WebSearch not assembled (core ships none).
|
|
118
36
|
const reqWebSearch = deps.requirePrincipal !== true
|
|
119
37
|
? webSearchConfigFromSettings(req?.settings?.webSearch)
|
|
120
38
|
: undefined;
|
|
@@ -123,43 +41,13 @@ export function buildScenarios(deps) {
|
|
|
123
41
|
tools: [
|
|
124
42
|
nowTool(),
|
|
125
43
|
...assembleCodeTools({
|
|
126
|
-
// [1900]/[1904]:WebFetch 摘要缝——键在场才铸(负控=修前字节形)。
|
|
127
44
|
...(deps.webFetchSummarize ? { webFetch: { summarize: deps.webFetchSummarize } } : {}),
|
|
128
|
-
// CC 201 parity: CC 201 makes the two planning families MUTUALLY
|
|
129
|
-
// EXCLUSIVE — with TodoV2 (the Task trio) enabled, TodoWriteTool.isEnabled returns false and the
|
|
130
|
-
// interactive model sees ONE family (TodoWrite survives only as an SDK/non-interactive compat slot).
|
|
131
|
-
// Both-on was the CC 198 posture (live-caught cost: the model wastes a turn comparing the two tools
|
|
132
|
-
// and juggles duplicate state). taskList:true below ⇒ TodoWrite OFF.
|
|
133
45
|
todoWrite: false,
|
|
134
|
-
// core 1.215 (design/119): the structured task-list family (TaskCreate/TaskGet/TaskUpdate/TaskList —
|
|
135
|
-
// stable ids, status transitions, dependencies); core defaults it OFF, the full-body deployment opts
|
|
136
|
-
// in. Under CC 201 this family is the ONLY planning leg (see todoWrite above).
|
|
137
46
|
taskList: true,
|
|
138
|
-
// #318([4659] F2 → [4692] 定谳):**会话级**清单店。缺这一键时 core 落
|
|
139
|
-
// `store ?? createMemoryTaskListStore()` 的私有 per-run 臂,而本工厂是**每请求**调用的
|
|
140
|
-
// (resolve-spec 的 selectScenario;resume 同链重解析)⇒ 同一会话每 turn 一只新店:
|
|
141
|
-
// TaskList 中途报空、TaskCreate 从 #1 重铸号,已发给用户的任务回执从此指向别的任务。
|
|
142
|
-
// 分区键 = 会话(同 session 跨 turn/跨 resume 连续,跨 session 互不可见);sessionId 只从
|
|
143
|
-
// 鉴权解析的 {@link ScenarioContext} 取,绝不从 req(= 调用方自报的 body)取。
|
|
144
|
-
// 无 sessionId 的调用形(parkedReviveTool 的裸 Agent 取用、能力详情探针)整键省略 ⇒
|
|
145
|
-
// per-call 私店 = 修前字节形(那两条腿都不消费 task-list 家族)。
|
|
146
47
|
...(ctx?.sessionId !== undefined && deps.taskListStoreFor
|
|
147
48
|
? { taskListStore: deps.taskListStoreFor(ctx.sessionId) }
|
|
148
49
|
: {}),
|
|
149
|
-
// core 1.206 (design/115 P3): `background` exposes CC's `run_in_background` on the Agent tool — the
|
|
150
|
-
// child runs async under an `a*` task id (TaskOutput/TaskStop; ONE "later" completion notification;
|
|
151
|
-
// parent teardown aborts orphans). Same trust envelope as the sync path (child ⊆ parent roster, same
|
|
152
|
-
// rights) — only the scheduling is async, so no posture gate. owner/scope: core 1.365 BREAKING 升必填,
|
|
153
|
-
// 但 core 仍 ctx-first(subagent.js `ctx.taskId ?? bg.owner` / `ctx.principal ?? bg.scope`)——引擎链
|
|
154
|
-
// 每 spawn 恒带 ctx.taskId,这里的值是类型要求的兜底:scope="default" 与引擎链 `principal ?? "default"`
|
|
155
|
-
// 同词([1509] 单租户拼法);owner 哨兵在 ctx.taskId 缺席的病态窗把行锚到无人可匹配的键(fail-closed
|
|
156
|
-
// 方向,default-deny 谓词下不可读,绝不放大)。
|
|
157
|
-
// core 1.364 agentStore = durable 写半场,与 RunnerDeps.backgroundAgentStore 同实例(deps 注入)。
|
|
158
|
-
// core 1.382 checkpointStore/ensureChildSessionDurable = design/153 parked 状态机的「同车必接」
|
|
159
|
-
// 一对([1561] 提货单①②,ScenarioDeps 字段注释详述);两者任一缺席 = 净是 pre-153 行为。
|
|
160
50
|
subagent: {
|
|
161
|
-
// #196:default/code 的委派子代**要**手(CC parity;main.ts subRunner 注里那条 "subagent
|
|
162
|
-
// couldn't run pwd" 缺陷就是这条腿缺手),故按本场景判别位取 full 支。
|
|
163
51
|
runner: subRunnerFor(deps, "full"),
|
|
164
52
|
background: {
|
|
165
53
|
registry: defaultTaskRegistry,
|
|
@@ -169,57 +57,26 @@ export function buildScenarios(deps) {
|
|
|
169
57
|
...(deps.checkpointStore ? { checkpointStore: deps.checkpointStore } : {}),
|
|
170
58
|
...(deps.ensureChildSessionDurable ? { ensureChildSessionDurable: deps.ensureChildSessionDurable } : {}),
|
|
171
59
|
},
|
|
172
|
-
// core 1.287 extraTools seam ([795]/[802]③): per-spawn dynamic tool injection (SendUserFile
|
|
173
|
-
// reaches the delegated-child roster; product still goes through resolveToolSubset).
|
|
174
60
|
...(deps.subagentExtraTools ? { extraTools: deps.subagentExtraTools } : {}),
|
|
175
|
-
// 历史复审轴B #3(1.254):extraTools 工厂 throw 的错误 sink——core 契约「absent ⇒ dropped after
|
|
176
|
-
// the generic disclosure」= 部署日志零痕迹,只剩模型面固定 note。接 warn 让故障可观测。
|
|
177
61
|
...(deps.subagentExtraTools && deps.logger
|
|
178
62
|
? { onExtraToolsError: (err, info) => deps.logger?.warn?.("subagent_extra_tools_error", { ...info, err: err instanceof Error ? err.message : String(err) }) }
|
|
179
63
|
: {}),
|
|
180
64
|
},
|
|
181
65
|
...(webSearch ? { webSearch } : {}),
|
|
182
|
-
// A-033.1(#256):工具名取 core 的 `WEB_FETCH_TOOL_NAME` 而不是裸串 —— 这是**多租户闸**
|
|
183
|
-
// (allowHosts 未设 = 全公网可达 ⇒ 一个租户能把另一个租户的内网可达面当出口)。core 改名该工具时,
|
|
184
|
-
// 裸串比对恒不相等,闸门整条不生效且零症状:名单里照样挂着一只全公网 WebFetch。
|
|
185
66
|
}).filter((t) => t.name !== WEB_FETCH_TOOL_NAME || deps.requirePrincipal !== true),
|
|
186
67
|
],
|
|
187
|
-
// default/code 是手带并集的**故意消费者**(上方 rank-1 BLOCKER 注:CC agent loop MUST have the
|
|
188
|
-
// full-body roster)——#196 判别位在这里表态 full,收窄只落在声明了 none 的场景上。
|
|
189
68
|
hands: "full",
|
|
190
69
|
skills: skillsForScenario(deps.skills, "default"),
|
|
191
|
-
// Local/TOC deployment brands the neutral default scenario as Sema (so the local engine answers "who
|
|
192
|
-
// are you" as Sema, not the model's hallucinated identity). Cloud leaves it neutral unless opted in.
|
|
193
70
|
...(deps.brandIdentity ? { promptProvider: semaIdentityProvider() } : {}),
|
|
194
71
|
};
|
|
195
72
|
};
|
|
196
73
|
return {
|
|
197
74
|
default: defaultScenario,
|
|
198
|
-
// [849]→[891] code(原名 autonomous,clay 裁定改名+persona×终验解耦):与 default 完全同 roster
|
|
199
|
-
// (full-body 工具面 + default 技能面原样复用,连 WebFetch 多租户闸/WebSearch 装配都跟着 default
|
|
200
|
-
// 工厂走),只换一轴——role 基底 = core CODE_SYSTEM_PROMPT(CC 编码 persona 蒸馏版,见
|
|
201
|
-
// codePromptProvider)。**不再定死 finalVerification**([891] 解耦:终验是无人值守运行模式旋钮,
|
|
202
|
-
// caller 显式声明,交互态不多烧终验轮)。这是 [891] 起的出厂缺省场景(config DEFAULT_SCENARIO
|
|
203
|
-
// 缺省 "code")——编码产品出厂态对标 CC 出厂态;通用域中性 persona 的 default 保留为显式可选。
|
|
204
|
-
// 刻意走内建、不走 center overlay:overlay 已无 prompt 通道([1053] ScenarioEntry.prompt 直删,场景级提示词=center prompts binding)。
|
|
205
|
-
// #318:`ctx` 必须原样转给 default 工厂 —— 漏转 = 出厂缺省场景(DEFAULT_SCENARIO 缺省即 code)
|
|
206
|
-
// 拿不到会话级清单店,F2 在最常用的那条腿上原地复活([4659] 症状③ 钉的就是这一格)。
|
|
207
75
|
code: (req, principal, ctx) => ({
|
|
208
76
|
...defaultScenario(req, principal, ctx),
|
|
209
77
|
promptProvider: codePromptProvider(deps.brandIdentity === true),
|
|
210
78
|
}),
|
|
211
|
-
// [891]→[2400] CAPS-OPS-11(clay 裁 2026-08-03,不留任何过渡):`autonomous` 过渡 alias 已退役。
|
|
212
|
-
// body 显式传它 ⇒ 5.1.0 起的 scenario_unknown 400 响亮拒(附现役词表);旧语义迁移形=
|
|
213
|
-
// scenario:"code" + body.finalVerification:true(终验自此=纯 caller 显式旋钮,场景层无定死)。
|
|
214
79
|
"code-review": (req) => codeReview(deps, req),
|
|
215
|
-
// Neutral repo-readonly scenario (OA ask): the SAME clone-free read-only repo tools as code-review
|
|
216
|
-
// (repo_tree / repo_read_file / repo_pull_diff over GIT_API_TOKEN) with NO promptProvider — the
|
|
217
|
-
// objective and the center-distributed skills own the output contract. The reviewer framing was
|
|
218
|
-
// never a security control (the boundary is the token's scope + the read-only tool set); it only
|
|
219
|
-
// fought skill-driven outputs (live: oa-repo-scan loaded but the lead still wrote a review).
|
|
220
|
-
// Deliberately NOT the alternative "let a scenario-targeted skill override promptProvider": that
|
|
221
|
-
// would let runtime-distributed content rewrite the deployment-pinned system prompt and break the
|
|
222
|
-
// stablePrompt STABLE→VARIABLE prefix-cache discipline (design/12/17).
|
|
223
80
|
scan: (req) => {
|
|
224
81
|
const repoClient = requireRepoClient(deps, "scan");
|
|
225
82
|
if (typeof req.repo !== "string" || !req.repo.trim()) {
|
|
@@ -227,28 +84,18 @@ export function buildScenarios(deps) {
|
|
|
227
84
|
}
|
|
228
85
|
return {
|
|
229
86
|
tools: [...repoToolsFor(repoClient, parseRepo(req.repo)), nowTool()],
|
|
230
|
-
// #196:头注的「工具集即边界」自此在**最终 roster** 上成立(修前 core 把手带 band 并集进来,
|
|
231
|
-
// clone-free 承诺只存在于这份声明里)。
|
|
232
87
|
hands: "none",
|
|
233
88
|
skills: skillsForScenario(deps.skills, "scan"),
|
|
234
89
|
};
|
|
235
90
|
},
|
|
236
|
-
// Multi-agent DISCUSSION (#273 / C-R14 改名,旧名 `team` = 入口 alias 一版,见 {@link SCENARIO_ALIASES}):
|
|
237
|
-
// pick a template, the consumer (OA) injects business context, we run it. Templates resolve from the
|
|
238
|
-
// live registry (`getTeam`) = BUILTIN_TEAMS overridden/extended by the sema registry at runtime
|
|
239
|
-
// (applyEffective → registerTeams), so the roster is config-driven; built-ins are the fallback when
|
|
240
|
-
// the center supplies none. ⚠️ 模板注册面(`req.team` / center `teams` 键 / registry TEAMS.md)刻意
|
|
241
|
-
// **不**改名:那是 registry-core 的配置词汇(跨仓契约),改它要另立件+center 侧同款 alias;C-R14 的
|
|
242
|
-
// server 射程 = 场景名/工具名/模型可见文案三件([4127] 认领形)。
|
|
243
91
|
discuss: (req) => {
|
|
244
92
|
const name = typeof req.team === "string" ? req.team : "default";
|
|
245
|
-
const template = getTeam(name);
|
|
93
|
+
const template = getTeam(name);
|
|
246
94
|
if (!template) {
|
|
247
95
|
throw new HttpError(404, `unknown discussion roster "${name}" (available: ${teamNames().join(", ")})`);
|
|
248
96
|
}
|
|
249
97
|
const objective = typeof req.objective === "string" ? req.objective : "Discuss the task.";
|
|
250
98
|
const businessContext = typeof req.businessContext === "string" ? req.businessContext : undefined;
|
|
251
|
-
// #196:成员/synthesizer 是纯讨论人格(模板声明零工具),跑在无手 subRunner 上。
|
|
252
99
|
const hands = "none";
|
|
253
100
|
return {
|
|
254
101
|
tools: createDiscussionTools(subRunnerFor(deps, hands), template, { objective, businessContext, ...(deps.logger ? { logger: deps.logger } : {}) }),
|
|
@@ -259,39 +106,26 @@ export function buildScenarios(deps) {
|
|
|
259
106
|
},
|
|
260
107
|
};
|
|
261
108
|
}
|
|
262
|
-
/** Resolve the scenario for a request (falls back to `default`). */
|
|
263
109
|
export function selectScenario(scenarios, name) {
|
|
264
|
-
|
|
265
|
-
// 对它们是**幂等**的;真正需要这一手的是**库面**调用方(index.ts 导出 selectScenario,嵌入式装配
|
|
266
|
-
// 自己传名字)—— 不归一的话旧名会静默落 `default`,那是比「名字过时」更坏的结果(整套工具面换人)。
|
|
267
|
-
const resolved = name === undefined ? undefined : canonicalScenarioName(name, Object.keys(scenarios));
|
|
268
|
-
// #193 P2-13:own-property 守卫——`Record` 字面量的裸索引对原型链键("constructor" 形状)会把
|
|
269
|
-
// Object.prototype 上的函数当 Scenario 返回。上游 resolve-spec 按 Object.keys 校验 ⇒ 当前不可利用,
|
|
270
|
-
// 本守卫是纵深防御(本函数是导出面,不得依赖单一调用方的入口校验)。
|
|
110
|
+
const resolved = name;
|
|
271
111
|
return (resolved && Object.hasOwn(scenarios, resolved) && scenarios[resolved]) || scenarios.default;
|
|
272
112
|
}
|
|
273
|
-
/** 把属主的判别式摊平成 wire 上的两个键(可用臂整键省略原因,契约=「缺席即没有理由」)。 */
|
|
274
113
|
function availabilityFields(deps, toolset) {
|
|
275
114
|
const verdict = scenarioAvailability(deps, toolset);
|
|
276
115
|
return verdict.available ? { available: true } : { available: false, unavailableReason: verdict.reason };
|
|
277
116
|
}
|
|
278
|
-
/** 内建五场景详情。default/code/discuss 工厂对良性请求无副作用可真调(拿真实工具名单);code-review/scan 是
|
|
279
|
-
* fail-loud 语义(缺 GIT_API 配置/principal 即 throw)→ 探针失败落静态表兜底(表↔工厂一致性由测试锁:
|
|
280
|
-
* 测试喂 fake deps 真调工厂对账工具名)。enabled 对内建恒 true(约定②)。 */
|
|
281
117
|
export function builtinScenarioDetails(scenarios, deps) {
|
|
282
118
|
const probe = (name, req, principal, fallback) => {
|
|
283
119
|
try {
|
|
284
|
-
return ((Object.hasOwn(scenarios, name) ? scenarios[name] : undefined)?.(req, principal)?.tools ?? []).map((t) => t.name);
|
|
120
|
+
return ((Object.hasOwn(scenarios, name) ? scenarios[name] : undefined)?.(req, principal)?.tools ?? []).map((t) => t.name);
|
|
285
121
|
}
|
|
286
122
|
catch {
|
|
287
|
-
return fallback;
|
|
123
|
+
return fallback;
|
|
288
124
|
}
|
|
289
125
|
};
|
|
290
126
|
const REPO_TOOLS = ["repo_tree", "repo_read_file", "repo_pull_diff", "Now"];
|
|
291
127
|
const mk = (name, summary, toolset, tools, promptSummary) => ({
|
|
292
128
|
name, source: "builtin", builtin: true, summary, toolset, tools, promptSummary, enabled: true,
|
|
293
|
-
// [C132]:可用性与上面的静态回退表分家 —— 回退表答的是「工具面长什么样」(缺配置时也照画),
|
|
294
|
-
// 这两个键答的是「现在点下去会不会 501」。同一份属主判据,内建与 center 两条产线共用。
|
|
295
129
|
...availabilityFields(deps, toolset),
|
|
296
130
|
});
|
|
297
131
|
return {
|
|
@@ -301,13 +135,9 @@ export function builtinScenarioDetails(scenarios, deps) {
|
|
|
301
135
|
default: mk("default", "通用/助理场景(域中性 persona,CC agent loop 全量工具面;[891] 起非出厂缺省,显式可选)", "full-body", probe("default", {}, undefined, ["Now"]), deps.brandIdentity ? "Sema 产品身份 + core 默认宪法(结构层由引擎合成)" : "core 默认宪法(中性,无场景附加 persona)"),
|
|
302
136
|
"code-review": mk("code-review", "代码评审(clone-free 只读仓库工具;council=true 升多镜头评审团)", "repo-readonly", probe("code-review", { repo: "probe/probe" }, undefined, REPO_TOOLS), "评审员/评审团协调提示词(镜头分工+产出契约)"),
|
|
303
137
|
scan: mk("scan", "中性只读仓库扫描(输出契约由 objective+skills 决定)", "repo-readonly", probe("scan", { repo: "probe/probe" }, undefined, REPO_TOOLS), "无场景附加提示词(objective+center skills 拥有输出契约)"),
|
|
304
|
-
|
|
305
|
-
// 列举面只列现役主名,免得消费方把别名当成第二条能力画上去。
|
|
306
|
-
discuss: mk("discuss", "多智能体讨论圆桌(模板成员+synthesizer,模板可由 registry 配置)", "discuss", probe("discuss", {}, undefined, ["run_discussion", "run_team"]), "讨论协调者提示词(圆桌纪律+合成流程)"),
|
|
138
|
+
discuss: mk("discuss", "多智能体讨论圆桌(模板成员+synthesizer,模板可由 registry 配置)", "discuss", probe("discuss", {}, undefined, ["run_discussion"]), "讨论协调者提示词(圆桌纪律+合成流程)"),
|
|
307
139
|
};
|
|
308
140
|
}
|
|
309
|
-
/** center 条目详情(有效性判定与 centerScenarios 完全同款:无效条目既不进 overlay 也不进详情——
|
|
310
|
-
* 保证约定①「详情显示的来源=运行实际用的定义」永不错位)。 */
|
|
311
141
|
export function centerScenarioDetails(specs, builtinNames, deps) {
|
|
312
142
|
const out = {};
|
|
313
143
|
for (const spec of specs ?? []) {
|
|
@@ -315,23 +145,17 @@ export function centerScenarioDetails(specs, builtinNames, deps) {
|
|
|
315
145
|
continue;
|
|
316
146
|
if (typeof spec.name !== "string" || !SCENARIO_NAME_RE.test(spec.name))
|
|
317
147
|
continue;
|
|
318
|
-
if (Object.hasOwn(SCENARIO_ALIASES, spec.name))
|
|
319
|
-
continue; // #273:保留名与 centerScenarios 同判(约定①)
|
|
320
148
|
if (!Object.hasOwn(TOOLSETS, spec.toolset) || !TOOLSETS[spec.toolset])
|
|
321
|
-
continue;
|
|
149
|
+
continue;
|
|
322
150
|
out[spec.name] = {
|
|
323
151
|
name: spec.name,
|
|
324
152
|
source: "center",
|
|
325
153
|
builtin: builtinNames.includes(spec.name),
|
|
326
|
-
summary: "",
|
|
154
|
+
summary: "",
|
|
327
155
|
toolset: spec.toolset,
|
|
328
156
|
tools: spec.toolset === "repo-readonly" ? ["repo_tree", "repo_read_file", "repo_pull_diff", "Now"] : ["Now"],
|
|
329
|
-
// [1053] ScenarioEntry.prompt 已删(scenario 级提示词=center prompts binding 单入口)——center 条目
|
|
330
|
-
// 恒空串;字段本身保留(builtin 条目仍有真值,wire 形不变)。
|
|
331
157
|
promptSummary: "",
|
|
332
158
|
enabled: true,
|
|
333
|
-
// [C132]:center 声明的 repo 型场景与内建的 scan/code-review 受**同一份**判据管辖
|
|
334
|
-
// ——overlay 不是判据的第二属主。
|
|
335
159
|
...availabilityFields(deps, spec.toolset),
|
|
336
160
|
};
|
|
337
161
|
}
|
|
@@ -352,47 +176,28 @@ const TOOLSETS = {
|
|
|
352
176
|
},
|
|
353
177
|
};
|
|
354
178
|
const SCENARIO_AVAILABLE = { available: true };
|
|
355
|
-
/**
|
|
356
|
-
* 🔴 场景可用性的**唯一属主**。列举面(`ScenarioDetail.available` / `unavailableReason`)与请求面
|
|
357
|
-
* ({@link requireRepoClient} 的 501 拒绝臂,三处调用点)都只从这里取值——两处各写一份就是本仓反复
|
|
358
|
-
* 吃过的「同一语义两个属主」病:判据一漂,列举面开始说谎而没人先红。一致性由 capabilities.test 的
|
|
359
|
-
* **对表格**逐名钉住(`available:false` ⟺ 良性请求真吃 501),而不是靠这段注释。
|
|
360
|
-
*
|
|
361
|
-
* 判据键 = **toolset**:内建详情与 center 条目都带这个字段,故两条产线天然共用同一份判据。
|
|
362
|
-
* `requiresRepo` 的 toolset 需要部署配好 git 后端(`GIT_API_BASEURL` ⇒ `deps.repoClient`)。
|
|
363
|
-
* 词表外的 toolset(内建的 `full-body`/`discuss`)不依赖后端 ⇒ 恒可用。
|
|
364
|
-
*/
|
|
365
179
|
export function scenarioAvailability(deps, toolset) {
|
|
366
|
-
if (Object.hasOwn(TOOLSETS, toolset) && TOOLSETS[toolset]?.requiresRepo === true && deps.repoClient === undefined) {
|
|
180
|
+
if (Object.hasOwn(TOOLSETS, toolset) && TOOLSETS[toolset]?.requiresRepo === true && deps.repoClient === undefined) {
|
|
367
181
|
return { available: false, reason: "git_client_unconfigured" };
|
|
368
182
|
}
|
|
369
183
|
return SCENARIO_AVAILABLE;
|
|
370
184
|
}
|
|
371
|
-
/** 拒绝文案的唯一属主:闭集穷举 switch(新增原因词不在这里表态即编译红)。 */
|
|
372
185
|
export function scenarioUnavailableMessage(reason, scenarioLabel) {
|
|
373
186
|
switch (reason) {
|
|
374
187
|
case "git_client_unconfigured":
|
|
375
188
|
return `${scenarioLabel} scenario needs GIT_API_BASEURL configured`;
|
|
376
189
|
}
|
|
377
190
|
}
|
|
378
|
-
/** repo 型场景取 git 客户端的唯一口(三处场景工厂同源)。不可用 ⇒ 按属主给的原因与文案 501 响亮拒。 */
|
|
379
191
|
function requireRepoClient(deps, scenarioLabel) {
|
|
380
192
|
const client = deps.repoClient;
|
|
381
193
|
if (client !== undefined)
|
|
382
194
|
return client;
|
|
383
195
|
const verdict = scenarioAvailability(deps, "repo-readonly");
|
|
384
|
-
// 判成 available 却没有客户端 = 属主与消费面脱钩(对表格会先红)。此处仍 fail-loud,不静默放行。
|
|
385
196
|
throw new HttpError(501, verdict.available
|
|
386
197
|
? `${scenarioLabel} scenario has no repo client although the availability owner reports it available (wiring defect)`
|
|
387
198
|
: scenarioUnavailableMessage(verdict.reason, scenarioLabel));
|
|
388
199
|
}
|
|
389
200
|
export const SCENARIO_NAME_RE = /^[a-z][a-z0-9-]{1,31}$/;
|
|
390
|
-
// ([1053] registry-core 0.10.15:SCENARIO_PROMPT_MAX 随 ScenarioEntry.prompt 一并退役)
|
|
391
|
-
/**
|
|
392
|
-
* Build the center-declared scenario overlay. Invalid specs are SKIPPED with a warning (never fail
|
|
393
|
-
* boot — same posture as skills/teams); valid ones become scenarios keyed by name, ready to be merged
|
|
394
|
-
* OVER the built-ins (center wins). Returns the overlay plus which built-in names it shadows.
|
|
395
|
-
*/
|
|
396
201
|
export function centerScenarios(deps, specs, builtinNames, logger) {
|
|
397
202
|
const overlay = {};
|
|
398
203
|
const shadows = [];
|
|
@@ -403,30 +208,15 @@ export function centerScenarios(deps, specs, builtinNames, logger) {
|
|
|
403
208
|
logger?.warn("sema_registry_scenario_invalid", { name: String(spec?.name), reason: "name must match " + String(SCENARIO_NAME_RE) });
|
|
404
209
|
continue;
|
|
405
210
|
}
|
|
406
|
-
|
|
407
|
-
// 一条场景会立刻造出两个属主:请求面归它、而按场景键的运维配置(skills/mcp/a2a/prompts 的旧名
|
|
408
|
-
// 标签)在 alias 窗里同时也算 `discuss` 的,于是那条影子场景的 MCP/A2A(工具面+egress 面)会静默
|
|
409
|
-
// 漏进 discuss 的 roster(codex 对抗复审 [high],验真后采纳)。二义在源头掐掉,并且**响亮**跳过
|
|
410
|
-
// ——静默跳过等于让运维以为声明生效了。窗撤销时随 SCENARIO_ALIASES 一起消失。
|
|
411
|
-
if (Object.hasOwn(SCENARIO_ALIASES, spec.name)) {
|
|
412
|
-
logger?.warn("sema_registry_scenario_invalid", {
|
|
413
|
-
name: spec.name,
|
|
414
|
-
reason: `"${spec.name}" is a RESERVED deprecated scenario alias during the rename window — it resolves to "${SCENARIO_ALIASES[spec.name]}". Declare this scenario under a different name.`,
|
|
415
|
-
});
|
|
416
|
-
continue;
|
|
417
|
-
}
|
|
418
|
-
const toolset = Object.hasOwn(TOOLSETS, spec.toolset) ? TOOLSETS[spec.toolset] : undefined; // P2-13 同族守卫
|
|
211
|
+
const toolset = Object.hasOwn(TOOLSETS, spec.toolset) ? TOOLSETS[spec.toolset] : undefined;
|
|
419
212
|
if (!toolset) {
|
|
420
213
|
logger?.warn("sema_registry_scenario_invalid", { name: spec.name, reason: `unknown toolset "${String(spec.toolset)}" (have: ${Object.keys(TOOLSETS).join(", ")})` });
|
|
421
214
|
continue;
|
|
422
215
|
}
|
|
423
|
-
// [1053] registry-core 0.10.15:ScenarioEntry.prompt 直删(clay 亲裁)——center 场景的提示词通道收敛为
|
|
424
|
-
// center prompts binding(scenario 维,[1050]①a/[1051]③a);overlay 只组装工具面+技能面,提示词由投影腿
|
|
425
|
-
// (effective 声明数组→core stableBlocks,[1054]③ 已认领)在 binding 落地后统一承载。
|
|
426
216
|
const name = spec.name;
|
|
427
217
|
overlay[name] = (req) => ({
|
|
428
218
|
tools: toolset.build(deps, req),
|
|
429
|
-
hands: toolset.hands,
|
|
219
|
+
hands: toolset.hands,
|
|
430
220
|
skills: skillsForScenario(deps.skills, name),
|
|
431
221
|
});
|
|
432
222
|
if (builtinNames.includes(name))
|
|
@@ -443,34 +233,19 @@ function codeReview(deps, req) {
|
|
|
443
233
|
const repoTools = repoToolsFor(repoClient, coords);
|
|
444
234
|
const skills = skillsForScenario(deps.skills, "code-review");
|
|
445
235
|
const objective = typeof req.objective === "string" ? req.objective : "Review this repository.";
|
|
446
|
-
// Tiering: `council: true` runs the multi-lens council (L1 parallel lenses + L3 arbiter) — for
|
|
447
|
-
// high-value/whole-repo review (~15× tokens). Default = the lead reviews the in-scope files DIRECTLY
|
|
448
|
-
// (cheap, reliable, finishes fast). A live run showed the model self-orchestrates unreliably, so for
|
|
449
|
-
// review (a KNOWN decomposition) the subagent fan-out is CODE-driven here, not left to the model
|
|
450
|
-
// (deterministic + cheaper + cacheable; see design/35). For OPEN-ENDED tasks where the decomposition
|
|
451
|
-
// isn't known, core's `createSubagentTool` (model-driven self-delegation, with maxDepth / isolated
|
|
452
|
-
// context / compressed-report guardrails) is the right tool — wire it in a dedicated scenario then.
|
|
453
|
-
// #196:两条腿(直评 / council)都声明 none —— 直评腿的 lead 只读仓库工具,council 腿的 lead 只调
|
|
454
|
-
// run_council;lens/arbiter 子任务同样只读仓库,故 council 工具拿无手 subRunner。
|
|
455
236
|
const hands = "none";
|
|
456
|
-
// [C143]:lenses 非 number 形响亮拒——此前 string[]/任意形静默滑过(typeof 门恒 false 整键落空),
|
|
457
|
-
// client-core 0.22.0 曾按想象契约钉 string[],用户发出的键被静默吞([C142] web-client wire 实证)。
|
|
458
|
-
// 与 (a) 案(client-core 改 number)对齐后客户端不会再发该形;本 400 是防第三方直调的纵深。
|
|
459
237
|
if (req.lenses !== undefined && typeof req.lenses !== "number") {
|
|
460
238
|
throw new HttpError(400, "lenses must be a number (council lens COUNT, 1-6) — a named lens subset is not a request-level knob", { code: "request.field_invalid" });
|
|
461
239
|
}
|
|
462
240
|
if (req.council === true) {
|
|
463
|
-
const rounds = clampRounds(req.rounds);
|
|
241
|
+
const rounds = clampRounds(req.rounds);
|
|
464
242
|
return {
|
|
465
243
|
tools: [
|
|
466
244
|
createCouncilTool(subRunnerFor(deps, hands), repoTools, objective, {
|
|
467
245
|
metrics: deps.metrics,
|
|
468
246
|
logger: deps.logger,
|
|
469
|
-
debate: req.debate === true,
|
|
470
|
-
// OA cost/coverage dial: an optional structured lens COUNT (clamped to [1,6] + NaN-guarded in pickLenses;
|
|
471
|
-
// absent = all 6 → zero regression). Per-request, no restart — orthogonal to the lens MODEL (startup env).
|
|
247
|
+
debate: req.debate === true,
|
|
472
248
|
...(typeof req.lenses === "number" ? { lensCount: req.lenses } : {}),
|
|
473
|
-
// Caller-settable debate rounds (finite, clamped [1,3]; absent/NaN = default 1). Only when debate=true.
|
|
474
249
|
...(rounds !== undefined ? { rounds } : {}),
|
|
475
250
|
}),
|
|
476
251
|
],
|
|
@@ -479,31 +254,16 @@ function codeReview(deps, req) {
|
|
|
479
254
|
promptProvider: coordinatorPrompt,
|
|
480
255
|
};
|
|
481
256
|
}
|
|
482
|
-
// [C144]([3296]⑤ web-client 实证):直评腿补 nowTool 与 scan 对齐——此前真装配无 Now 而 capabilities
|
|
483
|
-
// 声明 fallback 表 REPO_TOOLS 含 Now(repoClient 缺席时 probe 落 fallback 多报一枚=声明/装配错位;
|
|
484
|
-
// scan 当年照本场景抄还多加了 Now)。对齐后 fallback 表自动变准,评审报告带时间戳同样合理。
|
|
485
257
|
return { tools: [...repoTools, nowTool()], hands, skills, promptProvider: directReviewerPrompt };
|
|
486
258
|
}
|
|
487
259
|
const reviewBody = "Produce ONE prioritized review: a short summary, then findings grouped by severity " +
|
|
488
260
|
"(blocker / major / minor), each with `path:line`, the problem, and a concrete fix. Cite real code — never invent files or symbols.";
|
|
489
|
-
// Each provider supplies ONLY its stable base; `stablePrompt` enforces STABLE→VARIABLE ordering
|
|
490
|
-
// (base, then userSystemPrompt, then per-user memoryBlock) so the prefix-cache discipline can't be
|
|
491
|
-
// got wrong by hand (design/12, design/17).
|
|
492
|
-
/** Default: the lead reads the in-scope files and reviews them directly. */
|
|
493
261
|
const directReviewerPrompt = stablePrompt("You are a senior code reviewer. Call repo_tree to map the repository, then repo_read_file to read " +
|
|
494
262
|
"the files in scope, then review them yourself. " +
|
|
495
263
|
reviewBody);
|
|
496
|
-
/** Council mode: the lead just runs the (code-driven) council tool and returns its result verbatim. */
|
|
497
264
|
const coordinatorPrompt = stablePrompt("You coordinate a code-review council. Call `run_council` exactly once (no arguments). When it " +
|
|
498
265
|
"returns the arbitrated review, output that review as your final answer VERBATIM — do not " +
|
|
499
266
|
"summarize, shorten, or rewrite it.");
|
|
500
|
-
/**
|
|
501
|
-
* Personalization seam: merge the caller's own skills AFTER the scenario's, with
|
|
502
|
-
* SCENARIO-WINS on a name clash — the security baseline (scenario/center skills) can never be shadowed
|
|
503
|
-
* by user content. Duplicate names within the user list keep the first. Clashes are logged for audit
|
|
504
|
-
* (silent drops would make "my skill didn't fire" undebuggable). Input is already shape/size-validated
|
|
505
|
-
* by the HTTP layer (validateUserSkills); this stays pure merge policy.
|
|
506
|
-
*/
|
|
507
267
|
export function mergeUserSkills(scenarioSkills, userSkills, logger) {
|
|
508
268
|
if (!userSkills || userSkills.length === 0)
|
|
509
269
|
return scenarioSkills;
|
|
@@ -515,52 +275,31 @@ export function mergeUserSkills(scenarioSkills, userSkills, logger) {
|
|
|
515
275
|
dropped.push(s.name);
|
|
516
276
|
continue;
|
|
517
277
|
}
|
|
518
|
-
reserved.add(s.name);
|
|
278
|
+
reserved.add(s.name);
|
|
519
279
|
out.push(s);
|
|
520
280
|
}
|
|
521
281
|
if (dropped.length > 0)
|
|
522
282
|
logger?.warn("user_skills_dropped", { reason: "name reserved by scenario (or duplicate)", names: dropped });
|
|
523
283
|
return out;
|
|
524
284
|
}
|
|
525
|
-
/**
|
|
526
|
-
* resolveSpec 的执法入口(指派为默认、body.scenario 可换但限 allowlist)。返回本请求的
|
|
527
|
-
* 生效场景名(未做 unknown→default 回退——那是 resolveSpec 既有职责,保持单点)。
|
|
528
|
-
*
|
|
529
|
-
* - body.scenario 显式给出:allowlist 非空且集外 ⇒ typed 拒绝(400 `scenario_not_allowed`,附 allowlist
|
|
530
|
-
* ——机器码归 wire、人话归壳/web);集内 ⇒ 用户主动切换赢。allowlist 为空(无 ruling / 该 principal
|
|
531
|
-
* 三层皆无指派 / caps 面故障)⇒ 无治理约束,现状放行(与「null 落兜底链」同一语义:分配面未覆盖 =
|
|
532
|
-
* 不收紧,恒不比没有治理时更宽;caps 故障不把用户锁死在 default——场景切换不是权限放大面,fail-open
|
|
533
|
-
* 到现状,与 workflows 面的 fail-closed 是刻意的 posture 差异,见 runtime-caps-resolver)。
|
|
534
|
-
* - body.scenario 未给:ruling 胜者 ⇒ 指派为默认;无胜者 ⇒ defaultScenario 现状链。
|
|
535
|
-
*/
|
|
536
285
|
export function gateScenarioRequest(ruling, bodyScenario, defaultScenario, known, logger) {
|
|
537
286
|
if (typeof bodyScenario === "string") {
|
|
538
|
-
|
|
539
|
-
// allowlist 门/返回值三者此后只谈主名。allowlist 一并归一——运维写的是旧名、调用方用新名(或反过来)
|
|
540
|
-
// 说的是**同一个能力**,窗内不许因为改名把人挡在门外。
|
|
541
|
-
const requested = canonicalScenarioName(bodyScenario, known, logger);
|
|
542
|
-
// [2395]D③(5.1.0):body 显式给出的**未知名**响亮 400——此前静默折 default(oa 退役后老调用方
|
|
543
|
-
// 无声换了场景=更宽工具面,与零兼容纲领相反)。词表面先于治理面:名字都不存在时谈不上 allowlist。
|
|
544
|
-
// 指派链(ruling/default)不在此验——悬空指派名仍走 resolveSpec 既有 unknown→default(runtime-caps
|
|
545
|
-
// 面的误配另案,不该让一次中心误配把每个请求 400 死)。
|
|
287
|
+
const requested = bodyScenario;
|
|
546
288
|
if (!known.includes(requested)) {
|
|
547
|
-
// 文案点名调用方**发的**那个名字(归一后的名字对他没有意义:他没发过它)。
|
|
548
289
|
throw new HttpError(400, `unknown scenario "${bodyScenario}" — this deployment's scenarios are: ${known.join(", ")}`, {
|
|
549
290
|
code: "scenario_unknown",
|
|
550
291
|
extra: { known: [...known] },
|
|
551
292
|
});
|
|
552
293
|
}
|
|
553
294
|
const allowed = ruling?.allowlist ?? [];
|
|
554
|
-
if (allowed.length > 0 && !allowed.
|
|
295
|
+
if (allowed.length > 0 && !allowed.includes(requested)) {
|
|
555
296
|
throw new HttpError(400, `scenario "${bodyScenario}" is not in this principal's assigned allowlist`, {
|
|
556
297
|
code: "scenario_not_allowed",
|
|
557
|
-
extra: { allowlist: allowed },
|
|
298
|
+
extra: { allowlist: allowed },
|
|
558
299
|
});
|
|
559
300
|
}
|
|
560
301
|
return requested;
|
|
561
302
|
}
|
|
562
|
-
|
|
563
|
-
// 旧名不归一就会落到 resolveSpec 的 unknown→default 回退上——静默换场景,正是本窗要避免的。
|
|
564
|
-
return canonicalScenarioName(ruling?.scenario ?? defaultScenario, known, logger);
|
|
303
|
+
return ruling?.scenario ?? defaultScenario;
|
|
565
304
|
}
|
|
566
305
|
//# sourceMappingURL=scenarios.js.map
|
|
@@ -1,35 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* RFC A2 (sema-internal server/docs/design/ENV-SELECT-AND-REGION-SOURCE.md) — the model-facing `SelectEnvironment` tool.
|
|
3
|
-
* A 切片先行;挂载路线 = RFC 判定②(a):deployment 经 `spec.tools` 注入(同 lsp/
|
|
4
|
-
* 自定义工具),core 收编等真用起来再谈。
|
|
5
|
-
*
|
|
6
|
-
* Backend = the EXISTING trusted admission chain, nothing new:
|
|
7
|
-
* - discovery: `ImageIndex.list({latestOnly, status:'published', viewer})` — the SAME per-principal
|
|
8
|
-
* visibility the `/v1/images/select` catalog applies (SQL-baked, never caller enumeration).
|
|
9
|
-
* - selection: `resolveSandboxImageRef` (fail-closed profile→digest re-admission).
|
|
10
|
-
* - binding: a session-keyed PROFILE (intent — never a digest) the next task's resolveSpec re-resolves
|
|
11
|
-
* FAIL-CLOSED, exactly like a body-supplied `sandboxImageProfile`. Storing the profile (not the ref)
|
|
12
|
-
* keeps the re-admit discipline intact: every task re-resolves LIVE, a stale digest can never ride a
|
|
13
|
-
* session binding past admission.
|
|
14
|
-
*
|
|
15
|
-
* Boundary contract (verbatim in the tool's model-facing note): a binding change takes
|
|
16
|
-
* effect ONLY at a task boundary; any child (including design/129 session-scoped background children)
|
|
17
|
-
* inherits the binding at its spawn moment and never drifts mid-flight. This tool therefore only writes
|
|
18
|
-
* the session-profile store — the RUNNING task's sandbox is untouched.
|
|
19
|
-
*
|
|
20
|
-
* 409-style self-correction: a failed selection returns `missing` + the viewer-visible catalog
|
|
21
|
-
* (tenant-neutral profile names only — the list enters model context).
|
|
22
|
-
*/
|
|
23
1
|
import { Type } from "typebox";
|
|
24
2
|
import { BoundedSessionMap } from "../bounded-session-map.js";
|
|
25
3
|
import { resolveSandboxImageRef } from "../per-task-image.js";
|
|
26
|
-
/** Session-keyed selected PROFILE (intent). Mirrors PerTaskImageRegistry's bounded-eviction shape, but holds
|
|
27
|
-
* the profile string so every subsequent task re-resolves fail-closed (re-admit discipline). In-memory —
|
|
28
|
-
* honest v1 boundary: a worker restart drops the selection (the model can re-select; nothing fails closed
|
|
29
|
-
* the wrong way, the session just falls back to the worker default image). */
|
|
30
4
|
export class SessionEnvironmentSelection {
|
|
31
|
-
// #97 R11: same BoundedSessionMap basis as PerTaskImageRegistry (composition, not inheritance) — this
|
|
32
|
-
// class's own ctor/method surface is unchanged.
|
|
33
5
|
bounded;
|
|
34
6
|
constructor(maxEntries = 4096) {
|
|
35
7
|
this.bounded = new BoundedSessionMap(maxEntries);
|
|
@@ -46,7 +18,6 @@ const capList = (caps) => Object.entries(caps ?? {})
|
|
|
46
18
|
.map(([k]) => k);
|
|
47
19
|
async function availableProfiles(catalog, viewer) {
|
|
48
20
|
const { entries } = await catalog.list({ ...viewer, status: "published", latestOnly: true, limit: 100 });
|
|
49
|
-
// tenant-neutral: profile name + boolean capability keys only (this list enters model context).
|
|
50
21
|
return entries.map((e) => ({ profile: e.profile, capabilities: capList(e.capabilities) }));
|
|
51
22
|
}
|
|
52
23
|
export function selectEnvironmentTool(deps) {
|
|
@@ -58,7 +29,6 @@ export function selectEnvironmentTool(deps) {
|
|
|
58
29
|
"The change takes effect for the NEXT task/subagent — the current sandbox is not swapped mid-run; " +
|
|
59
30
|
"running work keeps the environment it started with, and artifacts hand over via the workspace/git. " +
|
|
60
31
|
"Use this instead of hand-installing SDK-level toolchains (Android SDK, JVM, browsers, …).",
|
|
61
|
-
// set-to-value on a session-keyed map: repeat-safe with the same args.
|
|
62
32
|
effect: "idempotent",
|
|
63
33
|
parameters: Type.Object({
|
|
64
34
|
profile: Type.Optional(Type.String({ description: "Target image profile name (from the available list). Omit to discover." })),
|
|
@@ -83,7 +53,6 @@ export function selectEnvironmentTool(deps) {
|
|
|
83
53
|
index: deps.catalog,
|
|
84
54
|
});
|
|
85
55
|
if (!resolved.ok) {
|
|
86
|
-
// self-correction payload: the error + the viewer's own catalog. Model retries with a valid one.
|
|
87
56
|
const available = await availableProfiles(deps.catalog, viewer);
|
|
88
57
|
return {
|
|
89
58
|
content: JSON.stringify({ error: resolved.message, ...(caps.length > 0 ? { missing: caps } : {}), available }),
|
|
@@ -91,7 +60,6 @@ export function selectEnvironmentTool(deps) {
|
|
|
91
60
|
};
|
|
92
61
|
}
|
|
93
62
|
if (!sessionId) {
|
|
94
|
-
// outside a Runner session there is nothing to bind to — honest failure, not a silent success.
|
|
95
63
|
return { content: JSON.stringify({ error: "no session to bind the environment selection to" }), details: { mode: "select-failed" } };
|
|
96
64
|
}
|
|
97
65
|
deps.selection.set(sessionId, a.profile);
|