@sema-agent/server 7.151.0 → 7.152.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 +15 -3
- package/README.zh-CN.md +10 -2
- package/USAGE.md +93 -64
- package/deploy/sema-up/README.md +5 -4
- package/deploy/sema-up/cluster-up.sh +6 -6
- package/deploy/sema-up/kube-up.sh +5 -5
- package/deploy/sema-up/lib/flagshape.sh +36 -8
- package/deploy/sema-up/machines.example.yaml +3 -1
- package/deploy/sema-up/sema-up.sh +22 -16
- package/dist/approval-ask-audit-store.d.ts +1 -1
- package/dist/approval-ask-machine.d.ts +4 -10
- package/dist/approval-ask-retention.d.ts +1 -1
- package/dist/approval-card.d.ts +10 -12
- package/dist/approval-gate-currency.d.ts +8 -8
- package/dist/approval-gate-currency.js +3 -4
- package/dist/approval-hmac.d.ts +17 -1
- package/dist/approval-hmac.js +7 -1
- package/dist/approval-queue-kind.d.ts +1 -1
- package/dist/approval.d.ts +2 -2
- package/dist/approval.js +2 -2
- package/dist/bind-host.d.ts +1 -3
- package/dist/bind-host.js +2 -3
- package/dist/boot/coordinators.d.ts +1 -1
- package/dist/boot/coordinators.js +9 -10
- package/dist/boot/device-lane.js +2 -0
- package/dist/boot/execution-env.d.ts +1 -0
- package/dist/boot/execution-env.js +31 -5
- package/dist/boot/leader.d.ts +31 -30
- package/dist/boot/leader.js +38 -28
- package/dist/boot/leg-path-adjudication.d.ts +40 -0
- package/dist/boot/leg-path-adjudication.js +18 -0
- package/dist/boot/parked-revive-gate.js +3 -15
- package/dist/boot/reapers.d.ts +1 -1
- package/dist/boot/reapers.js +1 -1
- package/dist/boot/resolve-spec.js +12 -26
- package/dist/boot/runner-deps.d.ts +39 -35
- package/dist/boot/runner-deps.js +92 -89
- package/dist/boot/shutdown.d.ts +6 -0
- package/dist/boot/shutdown.js +10 -4
- package/dist/boot/stage-02-web-admin-pull.js +4 -5
- package/dist/boot/stage-05-execution-env.js +2 -1
- package/dist/boot/stage-06-runners.d.ts +2 -0
- package/dist/boot/stage-06-runners.js +10 -4
- package/dist/boot/stage-07-capability-layer.d.ts +1 -0
- package/dist/boot/stage-07-capability-layer.js +1 -1
- package/dist/boot/stage-08-reapers.d.ts +1 -0
- package/dist/boot/stage-09-leader.d.ts +1 -0
- package/dist/boot/stage-09-leader.js +2 -2
- package/dist/boot/stage-10-http-server.d.ts +8 -0
- package/dist/boot/stage-10-http-server.js +11 -15
- package/dist/boot/stores.js +7 -4
- package/dist/boot/web-admin.js +2 -7
- package/dist/capabilities/approvals-push.d.ts +3 -3
- package/dist/capabilities/scenarios.d.ts +28 -13
- package/dist/capabilities/scenarios.js +2 -2
- package/dist/capability-facts.d.ts +22 -20
- package/dist/capability-facts.js +18 -34
- package/dist/card-rule-offers.d.ts +32 -0
- package/dist/card-rule-offers.js +130 -0
- package/dist/config-catalog.js +12 -11
- package/dist/config-dir-trust.js +4 -2
- package/dist/config-invariants.d.ts +18 -7
- package/dist/config-invariants.js +51 -8
- package/dist/config-lkg.d.ts +5 -19
- package/dist/config-lkg.js +8 -62
- package/dist/config-provider.d.ts +1 -1
- package/dist/config-root-migration.d.ts +2 -2
- package/dist/config-types.d.ts +28 -38
- package/dist/config.d.ts +7 -5
- package/dist/config.js +55 -16
- package/dist/control-socket.d.ts +51 -0
- package/dist/control-socket.js +115 -0
- package/dist/deployment-governance.d.ts +2 -1
- package/dist/device-ws-hub.d.ts +7 -0
- package/dist/device-ws-hub.js +7 -1
- package/dist/elicitation.js +2 -2
- package/dist/entry-problems.d.ts +40 -3
- package/dist/entry-problems.js +3 -1
- package/dist/execution-env-refusal.d.ts +8 -2
- package/dist/execution-env-refusal.js +3 -0
- package/dist/fleet/engine-signal.d.ts +12 -29
- package/dist/fleet/engine-signal.js +1 -7
- package/dist/fleet-client.js +2 -5
- package/dist/gate-settlement.d.ts +1 -8
- package/dist/gate-settlement.js +0 -4
- package/dist/history-anchor.js +1 -1
- package/dist/hitl-delivery.d.ts +2 -3
- package/dist/hitl-delivery.js +0 -2
- package/dist/hooks/hook-llm.js +4 -2
- package/dist/hooks/hook-runner.d.ts +3 -2
- package/dist/hooks/hook-runner.js +16 -1
- package/dist/host-decision.d.ts +11 -11
- package/dist/http/active-run-conflict.d.ts +35 -2
- package/dist/http/active-run-conflict.js +48 -19
- package/dist/http/approval-sweeps.d.ts +1 -1
- package/dist/http/approval-sweeps.js +5 -2
- package/dist/http/checkpoint-ctx.d.ts +2 -0
- package/dist/http/checkpoint-ctx.js +1 -0
- package/dist/http/dispatch.d.ts +6 -2
- package/dist/http/dispatch.js +25 -5
- package/dist/http/durable-run-leg.js +0 -1
- package/dist/http/health-reader.d.ts +16 -9
- package/dist/http/health-reader.js +2 -1
- package/dist/http/health-self-report.js +1 -1
- package/dist/http/owner-access.d.ts +2 -3
- package/dist/http/owner-access.js +3 -4
- package/dist/http/principal-gate.d.ts +49 -21
- package/dist/http/principal-gate.js +61 -11
- package/dist/http/request-channel.d.ts +23 -0
- package/dist/http/request-channel.js +9 -0
- package/dist/http/request-guards.js +17 -2
- package/dist/http/resume-ctx-read.js +20 -3
- package/dist/http/resume-legs.d.ts +2 -2
- package/dist/http/resume-legs.js +111 -41
- package/dist/http/route-ctx.d.ts +73 -7
- package/dist/http/route-ctx.js +17 -0
- package/dist/http/route-table.d.ts +4 -0
- package/dist/http/route-table.js +4 -0
- package/dist/http/routes/admin-config-refresh.js +3 -3
- package/dist/http/routes/admin-drain.d.ts +3 -0
- package/dist/http/routes/admin-drain.js +7 -7
- package/dist/http/routes/admin-memory-optout.js +3 -3
- package/dist/http/routes/adoption.js +3 -5
- package/dist/http/routes/approvals-assistant.d.ts +2 -1
- package/dist/http/routes/approvals-assistant.js +95 -48
- package/dist/http/routes/capabilities.d.ts +4 -0
- package/dist/http/routes/capabilities.js +30 -5
- package/dist/http/routes/config-catalog.js +2 -2
- package/dist/http/routes/devices.js +1 -1
- package/dist/http/routes/diagnostics.d.ts +3 -3
- package/dist/http/routes/diagnostics.js +19 -7
- package/dist/http/routes/images.js +10 -10
- package/dist/http/routes/memory-bundle.js +3 -3
- package/dist/http/routes/memory-compliance.js +3 -3
- package/dist/http/routes/memory-consolidation.js +2 -2
- package/dist/http/routes/memory-origin.js +3 -3
- package/dist/http/routes/memory-policy.js +2 -2
- package/dist/http/routes/observability.js +3 -3
- package/dist/http/routes/retention-ops.js +3 -3
- package/dist/http/routes/rules.js +5 -5
- package/dist/http/routes/run-permission-mode.d.ts +2 -1
- package/dist/http/routes/run-permission-mode.js +2 -2
- package/dist/http/routes/runs.d.ts +4 -9
- package/dist/http/routes/runs.js +73 -33
- package/dist/http/routes/session-sync.d.ts +18 -6
- package/dist/http/routes/session-sync.js +38 -36
- package/dist/http/routes/sessions.js +20 -9
- package/dist/http/routes/tasks.js +28 -37
- package/dist/http/routes/workflows.js +1 -1
- package/dist/http/server.d.ts +9 -3
- package/dist/http/server.js +15 -3
- package/dist/http/submit-ctx.d.ts +1 -1
- package/dist/http/submit-ctx.js +2 -0
- package/dist/human-facing-args.d.ts +33 -0
- package/dist/human-facing-args.js +33 -0
- package/dist/index.d.ts +1 -1
- package/dist/k8s-api-credentials.d.ts +29 -0
- package/dist/k8s-api-credentials.js +25 -0
- package/dist/lane-home-probe.d.ts +1 -1
- package/dist/lane-home-probe.js +2 -1
- package/dist/leader/diffup.d.ts +19 -0
- package/dist/leader/diffup.js +7 -0
- package/dist/leader/leader.d.ts +114 -10
- package/dist/leader/leader.js +69 -5
- package/dist/leader/repair-wire.js +2 -2
- package/dist/leader/run-entry.d.ts +2 -1
- package/dist/leader/run-entry.js +1 -1
- package/dist/leader/wire.d.ts +42 -132
- package/dist/leader/wire.js +81 -67
- package/dist/memory-scope.d.ts +20 -9
- package/dist/memory-scope.js +15 -3
- package/dist/model-entry-headers.d.ts +9 -10
- package/dist/model-entry-headers.js +0 -4
- package/dist/model-entry-refusal.d.ts +7 -4
- package/dist/model-entry-refusal.js +11 -5
- package/dist/model-plane-face.d.ts +1 -1
- package/dist/model-plane-face.js +3 -1
- package/dist/model-route-endpoint.d.ts +13 -7
- package/dist/model-route-endpoint.js +14 -11
- package/dist/model-select.d.ts +22 -0
- package/dist/model-select.js +9 -0
- package/dist/model-unreachable-notice.d.ts +11 -0
- package/dist/model-unreachable-notice.js +4 -4
- package/dist/object-store-buckets.d.ts +640 -6
- package/dist/object-store-buckets.js +166 -0
- package/dist/observability/fail-open.d.ts +20 -16
- package/dist/observability/fail-open.js +20 -16
- package/dist/observability/logger.js +3 -1
- package/dist/operator-roster.d.ts +68 -0
- package/dist/operator-roster.js +32 -0
- package/dist/orchestration/workflow-park-decision.d.ts +1 -1
- package/dist/outbound-dispatcher.d.ts +71 -8
- package/dist/outbound-dispatcher.js +48 -7
- package/dist/owner-faces.d.ts +1 -1
- package/dist/parked-decide.d.ts +2 -2
- package/dist/permission-mode-admission.d.ts +59 -26
- package/dist/permission-mode-admission.js +37 -10
- package/dist/plugins/approval-ask-store-file.d.ts +4 -0
- package/dist/plugins/approval-ask-store-file.js +3 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +4 -0
- package/dist/plugins/approval-ask-store-memory.js +7 -1
- package/dist/plugins/approval-ask-store-sql.d.ts +26 -2
- package/dist/plugins/approval-ask-store-sql.js +12 -1
- package/dist/plugins/blob-backend.d.ts +83 -7
- package/dist/plugins/blob-backend.js +57 -6
- package/dist/plugins/checkpoint-index-columns.d.ts +20 -16
- package/dist/plugins/checkpoint-index-columns.js +3 -6
- package/dist/plugins/checkpoint-store-face.d.ts +119 -61
- package/dist/plugins/checkpoint-store-face.js +134 -55
- package/dist/plugins/landed-attendants.d.ts +2 -2
- package/dist/plugins/local-checkpoint-store.d.ts +13 -3
- package/dist/plugins/local-checkpoint-store.js +38 -49
- package/dist/plugins/one-time-migrations.d.ts +51 -21
- package/dist/plugins/one-time-migrations.js +67 -45
- package/dist/plugins/pg-pool.js +11 -9
- package/dist/plugins/remote-env-host.d.ts +29 -10
- package/dist/plugins/remote-env-host.js +99 -19
- package/dist/plugins/remote-env-k8s.d.ts +68 -2
- package/dist/plugins/remote-env-k8s.js +107 -24
- package/dist/plugins/replica-registration.d.ts +1 -1
- package/dist/plugins/replica-registration.js +1 -1
- package/dist/plugins/s3-presign.d.ts +23 -0
- package/dist/plugins/s3-presign.js +37 -3
- package/dist/plugins/scheduler-support.d.ts +2 -2
- package/dist/plugins/scheduler-support.js +0 -3
- package/dist/plugins/schema-indexes.js +2 -0
- package/dist/plugins/send-file-ledger.d.ts +2 -2
- package/dist/plugins/send-file-ledger.js +2 -2
- package/dist/plugins/send-user-file.d.ts +3 -4
- package/dist/plugins/send-user-file.js +56 -52
- package/dist/plugins/session-blob-claim-token.d.ts +15 -0
- package/dist/plugins/session-blob-claim-token.js +20 -0
- package/dist/plugins/session-blob-namespace.d.ts +46 -0
- package/dist/plugins/session-blob-namespace.js +116 -0
- package/dist/plugins/snapshot-bucket-presence.d.ts +25 -2
- package/dist/plugins/snapshot-bucket-presence.js +8 -2
- package/dist/plugins/sql-json-column.d.ts +1 -1
- package/dist/plugins/store-backend.d.ts +44 -2
- package/dist/plugins/store-backend.js +75 -53
- package/dist/plugins/task-attachment-store.d.ts +2 -1
- package/dist/plugins/task-attachment-store.js +5 -1
- package/dist/plugins/tidb-pool.js +19 -24
- package/dist/plugins/workspace-custody.d.ts +4 -3
- package/dist/question.d.ts +2 -1
- package/dist/question.js +5 -13
- package/dist/request-form.d.ts +6 -1
- package/dist/request-form.js +4 -1
- package/dist/rule-issue-reading.d.ts +1 -1
- package/dist/rules-consent.d.ts +1 -1
- package/dist/run-local.js +8 -9
- package/dist/runs.d.ts +17 -8
- package/dist/runs.js +15 -2
- package/dist/runtime-governance.d.ts +2 -2
- package/dist/sema-config-dir.d.ts +2 -1
- package/dist/session-sync.d.ts +27 -11
- package/dist/session-sync.js +15 -7
- package/dist/stores-sql/blob-index-sql.d.ts +30 -9
- package/dist/stores-sql/blob-index-sql.js +40 -21
- package/dist/stores-sql/checkpoint-store-sql.d.ts +54 -27
- package/dist/stores-sql/checkpoint-store-sql.js +70 -146
- package/dist/stores-sql/file-history-store-sql.d.ts +64 -16
- package/dist/stores-sql/file-history-store-sql.js +100 -28
- package/dist/stores-sql/retention-store-sql.js +3 -9
- package/dist/task-settings.d.ts +6 -5
- package/dist/task-settings.js +3 -3
- package/dist/tool-approval.d.ts +342 -518
- package/dist/tool-approval.js +498 -1207
- package/dist/trace/core-keyset-guard.d.ts +1 -1
- package/dist/trace/ledger-events.d.ts +3 -3
- package/dist/trace/project.d.ts +2 -3
- package/dist/trace/redact.js +3 -2
- package/dist/trace/self-minted-wire.d.ts +287 -157
- package/dist/trace/self-minted-wire.js +93 -48
- package/dist/web-admin-client/apply-effective.js +2 -2
- package/dist/web-admin-client/read-warnings.d.ts +2 -2
- package/dist/web-admin-client/read-warnings.js +1 -1
- package/dist/web-admin-client/types.d.ts +1 -1
- package/dist/workspace-space.d.ts +10 -4
- package/dist/workspace-space.js +4 -1
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +1 -1
- package/package.json +6 -2
- package/scripts/embed-minimal.mjs +3 -3
- package/wire-changes/server@7.152.0.json +900 -0
- package/dist/config-d-migration.d.ts +0 -37
- package/dist/config-d-migration.js +0 -60
package/dist/leader/wire.d.ts
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type TaskSpec, type ExecutionEnvFactory, type RemoteExecutionEnv, type ToolResultStore, type SessionStore, type ExecutionEnv, type CheckpointToken } from "@sema-agent/core";
|
|
2
2
|
import type { Autonomy } from "../runtime-governance.js";
|
|
3
|
-
import { type
|
|
4
|
-
import type
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
3
|
+
import { type LeaderDiffStore } from "./diffup.js";
|
|
4
|
+
import { type LeaderBirth, type LeaderDurableSeat, type LeaderDeps, type LeaderResult } from "./leader.js";
|
|
5
|
+
import type { DeploymentPlaneDeps } from "../boot/runner-deps.js";
|
|
6
|
+
import type { SandboxPathEnvSlots } from "../boot/deferred-sandbox-path-env.js";
|
|
7
7
|
import type { LeaderRequestBody } from "./endpoint.js";
|
|
8
8
|
/**
|
|
9
|
-
* leader worker
|
|
10
|
-
* `
|
|
9
|
+
* leader worker 资源分片停驻行的 scope —— **唯一属主**(保留前缀见 `principal-shape.ts` 的 `RESERVED_PRINCIPAL_PREFIXES`;审批停驻那一只
|
|
10
|
+
* `LEADER_APPROVAL_SCOPE` 的属主是出生口所在的 `leader.ts`)。worker 的资源分片 spec 与取消时的残留过期({@link createLeaderParkExpirer})读这同一对。
|
|
11
11
|
*/
|
|
12
|
-
export declare const LEADER_APPROVAL_SCOPE = "_leader";
|
|
13
12
|
export declare function leaderResourceScope(workerId: string): string;
|
|
14
13
|
/** 过期残留停驻要的那两口(SQL 两方言与 local 店都有;结构型,单测用假件)。 */
|
|
15
14
|
export interface LeaderParkStore {
|
|
@@ -30,18 +29,6 @@ export declare function createLeaderParkExpirer(store: LeaderParkStore): (worker
|
|
|
30
29
|
readonly workerId: string;
|
|
31
30
|
readonly sessionId: string;
|
|
32
31
|
}>) => Promise<LeaderParkExpiry>;
|
|
33
|
-
/** leader worker 的 durable 审批座(`LeaderWireConfig.durable` 函数席每次产出的一份)。 */
|
|
34
|
-
export interface LeaderDurableSeat {
|
|
35
|
-
readonly checkpointStore: CheckpointStoreFull;
|
|
36
|
-
/** [ref]:写 worker 续跑上下文的封口(`ServiceDeps.checkpointCtxSealing` 同一只;规则属主 `http/checkpoint-ctx.ts` 末段「凭据位密封」)。
|
|
37
|
-
* worker 的续跑体只有入口词 + 子任务 objective、不带凭据位 ⇒ 实际不封任何值,但写 ctx 的每一笔都经同一只封口(没有不封的第二种写法)。 */
|
|
38
|
-
readonly ctxSealer: CheckpointCtxSealer | undefined;
|
|
39
|
-
readonly requireApproval: string[];
|
|
40
|
-
readonly deny?: string[];
|
|
41
|
-
readonly ttlMs?: number;
|
|
42
|
-
readonly autoBudget?: number;
|
|
43
|
-
readonly neverAuto?: string[];
|
|
44
|
-
}
|
|
45
32
|
export interface LeaderWireConfig {
|
|
46
33
|
/** Static-env compat mode (E2B only): the leader provisions/owns each env. Required when `envFactory` unset. */
|
|
47
34
|
e2bApiKey?: string;
|
|
@@ -49,17 +36,17 @@ export interface LeaderWireConfig {
|
|
|
49
36
|
* REMOTE_EXEC (e2b or k8s/Kata) — workers and the integration sandbox run on envs from THIS factory.
|
|
50
37
|
* Requires `s3` (diff-out is the worker's self-upload; there is no leader-held env to pull from). */
|
|
51
38
|
envFactory?: ExecutionEnvFactory;
|
|
52
|
-
/**
|
|
53
|
-
*
|
|
54
|
-
* (
|
|
55
|
-
*
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
* (`
|
|
59
|
-
*
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
39
|
+
/** 部署的停驻设施([ref] C4):键在场 ⟺ 部署接了停驻店。worker 首跑的出生点按车道决定递不递给这条腿:工厂车道 = 递(worker 的环境由它自己的 Runner
|
|
40
|
+
* 经工厂铸,停驻续得上);静态车道 = `leader.ts` 的 `staticLaneWorkerPark`(上一发布版的条件:另要任一审批名单在场,见 {@link approvalListInForce})。
|
|
41
|
+
* 递了且续跑上下文真落了 ⇒ 这条腿**耐久**(唯一读者 `leader.ts` 的 `leaderLegDurability`):停驻设施进 spec、ctx 保温、开资源分片停驻。
|
|
42
|
+
* 函数席:`provisionWorker` 每只 worker 调一次,同一只 worker 的停驻设施 / ctx 保温 / 资源分片读同一份。 */
|
|
43
|
+
durable?: () => LeaderDurableSeat;
|
|
44
|
+
/** 这台部署此刻有没有任一审批名单在场(`APPROVAL_REQUIRE` / `APPROVAL_DENY` / `APPROVAL_NEVER_AUTO`,含中心热换的那一张;装配处闭包同一个活 config,与
|
|
45
|
+
* {@link baseline} 同源)。**唯一读者** = 静态车道 worker 的停驻设施条件(`leader.ts` 的 `staticLaneWorkerPark`,上一发布版的条件);引擎提供
|
|
46
|
+
* 「宿主声明本腿审批停驻不可续」的声明位后,那条条件退役,本席随之删。函数席:每只 worker 现读一次。 */
|
|
47
|
+
approvalListInForce: () => boolean;
|
|
48
|
+
/** 审批基线的两臂(`LeaderBirth.baseline`;装配处闭包活 config,leader 不读 config)—— 每一条腿出生时经 {@link withLeaderLeg} 按它的耐久事实取一臂。 */
|
|
49
|
+
baseline: LeaderBirth["baseline"];
|
|
63
50
|
/** Durable tool-result offload store (TiDB). REQUIRED for `durable` to actually suspend: core's suspend
|
|
64
51
|
* pre-commit refuses with the default InMemoryToolResultStore (offloaded results would deref to null after
|
|
65
52
|
* a cross-replica resume) and silently falls back to the synchronous onAsk gate — which the leader does not
|
|
@@ -70,109 +57,35 @@ export interface LeaderWireConfig {
|
|
|
70
57
|
* the resume dies with SessionError "Entry <leafId> not found" (found live: drill c3 deny path). */
|
|
71
58
|
sessionStore?: SessionStore;
|
|
72
59
|
/**
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
60
|
+
* **部署平面层**(唯一铸点 `boot/runner-deps.ts` 的 `createDeploymentPlaneDeps`;起服第 6 段交出、`boot/leader.ts` 递进来)—— 本车道的每一只
|
|
61
|
+
* `new Runner` 头一项展开它,零逐席搬运:收紧面(治理三座 / 按主体准入 resolver / MCP 撤销台账 / 部署姿态座席族 / 豁免根)、计量面(tracer /
|
|
62
|
+
* 治理窗两键)、服务表(brain / 模型目录 / 定价 / 提示词目录)、部署座 / 手带、两条披露出口(通告 / 错误汇)。新的部署键进那一层即到达这里。
|
|
63
|
+
* 🔴 **函数席**([ref] 先例):姿态族与模型目录会被中心热换,本车道的 Runner 逐调用现构 ⇒ 每只构造时现铸一份,与主车道经 swap 门换代同代。
|
|
76
64
|
*/
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* [ref](黑板 [ref])—— **部署姿态座席族**(readFace 四席 `readFace`/`readDenyPatterns`/`readDenyBuiltinTiers`/
|
|
80
|
-
* `readDenyBuiltinExclude` + `memoryDelegationEvidence`/`memoryProvenance`/`memoryCapturePolicy`/
|
|
81
|
-
* `delegationEntryCaps`),**原样递给本车道的每一只 Runner**。唯一属主 = `boot/runner-deps.ts` 的
|
|
82
|
-
* `buildDeploymentPostureSeats(config)`(主 runner / subRunner / run-local 的共享基座展开的就是它),
|
|
83
|
-
* `boot/leader.ts` 把**同一函数、同一 config** 的产物搬过来:一个进程里「这台部署的 READ 面 / 记忆姿态 /
|
|
84
|
-
* 委派 caps」只能有一个答案。缺席 = 展开空对象 = 五处字面量键缺席(与接线前逐字相同)。
|
|
85
|
-
* 修前(≤7.53)这五只 Runner 一席都没有:运维写的 READ_DENY_PATTERNS / MEMORY_DELEGATION_EVIDENCE 等对
|
|
86
|
-
* leader 编排的 planner / worker / repair / conflict 四类任务**静默不生效**(core 内建 deny 表仍在)。
|
|
87
|
-
*
|
|
88
|
-
* 🔴 **是 provider 不是快照**([ref] 追加,codex 对抗复审 r1 [high] 验真后修):本车道的 Runner 是
|
|
89
|
-
* **逐调用现构**的,而 [ref] 起 `config.readFace` 在进程内**会变**(center 下发的 read face 转成了
|
|
90
|
-
* `Runner.swapDeps` 热换席)。boot 期取一次值再五处复用,等于让 leader 车道永远停在起服那一刻的 READ
|
|
91
|
-
* 姿态:读面(`/v1/capabilities`、`/v1/diagnostics/wiring`)报新档、`restart.reasons` 也不再要求重启,
|
|
92
|
-
* 而**新建的 leader Runner 仍在旧档上跑** —— 组织把 `open` 收紧成 `roots` 之后这条腿还在 open,方向是
|
|
93
|
-
* fail-OPEN。改成函数席之后每只 Runner 构造时现读,与主车道经 swap 门换代**同代**;已经准备好的腿
|
|
94
|
-
* 保留它准备时的那一份(core 的自然快照语义,两条腿同律)。 */
|
|
95
|
-
deploymentPosture?: () => DeploymentPostureSeats;
|
|
65
|
+
plane: () => DeploymentPlaneDeps;
|
|
96
66
|
/**
|
|
97
|
-
*
|
|
98
|
-
* 得出这条 run 的入口体(`LeaderDeps.entry`);本 run 铸的每一条 spec 与 worker 的续跑体都从它取词。入口词是 `plan` 的 run 进不了这条车道
|
|
99
|
-
* (`leaderEntryRefusal`:worker 会话没有计划审阅通道)⇒ 出生处即以拒句收场;HTTP 受理口用同一只判据先答 422。
|
|
100
|
-
*
|
|
101
|
-
* 🔴 **函数席**(与 `deploymentPosture` / `durable` 同一条先例):`config.autonomy` 被 web-admin 原地热改,boot 期取一次值会把这条腿钉在起服那一刻。
|
|
102
|
-
* **必填**:没有 AUTONOMY 的装配递 `() => undefined` —— 缺席不是「没有地板」的合法拼法(权限轴上不许静默放宽)。
|
|
103
|
-
*/
|
|
104
|
-
autonomy: () => Autonomy | undefined;
|
|
105
|
-
/**
|
|
106
|
-
* [ref]([ref])—— **计费/遥测追踪席**,原样递给本车道的每一只 Runner。唯一属主 =
|
|
107
|
-
* `boot/budget-tracing.ts` 的 `createTracer(...)`(主 runner / subRunner / hook runner 经共享基座吃的
|
|
108
|
-
* 就是它),`boot/leader.ts` 搬的是**同一只**。
|
|
109
|
-
*
|
|
110
|
-
* 🔴 为什么这一席是承重的:`src/budget.ts` 的 `createTracer` 是 `brain.call` **唯一**的记账点 ——
|
|
111
|
-
* `costQuota.add` / `fleetUsage.record` / `fleetLease.recordSpend` / `model_cost_micro_usd_total` 四个写口
|
|
112
|
-
* 全在那里(`createBrain` 自己不记账)。而 `POST /v1/leader` 的准入处**读**的正是 costQuota / fleetLease
|
|
113
|
-
* 这两个桶。缺席 ⇒ 门查的桶与花钱的手不是同一只:`MAX_PRINCIPAL_COST_USD` 与 fleet 租约对这条腿结构性
|
|
114
|
-
* 失效,而一条 leader run 扇出 ≤6 个带手 worker + planner + repair/conflict 环,全是实钱。
|
|
115
|
-
* 归因的另一半在 `leader/endpoint.ts` 的 `drive()`(ALS `withSubject`)—— 记账臂按 `currentPerson()`
|
|
116
|
-
* 分租户,只补席不包裹 = 归因恒 undefined = 假绿。缺席 ⇒ 展开空对象(与接线前逐字相同)。
|
|
67
|
+
* 部署治理折叠(`LeaderBirth.govern`;装配处闭包活 config,leader 不读 config)—— 每一条腿出生时经 {@link withLeaderLeg} 调一次。
|
|
117
68
|
*/
|
|
118
|
-
|
|
69
|
+
govern: LeaderBirth["govern"];
|
|
119
70
|
/**
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
* leader 不自铸、不自己装配(一个进程两份部署注册 = 主车道与 leader 车道各按一套扩展跑)。缺失时整个部署座在这条车道上缺席:运维声明的守卫包
|
|
123
|
-
* 管不到 leader 派出的腿,拒绝计量 / 工具追踪也漏这条腿。缺席 ⇒ 展开空对象。
|
|
71
|
+
* 每条腿的 per-model 凭据席(`LeaderBirth.auth`;装配处铸,与任务面同一只活引用)—— 本车道每一只 Runner 跑的 spec 都带它:五个出生点经 {@link withLeaderLeg},
|
|
72
|
+
* planner 路由在它的 Runner 构造那一拍取一只。**必填**:没有 per-model 钥匙的装配照样递(席对每只模型答「没有自己的钥」⇒ 网关钥,与不递逐字同)。
|
|
124
73
|
*/
|
|
125
|
-
|
|
74
|
+
auth: LeaderBirth["auth"];
|
|
126
75
|
/**
|
|
127
|
-
*
|
|
128
|
-
*
|
|
76
|
+
* 腿的路径裁决的槽表(进程内唯一那一只,`boot/deferred-sandbox-path-env.ts`)。本车道**手里握着 env** 的腿 —— 静态车道的 worker、集成修复腿 ——
|
|
77
|
+
* 的 env 不是部署工厂为那条腿铸的,工厂装饰器登记不到;每一次 run 由本车道按跑它的会话号登记、run 收场即注销(守卫在沙盒车道上按会话号取真身)。
|
|
129
78
|
*/
|
|
130
|
-
|
|
79
|
+
legSlots: Pick<SandboxPathEnvSlots, "bind">;
|
|
131
80
|
/**
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
* `
|
|
135
|
-
*
|
|
136
|
-
* 成对的理由是 core 的消费形:`prepare-task.js` 的 `buildUsageGovernance(usageWindows, deps, …)` 要求
|
|
137
|
-
* 声明与 `deps.usageWindowStore` **同时**在场才铸 `usageGovernance`,缺一即 undefined(既不 check 也不
|
|
138
|
-
* commit)⇒ 半席只是死键。缺席 ⇒ 展开空对象。
|
|
139
|
-
* 提交面那一半(`POST /v1/leader` 的 `usageWindowDenied` 门)在 `src/http/routes/leader.ts`。
|
|
140
|
-
*/
|
|
141
|
-
usageWindows?: RunnerDeps["usageWindows"];
|
|
142
|
-
usageWindowStore?: RunnerDeps["usageWindowStore"];
|
|
143
|
-
/**
|
|
144
|
-
* [ref]([ref])—— **center 发布的 prompt catalog** 席,原样递给本车道的每一只 Runner。唯一属主 =
|
|
145
|
-
* `boot/web-admin.ts` 的 `webAdmin.promptSource`(主 runner / subRunner 同一只;run-local 有自己
|
|
146
|
-
* 的等价腿)。缺席 ⇒ leader 的 planner/worker/repair/conflict 四类**顶层**任务跑引擎内置提示词,而同一
|
|
147
|
-
* 部署的 `/v1/tasks`、`/v1/runs` 跑运维发布的那一份 —— 且 core 顶层新任务走的是**静默**臂(pinned /
|
|
148
|
-
* parentCenterArtifactDigest 两支才 `prompt.snapshot_unavailable` fail-loud),运维面零信号。
|
|
149
|
-
* 缺席 ⇒ 展开空对象(与接线前逐字相同)。
|
|
150
|
-
*/
|
|
151
|
-
promptSource?: RunnerDeps["promptSource"];
|
|
152
|
-
/**
|
|
153
|
-
* [ref] 的**披露半件**([ref],codex 对抗复审 r2-[high],亲读装树 core 后修)—— 部署级错误汇。
|
|
154
|
-
*
|
|
155
|
-
* 🔴 为什么它与治理窗席**同生共死**:core 对「治理窗最终扣账失败」的唯一出口就是这一席 ——
|
|
156
|
-
* `dist/core/runner/runtask.js` 收尾段 `catch (flushErr) { this.deps.onError?.(flushErr, { phase: "config", … }) }`
|
|
157
|
-
* (以及 10s 慢盘披露的同一只回调),抛错之后任务**按原结果收尾**。挂了窗席却不挂本席 = 一次窗账
|
|
158
|
-
* 永久丢失时这条腿上零日志零计数,后续提交继续读偏低的窗被放行 —— CLAUDE.md [ref]「治理/门轴禁静默
|
|
159
|
-
* fail-open」正是说这个。它顺带也把 leader 车道其余 phase(degraded / rewind / memory / mcp / a2a /
|
|
160
|
-
* prompt-cache …)的既有观测面补齐,与 `onNotice` 席当年([ref]②)同一个理由。
|
|
81
|
+
* 运维 `AUTONOMY`(活 config 的那一位)—— 本车道每条 leader run **出生那一拍**读一次,经 `run-entry.ts` 的 `leaderRunEntry`(入口地板 + 受理门同一只入口函数 `entryPermissionMode`)
|
|
82
|
+
* 得出这条 run 的入口体(`LeaderDeps.birth.entry`);本 run 铸的每一条 spec 与 worker 的续跑体都从它取词。入口词是 `plan` 的 run 进不了这条车道
|
|
83
|
+
* (`leaderEntryRefusal`:worker 会话没有计划审阅通道)⇒ 出生处即以拒句收场;HTTP 受理口用同一只判据先答 422。
|
|
161
84
|
*
|
|
162
|
-
*
|
|
163
|
-
* `
|
|
164
|
-
* leader 绝不另写一份臂表(两份必漂)。缺席 ⇒ 展开空对象(与接线前逐字相同)。
|
|
85
|
+
* 🔴 **函数席**(与 `deploymentPosture` / `durable` 同一条先例):`config.autonomy` 被 web-admin 原地热改,boot 期取一次值会把这条腿钉在起服那一刻。
|
|
86
|
+
* **必填**:没有 AUTONOMY 的装配递 `() => undefined` —— 缺席不是「没有地板」的合法拼法(权限轴上不许静默放宽)。
|
|
165
87
|
*/
|
|
166
|
-
|
|
167
|
-
/** Worker model brain + catalog (the same the service runs tasks on). */
|
|
168
|
-
brain: Brain;
|
|
169
|
-
models: Record<string, Model>;
|
|
170
|
-
roles: ModelRoles;
|
|
171
|
-
/** The active tier table of the served catalog (boot hands the same object as `config.tiers`, mutated in place on a hot apply).
|
|
172
|
-
* Every leader Runner gets it with `models` / `roles` (one seat, `servedTableSeat`): a role resolves in the tier-expanded view,
|
|
173
|
-
* exactly as the main runner resolves it — absent ⇒ no tiers (the env table has none). */
|
|
174
|
-
tiers?: NonNullable<RunnerDeps["tiers"]>;
|
|
175
|
-
pricing: Record<string, ModelPricing>;
|
|
88
|
+
autonomy: () => Autonomy | undefined;
|
|
176
89
|
/** Workspace root inside each E2B VM. Default /home/user. */
|
|
177
90
|
workspace?: string;
|
|
178
91
|
/** Git identity for the Coordinator's local clone/commit. */
|
|
@@ -198,14 +111,7 @@ export interface LeaderWireConfig {
|
|
|
198
111
|
* complete path; a suspended worker's paused env is exempt from the leader reap by construction) and diff-out
|
|
199
112
|
* is the worker's mandatory self-upload to this MinIO/S3 store (presigned per worker; creds adapter-held).
|
|
200
113
|
* Unset = the original leader-owned static-env mode (pullDiff compat). */
|
|
201
|
-
s3?:
|
|
202
|
-
endpoint: string;
|
|
203
|
-
bucket: string;
|
|
204
|
-
accessKey: string;
|
|
205
|
-
secretKey: string;
|
|
206
|
-
region?: string;
|
|
207
|
-
keyPrefix?: string;
|
|
208
|
-
};
|
|
114
|
+
s3?: LeaderDiffStore;
|
|
209
115
|
logger?: {
|
|
210
116
|
warn?: (m: string, x?: Record<string, unknown>) => void;
|
|
211
117
|
info?: (m: string, x?: Record<string, unknown>) => void;
|
|
@@ -279,6 +185,10 @@ export declare function stageWorkerEnv(env: WireEnv, opts: {
|
|
|
279
185
|
* (URL) silently killed long autonomous builds or expired the diff upload mid-run. core's turn cap is now a
|
|
280
186
|
* high net (10000), so the leader gives each worker an explicit triple bound; a sub-task's own limits override.
|
|
281
187
|
*/
|
|
188
|
+
/** The leader's diff-out URL lifetime (`presignTtlSec` = `LEADER_TIMEOUT_MS` / 1000 + 600: the URL outlives the worker) over the SigV4 ceiling ⇒ the
|
|
189
|
+
* refusal sentence, naming the knob and its largest value; within it ⇒ `undefined`. The runner refuses to be built with a diff-out store on such a
|
|
190
|
+
* configuration (boot), instead of signing URLs the store would refuse at the end of a worker's run. */
|
|
191
|
+
export declare function leaderDiffUrlTtlRefusal(presignTtlSec: number): string | undefined;
|
|
282
192
|
export declare function leaderResourceConfig(env?: NodeJS.ProcessEnv): {
|
|
283
193
|
leaderTimeoutMs: number;
|
|
284
194
|
workerMaxTurns: number;
|
package/dist/leader/wire.js
CHANGED
|
@@ -3,30 +3,30 @@ import { parseNumOrFail } from "../config.js";
|
|
|
3
3
|
import { execFileSync } from "node:child_process";
|
|
4
4
|
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { join } from "node:path";
|
|
6
|
+
import { randomUUID } from "node:crypto";
|
|
6
7
|
import { tmpdir } from "node:os";
|
|
7
|
-
import { Runner,
|
|
8
|
+
import { Runner, delimitUntrusted, hasDestroy, } from "@sema-agent/core";
|
|
8
9
|
import { leaderEntryRefusal, leaderRunEntry } from "./run-entry.js";
|
|
9
10
|
import { buildCheckpointCtx } from "../http/checkpoint-ctx.js";
|
|
11
|
+
import { submissionPermissionModeWrite } from "../permission-mode-admission.js";
|
|
10
12
|
import { serviceVersion } from "../service-version.js";
|
|
11
13
|
import { RemoteContainerExecutionEnv } from "../plugins/remote-env-e2b.js";
|
|
12
14
|
import { buildLaneHomeClaim } from "../execution-lane-caps.js";
|
|
13
15
|
const e2bBaseTemplateHomeSeat = buildLaneHomeClaim({ remoteExec: { provider: "e2b" } });
|
|
14
|
-
import { createDurableAskPolicy } from "../approval.js";
|
|
15
16
|
import { gitSubprocessEnv } from "../server-secret-env.js";
|
|
16
|
-
import {
|
|
17
|
-
import { buildUploadScript, buildUploadLoopScript, uploadLoopCommand, uploadLoopScriptPath, uploadStepSuffix, fetchUploadedDiff, withStaging, UPLOAD_LOOP_PERIOD_SEC } from "./diffup.js";
|
|
17
|
+
import { buildLeaderDiffUrls, buildUploadScript, buildUploadLoopScript, uploadLoopCommand, uploadLoopScriptPath, uploadStepSuffix, fetchUploadedDiff, withStaging, UPLOAD_LOOP_PERIOD_SEC } from "./diffup.js";
|
|
18
18
|
import { pullDiff, safeRev } from "./diffout.js";
|
|
19
|
-
import { runLeaderTask, withLeaderLeg } from "./leader.js";
|
|
19
|
+
import { LEADER_APPROVAL_SCOPE, leaderLegDurability, runLeaderTask, staticLaneWorkerPark, withLeaderLeg } from "./leader.js";
|
|
20
20
|
import { attachRepairLoopDeps } from "./repair-wire.js";
|
|
21
21
|
import { routePlanWithFallback, validateSubtasks } from "./planner.js";
|
|
22
|
-
import { createEngineNoticeSeat } from "../boot/runner-deps.js";
|
|
23
22
|
import { buildInternalRunCtx } from "../internal-run-env.js";
|
|
24
23
|
import { currentSubject } from "../observability/principal-context.js";
|
|
25
24
|
import { partsOf } from "../owner-brands.js";
|
|
26
25
|
import { taskSpecIdentityOf } from "../engine-identity.js";
|
|
27
26
|
import { redactHead } from "../observability/run-terminal.js";
|
|
27
|
+
import { seatText } from "../trace/exit-seat.js";
|
|
28
|
+
import { SIGV4_PRESIGN_MAX_SEC } from "../object-store-buckets.js";
|
|
28
29
|
const REPAIR_LOOP_WIRED = true;
|
|
29
|
-
export const LEADER_APPROVAL_SCOPE = "_leader";
|
|
30
30
|
export function leaderResourceScope(workerId) {
|
|
31
31
|
return `_leader-resource-${workerId}`;
|
|
32
32
|
}
|
|
@@ -104,6 +104,12 @@ function parseNumOrFailNonNegative(name, raw) {
|
|
|
104
104
|
throw new Error(`env ${name}=${n} must not be negative`);
|
|
105
105
|
return n;
|
|
106
106
|
}
|
|
107
|
+
export function leaderDiffUrlTtlRefusal(presignTtlSec) {
|
|
108
|
+
if (presignTtlSec <= SIGV4_PRESIGN_MAX_SEC)
|
|
109
|
+
return undefined;
|
|
110
|
+
const maxTimeoutMs = (SIGV4_PRESIGN_MAX_SEC - 600) * 1000;
|
|
111
|
+
return `LEADER_TIMEOUT_MS makes the leader's diff-out links live ${presignTtlSec} s (the worker timeout + 600 s), longer than a presigned URL can (at most ${SIGV4_PRESIGN_MAX_SEC} s (7 days)) — set LEADER_TIMEOUT_MS to at most ${maxTimeoutMs}`;
|
|
112
|
+
}
|
|
107
113
|
export function leaderResourceConfig(env = process.env) {
|
|
108
114
|
const leaderTimeoutMs = Math.max(600_000, Math.floor(parseNumOrFailNonNegative("LEADER_TIMEOUT_MS", env.LEADER_TIMEOUT_MS) || 0) || 86_400_000);
|
|
109
115
|
const workerMaxTurns = Math.floor(parseNumOrFailNonNegative("LEADER_WORKER_MAX_TURNS", env.LEADER_WORKER_MAX_TURNS) || 0) || 10_000;
|
|
@@ -199,22 +205,28 @@ export function createLeaderRunner(cfg) {
|
|
|
199
205
|
};
|
|
200
206
|
const ident = cfg.git ?? { name: "leader", email: "leader@local" };
|
|
201
207
|
const { leaderTimeoutMs, workerLimits, presignTtlSec, resourceSuspend: resourceCfg } = leaderResourceConfig();
|
|
208
|
+
const ttlRefusal = cfg.s3 !== undefined ? leaderDiffUrlTtlRefusal(presignTtlSec) : undefined;
|
|
209
|
+
if (ttlRefusal !== undefined)
|
|
210
|
+
throw new Error(ttlRefusal);
|
|
202
211
|
const { repairRounds, repairBudgetUsd, repairLoopOn, measureGatesOn, repairLoopAttempts, oracleFlakyK, replanBudgetUsd, } = leaderLoopConfig({ repairRounds: cfg.repairRounds });
|
|
203
|
-
const
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
212
|
+
const mintLegSessionId = (stem) => `leader-${stem}-${Date.now()}-${randomUUID()}`;
|
|
213
|
+
const bindLegSlot = (key, env) => {
|
|
214
|
+
const release = cfg.legSlots.bind(key, env);
|
|
215
|
+
if (release === undefined)
|
|
216
|
+
cfg.logger?.warn?.("sandbox_path_env_slot_at_capacity", { sessionId: key, leg: "leader" });
|
|
217
|
+
return release ?? (() => { });
|
|
218
|
+
};
|
|
219
|
+
const withLegSlot = (runner, env, key) => {
|
|
220
|
+
const orig = runner.runTaskStream.bind(runner);
|
|
221
|
+
runner.runTaskStream = (...args) => {
|
|
222
|
+
const release = bindLegSlot(key, env);
|
|
223
|
+
const stream = orig(...args);
|
|
224
|
+
void stream.result().then(release, release);
|
|
225
|
+
return stream;
|
|
226
|
+
};
|
|
227
|
+
return runner;
|
|
216
228
|
};
|
|
217
|
-
const mkRepair = (rawEnv, repoDir, oracleFiles,
|
|
229
|
+
const mkRepair = (rawEnv, repoDir, oracleFiles, birth) => {
|
|
218
230
|
if (repairRounds <= 0)
|
|
219
231
|
return undefined;
|
|
220
232
|
return {
|
|
@@ -227,7 +239,6 @@ export function createLeaderRunner(cfg) {
|
|
|
227
239
|
throw new Error(`oracle still present after remove (${f.path}) — refusing repair (measurement integrity)`);
|
|
228
240
|
}
|
|
229
241
|
try {
|
|
230
|
-
const runner = new Runner({ brain: cfg.brain, ...servedTableSeat, pricing: cfg.pricing, ...onNoticeSeat, ...governanceSeat, ...deploymentPostureSeat(), ...tracerSeat, ...usageWindowSeat, ...promptSourceSeat, ...onErrorSeat, ...modsSeat, ...handsSeat, executionEnv: rawEnv, rootPath: repoDir });
|
|
231
242
|
const objective = [
|
|
232
243
|
`The integrated project at ${repoDir} fails its build/test. Make the MINIMAL change to the working tree so this command exits 0 (cd into the repo and run it yourself to confirm):`,
|
|
233
244
|
` ${testCmd}`,
|
|
@@ -236,17 +247,20 @@ export function createLeaderRunner(cfg) {
|
|
|
236
247
|
``,
|
|
237
248
|
delimitUntrusted("FAILING OUTPUT (untrusted)", errorText),
|
|
238
249
|
].join("\n");
|
|
250
|
+
const repairSessionId = mintLegSessionId(`repair-${round}`);
|
|
251
|
+
const runner = withLegSlot(new Runner({ ...cfg.plane(), executionEnv: rawEnv, rootPath: repoDir }), rawEnv, repairSessionId);
|
|
239
252
|
const res = await runner
|
|
240
253
|
.runTaskStream(withLeaderLeg({
|
|
241
254
|
objective,
|
|
242
|
-
|
|
243
|
-
sessionId: `leader-repair-${Date.now()}-${round}`,
|
|
255
|
+
sessionId: repairSessionId,
|
|
244
256
|
signal,
|
|
245
257
|
limits: { maxCostUsd: repairBudgetUsd, maxWalltimeMs: Math.max(300_000, Math.floor(leaderTimeoutMs / 2)) },
|
|
246
|
-
},
|
|
258
|
+
}, birth, { slotKey: repairSessionId, durability: leaderLegDurability({ continuation: "in_run" }), executor: { kind: "fresh" } }))
|
|
247
259
|
.result();
|
|
248
|
-
if (res.terminal.kind !== "completed")
|
|
249
|
-
|
|
260
|
+
if (res.terminal.kind !== "completed") {
|
|
261
|
+
const plane = outwardPlane(res.terminal);
|
|
262
|
+
throw new Error(`repair round ${round} did not complete (status=${plane.status}${plane.errorMessage !== undefined ? `: ${plane.errorMessage}` : ""})`);
|
|
263
|
+
}
|
|
250
264
|
return { costUsd: res.stats?.costMicroUsd !== undefined ? res.stats.costMicroUsd / 1e6 : undefined, note: res.result?.slice(0, 200) };
|
|
251
265
|
}
|
|
252
266
|
finally {
|
|
@@ -274,6 +288,8 @@ export function createLeaderRunner(cfg) {
|
|
|
274
288
|
const refused = leaderEntryRefusal(entry);
|
|
275
289
|
if (refused !== undefined)
|
|
276
290
|
return { ok: false, reports: [], cancelled: false, error: refused };
|
|
291
|
+
const subject = currentSubject();
|
|
292
|
+
const birth = { entry, identity: taskSpecIdentityOf(subject === undefined ? undefined : partsOf(subject)), govern: cfg.govern, baseline: cfg.baseline, auth: cfg.auth };
|
|
277
293
|
const injectOracles = async (env) => {
|
|
278
294
|
const ofs = body.oracleFiles ?? [];
|
|
279
295
|
if (ofs.length === 0)
|
|
@@ -295,15 +311,21 @@ export function createLeaderRunner(cfg) {
|
|
|
295
311
|
if (Array.isArray(body.subtasks) && body.subtasks.length > 0) {
|
|
296
312
|
return validateSubtasks(body.subtasks);
|
|
297
313
|
}
|
|
298
|
-
const planRunner = new Runner({
|
|
314
|
+
const planRunner = new Runner({ ...cfg.plane() });
|
|
315
|
+
const routeAuth = birth.auth(undefined);
|
|
299
316
|
const runRoute = async (prompt) => {
|
|
300
317
|
const res = await planRunner.runTaskStream({
|
|
301
318
|
objective: prompt,
|
|
302
|
-
...
|
|
303
|
-
|
|
319
|
+
...birth.identity,
|
|
320
|
+
getApiKeyAndHeaders: routeAuth,
|
|
321
|
+
sessionId: mintLegSessionId("route"),
|
|
304
322
|
signal,
|
|
305
323
|
...(cfg.routerModel ? { model: cfg.routerModel } : { modelRole: "classifier" }),
|
|
306
324
|
}).result();
|
|
325
|
+
if (res.terminal.kind !== "completed") {
|
|
326
|
+
const plane = outwardPlane(res.terminal);
|
|
327
|
+
cfg.logger?.warn?.("plan_route_run_incomplete", { status: plane.status, ...(plane.errorMessage !== undefined ? { err: seatText("operator-log-error", plane.errorMessage) } : {}) });
|
|
328
|
+
}
|
|
307
329
|
return res.result ?? "";
|
|
308
330
|
};
|
|
309
331
|
const { subs, collapsed, rawSample } = await routePlanWithFallback(body.objective, runRoute, {
|
|
@@ -315,23 +337,18 @@ export function createLeaderRunner(cfg) {
|
|
|
315
337
|
return subs;
|
|
316
338
|
};
|
|
317
339
|
const provisionWorker = async (sub) => {
|
|
318
|
-
const sessionId =
|
|
319
|
-
const
|
|
340
|
+
const sessionId = mintLegSessionId(sub.workerId);
|
|
341
|
+
const factory = cfg.s3 !== undefined && cfg.envFactory !== undefined ? { s3: cfg.s3, envFactory: cfg.envFactory } : undefined;
|
|
342
|
+
const park = factory !== undefined ? cfg.durable?.() : staticLaneWorkerPark(cfg.durable?.(), cfg.approvalListInForce());
|
|
320
343
|
const resumeBody = { ...entry, objective: sub.spec.objective };
|
|
321
|
-
const storedResumeCtx =
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
durableSpec = {
|
|
326
|
-
toolPolicy: combinePolicies(createDurableQuestionPolicy(), createDurableAskPolicy({ requireApproval: d.requireApproval, ...(d.deny ? { deny: d.deny } : {}), ...(d.autoBudget ? { autoBudget: d.autoBudget } : {}), ...(d.neverAuto ? { neverAuto: d.neverAuto } : {}) })),
|
|
327
|
-
checkpointStore: d.checkpointStore,
|
|
328
|
-
durableApproval: { scope: LEADER_APPROVAL_SCOPE, ...(d.ttlMs ? { ttlMs: d.ttlMs } : {}) },
|
|
329
|
-
onQuestion: QUESTION_AWAITS_RESUME,
|
|
330
|
-
};
|
|
331
|
-
await d.checkpointStore.putCtx(sessionId, storedResumeCtx).catch((e) => {
|
|
344
|
+
const storedResumeCtx = park !== undefined ? buildCheckpointCtx({ body: resumeBody, unattendedLeg: true, writerVersion: serviceVersion(), permissionModeWrite: submissionPermissionModeWrite(resumeBody) }, park.ctxSealer, sessionId) : undefined;
|
|
345
|
+
const durability = leaderLegDurability(park === undefined || storedResumeCtx === undefined
|
|
346
|
+
? { continuation: "replay", resumeCtx: "unwritten" }
|
|
347
|
+
: await park.checkpointStore.putCtx(sessionId, storedResumeCtx).then(() => ({ continuation: "replay", resumeCtx: "landed", park }), (e) => {
|
|
332
348
|
cfg.logger?.warn?.("leader_putctx_failed", { workerId: sub.workerId, err: redactHead(e instanceof Error ? e.message : String(e), 2000) });
|
|
333
|
-
|
|
334
|
-
|
|
349
|
+
return { continuation: "replay", resumeCtx: "lost" };
|
|
350
|
+
}));
|
|
351
|
+
const durable = durability.kind === "durable" ? durability.park : undefined;
|
|
335
352
|
let resourceSpec = {};
|
|
336
353
|
const repairLoopActive = repairLoopOn && REPAIR_LOOP_WIRED;
|
|
337
354
|
if (repairLoopActive && resourceCfg) {
|
|
@@ -348,8 +365,8 @@ export function createLeaderRunner(cfg) {
|
|
|
348
365
|
else if (resourceCfg && !repairLoopActive) {
|
|
349
366
|
cfg.logger?.warn?.("leader_resource_suspend_inactive", {
|
|
350
367
|
workerId: sub.workerId,
|
|
351
|
-
reason:
|
|
352
|
-
?
|
|
368
|
+
reason: durability.kind === "transient"
|
|
369
|
+
? durability.why
|
|
353
370
|
: !cfg.toolResultStore
|
|
354
371
|
? "no durable tool-result store"
|
|
355
372
|
: "no durable session store",
|
|
@@ -360,8 +377,8 @@ export function createLeaderRunner(cfg) {
|
|
|
360
377
|
if (!d || storedResumeCtx === undefined)
|
|
361
378
|
return runner;
|
|
362
379
|
const orig = runner.runTaskStream.bind(runner);
|
|
363
|
-
runner.runTaskStream = (
|
|
364
|
-
const stream = orig(
|
|
380
|
+
runner.runTaskStream = (...args) => {
|
|
381
|
+
const stream = orig(...args);
|
|
365
382
|
const iv = setInterval(() => {
|
|
366
383
|
void d.checkpointStore.putCtx(sessionId, storedResumeCtx).catch(() => { });
|
|
367
384
|
}, 45_000);
|
|
@@ -371,16 +388,11 @@ export function createLeaderRunner(cfg) {
|
|
|
371
388
|
};
|
|
372
389
|
return runner;
|
|
373
390
|
};
|
|
374
|
-
if (
|
|
375
|
-
const s3 =
|
|
376
|
-
const envFactory = cfg.envFactory;
|
|
391
|
+
if (factory !== undefined) {
|
|
392
|
+
const { s3, envFactory } = factory;
|
|
377
393
|
const baseSha = body.baseSha;
|
|
378
394
|
const seedCmd = body.seedCmd;
|
|
379
|
-
const
|
|
380
|
-
const ttl = presignTtlSec;
|
|
381
|
-
const base = { endpoint: s3.endpoint, bucket: s3.bucket, accessKey: s3.accessKey, secretKey: s3.secretKey, ...(s3.region ? { region: s3.region } : {}), key, expiresSec: ttl };
|
|
382
|
-
const putUrl = presignS3Url({ ...base, method: "PUT" });
|
|
383
|
-
const getUrl = presignS3Url({ ...base, method: "GET" });
|
|
395
|
+
const { putUrl, getUrl } = buildLeaderDiffUrls(s3, sub.workerId, presignTtlSec);
|
|
384
396
|
const script = buildUploadScript({ repoDir: repo, baseSha, putUrl, workDir: W });
|
|
385
397
|
const stage = async (env) => {
|
|
386
398
|
await stageWorkerEnv(env, { seedCmd, repo, branch: sub.branch, uploadScriptPath: `${W}/.leader-upload.sh`, uploadScript: script });
|
|
@@ -389,21 +401,22 @@ export function createLeaderRunner(cfg) {
|
|
|
389
401
|
return {
|
|
390
402
|
workerId: sub.workerId, sessionId, branch: sub.branch,
|
|
391
403
|
baseSha,
|
|
392
|
-
runner: keepCtxWarm(new Runner({
|
|
393
|
-
brain: cfg.brain, ...servedTableSeat, pricing: cfg.pricing, ...onNoticeSeat, ...governanceSeat, ...deploymentPostureSeat(), ...tracerSeat, ...usageWindowSeat, ...promptSourceSeat, ...onErrorSeat, ...modsSeat, ...handsSeat,
|
|
404
|
+
runner: keepCtxWarm(new Runner({ ...cfg.plane(),
|
|
394
405
|
...(cfg.toolResultStore ? { toolResultStore: cfg.toolResultStore } : {}),
|
|
395
406
|
...(cfg.sessionStore ? { sessionStore: cfg.sessionStore } : {}),
|
|
396
407
|
executionEnvFactory: async (ctx) => {
|
|
397
408
|
const env = await envFactory(ctx);
|
|
398
409
|
assertLeaderOwnedEnvReapable(env, "leader worker sandbox");
|
|
410
|
+
const releaseSlot = bindLegSlot(sessionId, env);
|
|
399
411
|
return withStaging(env, stage, async (e) => {
|
|
412
|
+
releaseSlot();
|
|
400
413
|
await stopUploadLoop(e, sub.workerId);
|
|
401
414
|
await sh(e)(`cd ${repo} && git add -A && git -c user.name='leader-belt' -c user.email='belt@leader' commit -qm 'belt: auto-commit uncommitted worker output' || true; sh ${W}/.leader-upload.sh`);
|
|
402
415
|
});
|
|
403
416
|
},
|
|
404
417
|
})),
|
|
405
418
|
fetchDiff: () => fetchUploadedDiff(getUrl),
|
|
406
|
-
spec: withLeaderLeg({ ...workerLimits, ...sub.spec, ...
|
|
419
|
+
spec: withLeaderLeg({ ...workerLimits, ...sub.spec, ...resourceSpec, objective: `${sub.spec.objective}${uploadStepSuffix(W)}` }, birth, { slotKey: sessionId, durability, executor: { kind: "fresh" } }),
|
|
407
420
|
};
|
|
408
421
|
}
|
|
409
422
|
if (!cfg.e2bApiKey)
|
|
@@ -415,15 +428,15 @@ export function createLeaderRunner(cfg) {
|
|
|
415
428
|
const baseSha = await sh(env)(`cd ${repo} && git rev-parse HEAD`);
|
|
416
429
|
return {
|
|
417
430
|
workerId: sub.workerId, sessionId, branch: sub.branch, baseSha,
|
|
418
|
-
runner: keepCtxWarm(new Runner({
|
|
431
|
+
runner: keepCtxWarm(withLegSlot(new Runner({ ...cfg.plane(), ...(cfg.toolResultStore ? { toolResultStore: cfg.toolResultStore } : {}), ...(cfg.sessionStore ? { sessionStore: cfg.sessionStore } : {}), executionEnv: env }), env, sessionId)),
|
|
419
432
|
diffEnv: env,
|
|
420
433
|
destroy: () => env.destroy().then(() => { }),
|
|
421
|
-
spec: withLeaderLeg({ ...workerLimits, ...sub.spec, ...
|
|
434
|
+
spec: withLeaderLeg({ ...workerLimits, ...sub.spec, ...resourceSpec }, birth, { slotKey: sessionId, durability, executor: { kind: "fresh" } }),
|
|
422
435
|
};
|
|
423
436
|
};
|
|
424
437
|
const provisionIntegrationSandbox = async () => {
|
|
425
438
|
if (cfg.envFactory) {
|
|
426
|
-
const integSessionId =
|
|
439
|
+
const integSessionId = mintLegSessionId("integ");
|
|
427
440
|
const env = await cfg.envFactory(buildInternalRunCtx(integSessionId));
|
|
428
441
|
const reap = createEnvReaper(env, "leader integration sandbox");
|
|
429
442
|
try {
|
|
@@ -436,7 +449,7 @@ export function createLeaderRunner(cfg) {
|
|
|
436
449
|
}
|
|
437
450
|
const rawEnv = env;
|
|
438
451
|
const oracleFiles = body.oracleFiles ?? [];
|
|
439
|
-
const repair = mkRepair(rawEnv, repo, oracleFiles,
|
|
452
|
+
const repair = mkRepair(rawEnv, repo, oracleFiles, birth);
|
|
440
453
|
return { env: asIntegrationEnv(env), destroy: reap, ...(repair ? { repair } : {}) };
|
|
441
454
|
}
|
|
442
455
|
if (!cfg.e2bApiKey)
|
|
@@ -454,11 +467,12 @@ export function createLeaderRunner(cfg) {
|
|
|
454
467
|
await env.destroy().catch(() => { });
|
|
455
468
|
throw e;
|
|
456
469
|
}
|
|
457
|
-
|
|
470
|
+
const repair = mkRepair(env, repo, body.oracleFiles ?? [], birth);
|
|
471
|
+
return { env: asIntegrationEnv(env), destroy: () => env.destroy().then(() => { }), ...(repair ? { repair } : {}) };
|
|
458
472
|
};
|
|
459
473
|
const push = createCoordinatorPush(body.durableRemote, body.targetRef, ident);
|
|
460
474
|
const deps = {
|
|
461
|
-
|
|
475
|
+
birth,
|
|
462
476
|
signal,
|
|
463
477
|
plan,
|
|
464
478
|
provisionWorker,
|
|
@@ -476,7 +490,7 @@ export function createLeaderRunner(cfg) {
|
|
|
476
490
|
const resolveRepair = async (solo, _sub) => {
|
|
477
491
|
let env;
|
|
478
492
|
if (cfg.envFactory) {
|
|
479
|
-
const graderSessionId =
|
|
493
|
+
const graderSessionId = mintLegSessionId("grader");
|
|
480
494
|
env = await cfg.envFactory(buildInternalRunCtx(graderSessionId));
|
|
481
495
|
}
|
|
482
496
|
else {
|
package/dist/memory-scope.d.ts
CHANGED
|
@@ -174,20 +174,31 @@ export declare function memoryEngineRootFor(config: Pick<ServiceConfig, "memoryE
|
|
|
174
174
|
* 所以它的根必须走这条链而不是 `memoryEngineRootFor` 的分派(codex 修复验证轮 [medium]:分派会把 run-local 的
|
|
175
175
|
* 记忆搬到 `<localDataRoot>/memory-work`,存量记忆与控制面升级后隐形)。 */
|
|
176
176
|
export declare function fileMemoryEngineRoot(config: Pick<ServiceConfig, "memoryEngineDir">, fallbackRoot?: string): string;
|
|
177
|
+
/**
|
|
178
|
+
* 一段路径**在不在盘**的唯一读法(三态,{@link canonicalPathOf} 逐段走用它;host 车道托管判在「读不出就不删」那一臂登记根时也读它):
|
|
179
|
+
* · `stat` 得动(跟随符号链接)⇒ `true`(在);
|
|
180
|
+
* · `ENOENT` / `ENOTDIR`(这一处不存在、悬空链接的目标不存在、中间一段不是目录)⇒ `false`(不在);
|
|
181
|
+
* · 其余错误(`EACCES` 没有搜索权限的段、`ELOOP` 链接成环、I/O 错误……)⇒ **原样抛**(读不出)。读不出不是「不在」:把它读成不在,
|
|
182
|
+
* 下游的路径包含判就会把一处它根本看不见的目录判成「不在根里」—— 那正是删除面上的 fail-open。
|
|
183
|
+
*/
|
|
184
|
+
export declare function presentOnDisk(p: string): boolean;
|
|
177
185
|
/**
|
|
178
186
|
* 一条路径的**规范形**(给 {@link judgeMemoryRootOutsideDataRoot} 的 `canonical` 座用的生产实现;host 车道的工作区托管判也读它):
|
|
179
|
-
* ·
|
|
187
|
+
* · 在盘的绝对路径 ⇒ **原样**交给 `realpath`(core `physicalPathOf` = realpath(3):大小写不敏感的文件系统上返回盘上的拼写;符号链接、macOS 的 `/var` → `/private/var` 在这一步展平)。
|
|
180
188
|
* 不先在字串上折 `..`:操作系统在展开符号链接**之后**才折 `..`,`/link/..` 的真身是链接目标的父目录,字串折叠会把它读成 `/`;
|
|
181
|
-
* · 其余(
|
|
182
|
-
* 与操作系统同序(`/别名/../新目录` 的真身在链接目标的父目录下;先在字串上折会读成别名的父目录,判到另一只挂载上)
|
|
189
|
+
* · 其余(尚不在盘 / 相对)⇒ 绝对化(**不折叠**)后逐段走:在盘的前缀每进一段取一次 `realpath`(符号链接在这一步展开),`..` 折在**已展开**的前缀上 ——
|
|
190
|
+
* 与操作系统同序(`/别名/../新目录` 的真身在链接目标的父目录下;先在字串上折会读成别名的父目录,判到另一只挂载上);第一段不在盘起,余下是尚不在盘的尾巴
|
|
183
191
|
* (尾巴只做字串规范化,与 `mkdir -p` 建出来的同形)。
|
|
184
192
|
*
|
|
185
|
-
*
|
|
186
|
-
* 而数据根那一侧已经存在、会被展平 ——
|
|
187
|
-
*
|
|
188
|
-
*
|
|
193
|
+
* 为什么按「最深在盘祖先」而不是直接 `realpath(p)`:boot 期记忆根常常还没建出来(新数据根),`realpath` 对不存在的路径抛 ENOENT,
|
|
194
|
+
* 而数据根那一侧已经存在、会被展平 —— 两侧拼写空间不一样,同一个目录会被读成「不在其下」。
|
|
195
|
+
*
|
|
196
|
+
* **读不出就抛**:每一段在不在盘读 {@link presentOnDisk}(三态)—— 不在(`ENOENT` / `ENOTDIR`)才接成尾巴;没有搜索权限的段、成环的链接、`realpath` 在
|
|
197
|
+
* 「探完到取值之间目录被挪走 / 搜索权限被收」的竞态里失败,一律**原样抛**,不在本函数里吞(吞了就是一条无声的降级臂:把看不见的一段当成「还不存在」,包含判就答
|
|
198
|
+
* 「不在里面」)。调用方各自接住、按自己的面响亮说「查不了」:起服记忆根判(`memory_engine_dir_check_unavailable`)· 配置根判(`sema_config_root_workspace_check_unavailable`)·
|
|
199
|
+
* 店的持久性取证(`path_unresolvable`)· host 车道托管判(铸时 ⇒ 这条腿不铸;删前 ⇒ 不删、留给退出兜底)。
|
|
189
200
|
*
|
|
190
|
-
* 取舍:尾巴(
|
|
201
|
+
* 取舍:尾巴(不在盘的那几段)只比规范化字串,**不折大小写**,尾巴里的 `..` 按字串折:两个只差大小写、且都还不在盘的拼写在大小写不敏感的盘上会被读成两处 ——
|
|
191
202
|
* 方向是多报一条 warn(这条判据的失败方向),不会漏报。
|
|
192
203
|
*/
|
|
193
204
|
export declare function canonicalPathOf(p: string): string;
|
|
@@ -195,7 +206,7 @@ export declare function canonicalPathOf(p: string): string;
|
|
|
195
206
|
* **路径包含**(含相等)的判官:`child` 是不是 `root` 本身或它的后代 —— `path.relative(canonical(root), canonical(child))` 不是 `..`、不以 `..` 加分隔符起头、也不是绝对路径(跨盘符)。
|
|
196
207
|
* `..` 要按**整段**判:名为 `..data` 的子目录在其下;`startsWith("..")` 会把它读成在其外。`canonical` 座缺省 `path.resolve`(字串规范形),boot 递 {@link canonicalPathOf} 取符号链接展平后的形;
|
|
197
208
|
* 两侧同一只座(先 root、后 child)。读者三处:记忆根「在数据根之外」那一判({@link judgeMemoryRootOutsideDataRoot})、起服时「配置根是不是工作区的祖先」那一判(`sema-config-dir.ts`)
|
|
198
|
-
* 与 host
|
|
209
|
+
* 与 host 车道工厂托管的两判(`plugins/remote-env-host.ts`,座 = {@link canonicalPathOf}:铸时「腿的目录落在哪只本服务铸的临时根里」· 删前「此刻谁的工作目录在这只根里」);
|
|
199
210
|
* 树里别处内联的同形表达式(`boot/deployment-mods.ts` · `plugins/local-data-dir-modes-m39.ts` · `plugins/remote-env-host.ts` 的残余镜像写判 · `plugins/worktree-isolation.ts`)不在本次收口范围。
|
|
200
211
|
*/
|
|
201
212
|
export declare function pathIsWithin(root: string, child: string, canonical?: (p: string) => string): boolean;
|