@sema-agent/server 7.123.0 → 7.124.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 +132 -0
- package/README.md +2 -2
- package/README.zh-CN.md +2 -2
- package/USAGE.md +53 -51
- package/dist/approval-ask-audit-store.d.ts +27 -32
- package/dist/approval-ask-audit-store.js +10 -9
- package/dist/approval-crash-convergence.d.ts +2 -2
- package/dist/approval-crash-convergence.js +5 -5
- package/dist/approval-deny-reasons.d.ts +163 -51
- package/dist/approval-deny-reasons.js +79 -8
- package/dist/approval-policy-settlement.d.ts +4 -1
- package/dist/approval-policy-settlement.js +3 -2
- package/dist/approval-reconciler.d.ts +3 -3
- package/dist/approval-reconciler.js +10 -10
- package/dist/approval.d.ts +1 -1
- package/dist/approval.js +1 -1
- package/dist/audit.js +1 -1
- package/dist/auth-bridge.d.ts +8 -8
- package/dist/auth-bridge.js +6 -6
- package/dist/auth-keys.d.ts +2 -2
- package/dist/auto-mode-face.d.ts +1 -1
- package/dist/boot/budget-tracing.js +1 -1
- package/dist/boot/execution-env.js +1 -0
- package/dist/boot/leader.d.ts +1 -1
- package/dist/boot/memory-consolidation.d.ts +4 -4
- package/dist/boot/org-memory.d.ts +3 -3
- package/dist/boot/org-memory.js +5 -5
- package/dist/boot/resolve-spec.js +7 -7
- package/dist/boot/runner-deps.d.ts +1 -1
- package/dist/boot/runtime-caps.d.ts +1 -1
- package/dist/boot/runtime-caps.js +10 -10
- package/dist/boot/shutdown.d.ts +2 -2
- package/dist/boot/shutdown.js +2 -2
- package/dist/boot/side-query-lane.d.ts +3 -3
- package/dist/boot/{stage-02-registry-pull.d.ts → stage-02-web-admin-pull.d.ts} +2 -2
- package/dist/boot/{stage-02-registry-pull.js → stage-02-web-admin-pull.js} +4 -4
- package/dist/boot/stage-03-store-backend.d.ts +2 -2
- package/dist/boot/stage-04-stores.d.ts +1 -1
- package/dist/boot/stage-05-execution-env.d.ts +1 -1
- package/dist/boot/stage-06-runners.d.ts +2 -2
- package/dist/boot/stage-06-runners.js +6 -6
- package/dist/boot/stage-07-capability-layer.d.ts +2 -2
- package/dist/boot/stage-07-capability-layer.js +6 -5
- package/dist/boot/stage-08-reapers.d.ts +3 -3
- package/dist/boot/stage-08-reapers.js +3 -3
- package/dist/boot/stage-09-leader.d.ts +3 -3
- package/dist/boot/stage-09-leader.js +7 -7
- package/dist/boot/stage-10-http-server.d.ts +3 -3
- package/dist/boot/stage-10-http-server.js +19 -19
- package/dist/boot/unpriced-ceiling-verdict.d.ts +1 -1
- package/dist/boot/{config-center.d.ts → web-admin.d.ts} +11 -11
- package/dist/boot/{config-center.js → web-admin.js} +38 -22
- package/dist/boot/webfetch-summarize-lane.d.ts +2 -2
- package/dist/brain.d.ts +1 -1
- package/dist/brain.js +1 -1
- package/dist/budget.d.ts +3 -3
- package/dist/canonical-json.d.ts +2 -2
- package/dist/capabilities/center-plugins.d.ts +1 -1
- package/dist/capabilities/center-wiring.d.ts +12 -5
- package/dist/capabilities/center-wiring.js +11 -2
- package/dist/capabilities/composite-members.d.ts +1 -1
- package/dist/capabilities/composite-members.js +1 -1
- package/dist/capabilities/scenarios.js +2 -2
- package/dist/capabilities/team.d.ts +1 -1
- package/dist/capabilities/tool-defer.d.ts +1 -1
- package/dist/center-credential-renewer.d.ts +1 -1
- package/dist/center-credential-renewer.js +7 -7
- package/dist/center-credential.d.ts +9 -9
- package/dist/center-credential.js +6 -6
- package/dist/config-catalog.d.ts +7 -10
- package/dist/config-catalog.js +15 -15
- package/dist/config-d-migration.d.ts +32 -0
- package/dist/config-d-migration.js +59 -0
- package/dist/config-invariants.d.ts +14 -4
- package/dist/config-invariants.js +31 -2
- package/dist/config-lkg.d.ts +26 -6
- package/dist/config-lkg.js +43 -14
- package/dist/config-provider.d.ts +23 -19
- package/dist/config-provider.js +24 -26
- package/dist/config-types.d.ts +52 -51
- package/dist/config.d.ts +9 -46
- package/dist/config.js +33 -92
- package/dist/execution-lane-caps.d.ts +1 -1
- package/dist/fleet/drain-entry.d.ts +1 -1
- package/dist/fleet/engine-signal.d.ts +8 -8
- package/dist/fleet/fleet-bus.d.ts +12 -3
- package/dist/fleet/fleet-bus.js +13 -9
- package/dist/fleet/serving-lease.d.ts +3 -3
- package/dist/fleet/serving-lease.js +1 -1
- package/dist/fleet-client.d.ts +7 -7
- package/dist/fleet-client.js +5 -4
- package/dist/fleet-lease.d.ts +3 -3
- package/dist/fleet-lease.js +2 -2
- package/dist/host-lsp-manager.d.ts +1 -1
- package/dist/hosted-posture.d.ts +4 -4
- package/dist/http/admission.js +4 -4
- package/dist/http/checkpoint-ctx.d.ts +20 -3
- package/dist/http/checkpoint-ctx.js +13 -5
- package/dist/http/dispatch.js +2 -2
- package/dist/http/durable-run-leg.js +2 -1
- package/dist/http/health-self-report.d.ts +4 -4
- package/dist/http/health-self-report.js +3 -3
- package/dist/http/idempotency.d.ts +1 -1
- package/dist/http/resume-legs.d.ts +4 -3
- package/dist/http/resume-legs.js +31 -18
- package/dist/http/route-ctx.d.ts +8 -0
- package/dist/http/routes/admin-config-refresh.d.ts +1 -1
- package/dist/http/routes/admin-config-refresh.js +1 -1
- package/dist/http/routes/admin-drain.d.ts +1 -1
- package/dist/http/routes/admin-drain.js +5 -4
- package/dist/http/routes/approvals-assistant.js +4 -4
- package/dist/http/routes/capabilities.js +5 -5
- package/dist/http/routes/config-catalog.js +2 -3
- package/dist/http/routes/diagnostics.js +1 -1
- package/dist/http/routes/runs.js +8 -4
- package/dist/http/routes/sessions-list.js +2 -1
- package/dist/http/routes/sessions.js +1 -1
- package/dist/http/routes/side-query.js +3 -3
- package/dist/http/routes/tasks.js +3 -2
- package/dist/http/run-meta.d.ts +1 -1
- package/dist/http/run-meta.js +2 -2
- package/dist/http/server.d.ts +7 -7
- package/dist/http/server.js +1 -1
- package/dist/http/stored-body-replay.js +3 -2
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/key-resolver.d.ts +1 -1
- package/dist/leader/wire.d.ts +2 -2
- package/dist/leader/wire.js +2 -1
- package/dist/main.js +1 -1
- package/dist/mcp-tool-faces.d.ts +2 -2
- package/dist/model-entry-refusal.d.ts +3 -3
- package/dist/model-entry-refusal.js +4 -4
- package/dist/model-provider.d.ts +2 -2
- package/dist/model-route-endpoint.d.ts +1 -1
- package/dist/model-route-url.d.ts +1 -1
- package/dist/model-route-url.js +2 -1
- package/dist/model-select.d.ts +24 -21
- package/dist/model-select.js +22 -17
- package/dist/observability/metrics.d.ts +1 -1
- package/dist/org-memory-admission.d.ts +1 -1
- package/dist/plugins/approval-ask-store-file.d.ts +4 -2
- package/dist/plugins/approval-ask-store-file.js +3 -3
- package/dist/plugins/approval-ask-store-memory.d.ts +4 -3
- package/dist/plugins/approval-ask-store-memory.js +10 -4
- package/dist/plugins/approval-ask-store-sql.d.ts +16 -2
- package/dist/plugins/approval-ask-store-sql.js +20 -13
- package/dist/plugins/caching-session-store.d.ts +0 -10
- package/dist/plugins/caching-session-store.js +0 -3
- package/dist/plugins/file-run-store.js +9 -3
- package/dist/plugins/leader-run-store-sql.d.ts +3 -2
- package/dist/plugins/leader-run-store-sql.js +3 -2
- package/dist/plugins/local-session-store.d.ts +20 -27
- package/dist/plugins/local-session-store.js +19 -17
- package/dist/plugins/memory-run-store.js +9 -3
- package/dist/plugins/one-time-migrations.js +26 -2
- package/dist/plugins/scheduler-support.d.ts +26 -7
- package/dist/plugins/scheduler-support.js +96 -53
- package/dist/plugins/store-backend.js +1 -1
- package/dist/plugins/store-contracts.d.ts +20 -4
- package/dist/plugins/web-search.d.ts +1 -1
- package/dist/plugins/web-search.js +2 -1
- package/dist/posture-source.d.ts +1 -1
- package/dist/read-face-posture.d.ts +3 -3
- package/dist/read-face-posture.js +1 -1
- package/dist/run-local.js +6 -3
- package/dist/runtime-caps-resolver.d.ts +4 -4
- package/dist/runtime-caps-resolver.js +2 -2
- package/dist/runtime-governance.d.ts +5 -5
- package/dist/sealed-key.d.ts +4 -4
- package/dist/sealed-key.js +3 -2
- package/dist/security.d.ts +3 -3
- package/dist/service-version.d.ts +1 -1
- package/dist/service-version.js +5 -0
- package/dist/session-titler.d.ts +0 -11
- package/dist/session-titler.js +3 -5
- package/dist/shared-memory-scope-authorizer.d.ts +4 -4
- package/dist/task-a2a.d.ts +1 -1
- package/dist/tool-approval.d.ts +43 -4
- package/dist/tool-approval.js +147 -98
- package/dist/trace/core-keyset-guard.d.ts +1 -1
- package/dist/trace/project.d.ts +3 -3
- package/dist/trace/redact.d.ts +2 -23
- package/dist/trace/redact.js +1 -6
- package/dist/trace/self-minted-wire.d.ts +147 -3
- package/dist/trace/self-minted-wire.js +50 -9
- package/dist/url-refusal.d.ts +35 -0
- package/dist/url-refusal.js +15 -0
- package/dist/user-authored-text.d.ts +31 -0
- package/dist/user-authored-text.js +18 -0
- package/dist/{config-center → web-admin-client}/apply-effective.d.ts +13 -70
- package/dist/{config-center → web-admin-client}/apply-effective.js +100 -119
- package/dist/{config-center → web-admin-client}/apply-ledger.d.ts +2 -2
- package/dist/{config-center → web-admin-client}/center-request.d.ts +7 -7
- package/dist/{config-center → web-admin-client}/center-request.js +5 -4
- package/dist/{config-center → web-admin-client}/effective-keys.d.ts +1 -3
- package/dist/{config-center → web-admin-client}/effective-keys.js +0 -9
- package/dist/{config-center → web-admin-client}/facade.d.ts +6 -6
- package/dist/{config-center → web-admin-client}/facade.js +2 -2
- package/dist/{config-center → web-admin-client}/http-client.d.ts +6 -10
- package/dist/{config-center → web-admin-client}/http-client.js +12 -12
- package/dist/{config-center → web-admin-client}/pull-state.d.ts +1 -1
- package/dist/{config-center → web-admin-client}/read-face.js +4 -4
- package/dist/{config-center → web-admin-client}/read-warnings.d.ts +23 -16
- package/dist/{config-center → web-admin-client}/read-warnings.js +33 -23
- package/dist/{config-center → web-admin-client}/restart-signal.d.ts +5 -3
- package/dist/{config-center → web-admin-client}/restart-signal.js +3 -4
- package/dist/{config-center → web-admin-client}/skills-mcp.d.ts +1 -1
- package/dist/{config-center → web-admin-client}/skills-mcp.js +13 -13
- package/dist/{config-center → web-admin-client}/stage-limits.d.ts +1 -7
- package/dist/{config-center → web-admin-client}/stage-limits.js +6 -7
- package/dist/{config-center → web-admin-client}/types.d.ts +12 -39
- package/package.json +2 -2
- package/skills/find-skills.md +2 -2
- package/dist/url-shape.d.ts +0 -31
- package/dist/url-shape.js +0 -41
- /package/dist/{config-center → web-admin-client}/apply-ledger.js +0 -0
- /package/dist/{config-center → web-admin-client}/hot-keys-registry.d.ts +0 -0
- /package/dist/{config-center → web-admin-client}/hot-keys-registry.js +0 -0
- /package/dist/{config-center → web-admin-client}/mcp-revocation.d.ts +0 -0
- /package/dist/{config-center → web-admin-client}/mcp-revocation.js +0 -0
- /package/dist/{config-center → web-admin-client}/pull-state.js +0 -0
- /package/dist/{config-center → web-admin-client}/read-face.d.ts +0 -0
- /package/dist/{config-center → web-admin-client}/types.js +0 -0
package/dist/config.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Model, type PathRuleBases, type PermissionRule } from "@sema-agent/core";
|
|
2
|
-
import { type CenterEndpoint } from "./
|
|
2
|
+
import { type CenterEndpoint } from "./web-admin-client/center-request.js";
|
|
3
3
|
import { type Autonomy } from "./runtime-governance.js";
|
|
4
4
|
import { type RunnerEnvNameAllowlistKnob, type ServerEnvNameAllowlistKnob } from "./env-name-allowlist-knobs.js";
|
|
5
5
|
import type { ServiceConfig, ServiceConfigFlat, ServiceConfigGroups } from "./config-types.js";
|
|
@@ -12,7 +12,7 @@ export { RETENTION_MODES, MEMORY_CONSOLIDATION_MIN_INTERVAL_SEC } from "./config
|
|
|
12
12
|
/** Parse the AUTONOMY env into a validated autonomy mode. Unset/empty → undefined (unmanaged → no extra
|
|
13
13
|
* tightening). An UNKNOWN value FAILS at startup rather than silently becoming a no-op (a typo'd `AUTONOMY=readonly`
|
|
14
14
|
* must not silently leave a deployment ungoverned — fail-loud, same discipline as numEnv). Exported so the HOT
|
|
15
|
-
* config overlay (
|
|
15
|
+
* config overlay (web-admin-client/facade.ts `applyRuntimeHot`) can re-derive the ENV BASELINE to revert to when center
|
|
16
16
|
* stops managing `autonomy` (a stale center override must not stick — see applyRuntimeHot). */
|
|
17
17
|
export declare function parseAutonomy(raw: string | undefined): Autonomy | undefined;
|
|
18
18
|
/** [ref]-T1 — parse `USAGE_WINDOWS`(单键 JSON 数组;逐窗散键在窗数可变时组合爆炸,JSON 是唯一
|
|
@@ -32,43 +32,6 @@ export declare function parseUsageWindows(raw: string | undefined): readonly {
|
|
|
32
32
|
maxCostUsd?: number;
|
|
33
33
|
anchor: "first-use" | "rolling";
|
|
34
34
|
}[] | undefined;
|
|
35
|
-
/** [ref] 兼容面全清:退役 env 名墓碑——老名**在场即拒启**带新名指引。静默忽略=部署带着失效配置无感跑;双读=兼容层吸收
|
|
36
|
-
* 下游冒烟。都不要。
|
|
37
|
-
*
|
|
38
|
-
* 🪦 **墓碑是永久的响亮拒,不设到期**(S-588)。一行墓碑就是那句拒启句本身,成本一行;删掉它 = 旧名重新被悄悄忽略。
|
|
39
|
-
* ⇒ 本表只增不减,**唯一的删除条件是这个名字要被赋予新含义**:那一次提交同时删掉墓碑行,并在 MIGRATION 写明旧名改作何用。
|
|
40
|
-
* (与一次性迁移不是一回事:迁移码每次起服都跑、碰真数据,所以有窗、窗关即删码 —— 见 `plugins/one-time-migrations.ts`
|
|
41
|
-
* 的登记表;墓碑不碰数据,只拒启。)
|
|
42
|
-
* A tombstone is a permanent loud refusal with no expiry: deleting a row lets the retired name be silently ignored again,
|
|
43
|
-
* so a row goes only when the name is given a new meaning — in that same commit, with a MIGRATION note.
|
|
44
|
-
*
|
|
45
|
-
* **旧名在场即拒,替代名在不在都一样**:判据只问旧名在不在场,不看替代键设没设、设成什么 ——「新旧两个名字都留着」正是
|
|
46
|
-
* 迁移到一半的部署最常见的形,旧名在那一形里若被静默忽略,运维会以为它还在生效。server 3.0.0 的旧负名(`X_DISABLED` →
|
|
47
|
-
* `X_ENABLED`)同在本表(`replaced` 族:极性相反,照抄旧值过去恰好是反义),与其余墓碑走同一只 {@link rejectRetiredEnvs};
|
|
48
|
-
* 那几个旋钮的读点只读正名(`boolEnv`),不再有第二套「正名缺席才看旧名」的判据(S-588 之前的 `boolEnvWithLegacyNegated`)。
|
|
49
|
-
*
|
|
50
|
-
* 墓碑分三族(A4 两族 + S-753 第三族),每族各说各的尾句 —— 族是**闭集**,渲染是穷举表(加一族不写尾句 = 编译红):
|
|
51
|
-
* · `renamed` = 同一能力换了个键名,值语义逐字不变 ⇒ 「照新名改写即可」;
|
|
52
|
-
* · `replaced` = 有替代键,但**值语义变了**(缺省 / `0` 义 / 计量段 / 极性不同)⇒ 点名新键 + 说清变了什么,**不许**说「语义不变」
|
|
53
|
-
* —— 照抄旧值过去就是另一个意思(S-753:`MODEL_CONNECT_TIMEOUT_MS` → `MODEL_FIRST_BYTE_TIMEOUT_MS`);
|
|
54
|
-
* · `removed` = 能力本身没了,`why` 是「为什么没了」,**没有可 rename 的目标**。
|
|
55
|
-
* 拒句带码 `[config.env_key_retired]`(拒启码,拼法随 `config.*` 家族;与中心凭证两码同形,出现在拒句方括号里)。
|
|
56
|
-
* 空串 = 未设(与 `env()` 同一条约定:compose `${X:-}` 透传的空值不是一次表态),不拒。 */
|
|
57
|
-
export type RetiredEnv = readonly [old: string, to: string, kind: "renamed"] | readonly [old: string, to: string, kind: "replaced", why: string] | readonly [old: string, why: string, kind: "removed"];
|
|
58
|
-
export type RetiredEnvKind = RetiredEnv[2];
|
|
59
|
-
/** 墓碑拒启码(机读;拒句方括号里)。 */
|
|
60
|
-
export declare const RETIRED_ENV_REFUSAL_CODE = "config.env_key_retired";
|
|
61
|
-
export declare const RETIRED_ENVS: readonly RetiredEnv[];
|
|
62
|
-
/** S-885 —— 墓碑表的 wire 投影一行(`GET /v1/config/catalog` 的 `retired[]`):按族定形 —— renamed 只带 `replacement`;replaced 带
|
|
63
|
-
* `replacement` + `reason`(值语义怎么变了);removed 只带 `reason`(能力为什么没了)。 */
|
|
64
|
-
export interface RetiredEnvWire {
|
|
65
|
-
readonly name: string;
|
|
66
|
-
readonly kind: RetiredEnvKind;
|
|
67
|
-
readonly replacement?: string;
|
|
68
|
-
readonly reason?: string;
|
|
69
|
-
}
|
|
70
|
-
/** 墓碑表 → wire 投影(纯数据 ⇒ `build*`)。**同一张表、同序**;族是闭集,穷举 switch(加一族不写这里 ⇒ 编译红)。 */
|
|
71
|
-
export declare function buildRetiredEnvWire(): RetiredEnvWire[];
|
|
72
35
|
/** Numeric env with validation: a non-numeric value FAILS at startup instead of silently becoming `NaN`
|
|
73
36
|
* (which e.g. slips past the `runStaleSec` liveness guard and silently disables the reaper). */
|
|
74
37
|
export declare function numEnv(name: string, fallback: string): number;
|
|
@@ -156,7 +119,7 @@ export declare function logConfigDiagnostics(logger: {
|
|
|
156
119
|
type ModelCost = NonNullable<Model["cost"]>;
|
|
157
120
|
/**
|
|
158
121
|
* 🔴 B-089 —— `Model.cost` 这**一个键**的唯一铸点(可展开片段):有价目表 ⇒ 键在;没配 ⇒ **键不出**。
|
|
159
|
-
* 三个铸点(env 主槽 / env cheap 槽 /
|
|
122
|
+
* 三个铸点(env 主槽 / env cheap 槽 / web-admin 车道)共用它,所以「缺席怎么表达」在本仓只有一处答案。
|
|
160
123
|
*
|
|
161
124
|
* `Model.cost` 自 core 7.16.0([ref])起在**类型面**上也是可选的(`dist/engine/llm/types.d.ts` 的
|
|
162
125
|
* `cost?:`),与它一直以来的运行期读法([ref] 的 `isModelPriced`:这个键在不在)对齐 ——
|
|
@@ -178,7 +141,7 @@ export declare function buildModelCostKey(cost: ModelCost | undefined): Pick<Mod
|
|
|
178
141
|
* `loadConfig` 只见 env 车道,而 `main.ts` 在第一次 effective 拉取**之前**就把 boot 诊断排空了 ——
|
|
179
142
|
* 在那里判会同时犯两个方向的错:center 名册已配价、env 未配 ⇒ **假警**;env 已配价、center 名册撤了价
|
|
180
143
|
* (或天花板只由 center 的 limits 下发)⇒ **漏警**。故本函数只给判据,席位在两只入口各自的
|
|
181
|
-
* **采纳之后**(`main.ts` 的 `
|
|
144
|
+
* **采纳之后**(`main.ts` 的 `createWebAdminRuntime` 之后 / `run-local.ts` 的 `applyEffective` 之后)。
|
|
182
145
|
*
|
|
183
146
|
* 判据 = **目录里没有任何一只带价模型**,问法与 `budget.buildPricing` 的填表判据是**同一只函数**
|
|
184
147
|
* (S-231:core 7.16.0 导出的 `isModelPriced`;第二参传 `undefined` = 这一问发生在注入表建起来之前,
|
|
@@ -263,17 +226,17 @@ export declare function parseEnvNameAllowlist(knob: RunnerEnvNameAllowlistKnob):
|
|
|
263
226
|
* here claiming this was "the exact CC alignment core recommends embedders set" mis-read core's per-model
|
|
264
227
|
* advice as a width rule). Returns a discriminant so the env lane can turn the removed implicit value into
|
|
265
228
|
* a loud CONFIG_NOTICES line ("removed-1m"); the center lane's roster culture is explicit declaration.
|
|
266
|
-
* Shared by the env lane (main + cheap models) and the center lane (
|
|
229
|
+
* Shared by the env lane (main + cheap models) and the center lane (web-admin toModel). */
|
|
267
230
|
export declare function applyAutoCompactWindow(m: Model, explicit?: number): "explicit" | "sonnet5" | "removed-1m" | "removed";
|
|
268
231
|
/**
|
|
269
|
-
* **严格名册布防**的唯一判据(boot 就绪门 `boot/
|
|
232
|
+
* **严格名册布防**的唯一判据(boot 就绪门 `boot/web-admin.ts` 与 S-623 端点判据同调这一只)。
|
|
270
233
|
*
|
|
271
234
|
* 布防 = 远程 registry ∧ 非 dryRun ∧ `CONFIG_REQUIRE_ROSTER=true`(严格 `"true"`,直读 env、不进 ServiceConfig —— 纯
|
|
272
235
|
* boot 期姿势旋钮,原判据逐字搬来,零语义变化)。布防时运维声明 env MODEL_ID 是**占位**:名册落地前计费提交 503、
|
|
273
236
|
* `/health` ready:false,落地后整张模型表被中心目录换装。dryRun 是 compare-only(名册从不被应用),local / 纯 env
|
|
274
237
|
* 部署没有「中心」可等 ⇒ 都不布防。
|
|
275
238
|
*/
|
|
276
|
-
export declare function isRosterGateArmed(
|
|
239
|
+
export declare function isRosterGateArmed(webAdmin: ServiceConfig["webAdmin"]): boolean;
|
|
277
240
|
/**
|
|
278
241
|
* 一条工具名**永不匹配任何现役工具**的三种拼法,及其修正指引。审批/权限名单是 server 侧 ToolPolicy 的
|
|
279
242
|
* RAW 逐字比对(canonicalToolName 折叠面已随 core 5.0.0 [ref] 退役),所以写错的名字不会报错、只会静默
|
|
@@ -281,7 +244,7 @@ export declare function isRosterGateArmed(configCenter: ServiceConfig["configCen
|
|
|
281
244
|
*
|
|
282
245
|
* 判据在此**单点成文**,三条腿共用(它们此前各自为政,拼法覆盖面不一致才是真缺口):
|
|
283
246
|
* ① env 腿(`APPROVAL_REQUIRE`/`DENY`/`NEVER_AUTO`,下方)—— boot 拒启;
|
|
284
|
-
* ② 中心下发腿(`runtime.approvalRequire`,
|
|
247
|
+
* ② 中心下发腿(`runtime.approvalRequire`,web-admin-client/apply-effective.ts)—— 域级拒绝+保前值+warn
|
|
285
248
|
* (常驻进程不 crash);
|
|
286
249
|
* ③ per-request 腿(`settings.permissions.{ask,deny}`,task-settings.ts)—— 该请求 422。
|
|
287
250
|
* (两张 allow 表 —— 请求的 `settings.permissions.allow` 与运维的 `APPROVAL_GRANT` —— 自 7.117.0 / core 7.42.0 起不经这里:它们整份交给引擎的
|
|
@@ -426,7 +389,7 @@ export interface FleetFenceLane {
|
|
|
426
389
|
*/
|
|
427
390
|
export declare function fleetFenceLaneOf(cfg: {
|
|
428
391
|
readonly fleetGeneration?: string | undefined;
|
|
429
|
-
readonly
|
|
392
|
+
readonly webAdmin?: (CenterEndpoint & {
|
|
430
393
|
readonly worker?: string | undefined;
|
|
431
394
|
}) | undefined;
|
|
432
395
|
readonly fleetAdvertiseAddress?: string | undefined;
|
package/dist/config.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
|
-
import { DEFAULT_MODEL_REF } from "./model-select.js";
|
|
2
|
+
import { DEFAULT_AT_MENTION, DEFAULT_MODEL_REF } from "./model-select.js";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { BUILTIN_COMPLIANCE_DENIES, COMPLIANCE_CAPABILITIES, CROSS_SESSION_INBOUND_SETTINGS, CROSS_SESSION_DIALOG_EXPIRY_VALUES, compileReadDeny, resolveReadDenyBuiltins, CODE_AGENT_PROMPT, isModelPriced, PROTOCOL_TABLE, RECOMMENDED_SENSITIVE_PATTERNS, judgeRuleToolName, resolveFileHistoryRetention, resolveLockedKeys, validatePermissionRules, WRITE_PROTECTED_DEFAULT_TABLE, resolveWriteProtectedTable } from "@sema-agent/core";
|
|
7
|
-
import { ROSTER_PRIMARY_ROLES, ROSTER_CHEAP_ROLES,
|
|
7
|
+
import { ROSTER_PRIMARY_ROLES, ROSTER_CHEAP_ROLES, WEB_ADMIN_ENV, retiredEnvRefusal } from "@sema-agent/settings-schema";
|
|
8
8
|
import { parseApprovalHmacKeys, parsePrincipalJwks } from "./auth-keys.js";
|
|
9
9
|
import { DEFAULT_ELICITATION_THROTTLE } from "./elicitation.js";
|
|
10
10
|
import { isV2ScopeKey, memoryReplicationCoverage, replicationCovers } from "./memory-scope.js";
|
|
@@ -13,7 +13,7 @@ import { GIT_API_KINDS, isGitApiKind } from "./git-api-kind.js";
|
|
|
13
13
|
import { CONFIG_PROVIDER_WORDS, RETENTION_MODES, MEMORY_CONSOLIDATION_MIN_INTERVAL_SEC, RESILIENCE_DEFAULTS, TASK_WRITE_FACE_ESCALATIONS, MAX_TIMER_DELAY_MS, AUTO_MODE_CLASSIFIER_TIMEOUT_BOUNDS, DRAIN_GRACE_FLOOR_MS, DRAIN_SECOND_SIGNAL_MIN_GAP_BOUNDS, DRAIN_SECOND_SIGNAL_MIN_GAP_DEFAULT_MS, FIRST_BYTE_TIMEOUT_BOUNDS, FLEET_LEASE_OUTAGE_MAX_DEFAULT_MS, fleetScopeOf } from "./config-types.js";
|
|
14
14
|
import { FLEET_GENERATION_ENV, FLEET_SCOPE_ENV, SERVING_LEASE_TTL_FLOOR_MS, isCanonicalGeneration } from "@sema-agent/settings-schema/fleet";
|
|
15
15
|
import { ScopeId } from "@sema-agent/settings-schema/api/scopes";
|
|
16
|
-
import { centerLaneConfigured, pathBaseUrlRefusal } from "./
|
|
16
|
+
import { centerLaneConfigured, pathBaseUrlRefusal } from "./web-admin-client/center-request.js";
|
|
17
17
|
import { resolveLocalDataRoot } from "./local-data-root.js";
|
|
18
18
|
import { buildWriteProtectionPosture } from "./write-protection.js";
|
|
19
19
|
import { normalizeSshFingerprint } from "./ssh-host-key.js";
|
|
@@ -22,7 +22,7 @@ import { THINKING_LEVELS, THINKING_FORMATS, buildModelCompat, isThinkingFormat,
|
|
|
22
22
|
import {} from "./posture-source.js";
|
|
23
23
|
import { CONTROL_AND_BIDI_STRIP_RE } from "./text-bidi.js";
|
|
24
24
|
import { describeUnmatchableRuleName, ruleEntryToolName, unmatchableRuleNameOf } from "./namespaced-rule-name.js";
|
|
25
|
-
import { bakeOperatorPrincipalsRefusal, bakeRunnerCredentialRefusal, halfOpenDirectDoorRefusal, leaderDurableStoreRefusal, operatorPrincipalsRequiredRefusal } from "./config-invariants.js";
|
|
25
|
+
import { bakeOperatorPrincipalsRefusal, bakeRunnerCredentialRefusal, centerIdentityRefusal, halfOpenDirectDoorRefusal, leaderDurableStoreRefusal, operatorPrincipalsRequiredRefusal } from "./config-invariants.js";
|
|
26
26
|
import { declaredSemaConfigDir } from "./sema-config-dir.js";
|
|
27
27
|
import { lkgPathOverrideOf } from "./config-lkg.js";
|
|
28
28
|
import { REMOTE_EXEC_PROVIDER_WORDS, executionLaneOf, executionLaneRequiredRefusal, isSingleMachineDefaultLane, laneRequiredEnv } from "./execution-lane-caps.js";
|
|
@@ -33,7 +33,8 @@ import { createCenterCredentialSource, readCenterCredentialDeclaration } from ".
|
|
|
33
33
|
import { parseCenterCredentialRenewLeadMs } from "./center-credential-renewer.js";
|
|
34
34
|
import { modelProviderRefusal } from "./model-provider.js";
|
|
35
35
|
import { modelRouteUrlRefusal } from "./model-route-url.js";
|
|
36
|
-
import {
|
|
36
|
+
import { httpUrlFlaws } from "@sema-agent/settings-schema";
|
|
37
|
+
import { buildHttpUrlRefusal } from "./url-refusal.js";
|
|
37
38
|
import { csvOf, envLaneTable, judgeModelRouteGap, mintedCheapId, readModelRouteEnv } from "./model-route-gap.js";
|
|
38
39
|
import { displayListEntry } from "./list-entry-display.js";
|
|
39
40
|
import { buildDisplaySafeUrl, redactSecrets } from "./trace/redact.js";
|
|
@@ -113,74 +114,10 @@ function defaultSkillsDir() {
|
|
|
113
114
|
return "skills";
|
|
114
115
|
}
|
|
115
116
|
}
|
|
116
|
-
export const RETIRED_ENV_REFUSAL_CODE = "config.env_key_retired";
|
|
117
|
-
export const RETIRED_ENVS = [
|
|
118
|
-
["TIDB_HOST", "MYSQL_HOST", "renamed"], ["TIDB_PORT", "MYSQL_PORT", "renamed"], ["TIDB_USER", "MYSQL_USER", "renamed"],
|
|
119
|
-
["TIDB_PASSWORD", "MYSQL_PASSWORD", "renamed"], ["TIDB_DATABASE", "MYSQL_DATABASE", "renamed"], ["TIDB_POOL_SIZE", "MYSQL_POOL_SIZE", "renamed"],
|
|
120
|
-
["CONFIG_CENTER_URL", "SEMA_REGISTRY_URL", "renamed"], ["CONFIG_CENTER_TOKEN", CENTER_CREDENTIAL_ENV.token, "renamed"],
|
|
121
|
-
["CONFIG_CENTER_DRY_RUN", "SEMA_REGISTRY_DRY_RUN", "renamed"], ["CONFIG_CENTER_WORKER", "SEMA_REGISTRY_WORKER", "renamed"],
|
|
122
|
-
["ANTHROPIC_BASEURL", "ANTHROPIC_BASE_URL", "renamed"],
|
|
123
|
-
["REGISTRY_ADMIN_TOKEN", "SEMA_REGISTRY_ADMIN_TOKEN", "renamed"],
|
|
124
|
-
["OA_API_BASEURL", "the OA scenario was removed in 5.0.0", "removed"],
|
|
125
|
-
["OA_SERVICE_TOKEN", "the OA scenario was removed in 5.0.0", "removed"],
|
|
126
|
-
["OA_ISSUE_TOKEN", "the OA scenario was removed in 5.0.0", "removed"],
|
|
127
|
-
["OA_ISSUE_BASEURL", "the OA scenario was removed in 5.0.0", "removed"],
|
|
128
|
-
["OA_ISSUE_OWNER", "the OA scenario was removed in 5.0.0", "removed"],
|
|
129
|
-
["OA_ISSUE_REPO", "the OA scenario was removed in 5.0.0", "removed"],
|
|
130
|
-
["OA_ISSUE_LABELS", "the OA scenario was removed in 5.0.0", "removed"],
|
|
131
|
-
["APPROVAL_POLL_MS", "the OA poll-approval lane was removed in 5.0.0; the durable checkpoint lane is the only gate", "removed"],
|
|
132
|
-
["LEADER_CONFLICT_ROUNDS", "the bounded merge-conflict-resolution agent was deleted in 7.83.0 按 C-R63 删除,合不上交用户:leader 交回 result.conflict(分支 + 冲突文件),run 状态 needs_human", "removed"],
|
|
133
|
-
[
|
|
134
|
-
"MODEL_CONNECT_TIMEOUT_MS",
|
|
135
|
-
"MODEL_FIRST_BYTE_TIMEOUT_MS",
|
|
136
|
-
"replaced",
|
|
137
|
-
"since core 7.33.0 the TCP + TLS connect clock is the transport's own; the wait from sending the request to its response headers — " +
|
|
138
|
-
"what this key really bounded — is MODEL_FIRST_BYTE_TIMEOUT_MS (unset = core's own default, plus an upload allowance and one " +
|
|
139
|
-
"widened retry; 0 = no engine clock on that segment and the transport's header / body clocks off too — the TCP + TLS connect " +
|
|
140
|
-
"keeps the transport's own clock)",
|
|
141
|
-
],
|
|
142
|
-
["PROJECT_MEMORY_DISABLED", "PROJECT_MEMORY_ENABLED", "replaced", "negative-name alias retired in server 3.0.0 — unset it; the polarity is inverted: PROJECT_MEMORY_DISABLED=true is PROJECT_MEMORY_ENABLED=false (the positive name defaults on)"],
|
|
143
|
-
["CONFIG_LKG_DISABLED", "CONFIG_LKG_ENABLED", "replaced", "negative-name alias retired in server 3.0.0 — unset it; the polarity is inverted: CONFIG_LKG_DISABLED=true is CONFIG_LKG_ENABLED=false (the positive name defaults on)"],
|
|
144
|
-
["HOST_BG_DISABLED", "HOST_BG_ENABLED", "replaced", "negative-name alias retired in server 3.0.0 — unset it; the polarity is inverted: HOST_BG_DISABLED=true is HOST_BG_ENABLED=false (the positive name defaults on)"],
|
|
145
|
-
["HOST_EXEC_SPOOL_DISABLED", "HOST_EXEC_SPOOL_ENABLED", "replaced", "negative-name alias retired in server 3.0.0 — unset it; the polarity is inverted: HOST_EXEC_SPOOL_DISABLED=true is HOST_EXEC_SPOOL_ENABLED=false (the positive name defaults on)"],
|
|
146
|
-
["UNATTENDED_PERMISSION_MODE", "since server 7.109.0 the unattended legs (leader workers and their repair legs, run-local, and their durable resumes) always run permissionMode \"default\" with an approver that answers by ask class: a machine answers only \"ordinary\" asks, and every other class goes to the leg's approver seat (run-local's terminal prompt) or parks / is refused — there is no mode to choose", "removed"],
|
|
147
|
-
];
|
|
148
|
-
for (const row of RETIRED_ENVS)
|
|
149
|
-
Object.freeze(row);
|
|
150
|
-
Object.freeze(RETIRED_ENVS);
|
|
151
|
-
export function buildRetiredEnvWire() {
|
|
152
|
-
return RETIRED_ENVS.map((row) => {
|
|
153
|
-
switch (row[2]) {
|
|
154
|
-
case "renamed":
|
|
155
|
-
return { name: row[0], kind: row[2], replacement: row[1] };
|
|
156
|
-
case "replaced":
|
|
157
|
-
return { name: row[0], kind: row[2], replacement: row[1], reason: row[3] };
|
|
158
|
-
case "removed":
|
|
159
|
-
return { name: row[0], kind: row[2], reason: row[1] };
|
|
160
|
-
default: {
|
|
161
|
-
const unhandled = row;
|
|
162
|
-
throw new Error(`unhandled retired-env kind: ${String(unhandled[2])}`);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
const RETIRED_ENV_SENTENCE = {
|
|
168
|
-
renamed: (hits) => `${hits.map(([old, to]) => `${old} → use ${to}`).join("; ")} — rename the env key(s); the value semantics are unchanged`,
|
|
169
|
-
replaced: (hits) => `${hits.map(([old, to, , why]) => `${old} → ${to} (${why})`).join("; ")} — set the replacement deliberately: ` +
|
|
170
|
-
`its value semantics differ from the retired key's, so do not copy the old value across unread`,
|
|
171
|
-
removed: (hits) => `${hits.map(([old, why]) => `${old} (${why})`).join("; ")} — remove the env key(s): the capability itself was retired, ` +
|
|
172
|
-
`there is no replacement name and no rename that restores it`,
|
|
173
|
-
};
|
|
174
|
-
function retiredEnvSentence(kind, hit) {
|
|
175
|
-
const ofKind = hit.filter((h) => h[2] === kind);
|
|
176
|
-
return ofKind.length > 0 ? [RETIRED_ENV_SENTENCE[kind](ofKind)] : [];
|
|
177
|
-
}
|
|
178
117
|
function rejectRetiredEnvs() {
|
|
179
|
-
const
|
|
180
|
-
if (
|
|
181
|
-
|
|
182
|
-
const parts = Object.keys(RETIRED_ENV_SENTENCE).flatMap((kind) => retiredEnvSentence(kind, hit));
|
|
183
|
-
throw new Error(`retired env name(s) set [${RETIRED_ENV_REFUSAL_CODE}] — refused while present, whether or not the replacement is also set: ${parts.join(" | ")}.`);
|
|
118
|
+
const refusal = retiredEnvRefusal(process.env);
|
|
119
|
+
if (refusal !== undefined)
|
|
120
|
+
throw new Error(refusal);
|
|
184
121
|
}
|
|
185
122
|
export function numEnv(name, fallback) {
|
|
186
123
|
return parseNumOrFail(name, env(name, fallback));
|
|
@@ -247,7 +184,7 @@ function parseConfigProvider() {
|
|
|
247
184
|
return undefined;
|
|
248
185
|
const word = CONFIG_PROVIDER_WORDS.find((w) => w === raw);
|
|
249
186
|
if (word === undefined) {
|
|
250
|
-
throw new Error(`env CONFIG_PROVIDER="${raw.slice(0, 120)}" must be one of: ${CONFIG_PROVIDER_WORDS.join(", ")} — or leave it unset (then
|
|
187
|
+
throw new Error(`env CONFIG_PROVIDER="${raw.slice(0, 120)}" must be one of: ${CONFIG_PROVIDER_WORDS.join(", ")} — or leave it unset (then ${WEB_ADMIN_ENV.url}, if set, selects the center as the config source; otherwise this worker is env-only). ` +
|
|
251
188
|
`The word is matched exactly (no trimming, no case folding). Refusing to boot rather than guessing: the config source, the execution-lane default and the local config root all key on this one word.`);
|
|
252
189
|
}
|
|
253
190
|
return word;
|
|
@@ -937,8 +874,8 @@ function parseStoreDomain(ctx) {
|
|
|
937
874
|
: undefined,
|
|
938
875
|
};
|
|
939
876
|
}
|
|
940
|
-
export function isRosterGateArmed(
|
|
941
|
-
return
|
|
877
|
+
export function isRosterGateArmed(webAdmin) {
|
|
878
|
+
return webAdmin !== undefined && !webAdmin.dryRun && process.env.CONFIG_REQUIRE_ROSTER === "true";
|
|
942
879
|
}
|
|
943
880
|
function parseModelDomain() {
|
|
944
881
|
const route = readModelRouteEnv(process.env);
|
|
@@ -1009,7 +946,7 @@ function parseModelDomain() {
|
|
|
1009
946
|
CONFIG_NOTICES.push({
|
|
1010
947
|
level: "warn",
|
|
1011
948
|
event: "model_cheap_slot_without_main",
|
|
1012
|
-
fields: { hint: "MODEL_CHEAP_ID is set but MODEL_ID is not — the env cheap slot derives from the env main model, so it is not minted; the catalog (config.d/models.json or the
|
|
949
|
+
fields: { hint: "MODEL_CHEAP_ID is set but MODEL_ID is not — the env cheap slot derives from the env main model, so it is not minted; the catalog (config.d/models.json or the web-admin) serves the roles. Set MODEL_ID to use the env slots, or unset MODEL_CHEAP_ID to silence this line." },
|
|
1013
950
|
});
|
|
1014
951
|
break;
|
|
1015
952
|
case "same_as_main":
|
|
@@ -1145,7 +1082,7 @@ function parseModelDomain() {
|
|
|
1145
1082
|
tiers: {},
|
|
1146
1083
|
projects: {},
|
|
1147
1084
|
roles,
|
|
1148
|
-
|
|
1085
|
+
atMention: DEFAULT_AT_MENTION,
|
|
1149
1086
|
cascadeLadder: csv("MODEL_CASCADE_LADDER"),
|
|
1150
1087
|
degrade: process.env.MODEL_DEGRADE_TO
|
|
1151
1088
|
? {
|
|
@@ -2108,7 +2045,7 @@ function parseLimitsHttpDomain() {
|
|
|
2108
2045
|
toolResultTtlSec: (() => {
|
|
2109
2046
|
const ttl = numEnv("TOOL_RESULT_TTL_SEC", "86400");
|
|
2110
2047
|
if (ttl <= 0) {
|
|
2111
|
-
throw new Error(`env TOOL_RESULT_TTL_SEC=${ttl} must be > 0 — it is the age (seconds) after which an offloaded tool result is reaped, so 0 or less puts the cutoff at or after now and every reaper tick would delete ALL of them; there is no "off": set a larger value to keep results longer (the
|
|
2048
|
+
throw new Error(`env TOOL_RESULT_TTL_SEC=${ttl} must be > 0 — it is the age (seconds) after which an offloaded tool result is reaped, so 0 or less puts the cutoff at or after now and every reaper tick would delete ALL of them; there is no "off": set a larger value to keep results longer (the web-admin refuses the same value)`);
|
|
2112
2049
|
}
|
|
2113
2050
|
return ttl;
|
|
2114
2051
|
})(),
|
|
@@ -2165,13 +2102,13 @@ function parseGitApiKind(raw, baseUrl) {
|
|
|
2165
2102
|
}
|
|
2166
2103
|
function parseIntegrationsDomain(ctx) {
|
|
2167
2104
|
const { requirePrincipal, configProvider } = ctx;
|
|
2168
|
-
const
|
|
2169
|
-
const
|
|
2170
|
-
const
|
|
2171
|
-
const
|
|
2105
|
+
const baseUrl = parseCenterBaseUrl(WEB_ADMIN_ENV.url, process.env[WEB_ADMIN_ENV.url], `It is the center base every config pull, fleet and lease request is sent to; setting it selects the center as the config source.`);
|
|
2106
|
+
const liveBaseUrl = parseCenterBaseUrl(WEB_ADMIN_ENV.liveUrl, process.env[WEB_ADMIN_ENV.liveUrl], `It is the center base the fleet liveness endpoints (heartbeat, serving lease) are sent to; unset it to send them to ${WEB_ADMIN_ENV.url}.`);
|
|
2107
|
+
const webBaseUrl = parseCenterBaseUrl(WEB_ADMIN_ENV.webUrl, process.env[WEB_ADMIN_ENV.webUrl], `It is the center's web console base this engine reports on GET /health (center.webBaseUrl); unset it if the center has no web console to link to.`);
|
|
2108
|
+
const webAdmin = baseUrl !== undefined ? parseWebAdmin(baseUrl, requirePrincipal, liveBaseUrl, webBaseUrl) : undefined;
|
|
2172
2109
|
const fleetGeneration = parseFleetGeneration(process.env.FLEET_GENERATION);
|
|
2173
2110
|
const fleetAdvertiseAddress = parseFleetAdvertiseAddress(process.env.FLEET_ADVERTISE_ADDRESS);
|
|
2174
|
-
fleetFenceLaneOf({ ...fleetGeneration,
|
|
2111
|
+
fleetFenceLaneOf({ ...fleetGeneration, webAdmin, ...fleetAdvertiseAddress });
|
|
2175
2112
|
return {
|
|
2176
2113
|
pluginsAllowHosts: csvOf(process.env.PLUGINS_ALLOW_HOSTS ?? "github.com"),
|
|
2177
2114
|
configBootFetchBudgetMs: clampEnvWithWarn("CONFIG_BOOT_FETCH_BUDGET_MS", "1500", 0),
|
|
@@ -2181,7 +2118,7 @@ function parseIntegrationsDomain(ctx) {
|
|
|
2181
2118
|
defaultScenario: env("DEFAULT_SCENARIO", "code"),
|
|
2182
2119
|
skillsDir: env("SKILLS_DIR", defaultSkillsDir()),
|
|
2183
2120
|
centerCredentialRenewLeadMs: parseCenterCredentialRenewLeadMs(process.env.CENTER_CREDENTIAL_RENEW_LEAD_MS),
|
|
2184
|
-
|
|
2121
|
+
webAdmin,
|
|
2185
2122
|
fleetLeaseFailClosed: parseFleetLeaseFailClosed(process.env.FLEET_LEASE_FAIL_CLOSED, requirePrincipal),
|
|
2186
2123
|
...fleetGeneration,
|
|
2187
2124
|
fleetScope: parseFleetScope(process.env.FLEET_SCOPE),
|
|
@@ -2239,9 +2176,9 @@ export function fleetFenceLaneOf(cfg) {
|
|
|
2239
2176
|
return undefined;
|
|
2240
2177
|
const laneConfigured = centerLaneConfigured(cfg);
|
|
2241
2178
|
if (laneConfigured && cfg.fleetAdvertiseAddress !== undefined)
|
|
2242
|
-
return { center: cfg.
|
|
2179
|
+
return { center: cfg.webAdmin, generation };
|
|
2243
2180
|
const missing = [
|
|
2244
|
-
...(laneConfigured ? [] : [`the center lane (
|
|
2181
|
+
...(laneConfigured ? [] : [`the center lane (${WEB_ADMIN_ENV.url} + ${WEB_ADMIN_ENV.token} or ${WEB_ADMIN_ENV.tokenFile} + ${WEB_ADMIN_ENV.worker})`]),
|
|
2245
2182
|
...(cfg.fleetAdvertiseAddress === undefined ? ["the announce address (FLEET_ADVERTISE_ADDRESS)"] : []),
|
|
2246
2183
|
];
|
|
2247
2184
|
throw fleetEnvRefusal("member_unfenced", `fleet member cannot be fenced — env FLEET_GENERATION=${JSON.stringify(generation)} makes this engine a fleet member, ` +
|
|
@@ -2276,15 +2213,15 @@ function parseCenterBaseUrl(name, raw, role) {
|
|
|
2276
2213
|
throw new Error(`${refusal}. ${role}`);
|
|
2277
2214
|
return raw;
|
|
2278
2215
|
}
|
|
2279
|
-
function
|
|
2280
|
-
const worker = process.env.
|
|
2216
|
+
function parseWebAdmin(baseUrl, requirePrincipal, liveBaseUrl, webBaseUrl) {
|
|
2217
|
+
const worker = process.env[WEB_ADMIN_ENV.worker] || undefined;
|
|
2281
2218
|
const declared = readCenterCredentialDeclaration();
|
|
2282
2219
|
return {
|
|
2283
2220
|
baseUrl,
|
|
2284
2221
|
...(liveBaseUrl !== undefined ? { liveBaseUrl } : {}),
|
|
2285
2222
|
...(webBaseUrl !== undefined ? { webBaseUrl } : {}),
|
|
2286
2223
|
credential: createCenterCredentialSource(declared.from === "file" ? { ...declared, multiTenant: requirePrincipal } : declared, worker),
|
|
2287
|
-
dryRun: boolEnv(
|
|
2224
|
+
dryRun: boolEnv(WEB_ADMIN_ENV.dryRun, false),
|
|
2288
2225
|
worker,
|
|
2289
2226
|
};
|
|
2290
2227
|
}
|
|
@@ -2371,7 +2308,7 @@ const STORE_GROUP_KEYS = [
|
|
|
2371
2308
|
];
|
|
2372
2309
|
const MODEL_PLANE_GROUP_KEYS = [
|
|
2373
2310
|
"gatewayBaseUrl", "gatewayApiKey", "gatewayFallbackUrls", "gatewayMaxRetries", "anthropic", "resilience", "model", "envModel", "models",
|
|
2374
|
-
"modelApiKeyEnv", "modelApiKeys", "modelRefusals", "droppedCatalogEntries", "modelQuotaWeights", "tiers", "projects", "roles", "
|
|
2311
|
+
"modelApiKeyEnv", "modelApiKeys", "modelRefusals", "droppedCatalogEntries", "modelQuotaWeights", "tiers", "projects", "roles", "atMention", "cascadeLadder", "degrade",
|
|
2375
2312
|
];
|
|
2376
2313
|
const APPROVAL_GROUP_KEYS = [
|
|
2377
2314
|
"approvalRequire", "approvalDeny", "approvalTimeoutSec", "approvalAutoBudget", "approvalNeverAuto", "approvalGrant",
|
|
@@ -2411,7 +2348,7 @@ const LIMITS_HTTP_GROUP_KEYS = [
|
|
|
2411
2348
|
const OBSERVABILITY_GROUP_KEYS = ["metricsToken", "traceToken", "toolTrace", "traceThinking", "logLevel", "otel"];
|
|
2412
2349
|
const INTEGRATIONS_GROUP_KEYS = [
|
|
2413
2350
|
"pluginsAllowHosts", "mcpServers", "a2aPeers", "a2aServe", "configBootFetchBudgetMs", "gitApiBaseUrl", "gitApiToken", "gitApiKind", "defaultScenario",
|
|
2414
|
-
"skillsDir", "centerCredentialRenewLeadMs", "
|
|
2351
|
+
"skillsDir", "centerCredentialRenewLeadMs", "webAdmin", "fleetLeaseFailClosed", "fleetGeneration", "fleetScope", "fleetAdvertiseAddress", "fleetLeaseOutageMaxMs", "configProvider", "configLocalDir",
|
|
2415
2352
|
];
|
|
2416
2353
|
export const CONFIG_GROUP_KEYS = {
|
|
2417
2354
|
store: STORE_GROUP_KEYS,
|
|
@@ -2473,6 +2410,10 @@ export function loadConfig() {
|
|
|
2473
2410
|
const limitsHttp = parseLimitsHttpDomain();
|
|
2474
2411
|
const observability = parseObservabilityDomain();
|
|
2475
2412
|
const integrations = parseIntegrationsDomain({ requirePrincipal, configProvider });
|
|
2413
|
+
const centerIdentity = centerIdentityRefusal({ authBridgeIssuer: auth.authBridgeIssuer, webAdmin: integrations.webAdmin });
|
|
2414
|
+
if (centerIdentity !== undefined) {
|
|
2415
|
+
throw new Error(centerIdentity);
|
|
2416
|
+
}
|
|
2476
2417
|
const { directApprovalDoor, durableApproval: dgDurable, approvalHmacKeys: dgHmacKeys } = approval;
|
|
2477
2418
|
const { principalJwtPubkeys, principalJwtIss, principalJwtAud, operatorPrincipals: dgOperators, authTokens } = auth;
|
|
2478
2419
|
const directDoorActive = directApprovalDoor && dgDurable && dgHmacKeys.length > 0 && principalJwtPubkeys.length > 0 && !!principalJwtIss && !!principalJwtAud;
|
|
@@ -2510,7 +2451,7 @@ export function loadConfig() {
|
|
|
2510
2451
|
throw new Error(laneRequiredRefusal);
|
|
2511
2452
|
}
|
|
2512
2453
|
{
|
|
2513
|
-
const routeGap = judgeModelRouteGap(process.env, { envLaneDispatchable: !isRosterGateArmed(integrations.
|
|
2454
|
+
const routeGap = judgeModelRouteGap(process.env, { envLaneDispatchable: !isRosterGateArmed(integrations.webAdmin) });
|
|
2514
2455
|
if (routeGap.gap !== "none") {
|
|
2515
2456
|
throw new Error(routeGap.reason);
|
|
2516
2457
|
}
|
|
@@ -144,7 +144,7 @@ export declare function laneRequiredEnv(lane: RemoteExecProvider): readonly stri
|
|
|
144
144
|
*
|
|
145
145
|
* 🔴 病(S-1008,test d327-g6-engine-7112 OBS-4 / OBS-5;2026-10-03 亲核):修前**两份句子**。运行期真拒启的是 `config.ts` 手写 throw
|
|
146
146
|
* (点名 `REQUIRE_EXECUTION_LANE` / `REMOTE_EXEC` + 修法,用户在 stderr 读到的就是它);注册表条目另写了一句短的
|
|
147
|
-
* 「the deployment asked to refuse this state」,而它只在 `
|
|
147
|
+
* 「the deployment asked to refuse this state」,而它只在 `web-admin-client/stage-limits.ts` 的全表校验里被调 —— 候选视图只装
|
|
148
148
|
* `BATCH1_LIMIT_KEYS` 的限额键,带不上这两键 ⇒ 对本条恒 `next === live`,**那一句没有任何读者**(test 六个拒启格 stderr 里零命中)。
|
|
149
149
|
* 改一份另一份不跟。现形:boot 的 throw 与注册表条目的 `check` **都**调本函数 —— 一只判据、一句话,没有第二份文本可漂。
|
|
150
150
|
*
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* · `worker` / `expectedGeneration`:缺席对缺席(非 fleet 成员没有代际,不带 `expectedGeneration` 的请求是单机形,不是通配)。
|
|
22
22
|
* · `instanceId`:请求带了才比(它是引擎每进程自铸的身份,`/health` 上可读);「点名的是不是别的进程」与 run 行同一只判据
|
|
23
23
|
* `runProvenElsewhere`。
|
|
24
|
-
* 引擎自己的 worker / instanceId 读不出 ⇒ 带了这一项的请求不符(认不出自己就不认任何点名;没配 `
|
|
24
|
+
* 引擎自己的 worker / instanceId 读不出 ⇒ 带了这一项的请求不符(认不出自己就不认任何点名;没配 `SEMA_WEB_ADMIN_WORKER` 的引擎因此
|
|
25
25
|
* 只能用停止信号排空)。
|
|
26
26
|
* 5. **进入那一拍让出在飞**:本副本可抢占的在飞腿经 core `TaskSpec.preemptSignal` 让出(在下一个干净的回合边界耐久停驻,
|
|
27
27
|
* `resource_limit` / `preempt`;不合格的腿上 core 静默不动,等到期限硬停 —— 既有 `crashed` 臂);活的审批卡按断连同路改路耐久停驻
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* `ready ∧ ¬draining ∧ leaseState ≠ denied` —— 后两项不是新判据:`draining` 本来就是就绪原因,而租约被拒**同一拍**经
|
|
11
11
|
* 唯一的排空入口进入排空(`fleet/serving-lease.ts`),所以「被拒 ⇒ 排空 ⇒ 不就绪」是构造出来的,不靠第二只谓词。
|
|
12
12
|
* `leaseState = expired` **不**进就绪(中心不可达不是本实例的病,见租约模块头注)。
|
|
13
|
-
* 3. **重启**:`restart` = 已发布的重启信号;没有已发布信号而有一只**扣着**的候选(
|
|
13
|
+
* 3. **重启**:`restart` = 已发布的重启信号;没有已发布信号而有一只**扣着**的候选(web-admin 的保留候选状态机)且它确有被扣的片时,
|
|
14
14
|
* 铸 `{reasons: 被扣的片, version, since, withheld: true}`(「要重启,但此刻换掉本实例会丢它手里的候选」)。已发布的信号恒胜(那几片
|
|
15
15
|
* 是安全可重启的,扣着的片不阻止它们);被扣的片为空(只差发布重试)⇒ 不是重启事实,不铸(契约 `RestartSignal.reasons` 至少一词;
|
|
16
16
|
* 那一形的面只有每拍一行运维 warn + 计数)。「扣着」在两出口上只有这一种读法(7.120.x 的 `/health.modelPlaneDeferred` 本版删除)。
|
|
@@ -54,7 +54,7 @@ export type ServingLeaseView = {
|
|
|
54
54
|
export type FleetMembershipKeys = Pick<InstanceAnnouncement, "generation" | "leaseState" | "leaseUntil">;
|
|
55
55
|
/** 非 fleet 成员 / 没装租约客户端时的读数(唯一拼法)。 */
|
|
56
56
|
export declare const LEASE_NONE: ServingLeaseView;
|
|
57
|
-
/** 扣着的候选(
|
|
57
|
+
/** 扣着的候选(web-admin 的 `planeDeferredNoHandoff` 投影):版本、起扣时刻、被扣的重启片。 */
|
|
58
58
|
export interface RetainedCandidate {
|
|
59
59
|
readonly version: number;
|
|
60
60
|
readonly since: number;
|
|
@@ -62,7 +62,7 @@ export interface RetainedCandidate {
|
|
|
62
62
|
}
|
|
63
63
|
/**
|
|
64
64
|
* 重启事实的**唯一**合成点(规则 3):已发布信号恒胜;否则扣着的候选有被扣的片 ⇒ `withheld:true` 的信号;否则缺席。
|
|
65
|
-
* `build*` = 纯数据。泛型让
|
|
65
|
+
* `build*` = 纯数据。泛型让 web-admin 交进来的窄型(`EngineRestartSignal`,`reasons` 是片闭集)原样回来。
|
|
66
66
|
*/
|
|
67
67
|
export declare function buildRestartSignal<R extends RestartSignal>(published: R | undefined, retained: (RetainedCandidate & {
|
|
68
68
|
readonly blocked?: readonly R["reasons"][number][];
|
|
@@ -72,8 +72,8 @@ export declare const CONFIG_HANDOFF_STATES: readonly ["missing"];
|
|
|
72
72
|
export type ConfigHandoffState = (typeof CONFIG_HANDOFF_STATES)[number];
|
|
73
73
|
/**
|
|
74
74
|
* `/health.configHandoff`(只在 `/health`,不上心跳)—— 一件**事故**:**在场 ⇔ 部署声明了耐久接力 ∧ 应用着的那一代没在下一次起服将用的身份的桶里确认耐久落盘**
|
|
75
|
-
* (
|
|
76
|
-
* 的身份选桶;部署形门在
|
|
75
|
+
* (web-admin 的接力账 {@link ConfigHandoffLedger}:最后确认耐久的那一代 + 写进的那只身份桶,对比应用着的那一代 + 此刻的凭证身份 —— 离线起服按此刻
|
|
76
|
+
* 的身份选桶;部署形门在 web-admin 的取值口,读判「handoff confirmed」的同一只谓词)。凭证换了人(换了身份)而新身份的桶里没有这一代 ⇒ 在场。覆盖 LKG 发布失败(含保留候选、启动期技能债)与部分应用(某组被整拒、其余组已热应用,LKG 停在上一个完整世代)两形。**部署形**不在这里报:
|
|
77
77
|
* 没有耐久声明(`CONFIG_LKG_DURABLE` 不真 / LKG 关)的部署「重启靠中心重拉」是配置时声明的事实 ⇒ 恒缺席;本地腿 / 没有配置管道 ⇒ 缺席。
|
|
78
78
|
* 与 `restart.withheld` 两个事实两张脸(可同在):要不要重启归 `restart`,声明了的接力缺不缺归本键。
|
|
79
79
|
* `version` = 应用着的那一代;`since` = 这一代开始没有确认接力的时刻(持续缺着时不刷新,确认即清)。
|
|
@@ -83,7 +83,7 @@ export interface ConfigHandoff {
|
|
|
83
83
|
readonly version: number;
|
|
84
84
|
readonly since: number;
|
|
85
85
|
}
|
|
86
|
-
/** 配置接力账(
|
|
86
|
+
/** 配置接力账(web-admin 持有,`/health.configHandoff` 的唯一来源):应用着的那一代、最后一次确认耐久接力的那一代与它写进的身份桶、
|
|
87
87
|
* 下一次起服将用的身份(此刻的凭证身份 —— 离线起服选桶读的同一只)。 */
|
|
88
88
|
export interface ConfigHandoffLedger {
|
|
89
89
|
readonly applied?: number;
|
|
@@ -96,9 +96,9 @@ export interface ConfigHandoffLedger {
|
|
|
96
96
|
/** 「接力缺着」的**唯一**判据(纯):应用过一代 ∧ 最后确认耐久的不是「这一代 ∧ 下一次起服将用的身份桶」。 */
|
|
97
97
|
export declare function configHandoffMissing(ledger: ConfigHandoffLedger): boolean;
|
|
98
98
|
/** `configHandoff` 的**唯一**合成点(纯):缺着 ⇒ `{ state: "missing", version: 应用着的那一代, since }`;否则缺席。`since` 由持账方锁存(发现缺着的那一拍)。
|
|
99
|
-
* `build*` = 纯数据;
|
|
99
|
+
* `build*` = 纯数据;web-admin 的 `configHandoffState()` 是唯一调用方。 */
|
|
100
100
|
export declare function buildConfigHandoff(ledger: ConfigHandoffLedger, since: number | undefined): ConfigHandoff | undefined;
|
|
101
|
-
/** 世代账的一次读数(
|
|
101
|
+
/** 世代账的一次读数(web-admin 的 `configApplyState()` 交出的那一份里本模块读的五键;`/health` 扁平五键与嵌套形的两键读同一份)。 */
|
|
102
102
|
export interface ConfigLedgerReading {
|
|
103
103
|
readonly configTargetVersion: number;
|
|
104
104
|
readonly configAppliedVersion: number;
|
|
@@ -566,6 +566,7 @@ export declare function fleetRunPublisher(bus: FleetEventBus | undefined, run: {
|
|
|
566
566
|
name?: string;
|
|
567
567
|
toolName?: string;
|
|
568
568
|
parentToolCallId?: string;
|
|
569
|
+
workflowRunId?: string;
|
|
569
570
|
status?: string;
|
|
570
571
|
seq?: number;
|
|
571
572
|
}) => void;
|
|
@@ -576,6 +577,7 @@ export declare function fleetRunPublisher(bus: FleetEventBus | undefined, run: {
|
|
|
576
577
|
name?: string;
|
|
577
578
|
usage?: unknown;
|
|
578
579
|
parentToolCallId?: string;
|
|
580
|
+
workflowRunId?: string;
|
|
579
581
|
status?: string;
|
|
580
582
|
seq?: number;
|
|
581
583
|
}) => void;
|
|
@@ -639,13 +641,20 @@ export declare function fleetRunResiduals(result: {
|
|
|
639
641
|
* session attribution → unscoped, back-compat visible). Names ride the same redactSecrets discipline.
|
|
640
642
|
*/
|
|
641
643
|
export declare function fleetBackgroundChildPublisher(bus?: FleetEventBus, log?: (msg: string, fields: Record<string, unknown>) => void): (e: import("@sema-agent/core").BackgroundChildEvent) => void;
|
|
644
|
+
/**
|
|
645
|
+
* 🔴 **run 的短名 —— 一只折法、一个输入**:输入 = run 行的预览(`user-authored-text.ts` 的 `buildRunObjectivePreview` 的产物,run 行上存的就是它);
|
|
646
|
+
* fleet 行的 `name`(发布时由 objective 现算同一只预览)与 `GET /v1/assistant/tasks` 的 `name`(读 run 行上存的预览)读同一只,
|
|
647
|
+
* 同一个 run 两面同名。预览是 `""`(有记录、剥完没有用户正文)⇒ `(notification turn)`;否则单行折叠、超过 48 字截断带 `…`。预览已脱敏。
|
|
648
|
+
* 入参只收「有记录」的预览:列上的 NULL(没记录)不是通告轮,由读面自己按契约缺席,不进这只折法。
|
|
649
|
+
*/
|
|
650
|
+
export declare function buildRunName(preview: string): string;
|
|
642
651
|
/** BC-1 (clay-decided 2026-06-27): a top-level run's fleet-row `name` = a SHORT, single-line **objective preview**
|
|
643
652
|
* (the readable "what is this task" label) — NOT the full objective dumped in, and NOT duplicated into `description`.
|
|
644
653
|
* `description` is left to the publisher's LIVE-ACTIVITY update (`onEvent` tool_start → the current tool), so the row
|
|
645
654
|
* shows `name`=objective + `description`=current activity (two DISTINCT things, killing the earlier "objective shown
|
|
646
|
-
* twice" dup).
|
|
647
|
-
*
|
|
648
|
-
*
|
|
655
|
+
* twice" dup). (A subagent CHILD row's name = its agent-type — BC-2.)
|
|
656
|
+
* 一只折法({@link buildRunName}),输入 = 与 run 行同一只预览(用户写的那段 → 脱敏 → 截):`GET /v1/assistant/tasks`
|
|
657
|
+
* 读 run 行上存的预览、过同一只折法 ⇒ 同一个 run 两面同名。剥完没有用户正文 ⇒ `(notification turn)`;闭集外的 XML 头当普通正文标。 */
|
|
649
658
|
export declare function fleetRunLabels(objective: string | undefined): {
|
|
650
659
|
name: string;
|
|
651
660
|
};
|
package/dist/fleet/fleet-bus.js
CHANGED
|
@@ -3,6 +3,7 @@ import { DURABLE_AGENT_HANDLE_RE, deriveAgentDisplayStatus, isDelegatedAgentTerm
|
|
|
3
3
|
import { persistedPlaneOf } from "../terminal.js";
|
|
4
4
|
import { recordFailOpen } from "../observability/fail-open.js";
|
|
5
5
|
import { redactSecrets } from "../trace/redact.js";
|
|
6
|
+
import { buildRunObjectivePreview } from "../user-authored-text.js";
|
|
6
7
|
export function isFleetAgentTerminalNotification(n) {
|
|
7
8
|
return isDelegatedAgentTerminal(n);
|
|
8
9
|
}
|
|
@@ -206,6 +207,7 @@ export function fleetRunPublisher(bus, run) {
|
|
|
206
207
|
let settledLeg = false;
|
|
207
208
|
const childId = (taskId) => `${run.runId} ${taskId}`;
|
|
208
209
|
const tickStatus = (st) => (st === "completed" ? "completed" : st === "failed" ? "failed" : "running");
|
|
210
|
+
const workflowRunIdField = (ev) => (ev.workflowRunId ? { workflowRunId: ev.workflowRunId } : {});
|
|
209
211
|
const toolUsesOf = (usage) => {
|
|
210
212
|
const t = usage?.toolUses;
|
|
211
213
|
return typeof t === "number" ? t : undefined;
|
|
@@ -269,7 +271,7 @@ export function fleetRunPublisher(bus, run) {
|
|
|
269
271
|
childStartedAt.set(cid, Date.now());
|
|
270
272
|
if (ev.parentToolCallId)
|
|
271
273
|
childByToolCall.set(ev.parentToolCallId, cid);
|
|
272
|
-
bus.publishTask({ id: cid, sourceLane: "run-leg", ...(childName !== undefined ? { name: childName, agentType: childName } : {}), parentId: run.runId, scope: run.scope, ...sessionField, status: tickStatus(ev.status), tokens: sumTokens(ev.usage), ...(typeof ev.seq === "number" ? { cycleSeq: ev.seq } : {}), ...(() => { const t = toolUsesOf(ev.usage); return t !== undefined ? { toolUses: t } : {}; })(), elapsedMs: Date.now() - childStartedAt.get(cid) });
|
|
274
|
+
bus.publishTask({ id: cid, sourceLane: "run-leg", ...(childName !== undefined ? { name: childName, agentType: childName } : {}), parentId: run.runId, scope: run.scope, ...sessionField, ...workflowRunIdField(ev), status: tickStatus(ev.status), tokens: sumTokens(ev.usage), ...(typeof ev.seq === "number" ? { cycleSeq: ev.seq } : {}), ...(() => { const t = toolUsesOf(ev.usage); return t !== undefined ? { toolUses: t } : {}; })(), elapsedMs: Date.now() - childStartedAt.get(cid) });
|
|
273
275
|
}
|
|
274
276
|
else if (ev.type === "tool_start" && ev.toolName) {
|
|
275
277
|
bus.publishTask({ id: run.runId, description: ev.toolName });
|
|
@@ -290,7 +292,7 @@ export function fleetRunPublisher(bus, run) {
|
|
|
290
292
|
childStartedAt.set(cid, Date.now());
|
|
291
293
|
if (ev.parentToolCallId)
|
|
292
294
|
childByToolCall.set(ev.parentToolCallId, cid);
|
|
293
|
-
bus.publishTask({ id: cid, sourceLane: "run-leg", ...(fwdName !== undefined ? { name: fwdName, agentType: fwdName } : {}), parentId, scope: run.scope, ...sessionField, status: tickStatus(ev.status), tokens: sumTokens(ev.usage), ...(typeof ev.seq === "number" ? { cycleSeq: ev.seq } : {}), ...(() => { const t = toolUsesOf(ev.usage); return t !== undefined ? { toolUses: t } : {}; })(), elapsedMs: Date.now() - childStartedAt.get(cid) });
|
|
295
|
+
bus.publishTask({ id: cid, sourceLane: "run-leg", ...(fwdName !== undefined ? { name: fwdName, agentType: fwdName } : {}), parentId, scope: run.scope, ...sessionField, ...workflowRunIdField(ev), status: tickStatus(ev.status), tokens: sumTokens(ev.usage), ...(typeof ev.seq === "number" ? { cycleSeq: ev.seq } : {}), ...(() => { const t = toolUsesOf(ev.usage); return t !== undefined ? { toolUses: t } : {}; })(), elapsedMs: Date.now() - childStartedAt.get(cid) });
|
|
294
296
|
},
|
|
295
297
|
onChildTerminal(taskId, status, altId, toolUseId) {
|
|
296
298
|
if (settledLeg)
|
|
@@ -612,14 +614,16 @@ export function fleetBackgroundChildPublisher(bus, log) {
|
|
|
612
614
|
handleTerminal(e, m);
|
|
613
615
|
};
|
|
614
616
|
}
|
|
617
|
+
const NOTIFICATION_TURN_NAME = "(notification turn)";
|
|
618
|
+
const RUN_NAME_CHARS = 48;
|
|
619
|
+
export function buildRunName(preview) {
|
|
620
|
+
const oneLine = preview.replace(/\s+/g, " ").trim();
|
|
621
|
+
if (oneLine === "")
|
|
622
|
+
return NOTIFICATION_TURN_NAME;
|
|
623
|
+
return oneLine.length > RUN_NAME_CHARS ? `${oneLine.slice(0, RUN_NAME_CHARS - 1)}…` : oneLine;
|
|
624
|
+
}
|
|
615
625
|
export function fleetRunLabels(objective) {
|
|
616
|
-
|
|
617
|
-
if (!oneLine)
|
|
618
|
-
return { name: "task" };
|
|
619
|
-
if (/^<[a-z][a-z0-9_-]*[\s>/]/i.test(oneLine))
|
|
620
|
-
return { name: "(notification turn)" };
|
|
621
|
-
const name = oneLine.length > 48 ? `${oneLine.slice(0, 47)}…` : oneLine;
|
|
622
|
-
return { name };
|
|
626
|
+
return { name: buildRunName(buildRunObjectivePreview(objective ?? "")) };
|
|
623
627
|
}
|
|
624
628
|
export function isTerminalFleetStatus(status) {
|
|
625
629
|
switch (status) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
import { type CenterEndpoint } from "../
|
|
1
|
+
import { type WebAdminCapabilities } from "@sema-agent/settings-schema/fleet";
|
|
2
|
+
import { type CenterEndpoint } from "../web-admin-client/center-request.js";
|
|
3
3
|
import { type DrainEntry } from "./drain-entry.js";
|
|
4
4
|
import type { ServingLeaseView } from "./engine-signal.js";
|
|
5
5
|
/** 续租请求的上界(ms)—— 与 fleet 心跳同量级(不在提交热路径上)。 */
|
|
@@ -34,7 +34,7 @@ export interface ServingLeaseClientOpts {
|
|
|
34
34
|
}
|
|
35
35
|
export interface ServingLeaseClient {
|
|
36
36
|
/** 一次中心能力读数(`undefined` = `undeclared`,中心没宣告 = 不支持)。每一次读数调一次;`unreadable` 不是读数,不调(`fleet-client.ts` `capabilityReadingOf`)。 */
|
|
37
|
-
noteCenterCapabilities(caps:
|
|
37
|
+
noteCenterCapabilities(caps: WebAdminCapabilities | undefined): void;
|
|
38
38
|
/** 此刻的租约读数(铸点与准入判读它)。 */
|
|
39
39
|
view(): ServingLeaseView;
|
|
40
40
|
/** 起步读黏性拒(装配层在唯一排空入口装好之后调一次)。 */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { SERVING_LEASE_TTL_DEFAULT_MS, readServingLeaseResponse } from "@sema-agent/settings-schema/fleet";
|
|
4
|
-
import { centerFetch } from "../
|
|
4
|
+
import { centerFetch } from "../web-admin-client/center-request.js";
|
|
5
5
|
import { recordFailOpen } from "../observability/fail-open.js";
|
|
6
6
|
import { leaseDrainActionId } from "./drain-entry.js";
|
|
7
7
|
export const SERVING_LEASE_FETCH_TIMEOUT_MS = 5_000;
|