@sema-agent/server 7.136.0 → 7.138.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 +501 -139
- package/README.md +1 -0
- package/README.zh-CN.md +1 -0
- package/USAGE.md +149 -34
- package/deploy/sema-up/README.md +14 -0
- package/deploy/sema-up/chart/templates/sandbox-rbac.yaml +7 -1
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +7 -1
- package/dist/approval-card.d.ts +21 -14
- package/dist/approval-card.js +1 -0
- package/dist/approval-content-kind.d.ts +6 -0
- package/dist/approval-content-kind.js +7 -0
- package/dist/approval-gate-currency.d.ts +48 -6
- package/dist/approval-gate-currency.js +16 -9
- package/dist/approval-hmac.d.ts +13 -1
- package/dist/approval-hmac.js +1 -1
- package/dist/approval.js +3 -3
- package/dist/audit.js +1 -0
- package/dist/auth-bridge.js +2 -2
- package/dist/background-agent-name.d.ts +5 -0
- package/dist/background-agent-name.js +5 -0
- package/dist/boot/budget-tracing.d.ts +1 -12
- package/dist/boot/deployment-mods.d.ts +46 -16
- package/dist/boot/deployment-mods.js +82 -6
- package/dist/boot/execution-env.d.ts +24 -1
- package/dist/boot/execution-env.js +69 -6
- package/dist/boot/governance-seams.d.ts +10 -17
- package/dist/boot/governance-seams.js +5 -17
- package/dist/boot/leader.d.ts +3 -0
- package/dist/boot/leader.js +1 -0
- package/dist/boot/org-delivery.js +15 -2
- package/dist/boot/reapers.d.ts +3 -0
- package/dist/boot/reapers.js +15 -1
- package/dist/boot/resolve-spec.d.ts +7 -0
- package/dist/boot/resolve-spec.js +36 -26
- package/dist/boot/retention-lane.d.ts +11 -5
- package/dist/boot/retention-lane.js +2 -2
- package/dist/boot/runner-deps.d.ts +7 -3
- package/dist/boot/runner-deps.js +1 -0
- package/dist/boot/stage-03-store-backend.d.ts +1 -1
- package/dist/boot/stage-04-stores.d.ts +2 -13
- package/dist/boot/stage-05-execution-env.d.ts +6 -13
- package/dist/boot/stage-05-execution-env.js +17 -5
- package/dist/boot/stage-06-runners.d.ts +6 -13
- package/dist/boot/stage-06-runners.js +10 -3
- package/dist/boot/stage-07-capability-layer.d.ts +7 -13
- package/dist/boot/stage-07-capability-layer.js +3 -3
- package/dist/boot/stage-08-reapers.d.ts +7 -13
- package/dist/boot/stage-08-reapers.js +2 -1
- package/dist/boot/stage-09-leader.d.ts +7 -13
- package/dist/boot/stage-09-leader.js +2 -2
- package/dist/boot/stage-10-http-server.d.ts +7 -13
- package/dist/boot/stage-10-http-server.js +6 -3
- package/dist/boot/stores.d.ts +1 -1
- package/dist/boot/web-admin.d.ts +5 -2
- package/dist/boot/web-admin.js +3 -3
- package/dist/brain.js +5 -5
- package/dist/broker/broker.d.ts +89 -0
- package/dist/broker/broker.js +287 -0
- package/dist/broker/constants.d.ts +39 -0
- package/dist/broker/constants.js +15 -0
- package/dist/broker/http1.d.ts +111 -0
- package/dist/broker/http1.js +256 -0
- package/dist/broker/lease-book.d.ts +87 -0
- package/dist/broker/lease-book.js +142 -0
- package/dist/broker/lease-file.d.ts +60 -0
- package/dist/broker/lease-file.js +127 -0
- package/dist/broker/main.d.ts +2 -0
- package/dist/broker/main.js +20 -0
- package/dist/budget.d.ts +17 -15
- package/dist/budget.js +2 -2
- package/dist/capabilities/composite-members.d.ts +2 -1
- package/dist/capabilities/composite-members.js +2 -1
- package/dist/capabilities/engine-capabilities.js +1 -0
- package/dist/capabilities/mcp-probe.d.ts +36 -11
- package/dist/capabilities/mcp-probe.js +44 -5
- package/dist/capabilities/scenarios.d.ts +23 -8
- package/dist/capabilities/scenarios.js +13 -8
- package/dist/capabilities/skills.d.ts +28 -5
- package/dist/capabilities/skills.js +8 -0
- package/dist/capability-facts.d.ts +6 -0
- package/dist/capability-facts.js +5 -0
- package/dist/center-credential-renewer.js +5 -1
- package/dist/checkpoint-ctx-seal-m28.d.ts +3 -10
- package/dist/checkpoint-ctx-seal-m28.js +1 -1
- package/dist/checkpoint-identity.d.ts +13 -6
- package/dist/config-catalog.js +16 -7
- package/dist/config-types.d.ts +24 -7
- package/dist/config.d.ts +1 -1
- package/dist/config.js +42 -13
- package/dist/deployment-governance.d.ts +2 -2
- package/dist/deployment-governance.js +7 -9
- package/dist/deployment-shape.d.ts +6 -6
- package/dist/device-ws-protocol.d.ts +1 -0
- package/dist/device-ws-protocol.js +2 -1
- package/dist/file-history-disclosure.d.ts +4 -2
- package/dist/file-history-disclosure.js +2 -0
- package/dist/gate-settlement.d.ts +71 -0
- package/dist/gate-settlement.js +40 -0
- package/dist/hooks/classic-stations.d.ts +12 -54
- package/dist/hooks/classic-stations.js +1 -0
- package/dist/hooks/command-spawn.d.ts +2 -2
- package/dist/hooks/hook-runner.js +14 -14
- package/dist/http/admission.js +14 -9
- package/dist/http/approval-sweeps.js +4 -3
- package/dist/http/caller-trust.d.ts +2 -1
- package/dist/http/caller-trust.js +1 -3
- package/dist/http/checkpoint-ctx.d.ts +48 -7
- package/dist/http/checkpoint-ctx.js +40 -0
- package/dist/http/dispatch.d.ts +4 -0
- package/dist/http/dispatch.js +18 -10
- package/dist/http/durable-run-leg.d.ts +5 -1
- package/dist/http/durable-run-leg.js +5 -3
- package/dist/http/health-self-report.d.ts +2 -2
- package/dist/http/memory-compliance-failure-reply.js +3 -0
- package/dist/http/principal-gate.d.ts +15 -10
- package/dist/http/principal-gate.js +48 -9
- package/dist/http/resume-legs.d.ts +7 -31
- package/dist/http/resume-legs.js +185 -126
- package/dist/http/route-ctx.d.ts +38 -53
- package/dist/http/route-ctx.js +2 -5
- package/dist/http/routes/a2a-serve.js +10 -4
- package/dist/http/routes/agents-roster.d.ts +1 -1
- package/dist/http/routes/agents-roster.js +5 -1
- package/dist/http/routes/approvals-assistant.js +24 -10
- package/dist/http/routes/capabilities.js +23 -11
- package/dist/http/routes/mcp-reconnect.d.ts +3 -2
- package/dist/http/routes/mcp-reconnect.js +7 -7
- package/dist/http/routes/memory-consolidation.d.ts +1 -1
- package/dist/http/routes/memory-origin.d.ts +1 -1
- package/dist/http/routes/rules.js +3 -3
- package/dist/http/routes/runs.js +13 -8
- package/dist/http/routes/session-sync.js +42 -6
- package/dist/http/routes/sessions.js +6 -3
- package/dist/http/routes/side-query.js +2 -3
- package/dist/http/routes/tasks.js +794 -780
- package/dist/http/server.d.ts +35 -25
- package/dist/http/stored-body-replay.d.ts +3 -3
- package/dist/http/stored-body-replay.js +6 -1
- package/dist/http/wire-types.d.ts +66 -33
- package/dist/identity-source.d.ts +65 -0
- package/dist/identity-source.js +45 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/leader/wire.d.ts +7 -0
- package/dist/leader/wire.js +5 -4
- package/dist/mcp-assertion-header.d.ts +51 -40
- package/dist/mcp-assertion-header.js +10 -11
- package/dist/mcp-authorization-face.d.ts +27 -0
- package/dist/mcp-authorization-face.js +15 -0
- package/dist/memory-operator-faces.d.ts +13 -4
- package/dist/memory-operator-faces.js +1 -17
- package/dist/memory-store-refusal.d.ts +3 -3
- package/dist/memory-sync-client.js +72 -57
- package/dist/memory-sync.d.ts +1 -1
- package/dist/model-entry-refusal.d.ts +2 -0
- package/dist/model-entry-refusal.js +11 -0
- package/dist/model-route-gap.d.ts +6 -22
- package/dist/model-route-gap.js +7 -5
- package/dist/model-select.d.ts +6 -17
- package/dist/model-select.js +0 -3
- package/dist/mods-declaration.d.ts +110 -0
- package/dist/mods-declaration.js +109 -0
- package/dist/namespaced-rule-name.d.ts +1 -1
- package/dist/observability/err-text.d.ts +5 -0
- package/dist/observability/err-text.js +9 -0
- package/dist/observability/fail-open.d.ts +17 -1
- package/dist/observability/fail-open.js +17 -1
- package/dist/observability/metrics.js +1 -1
- package/dist/observability/run-terminal.js +1 -0
- package/dist/observability/secret-env-scrub.d.ts +1 -1
- package/dist/observability/secret-env-scrub.js +1 -1
- package/dist/operator-ask.d.ts +2 -2
- package/dist/org-delivery-gate.js +1 -1
- package/dist/org-memory-admission.d.ts +2 -2
- package/dist/org-memory-admission.js +39 -2
- package/dist/parked-decide.d.ts +15 -2
- package/dist/parked-decide.js +17 -10
- package/dist/peer-directory.js +2 -0
- package/dist/peer-seat.d.ts +150 -0
- package/dist/peer-seat.js +239 -0
- package/dist/permission-rule-list.d.ts +2 -2
- package/dist/permission-rule-vocab.d.ts +7 -7
- package/dist/permission-rule-vocab.js +3 -3
- package/dist/plain-string-record.d.ts +38 -0
- package/dist/plain-string-record.js +38 -0
- package/dist/plugins/background-agent-store-sql.js +6 -3
- package/dist/plugins/caching-session-store.d.ts +5 -0
- package/dist/plugins/caching-session-store.js +6 -0
- package/dist/plugins/checkpoint-store-sql.d.ts +34 -29
- package/dist/plugins/checkpoint-store-sql.js +14 -14
- package/dist/plugins/file-history-store-sql.js +10 -16
- package/dist/plugins/file-run-store.js +8 -2
- package/dist/plugins/k8s-exec-protocol.d.ts +69 -13
- package/dist/plugins/k8s-exec-protocol.js +116 -28
- package/dist/plugins/k8s-pod-delete-failure.d.ts +25 -0
- package/dist/plugins/k8s-pod-delete-failure.js +17 -0
- package/dist/plugins/k8s-pod-reaper.d.ts +106 -0
- package/dist/plugins/k8s-pod-reaper.js +122 -0
- package/dist/plugins/local-checkpoint-store.d.ts +4 -17
- package/dist/plugins/local-checkpoint-store.js +3 -4
- package/dist/plugins/local-session-store.d.ts +66 -27
- package/dist/plugins/local-session-store.js +60 -28
- package/dist/plugins/mailbox-store-sql.d.ts +11 -3
- package/dist/plugins/mailbox-store-sql.js +103 -15
- package/dist/plugins/memory-run-store.js +2 -0
- package/dist/plugins/memory-sync-store-pg.d.ts +16 -5
- package/dist/plugins/memory-sync-store-tidb.d.ts +3 -3
- package/dist/plugins/one-time-migrations.d.ts +34 -12
- package/dist/plugins/one-time-migrations.js +51 -9
- package/dist/plugins/permission-rule-store-file.js +2 -2
- package/dist/plugins/permission-rule-store-sql.d.ts +17 -17
- package/dist/plugins/permission-rule-store-sql.js +37 -30
- package/dist/plugins/pg-pool.js +4 -0
- package/dist/plugins/pg-session-storage.d.ts +10 -2
- package/dist/plugins/pg-session-storage.js +20 -7
- package/dist/plugins/remote-env-adb.d.ts +6 -1
- package/dist/plugins/remote-env-adb.js +2 -1
- package/dist/plugins/remote-env-device.d.ts +6 -1
- package/dist/plugins/remote-env-device.js +5 -1
- package/dist/plugins/remote-env-e2b.d.ts +5 -0
- package/dist/plugins/remote-env-e2b.js +2 -1
- package/dist/plugins/remote-env-file-error.d.ts +8 -1
- package/dist/plugins/remote-env-file-error.js +7 -1
- package/dist/plugins/remote-env-host.d.ts +10 -2
- package/dist/plugins/remote-env-host.js +8 -2
- package/dist/plugins/remote-env-k8s.d.ts +140 -11
- package/dist/plugins/remote-env-k8s.js +277 -15
- package/dist/plugins/remote-env-local-docker.d.ts +5 -0
- package/dist/plugins/remote-env-local-docker.js +2 -1
- package/dist/plugins/remote-env-ssh.d.ts +6 -1
- package/dist/plugins/remote-env-ssh.js +2 -1
- package/dist/plugins/retention-store-sql.d.ts +14 -2
- package/dist/plugins/retention-store-sql.js +6 -0
- package/dist/plugins/run-store-sql.js +10 -4
- package/dist/plugins/session-fork.d.ts +10 -13
- package/dist/plugins/session-fork.js +5 -25
- package/dist/plugins/session-ownership.d.ts +24 -3
- package/dist/plugins/session-ownership.js +24 -5
- package/dist/plugins/session-workspace-cell.d.ts +17 -0
- package/dist/plugins/session-workspace-cell.js +38 -0
- package/dist/plugins/sql-errors.d.ts +23 -2
- package/dist/plugins/sql-errors.js +15 -0
- package/dist/plugins/store-backend.js +7 -7
- package/dist/plugins/store-contracts.d.ts +10 -1
- package/dist/plugins/store-fault.d.ts +2 -2
- package/dist/plugins/store-fault.js +4 -2
- package/dist/plugins/tidb-pool.js +13 -0
- package/dist/plugins/tidb-session-store.d.ts +17 -2
- package/dist/plugins/tidb-session-store.js +18 -7
- package/dist/plugins/tool-result-store-sql.d.ts +13 -6
- package/dist/plugins/tool-result-store-sql.js +8 -7
- package/dist/plugins/worktree-isolation.d.ts +3 -2
- package/dist/plugins/worktree-isolation.js +1 -7
- package/dist/project-identity.d.ts +1 -14
- package/dist/project-identity.js +0 -4
- package/dist/request-key-closure.js +1 -1
- package/dist/request-value-closure.d.ts +31 -2
- package/dist/request-value-closure.js +7 -1
- package/dist/rule-entry-list.d.ts +3 -2
- package/dist/rule-entry-list.js +2 -2
- package/dist/rules-consent.js +12 -7
- package/dist/run-local.d.ts +2 -2
- package/dist/run-local.js +12 -6
- package/dist/runs.d.ts +7 -1
- package/dist/runs.js +8 -2
- package/dist/runtime-governance.d.ts +5 -5
- package/dist/sandbox-git-lease.d.ts +49 -0
- package/dist/sandbox-git-lease.js +60 -0
- package/dist/sandbox-git-plane.d.ts +84 -0
- package/dist/sandbox-git-plane.js +105 -0
- package/dist/security.d.ts +16 -4
- package/dist/security.js +8 -3
- package/dist/server-secret-env.d.ts +12 -3
- package/dist/server-secret-env.js +18 -2
- package/dist/session-error-wire.d.ts +14 -6
- package/dist/session-error-wire.js +2 -1
- package/dist/session-incarnation.d.ts +4 -5
- package/dist/session-incarnation.js +2 -2
- package/dist/session-policy-wire.d.ts +1 -1
- package/dist/session-policy-wire.js +2 -2
- package/dist/session-sync.d.ts +1 -1
- package/dist/session-workspace.d.ts +130 -0
- package/dist/session-workspace.js +83 -0
- package/dist/spec-fields.d.ts +44 -14
- package/dist/spec-fields.js +33 -12
- package/dist/standing-answer-grant.d.ts +2 -13
- package/dist/standing-answer-grant.js +0 -7
- package/dist/stored-request-prompt-profile-m30.d.ts +49 -0
- package/dist/stored-request-prompt-profile-m30.js +25 -0
- package/dist/task-a2a.d.ts +44 -14
- package/dist/task-a2a.js +46 -20
- package/dist/task-mcp.d.ts +34 -21
- package/dist/task-mcp.js +46 -22
- package/dist/task-settings.d.ts +2 -2
- package/dist/tool-approval.d.ts +43 -9
- package/dist/tool-approval.js +57 -15
- package/dist/tool-rule-names.d.ts +5 -0
- package/dist/trace/core-keyset-guard.d.ts +34 -19
- package/dist/trace/engine-notice-wire.d.ts +1 -1
- package/dist/trace/engine-notice-wire.js +4 -0
- package/dist/trace/exit-seat.d.ts +20 -1
- package/dist/trace/exit-seat.js +5 -2
- package/dist/trace/extension-call-face.d.ts +33 -0
- package/dist/trace/extension-call-face.js +39 -0
- package/dist/trace/ledger-sink.d.ts +4 -5
- package/dist/trace/ledger-sink.js +3 -7
- package/dist/trace/project.d.ts +62 -10
- package/dist/trace/project.js +49 -9
- package/dist/trace/redact.d.ts +18 -6
- package/dist/trace/redact.js +154 -60
- package/dist/trace/self-minted-wire.d.ts +500 -7
- package/dist/trace/self-minted-wire.js +182 -1
- package/dist/trace/wire-projection-faces.d.ts +7 -5
- package/dist/trace/wire-projection-faces.js +9 -4
- package/dist/user-authored-text.d.ts +2 -2
- package/dist/user-authored-text.js +16 -1
- package/dist/web-admin-client/apply-effective.js +0 -1
- package/dist/web-admin-client/center-request.d.ts +23 -4
- package/dist/web-admin-client/center-request.js +42 -8
- package/dist/web-admin-client/http-client.js +6 -6
- package/dist/web-admin-client/skills-mcp.d.ts +8 -4
- package/dist/web-admin-client/skills-mcp.js +31 -18
- package/dist/web-admin-client/types.d.ts +10 -5
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +11 -5
- package/package.json +3 -3
- package/wire-changes/server@7.137.0.json +825 -0
- package/wire-changes/server@7.138.0.json +446 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { BROKER_HOST, BROKER_LEASE_PATH, BROKER_LEASE_POLL_MS, BROKER_PORT, BROKER_PROBE_ARG } from "./constants.js";
|
|
2
|
+
import { probeBroker, runBroker } from "./broker.js";
|
|
3
|
+
const PROBE_TIMEOUT_MS = 2_000;
|
|
4
|
+
async function main() {
|
|
5
|
+
if (process.argv.includes(BROKER_PROBE_ARG)) {
|
|
6
|
+
process.exit((await probeBroker(BROKER_HOST, BROKER_PORT, PROBE_TIMEOUT_MS)) ? 0 : 1);
|
|
7
|
+
}
|
|
8
|
+
await runBroker({
|
|
9
|
+
leasePath: BROKER_LEASE_PATH,
|
|
10
|
+
host: BROKER_HOST,
|
|
11
|
+
port: BROKER_PORT,
|
|
12
|
+
pollMs: BROKER_LEASE_POLL_MS,
|
|
13
|
+
log: (e) => void process.stdout.write(`${JSON.stringify(e)}\n`),
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
main().catch((e) => {
|
|
17
|
+
process.stderr.write(`${JSON.stringify({ event: "broker_failed", error: e instanceof Error ? e.message : String(e) })}\n`);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
});
|
|
20
|
+
//# sourceMappingURL=main.js.map
|
package/dist/budget.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* ④ createTracer — core's content-free TraceEvents → /metrics (spend, first-token, tool calls).
|
|
6
6
|
* ⑤ cappedCeiling — clamp a caller's requested per-task budget DOWN to the operator ceiling.
|
|
7
7
|
*/
|
|
8
|
-
import { type Model, type ModelPricing, type TracerHook } from "@sema-agent/core";
|
|
8
|
+
import { type AccountRow, type Model, type ModelPricing, type TracerHook } from "@sema-agent/core";
|
|
9
9
|
import type { Metrics } from "./observability/metrics.js";
|
|
10
10
|
import type { QuotaTracker } from "./observability/cost-quota.js";
|
|
11
11
|
import type { FleetUsageBins } from "./fleet-client.js";
|
|
@@ -116,23 +116,25 @@ export declare function createTracer(metrics: Pick<Metrics, "inc" | "observe">,
|
|
|
116
116
|
* (tokens×quotaWeight,weight-at-burn 固化)、micro-USD 同轴。装配点与 createTracer 同一处(main.ts),
|
|
117
117
|
* 传同一组实例——两臂永不分家。
|
|
118
118
|
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
* (
|
|
119
|
+
* 金额源 = 引擎定价的账行 `SideQueryResult.account.costMicroUsd`(core 7.59.0:与 run 的旁路调用同一只定价函数、
|
|
120
|
+
* 按部署价表、按实际作答的模型)—— 与 tracer 的 `e.costMicroUsd` 同一口径;缺席 = 那只模型没有价表 = **未知**(不编 0)。
|
|
121
|
+
* 适配器自报的 `usage.cost.total`(cache 命中按全价)不是金额源(7.58.x 及更早读它,cache-heavy 时多收)。model 标签 /
|
|
122
122
|
* weight 键用**路由身份 r.model**(池配置有界)非 servedModel(provider 上报,无界)。
|
|
123
123
|
*/
|
|
124
|
-
export
|
|
125
|
-
model: string;
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
total?: number;
|
|
133
|
-
};
|
|
124
|
+
export interface SideQueryAccountingInput {
|
|
125
|
+
readonly model: string;
|
|
126
|
+
/** 引擎归一的计数(`input` 已是 uncached 量,见函数体 [ref] 注)。 */
|
|
127
|
+
readonly usage?: {
|
|
128
|
+
readonly input?: number;
|
|
129
|
+
readonly output?: number;
|
|
130
|
+
readonly cacheRead?: number;
|
|
131
|
+
readonly cacheWrite?: number;
|
|
134
132
|
};
|
|
135
|
-
|
|
133
|
+
/** 引擎定价的账行(`origin: "side_query"`);只读它的 `costMicroUsd`。 */
|
|
134
|
+
readonly account?: AccountRow;
|
|
135
|
+
}
|
|
136
|
+
export type SideQueryAccounting = (principal: string | undefined, r: SideQueryAccountingInput) => void;
|
|
137
|
+
export declare function createSideQueryAccountant(metrics: Pick<Metrics, "inc">, costQuota?: QuotaTracker, fleetUsage?: Pick<FleetUsageBins, "record">, fleetLease?: Pick<FleetLeaseManager, "recordSpend">, quotaWeightFor?: (model: string) => number): SideQueryAccounting;
|
|
136
138
|
/**
|
|
137
139
|
* ⑤ Resolve a per-task budget: honor the caller's requested value but never let it EXCEED the operator
|
|
138
140
|
* ceiling. `0`/unset ceiling = no limit (returns the caller's value, or undefined). A non-positive /
|
package/dist/budget.js
CHANGED
|
@@ -144,8 +144,8 @@ export function createSideQueryAccountant(metrics, costQuota, fleetUsage, fleetL
|
|
|
144
144
|
const cacheRead = typeof r.usage?.cacheRead === "number" ? r.usage.cacheRead : 0;
|
|
145
145
|
const cacheWrite = typeof r.usage?.cacheWrite === "number" ? r.usage.cacheWrite : 0;
|
|
146
146
|
const promptTokens = input + cacheRead + cacheWrite;
|
|
147
|
-
const
|
|
148
|
-
const micro =
|
|
147
|
+
const costMicro = r.account?.costMicroUsd;
|
|
148
|
+
const micro = typeof costMicro === "number" && Number.isFinite(costMicro) ? Math.round(costMicro) : undefined;
|
|
149
149
|
if (micro !== undefined && micro > 0) {
|
|
150
150
|
metrics.inc("model_cost_micro_usd_total", { model: r.model }, micro);
|
|
151
151
|
if (principal)
|
|
@@ -38,7 +38,7 @@ import type { NamedKeysOf } from "../request-key-closure.js";
|
|
|
38
38
|
* B.2b)与 CHANGELOG。present-iff 的位与成员照样登记(在场律写在附录的「在场律」列)。
|
|
39
39
|
*/
|
|
40
40
|
export declare const COMPOSITE_CAPABILITY_MEMBERS: {
|
|
41
|
-
readonly deviceExecutor: readonly ["enabled", "protocolVersion", "maxInflightPerDevice", "wsPath", "management"];
|
|
41
|
+
readonly deviceExecutor: readonly ["enabled", "protocolVersion", "maxInflightPerDevice", "wsPath", "management", "relayUrl"];
|
|
42
42
|
readonly fleet: readonly ["stream", "sessionScope", "observe", "resume", "bgNotifyFailClosed", "steerPriority", "hookFailureNotice", "leaseClient", "generationEcho"];
|
|
43
43
|
readonly memoryEngine: readonly ["backend", "vectorMode"];
|
|
44
44
|
readonly store: readonly ["declared", "backend", "durable", "degradedReason", "sql"];
|
|
@@ -55,6 +55,7 @@ export declare const COMPOSITE_CAPABILITY_MEMBERS: {
|
|
|
55
55
|
readonly sealedKey: readonly ["alg", "publicKeyId", "publicKey"];
|
|
56
56
|
readonly workspaceSync: readonly ["persist", "keep", "timeoutMs", "cache"];
|
|
57
57
|
readonly userAttachments: readonly ["entries", "kinds", "supplies", "limits"];
|
|
58
|
+
readonly credentialPlane: readonly ["sandboxGit"];
|
|
58
59
|
};
|
|
59
60
|
type CompositeTable = typeof COMPOSITE_CAPABILITY_MEMBERS;
|
|
60
61
|
/** 值的**具名成员对象臂**(标量 / 字面词 / `false` / `null` / `undefined` / 数组 / 函数臂剥掉)。 */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const COMPOSITE_CAPABILITY_MEMBERS = {
|
|
2
|
-
deviceExecutor: ["enabled", "protocolVersion", "maxInflightPerDevice", "wsPath", "management"],
|
|
2
|
+
deviceExecutor: ["enabled", "protocolVersion", "maxInflightPerDevice", "wsPath", "management", "relayUrl"],
|
|
3
3
|
fleet: ["stream", "sessionScope", "observe", "resume", "bgNotifyFailClosed", "steerPriority", "hookFailureNotice", "leaseClient", "generationEcho"],
|
|
4
4
|
memoryEngine: ["backend", "vectorMode"],
|
|
5
5
|
store: ["declared", "backend", "durable", "degradedReason", "sql"],
|
|
@@ -16,6 +16,7 @@ export const COMPOSITE_CAPABILITY_MEMBERS = {
|
|
|
16
16
|
sealedKey: ["alg", "publicKeyId", "publicKey"],
|
|
17
17
|
workspaceSync: ["persist", "keep", "timeoutMs", "cache"],
|
|
18
18
|
userAttachments: ["entries", "kinds", "supplies", "limits"],
|
|
19
|
+
credentialPlane: ["sandboxGit"],
|
|
19
20
|
};
|
|
20
21
|
export function gateCompositeMembers(body) {
|
|
21
22
|
return body;
|
|
@@ -3,6 +3,7 @@ import { ownCredentialsWithheld, ownCredentialValuesWithheld } from "../server-s
|
|
|
3
3
|
const ENGINE_CAPABILITY_FACTS = {
|
|
4
4
|
"inherit_env.own_credentials_withheld": ownCredentialsWithheld,
|
|
5
5
|
"inherit_env.own_credential_values_withheld": ownCredentialValuesWithheld,
|
|
6
|
+
"mods.skill_seat": () => false,
|
|
6
7
|
};
|
|
7
8
|
export function engineCapabilityBits() {
|
|
8
9
|
const out = {};
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
*/
|
|
35
35
|
import { type McpServerSpec } from "@sema-agent/core";
|
|
36
36
|
import type { DeclarationRefusal } from "../request-declaration-refusal.js";
|
|
37
|
+
import { type McpDraft, type PeerDesk } from "../peer-seat.js";
|
|
37
38
|
/**
|
|
38
39
|
* 本面的**拒码闭集**(设计稿 §2 的四枚)。闭集写成型,是为了让 {@link MCP_PROBE_HTTP_STATUS} 那张表
|
|
39
40
|
* 「漏一枚 = 编译红」—— [ref] 的安全轴纪律:词表是闭集,未处置的成员必须是编译错误而不是运行期惊喜。
|
|
@@ -163,25 +164,29 @@ export interface McpProbeRefusal {
|
|
|
163
164
|
readonly facts?: DeclarationRefusal["facts"];
|
|
164
165
|
}
|
|
165
166
|
/**
|
|
166
|
-
* `POST …/probe` 的体读器:闭形、逐条点名、零静默丢。成功 ⇒
|
|
167
|
-
*
|
|
167
|
+
* `POST …/probe` 的体读器:闭形、逐条点名、零静默丢。成功 ⇒ 每条申报的**草稿**(被读出来的条目经 `toMcpDraft` 拆成声明 + 件,
|
|
168
|
+
* 声明里 `McpServerSpec` 的可选键一个都不重写 —— 重写就是在 core 的型上做第二次投影)。
|
|
168
169
|
*
|
|
169
170
|
* ## 申报「能不能原样用」:问提交腿 fresh 门**同一只**回答者,不另判
|
|
170
171
|
* 本面只判自己那一层(体是对象、顶层只受理 `mcpServers`、这个键必填);`mcpServers` 本身 —— 列表的形、上限、每条的键名与键值 —— 全部交给
|
|
171
172
|
* `task-mcp.ts` 的 `requestMcpDeclarationRefusal`,拒(码 + 句 + `unknownKeys` + 撞帽 / url 带凭据两形的机读位)原样转述:同一份申报在两扇门上只有一个答案,零拨号之前就给。
|
|
172
|
-
* 回答者受理的申报由**同一只**读器(`validateRequestMcp`)交回,读器的产物就是申报本身(只差判官自己的合法归一),经 `
|
|
173
|
-
*
|
|
174
|
-
* (`source` 写坏的 F 类丢弃)不会在一次被拒的探测上虚记。
|
|
173
|
+
* 回答者受理的申报由**同一只**读器(`validateRequestMcp`)交回,读器的产物就是申报本身(只差判官自己的合法归一),经 `toMcpDraft`
|
|
174
|
+
* 拆出的草稿就是一条任务提交会交给铸点的那一份 —— 走查在自己的租约下铸它(见 {@link createMcpProbeWalk}),本面拨的正是铸出的声明。读器只在回答者受理之后才跑,
|
|
175
|
+
* 所以它对重放存量 body 才有的降级留痕(`source` 写坏的 F 类丢弃)不会在一次被拒的探测上虚记。
|
|
175
176
|
*
|
|
176
|
-
* ## 唯一一处按门分的后果:声明了 `assertionHeader`(
|
|
177
|
+
* ## 唯一一处按门分的后果:声明了 `assertionHeader`(本部署的对端座对断言一种引用恒拒、没有断言来源)
|
|
177
178
|
* 事实只有一个、读它的谓词只有一只(`specWithholdsMcpAssertionHeader`,读发送开关 `MCP_ASSERTION_HEADER_SENT`):这台 server 声明的断言头本版**承载、不发送**,交给引擎的规格里没有它。
|
|
178
179
|
* 新提交照挂并给运维一行 info(`mcp_assertion_header_not_sent`;settings 面同读法);本面**整条拒** —— 拨出去的不是申报的那一份,一台握手放行、
|
|
179
180
|
* 调用才要断言的对端会被答成 connected,而它的调用会被拒。判据同一只、后果按门分(与重放腿对同一组身份头「降级到升级前读法」同一个姿势);
|
|
180
|
-
*
|
|
181
|
+
* 开关与它的退役门在 `mcp-assertion-header.ts`(押在对端座上)。
|
|
182
|
+
*
|
|
183
|
+
* ## 带件的申报(`transport.headers` / `transport.env`):与任务提交同一条路
|
|
184
|
+
* 件进草稿、不进声明;走查在自己的宿主租约下把件登记进部署的对端座,交给引擎的声明只带一只引用,引擎在起子进程 / 发请求时向同一只座要 ——
|
|
185
|
+
* 拨出去的就是申报的那一份,件形的判(多行值、协议自有头名 …)也是任务那一份判。
|
|
181
186
|
*/
|
|
182
187
|
export declare function readMcpProbeBody(raw: unknown): {
|
|
183
188
|
ok: true;
|
|
184
|
-
|
|
189
|
+
drafts: McpDraft[];
|
|
185
190
|
} | {
|
|
186
191
|
ok: false;
|
|
187
192
|
refusal: McpProbeRefusal;
|
|
@@ -194,8 +199,28 @@ export declare function readMcpProbeBody(raw: unknown): {
|
|
|
194
199
|
* 无 principal(单用户部署上恒如此)折成 `local`:那台机器上只有一个人。
|
|
195
200
|
*/
|
|
196
201
|
export declare function buildMcpProbeIdentity(principal: string | undefined): string;
|
|
197
|
-
/**
|
|
198
|
-
|
|
202
|
+
/**
|
|
203
|
+
* 一次探测问的是什么 —— 两条口各一臂,**谁写的申报**就是判别位:
|
|
204
|
+
* · `deployment`(`GET /v1/capabilities/mcp`)= 本部署名册里这个场景挂的声明。它们起服时已在名册租约下铸过(件在对端座里、声明只带引用),
|
|
205
|
+
* 走查直接拨、不开租约、不再登记;
|
|
206
|
+
* · `caller`(`POST …/probe`)= 调用方自带申报的草稿(声明 + 件)。走查在自己的宿主租约下经唯一铸点登记件,见 {@link createMcpProbeWalk}。
|
|
207
|
+
* 两臂的声明都由同一只座作答。缓存键、走查、失败归属(谁写的申报谁的错)都读这一只输入。
|
|
208
|
+
*/
|
|
209
|
+
export type McpProbeInput = {
|
|
210
|
+
readonly declaredBy: "deployment";
|
|
211
|
+
readonly specs: readonly McpServerSpec[];
|
|
212
|
+
} | {
|
|
213
|
+
readonly declaredBy: "caller";
|
|
214
|
+
readonly drafts: readonly McpDraft[];
|
|
215
|
+
};
|
|
216
|
+
/** 这次探测申报了几台(零台 ⇒ 诚实空面,不进缓存、不占限速、不开租约)。 */
|
|
217
|
+
export declare function countMcpProbeDeclarations(input: McpProbeInput): number;
|
|
218
|
+
/**
|
|
219
|
+
* 缓存键 = `(身份, sha256(规范化的整份输入))`。**对输入算**:键在缓存命中 / 在途帽 / 限速三道前置拒里就要用,那时还没有登记任何件(登记在走查里),
|
|
220
|
+
* 所以只能对问的那一份算 —— 调用方臂的件在键内(只差凭据的两份申报是两次走查,与件写在声明里时同义),申报方也在键内(同一份声明在两臂上是两件事)。
|
|
221
|
+
* 部署臂的声明带的是引用,同一进程同内容同 id,换了名册的件就换了 id。键只在进程内的表里用,不出门。**纯数据** ⇒ `build*`。
|
|
222
|
+
*/
|
|
223
|
+
export declare function buildMcpProbeCacheKey(principal: string | undefined, input: McpProbeInput): string;
|
|
199
224
|
/** 限速键(设计稿 §3:`mcp-probe:<身份>`)。**纯数据** ⇒ `build*`。 */
|
|
200
225
|
export declare function buildMcpProbeRateKey(principal: string | undefined): string;
|
|
201
226
|
/** 本域独占的运行期状态(每 server 实例一份 —— 模块级会把缓存与限速窗跨实例串味)。 */
|
|
@@ -281,7 +306,7 @@ export interface McpProbeWalk {
|
|
|
281
306
|
readonly answer: Promise<McpProbeFaceBody>;
|
|
282
307
|
readonly dials: Promise<unknown>;
|
|
283
308
|
}
|
|
284
|
-
export declare function createMcpProbeWalk(
|
|
309
|
+
export declare function createMcpProbeWalk(input: McpProbeInput, principal: string | undefined, desk: PeerDesk, now?: () => number): McpProbeWalk;
|
|
285
310
|
/**
|
|
286
311
|
* 下标对齐的**内部断言**没过(行数 ≠ 申报数,或读数条数 ≠ 行数):core 的 `@contract mcp.probe.index_aligned` 在今天结构上保证它不发生,
|
|
287
312
|
* 所以它一旦发生,是**这台服务内部的读数违约**,不是调用方的申报写错 —— 修申报修不好它。**具名型**而不是按文案或按「非 Incomplete 的 reject」分诊:
|
|
@@ -4,7 +4,8 @@ import { createFixedWindowRateLimiter } from "../device-enrollment.js";
|
|
|
4
4
|
import { canonicalJsonStringify } from "@sema-agent/core";
|
|
5
5
|
import { keyClosureClause, scanKeyClosure } from "../request-key-closure.js";
|
|
6
6
|
import { requestMcpDeclarationRefusal, validateRequestMcp } from "../task-mcp.js";
|
|
7
|
-
import { specWithholdsMcpAssertionHeader,
|
|
7
|
+
import { specWithholdsMcpAssertionHeader, toMcpDraft } from "../mcp-assertion-header.js";
|
|
8
|
+
import { mintDeclaration } from "../peer-seat.js";
|
|
8
9
|
import { projectWiringManifestMcpRows } from "../trace/project.js";
|
|
9
10
|
import { buildBoundedToolNames } from "../panel-tool-names.js";
|
|
10
11
|
export const MCP_PROBE_REFUSAL_CODES = [
|
|
@@ -80,13 +81,26 @@ export function readMcpProbeBody(raw) {
|
|
|
80
81
|
"Probe the entry without the key to see how the server answers without it"),
|
|
81
82
|
};
|
|
82
83
|
}
|
|
83
|
-
return { ok: true,
|
|
84
|
+
return { ok: true, drafts: validated.ok.map(toMcpDraft) };
|
|
84
85
|
}
|
|
85
86
|
export function buildMcpProbeIdentity(principal) {
|
|
86
87
|
return principal !== undefined && principal.length > 0 ? principal : "local";
|
|
87
88
|
}
|
|
88
|
-
export function
|
|
89
|
-
|
|
89
|
+
export function countMcpProbeDeclarations(input) {
|
|
90
|
+
switch (input.declaredBy) {
|
|
91
|
+
case "deployment":
|
|
92
|
+
return input.specs.length;
|
|
93
|
+
case "caller":
|
|
94
|
+
return input.drafts.length;
|
|
95
|
+
default: {
|
|
96
|
+
const unknownArm = input;
|
|
97
|
+
void unknownArm;
|
|
98
|
+
throw new Error("mcp probe: an input arm this module does not know (the arm set is closed: deployment / caller)");
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
export function buildMcpProbeCacheKey(principal, input) {
|
|
103
|
+
return `${buildMcpProbeIdentity(principal)}::${createHash("sha256").update(canonicalJsonStringify(input), "utf8").digest("hex")}`;
|
|
90
104
|
}
|
|
91
105
|
export function buildMcpProbeRateKey(principal) {
|
|
92
106
|
return `mcp-probe:${buildMcpProbeIdentity(principal)}`;
|
|
@@ -155,7 +169,8 @@ export function buildMcpProbeFaceRows(rows, readings) {
|
|
|
155
169
|
function isStringList(v) {
|
|
156
170
|
return Array.isArray(v) && Array.from(v).every((t) => typeof t === "string");
|
|
157
171
|
}
|
|
158
|
-
export function createMcpProbeWalk(
|
|
172
|
+
export function createMcpProbeWalk(input, principal, desk, now = Date.now) {
|
|
173
|
+
const { specs, lease } = probeDeclarations(input, desk);
|
|
159
174
|
const bound = buildMcpProbeWalkTimeoutMs(specs.length);
|
|
160
175
|
const controller = new AbortController();
|
|
161
176
|
const dials = probeMcpServers(specs, {
|
|
@@ -163,7 +178,10 @@ export function createMcpProbeWalk(specs, principal, now = Date.now) {
|
|
|
163
178
|
timeoutMs: MCP_PROBE_VERDICT_TIMEOUT_MS,
|
|
164
179
|
concurrency: MCP_PROBE_CONCURRENCY,
|
|
165
180
|
signal: controller.signal,
|
|
181
|
+
peerSeat: desk.seat.answer,
|
|
166
182
|
});
|
|
183
|
+
if (lease !== undefined)
|
|
184
|
+
void dials.then(() => lease.release(), () => lease.release());
|
|
167
185
|
dials.catch(() => undefined);
|
|
168
186
|
let timer;
|
|
169
187
|
const deadline = new Promise((_resolve, reject) => {
|
|
@@ -189,6 +207,27 @@ export function createMcpProbeWalk(specs, principal, now = Date.now) {
|
|
|
189
207
|
answer.catch(() => undefined);
|
|
190
208
|
return { answer, dials };
|
|
191
209
|
}
|
|
210
|
+
function probeDeclarations(input, desk) {
|
|
211
|
+
switch (input.declaredBy) {
|
|
212
|
+
case "deployment":
|
|
213
|
+
return { specs: input.specs };
|
|
214
|
+
case "caller": {
|
|
215
|
+
const lease = desk.lease("probe");
|
|
216
|
+
try {
|
|
217
|
+
return { specs: input.drafts.map((draft) => mintDeclaration(desk, draft, lease)), lease };
|
|
218
|
+
}
|
|
219
|
+
catch (err) {
|
|
220
|
+
lease.release();
|
|
221
|
+
throw err;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
default: {
|
|
225
|
+
const unknownArm = input;
|
|
226
|
+
void unknownArm;
|
|
227
|
+
throw new Error("mcp probe: an input arm this module does not know (the arm set is closed: deployment / caller)");
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
192
231
|
export class McpProbeMisaligned extends Error {
|
|
193
232
|
constructor(message) {
|
|
194
233
|
super(message);
|
|
@@ -2,7 +2,7 @@ import { type WebFetchConfig, type BackgroundAgentStore, type CheckpointStore, t
|
|
|
2
2
|
import type { Logger } from "../observability/logger.js";
|
|
3
3
|
import { type SubagentExtraToolSet } from "./builtin-tools.js";
|
|
4
4
|
import { type RepoReadClient } from "./repo-tools.js";
|
|
5
|
-
import { type LoadedSkill, type ScenarioSkillEntry } from "./skills.js";
|
|
5
|
+
import { type LoadedSkill, type RunSkillEntry, type ScenarioSkillEntry, type SkillSource } from "./skills.js";
|
|
6
6
|
import { type ScenarioHands } from "./hands-lane.js";
|
|
7
7
|
import type { DelegationRootWitness } from "../delegated-session-owner.js";
|
|
8
8
|
/**
|
|
@@ -315,14 +315,29 @@ export declare function centerScenarios(deps: ScenarioDeps, specs: CenterScenari
|
|
|
315
315
|
shadows: string[];
|
|
316
316
|
};
|
|
317
317
|
/**
|
|
318
|
-
*
|
|
319
|
-
*
|
|
320
|
-
*
|
|
321
|
-
* unload the whole set with `disableSkills`, [ref]); user content never shadows them. Duplicate names within the user list keep the first. Clashes are logged for audit
|
|
322
|
-
* (silent drops would make "my skill didn't fire" undebuggable). Input is already shape/size-validated
|
|
323
|
-
* by the HTTP layer (validateUserSkills); this stays pure merge policy.
|
|
318
|
+
* 一条 run 的技能(交给引擎的 `TaskSpec.skills`)与它的名册(`wiring_manifest.skills`)—— **同一次合并的两个投影**,铸点只有 {@link buildRunSkills}。
|
|
319
|
+
* · `specs` —— 交给引擎的那一份(`undefined` = 一只都没有且没被关;`disable` ⇒ 显式 `[]`,引擎对空表零 `<skills>` 块、不挂 `Skill`);
|
|
320
|
+
* · `roster` —— 同一组、同一个序,逐条带来处;零技能 ⇒ `[]`(零技能是一句陈述,不是缺席)。
|
|
324
321
|
*/
|
|
325
|
-
export
|
|
322
|
+
export interface RunSkills {
|
|
323
|
+
readonly specs: SkillSpec[] | undefined;
|
|
324
|
+
readonly roster: RunSkillEntry[];
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Personalization seam + run 名册的**唯一铸点**:调用方自带的技能接在场景的之后,**同名场景赢**(场景 / 中心的技能拥有那个名字 —— 它们是部署的基线措辞,
|
|
328
|
+
* 不是执法面:权限 / 写门 / hook 都不骑在技能上,调用方要整组卸掉用 `disableSkills`,[ref]);用户内容永不遮住它们。用户表内重名留第一个。
|
|
329
|
+
* 被丢的名字落审计行(静默丢会让「我的技能没生效」查不出来)。形已由 HTTP 门判过(`validateUserSkills`);本函数只做合并政策与来处。
|
|
330
|
+
*
|
|
331
|
+
* 来处(`roster[].source`):场景那一半按**部署装载簿**的来处标(`deploymentSources`:装载腿写下的 `LoadedSkill.source`,名字在装载簿里唯一 ——
|
|
332
|
+
* 装载器同名即抛、配置源按名覆盖);场景里有、装载簿里没有的技能是嵌入方场景代码自带的 ⇒ `factory`(本部署自带,不是配置源交来的、也不是这次请求带的)。
|
|
333
|
+
* 请求那一半恒 `request`。`disable` ⇒ 两个投影都空(`specs: []`、`roster: []`)。
|
|
334
|
+
*/
|
|
335
|
+
export declare function buildRunSkills(args: {
|
|
336
|
+
readonly scenario: SkillSpec[] | undefined;
|
|
337
|
+
readonly request: readonly SkillSpec[] | undefined;
|
|
338
|
+
readonly disable: boolean;
|
|
339
|
+
readonly deploymentSources: ReadonlyMap<string, SkillSource>;
|
|
340
|
+
}, logger?: Logger): RunSkills;
|
|
326
341
|
/** center caps view 的解析结果两键(形状锚定)。`scenario` null = 三层皆未配。 */
|
|
327
342
|
export interface ScenarioRuling {
|
|
328
343
|
scenario: string | null;
|
|
@@ -262,23 +262,28 @@ const REVIEWER_ROLE_TEXT = "You are a senior code reviewer. Call repo_tree to ma
|
|
|
262
262
|
"the files in scope, then review them yourself. " +
|
|
263
263
|
"Produce ONE prioritized review: a short summary, then findings grouped by severity " +
|
|
264
264
|
"(blocker / major / minor), each with `path:line`, the problem, and a concrete fix. Cite real code — never invent files or symbols.";
|
|
265
|
-
export function
|
|
266
|
-
if (
|
|
267
|
-
return
|
|
268
|
-
const
|
|
269
|
-
const
|
|
265
|
+
export function buildRunSkills(args, logger) {
|
|
266
|
+
if (args.disable)
|
|
267
|
+
return { specs: [], roster: [] };
|
|
268
|
+
const scenario = args.scenario ?? [];
|
|
269
|
+
const roster = scenario.map((s) => ({ name: s.name, description: s.description, source: args.deploymentSources.get(s.name) ?? "factory" }));
|
|
270
|
+
if (!args.request || args.request.length === 0)
|
|
271
|
+
return { specs: args.scenario, roster };
|
|
272
|
+
const reserved = new Set(scenario.map((s) => s.name));
|
|
273
|
+
const specs = [...scenario];
|
|
270
274
|
const dropped = [];
|
|
271
|
-
for (const s of
|
|
275
|
+
for (const s of args.request) {
|
|
272
276
|
if (reserved.has(s.name)) {
|
|
273
277
|
dropped.push(s.name);
|
|
274
278
|
continue;
|
|
275
279
|
}
|
|
276
280
|
reserved.add(s.name);
|
|
277
|
-
|
|
281
|
+
specs.push(s);
|
|
282
|
+
roster.push({ name: s.name, description: s.description, source: "request" });
|
|
278
283
|
}
|
|
279
284
|
if (dropped.length > 0)
|
|
280
285
|
logger?.warn("user_skills_dropped", { reason: "name reserved by scenario (or duplicate)", names: dropped });
|
|
281
|
-
return
|
|
286
|
+
return { specs, roster };
|
|
282
287
|
}
|
|
283
288
|
function registeredScenariosClause(known) {
|
|
284
289
|
return `this deployment's scenarios are: ${known.join(", ")}`;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SkillSpec } from "@sema-agent/core";
|
|
1
|
+
import type { SkillSpec, TaskSpec } from "@sema-agent/core";
|
|
2
2
|
import type { RemoteExecProvider } from "../execution-lane-caps.js";
|
|
3
3
|
import { type Logger } from "../observability/logger.js";
|
|
4
4
|
/**
|
|
@@ -90,14 +90,37 @@ export declare function loadDeploymentSkills(config: {
|
|
|
90
90
|
/** 一个技能范围交进 `TaskSpec` 的技能(场景工厂的 `skills`)。范围从哪来见 `scenarios.ts` 的 `BUILTIN_SCENARIO_SKILL_SCOPE`(center 场景 = 它自己的名字)。 */
|
|
91
91
|
export declare function skillsForScenario(loaded: readonly LoadedSkill[], scope: string): SkillSpec[];
|
|
92
92
|
/**
|
|
93
|
-
*
|
|
94
|
-
* (`allowedTools` / `disallowedTools`)
|
|
93
|
+
* 技能清单的一条 —— **一张形,两个面**:场景卡(`GET /v1/capabilities/scenarios/:name` 的 `skills[]`,[ref])与 run 级名册
|
|
94
|
+
* (`wiring_manifest.skills[]`)。名字 / 描述 / 来处,**不带正文**,也不带技能上的两只工具清单(`allowedTools` / `disallowedTools`)。
|
|
95
|
+
* 名字就是提交体 `userInvokedSkills` 点名时用的那个串。两个面只差来处的值域(`S`):场景卡上只有部署两处,run 名册上多一个 `request`。
|
|
95
96
|
*/
|
|
96
|
-
export interface
|
|
97
|
+
export interface SkillListEntry<S extends string> {
|
|
97
98
|
readonly name: string;
|
|
98
99
|
readonly description: string;
|
|
99
|
-
readonly source:
|
|
100
|
+
readonly source: S;
|
|
100
101
|
}
|
|
102
|
+
/** 场景卡技能清单的一条(来处 = 部署两处)。 */
|
|
103
|
+
export type ScenarioSkillEntry = SkillListEntry<SkillSource>;
|
|
104
|
+
/** run 级技能来处的闭集 = 部署两处({@link SkillSource})∪ 本请求体 `skills`。 */
|
|
105
|
+
export type RunSkillSource = SkillSource | "request";
|
|
106
|
+
/** run 级名册的一条(`wiring_manifest.skills[]`)。铸点唯一:`capabilities/scenarios.ts` 的 `buildRunSkills`。 */
|
|
107
|
+
export type RunSkillEntry = SkillListEntry<RunSkillSource>;
|
|
108
|
+
/**
|
|
109
|
+
* run 级技能名册在 TaskSpec 上的**显式字段键** —— 与执行车道字段(`hands-lane.ts` 的 `HANDS_LANE_FIELD`,[ref])同一形:symbol 键随
|
|
110
|
+
* spread / rest 解构走(续跑腿的 `taskConfig` 就是 rest 解构出来的),对上游 core 的键面不可见(JSON / 结构化克隆跳过 symbol 键)。
|
|
111
|
+
* 铸点唯一 = `boot/resolve-spec.ts` 的 resolveSpec 出口({@link stampRunSkills});读点唯一 = {@link runSkillsOf}(每条投 `wiring_manifest` 的腿)。
|
|
112
|
+
*/
|
|
113
|
+
export declare const RUN_SKILLS_FIELD: unique symbol;
|
|
114
|
+
/**
|
|
115
|
+
* 铸名册(**单一属主**:只许 resolveSpec 的出口调用)。字段 `enumerable`(复制得走)、`writable:false` + `configurable:false`(同一只 spec 被第二次铸 ⇒
|
|
116
|
+
* 当场 TypeError,两个写者是漂移的成因)。名册冻结一份拷贝(spec 与腿不共享可变引用)。
|
|
117
|
+
*/
|
|
118
|
+
export declare function stampRunSkills<T extends TaskSpec>(spec: T, roster: readonly RunSkillEntry[]): T;
|
|
119
|
+
/**
|
|
120
|
+
* 读名册。`undefined` = 这只 spec 不是本仓装配出口产的(嵌入方自写 `resolveSpec` / 测试桩)⇒ 腿上没有关于技能的陈述(段缺席)。
|
|
121
|
+
* 不是保护型量(缺席只少一段披露,不放宽任何东西)⇒ 缺席照常跑,与车道字段的「缺席即拒」不同。入参收 `object`:续跑腿手里是 rest 解构出来的 taskConfig。
|
|
122
|
+
*/
|
|
123
|
+
export declare function runSkillsOf(spec: object): readonly RunSkillEntry[] | undefined;
|
|
101
124
|
/** 一个技能范围的卡上清单 —— 与 {@link skillsForScenario} 同一只过滤、同一个序,只是投影不同。 */
|
|
102
125
|
export declare function scenarioSkillEntries(loaded: readonly LoadedSkill[], scope: string): ScenarioSkillEntry[];
|
|
103
126
|
/** {@link parseFrontmatter} 的三种读数(闭集):`absent` = 第一行不是围栏,没有 frontmatter(正当的全局技能)· `block` = 围栏收好了的块 · `unclosed` = 第一行是围栏而块没收好(读不了 —— 调用方拒载)。 */
|
|
@@ -127,6 +127,14 @@ function skillsInScope(loaded, scope) {
|
|
|
127
127
|
export function skillsForScenario(loaded, scope) {
|
|
128
128
|
return skillsInScope(loaded, scope).map((k) => k.spec);
|
|
129
129
|
}
|
|
130
|
+
export const RUN_SKILLS_FIELD = Symbol("sema-server.runSkills");
|
|
131
|
+
export function stampRunSkills(spec, roster) {
|
|
132
|
+
Object.defineProperty(spec, RUN_SKILLS_FIELD, { value: Object.freeze(roster.map((e) => Object.freeze({ ...e }))), enumerable: true, writable: false, configurable: false });
|
|
133
|
+
return spec;
|
|
134
|
+
}
|
|
135
|
+
export function runSkillsOf(spec) {
|
|
136
|
+
return spec[RUN_SKILLS_FIELD];
|
|
137
|
+
}
|
|
130
138
|
export function scenarioSkillEntries(loaded, scope) {
|
|
131
139
|
return skillsInScope(loaded, scope).map((k) => ({ name: k.spec.name, description: k.spec.description, source: k.source }));
|
|
132
140
|
}
|
|
@@ -87,6 +87,7 @@ export declare const CAPABILITY_FACT_WHY: {
|
|
|
87
87
|
readonly not_k8s_lane: "the execution lane is not the k8s pod sandbox (REMOTE_EXEC=k8s)";
|
|
88
88
|
readonly workspace_snapshot_store_absent: "no workspace snapshot store is configured (MINIO_ENDPOINT / MINIO_ACCESS_KEY / MINIO_SECRET_KEY)";
|
|
89
89
|
readonly workspace_cache_off: "the build-cache volume per workspace space is off (WORKSPACE_CACHE=off, the default)";
|
|
90
|
+
readonly deployment_mod_packages_absent: "no operator-declared mod package was loaded at boot (MODS_ROOT / MODS_PACKAGES)";
|
|
90
91
|
};
|
|
91
92
|
export type CapabilityFactWhy = keyof typeof CAPABILITY_FACT_WHY;
|
|
92
93
|
/** 不可用臂。 */
|
|
@@ -355,6 +356,11 @@ export declare function workspaceSpace(c: Pick<ServiceConfig, "remoteExec">): Fa
|
|
|
355
356
|
export declare function workspaceCache(c: Pick<ServiceConfig, "remoteExec">): Fact<"not_k8s_lane" | "workspace_cache_off", {
|
|
356
357
|
cache: WorkspaceCacheCapability;
|
|
357
358
|
}>;
|
|
359
|
+
/** 运维声明的 mod 包:本进程起服装上了几只(部署座装配口 `assembleDeploymentMods` 的读数;本服务自铸的部署注册不算)。
|
|
360
|
+
* `/health.mods.deploymentPackages`(投 `count`)与 caps `modsDeploymentPackages`(投 `.available`,false ⇒ 键缺席)同调这一只。 */
|
|
361
|
+
export declare function deploymentModPackages(d: Pick<Deps, "deploymentModPackages">): Fact<"deployment_mod_packages_absent", {
|
|
362
|
+
count: number;
|
|
363
|
+
}>;
|
|
358
364
|
/** 自唤醒调度器挂在宿主 env 上:`SCHEDULER_ENABLED` ∧ 单用户 ∧ host 车道。装配(`boot/execution-env.ts`)与能力位同调。 */
|
|
359
365
|
export declare function hostScheduler(c: Pick<ServiceConfig, "schedulerEnabled" | "requirePrincipal" | "remoteExec">): Fact<"scheduler_disabled" | "multi_tenant_deployment" | "not_host_lane">;
|
|
360
366
|
/** 引擎能力词的事实(core `ENGINE_CAPABILITIES` 每词一只谓词,值 = 本进程的事实;`/v1/capabilities` 以顶层布尔键展开它们)—— 住在
|
package/dist/capability-facts.js
CHANGED
|
@@ -67,6 +67,7 @@ export const CAPABILITY_FACT_WHY = {
|
|
|
67
67
|
not_k8s_lane: "the execution lane is not the k8s pod sandbox (REMOTE_EXEC=k8s)",
|
|
68
68
|
workspace_snapshot_store_absent: "no workspace snapshot store is configured (MINIO_ENDPOINT / MINIO_ACCESS_KEY / MINIO_SECRET_KEY)",
|
|
69
69
|
workspace_cache_off: "the build-cache volume per workspace space is off (WORKSPACE_CACHE=off, the default)",
|
|
70
|
+
deployment_mod_packages_absent: "no operator-declared mod package was loaded at boot (MODS_ROOT / MODS_PACKAGES)",
|
|
70
71
|
};
|
|
71
72
|
const no = (why) => ({ available: false, why });
|
|
72
73
|
const yes = (w) => ({ available: true, ...w });
|
|
@@ -391,6 +392,10 @@ export function workspaceCache(c) {
|
|
|
391
392
|
return no("workspace_cache_off");
|
|
392
393
|
return yes({ cache: { mount: rx.workspaceCache.mount, size: rx.workspaceCache.size } });
|
|
393
394
|
}
|
|
395
|
+
export function deploymentModPackages(d) {
|
|
396
|
+
const n = d.deploymentModPackages;
|
|
397
|
+
return n !== undefined && n > 0 ? yes({ count: n }) : no("deployment_mod_packages_absent");
|
|
398
|
+
}
|
|
394
399
|
export function hostScheduler(c) {
|
|
395
400
|
if (c.schedulerEnabled !== true)
|
|
396
401
|
return no("scheduler_disabled");
|
|
@@ -3,7 +3,7 @@ import { closeSync, fchmodSync, fsyncSync, openSync, readdirSync, readFileSync,
|
|
|
3
3
|
import { basename, dirname, join } from "node:path";
|
|
4
4
|
import { WEB_ADMIN_ENV, WebAdminCredentialEnvelope, parseWebAdminCredentialFile } from "@sema-agent/settings-schema";
|
|
5
5
|
import { ACCESS_TOKEN_TTL_SECONDS, OAuthErrorResponse, TokenGrantResponse } from "@sema-agent/settings-schema/api/auth";
|
|
6
|
-
import { CENTER_PULL_TIMEOUT_MS, centerTokenRefresh } from "./web-admin-client/center-request.js";
|
|
6
|
+
import { CENTER_PULL_TIMEOUT_MS, CenterRedirectRefusedError, centerTokenRefresh } from "./web-admin-client/center-request.js";
|
|
7
7
|
export const CENTER_CREDENTIAL_RENEW_LEAD_KEY = "CENTER_CREDENTIAL_RENEW_LEAD_MS";
|
|
8
8
|
export const CENTER_CREDENTIAL_RENEW_LEAD_DEFAULT_MS = 5 * 60_000;
|
|
9
9
|
export const CENTER_CREDENTIAL_RENEW_LEAD_MIN_MS = CENTER_PULL_TIMEOUT_MS;
|
|
@@ -277,6 +277,10 @@ export function createCenterCredentialRenewer(deps) {
|
|
|
277
277
|
res = await centerTokenRefresh(envelope.issuer, envelope.refreshToken, { timeoutMs: CENTER_PULL_TIMEOUT_MS, ...(deps.fetchImpl ? { fetchImpl: deps.fetchImpl } : {}) });
|
|
278
278
|
}
|
|
279
279
|
catch (err) {
|
|
280
|
+
if (err instanceof CenterRedirectRefusedError) {
|
|
281
|
+
judgeRefusal(usedDigest, "rejected", { status: err.status });
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
280
284
|
settleRetrying("center_unavailable", usedDigest, { error: err instanceof Error ? err.name : "fetch error" });
|
|
281
285
|
return;
|
|
282
286
|
}
|
|
@@ -12,16 +12,9 @@
|
|
|
12
12
|
* 本条在起服第 6 段 checkpoint 店建成、封签器的装配判(`CHECKPOINT_CTX_SEALING_REQUIRED`)过了之后调一次,早于任何路由装配(与 M10 / M19 / M25
|
|
13
13
|
* 同为在迁移段之外跑的条目)。读数一行 info `checkpoint_ctx_credentials_sealed`,不进 `OneTimeMigrationReport`(登记行 `reportKeys` 空)。
|
|
14
14
|
*/
|
|
15
|
-
import { type CheckpointCtxSealer
|
|
15
|
+
import { type CheckpointCtxSealer } from "./http/checkpoint-ctx.js";
|
|
16
16
|
import { type OneTimeMigrationWindow } from "./plugins/one-time-migrations.js";
|
|
17
|
-
import type {
|
|
18
|
-
/** 两孪生的店腿(`SqlCheckpointStore` / `LocalCheckpointStore` 的 `rewriteCtxRowsM28`)。 */
|
|
19
|
-
export interface CheckpointCtxRowsRewriterM28 {
|
|
20
|
-
rewriteCtxRowsM28(rewrite: (sessionId: string, ctx: object) => {
|
|
21
|
-
readonly ctx: SealedCheckpointCtx;
|
|
22
|
-
readonly values: number;
|
|
23
|
-
} | undefined): Promise<CtxRowsRewriteM28>;
|
|
24
|
-
}
|
|
17
|
+
import type { CheckpointCtxRowsRewriter } from "./plugins/checkpoint-store-sql.js";
|
|
25
18
|
/** M28 一次起服的读数(起服 info 行逐键打出;测试按它断言)。`window: "closed"` ⇒ 一行都没读(其余全 0)。 */
|
|
26
19
|
export interface CheckpointCtxSealM28Report {
|
|
27
20
|
readonly window: "open" | "closed";
|
|
@@ -35,7 +28,7 @@ export interface CheckpointCtxSealM28Report {
|
|
|
35
28
|
* 跑一次 M28(`today` = UTC 日历日 YYYY-MM-DD;`window` 缺省 = 登记表 M28 那一行 —— 只有测试递别的窗)。窗关 ⇒ 不扫。
|
|
36
29
|
* 店腿的每一行:`sealStoredCheckpointCtxM28` 交回新体(凭据位上的明文封好)⇒ 回写;交回 `undefined`(没有明文)⇒ 不写。
|
|
37
30
|
*/
|
|
38
|
-
export declare function sealCheckpointCtxCredentialsM28(store:
|
|
31
|
+
export declare function sealCheckpointCtxCredentialsM28(store: CheckpointCtxRowsRewriter, sealer: CheckpointCtxSealer, opts: {
|
|
39
32
|
readonly today: string;
|
|
40
33
|
readonly window?: Pick<OneTimeMigrationWindow, "removableAfter">;
|
|
41
34
|
}): Promise<CheckpointCtxSealM28Report>;
|
|
@@ -10,7 +10,7 @@ export async function sealCheckpointCtxCredentialsM28(store, sealer, opts) {
|
|
|
10
10
|
if (!migrationWindowOpen(opts.window ?? m28Window(), opts.today)) {
|
|
11
11
|
return { window: "closed", rowsScanned: 0, rowsSealed: 0, valuesSealed: 0, rowsUnreadable: 0, rowsTooLarge: 0 };
|
|
12
12
|
}
|
|
13
|
-
const r = await store.
|
|
13
|
+
const r = await store.rewriteCtxRows((sessionId, ctx) => {
|
|
14
14
|
const out = sealStoredCheckpointCtxM28(ctx, sealer, sessionId);
|
|
15
15
|
return out === undefined ? undefined : { ctx: out.ctx, values: out.valuesSealed };
|
|
16
16
|
});
|
|
@@ -7,15 +7,22 @@ export declare const MAX_CHECKPOINT_ID_CHARS = 128;
|
|
|
7
7
|
export declare function withoutCheckpointToken(text: string, token: unknown): string;
|
|
8
8
|
/** 持久层读出的 `checkpointId` 过信任边界:是串、非空、不超长、不含 token(大小写不敏感)⇒ 原值;否则 `undefined`。判据全文见本文件头注。 */
|
|
9
9
|
export declare function trustedCheckpointId(raw: unknown, token: unknown): string | undefined;
|
|
10
|
-
/**
|
|
11
|
-
|
|
10
|
+
/**
|
|
11
|
+
* 带 `checkpointId` 当 join 键的面(计数 detail 的 `face`):运维队列行、停驻收件行、park 账本行(`GET /v1/runs/:id/events` 的 `suspended` /
|
|
12
|
+
* `needs_review`,写时判一次),与回决门族的 200 体(`decision-receipt`:`/decide` / `/resume` / `/plan_review` 执行**前**从选中的那一行捕获一次,
|
|
13
|
+
* 结清证据带它 —— 语义属主 = `gate-settlement.ts`)。四面同一只读法、同一个计数。
|
|
14
|
+
*/
|
|
15
|
+
export type DurableCheckpointFace = "approvals-queue" | "assistant-inbox" | "run-events-park" | "decision-receipt";
|
|
16
|
+
/** 一行的身份片段:读得出可信值 ⇒ `{ checkpointId }`;读不出 ⇒ `{}`(键缺席)。由调用方原样展开进行投影 / 结清证据。 */
|
|
17
|
+
export type GateIdentity = {
|
|
18
|
+
readonly checkpointId?: string;
|
|
19
|
+
};
|
|
12
20
|
/**
|
|
13
21
|
* durable 读面的一行 → 它的身份片段,**由调用方原样展开进行投影**(`...durableRowIdentity(face, raw, token)`):读得出可信值 ⇒ `{ checkpointId }`;
|
|
14
22
|
* 读不出 ⇒ `{}`(这一行**照列**,键缺席)+ 计一次(见本文件头注「durable 面的 join 键」)。
|
|
15
23
|
* `raw === undefined` = 行上没有这一格(`why=absent`,老行);在场却没过信任边界(非串 / 空串 / 超长 / 含 token / 读不出)= `why=untrusted`。
|
|
16
|
-
* 三处读面(两只店的 `listPending` + 收件 handler)
|
|
24
|
+
* 三处读面(两只店的 `listPending` + 收件 handler)、park 账本行的唯一构造器(`trace/project.ts` 的 `parkEventData`)与回决门族三条续跑腿的执行前捕获点
|
|
25
|
+
* (`http/resume-legs.ts`:`/decide` 在分流之前一次、`/resume`、`/plan_review`)只经这一只 —— 读法、计数、缺席形各只有一份。
|
|
17
26
|
*/
|
|
18
|
-
export declare function durableRowIdentity(face: DurableCheckpointFace, raw: unknown, token: unknown):
|
|
19
|
-
readonly checkpointId?: string;
|
|
20
|
-
};
|
|
27
|
+
export declare function durableRowIdentity(face: DurableCheckpointFace, raw: unknown, token: unknown): GateIdentity;
|
|
21
28
|
//# sourceMappingURL=checkpoint-identity.d.ts.map
|