@sema-agent/server 7.137.0 → 7.139.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 +600 -142
- package/README.md +7 -3
- package/README.zh-CN.md +6 -3
- package/USAGE.md +132 -41
- package/deploy/sema-up/README.md +1 -1
- package/deploy/sema-up/lib/lanes.json +3 -2
- package/dist/adoption/wire.d.ts +3 -3
- package/dist/approval-card.d.ts +23 -16
- package/dist/approval-card.js +1 -0
- package/dist/audit.js +1 -0
- package/dist/background-agent-name.d.ts +5 -0
- package/dist/background-agent-name.js +5 -0
- package/dist/bench/s1/arms.d.ts +1 -1
- package/dist/bench/s1/arms.js +1 -3
- package/dist/bench/s1/run-firm.js +2 -2
- 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/device-lane.d.ts +8 -3
- package/dist/boot/device-lane.js +7 -2
- package/dist/boot/execution-env.d.ts +4 -2
- package/dist/boot/execution-env.js +16 -24
- package/dist/boot/execution-lane.d.ts +1 -1
- package/dist/boot/governance-seams.d.ts +12 -18
- package/dist/boot/governance-seams.js +10 -24
- package/dist/boot/leader.d.ts +3 -0
- package/dist/boot/leader.js +1 -0
- package/dist/boot/memory-consolidation.js +2 -2
- package/dist/boot/org-delivery.js +15 -2
- package/dist/boot/resolve-spec.d.ts +4 -1
- package/dist/boot/resolve-spec.js +29 -19
- package/dist/boot/retention-lane.d.ts +14 -8
- package/dist/boot/retention-lane.js +2 -8
- package/dist/boot/runner-deps.d.ts +10 -4
- package/dist/boot/runner-deps.js +2 -0
- package/dist/boot/session-faces.d.ts +0 -3
- package/dist/boot/session-faces.js +15 -8
- package/dist/boot/stage-02-web-admin-pull.js +2 -2
- package/dist/boot/stage-04-stores.d.ts +1 -12
- package/dist/boot/stage-05-execution-env.d.ts +3 -12
- package/dist/boot/stage-05-execution-env.js +8 -5
- package/dist/boot/stage-06-runners.d.ts +3 -12
- package/dist/boot/stage-06-runners.js +5 -3
- package/dist/boot/stage-07-capability-layer.d.ts +3 -12
- package/dist/boot/stage-07-capability-layer.js +2 -2
- package/dist/boot/stage-08-reapers.d.ts +3 -12
- package/dist/boot/stage-09-leader.d.ts +3 -12
- package/dist/boot/stage-09-leader.js +2 -3
- package/dist/boot/stage-10-http-server.d.ts +3 -12
- package/dist/boot/stage-10-http-server.js +5 -3
- package/dist/boot/stores.js +4 -4
- package/dist/boot/web-admin.d.ts +5 -2
- package/dist/boot/web-admin.js +5 -5
- package/dist/brain.js +5 -5
- package/dist/budget.d.ts +17 -15
- package/dist/budget.js +2 -2
- package/dist/capabilities/mcp-probe.d.ts +36 -11
- package/dist/capabilities/mcp-probe.js +44 -5
- package/dist/capabilities/scenarios.d.ts +1 -1
- package/dist/capability-facts.d.ts +21 -7
- package/dist/capability-facts.js +13 -3
- package/dist/checkpoint-identity.d.ts +13 -6
- package/dist/config-catalog.js +14 -8
- package/dist/config-invariants.d.ts +23 -3
- package/dist/config-invariants.js +42 -0
- package/dist/config-provider.d.ts +19 -24
- package/dist/config-provider.js +27 -12
- package/dist/config-types.d.ts +25 -12
- package/dist/config.d.ts +33 -0
- package/dist/config.js +52 -20
- package/dist/delegated-session-owner.d.ts +2 -2
- package/dist/deployment-shape.d.ts +7 -7
- package/dist/device-enrollment.d.ts +41 -2
- package/dist/device-enrollment.js +27 -12
- package/dist/device-store.d.ts +58 -85
- package/dist/device-store.js +19 -49
- package/dist/device-ws-hub.js +2 -1
- package/dist/env-name-allowlist-knobs.d.ts +5 -4
- package/dist/exec-cut.d.ts +60 -0
- package/dist/exec-cut.js +36 -0
- package/dist/execution-lane-caps.d.ts +19 -0
- package/dist/execution-lane-caps.js +10 -0
- package/dist/execution-placement.d.ts +259 -0
- package/dist/execution-placement.js +199 -0
- package/dist/field-conflict.d.ts +3 -2
- package/dist/field-conflict.js +1 -0
- package/dist/gate-settlement.d.ts +71 -0
- package/dist/gate-settlement.js +40 -0
- package/dist/hooks/classic-stations.d.ts +1 -0
- 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/hosted-posture.d.ts +2 -2
- package/dist/http/admission.js +10 -19
- package/dist/http/checkpoint-ctx.d.ts +21 -12
- package/dist/http/checkpoint-ctx.js +4 -2
- package/dist/http/claimed-run.d.ts +1 -1
- package/dist/http/dispatch.d.ts +4 -0
- package/dist/http/dispatch.js +3 -0
- package/dist/http/durable-run-leg.js +12 -6
- package/dist/http/execution-context.d.ts +218 -0
- package/dist/http/execution-context.js +330 -0
- package/dist/http/memory-compliance-failure-reply.js +3 -0
- package/dist/http/resume-legs.d.ts +5 -11
- package/dist/http/resume-legs.js +179 -104
- package/dist/http/route-ctx.d.ts +44 -59
- 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 +6 -6
- package/dist/http/routes/background.d.ts +29 -1
- package/dist/http/routes/background.js +29 -2
- package/dist/http/routes/capabilities.js +12 -10
- package/dist/http/routes/devices.d.ts +13 -19
- package/dist/http/routes/devices.js +21 -26
- package/dist/http/routes/mcp-reconnect.d.ts +3 -2
- package/dist/http/routes/mcp-reconnect.js +7 -5
- 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 +11 -7
- package/dist/http/routes/session-sync.js +110 -15
- package/dist/http/routes/sessions.d.ts +6 -0
- package/dist/http/routes/sessions.js +119 -13
- package/dist/http/routes/side-query.d.ts +12 -4
- package/dist/http/routes/side-query.js +6 -8
- package/dist/http/routes/tasks.js +800 -782
- package/dist/http/server.d.ts +61 -39
- package/dist/http/server.js +11 -0
- package/dist/http/session-inherit-env.d.ts +3 -4
- package/dist/http/session-inherit-env.js +1 -1
- package/dist/http/wire-types.d.ts +22 -18
- package/dist/identity-source.d.ts +1 -1
- package/dist/index.d.ts +3 -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-sync-client.d.ts +53 -14
- package/dist/memory-sync-client.js +187 -92
- package/dist/memory-sync.d.ts +1 -1
- package/dist/memory-sync.js +3 -2
- package/dist/model-route-gap.d.ts +6 -22
- package/dist/model-route-gap.js +7 -5
- package/dist/mods-declaration.d.ts +110 -0
- package/dist/mods-declaration.js +109 -0
- package/dist/observability/cost-taxonomy.d.ts +2 -2
- 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/run-terminal.js +0 -1
- package/dist/observability/secret-env-scrub.d.ts +1 -1
- package/dist/observability/secret-env-scrub.js +1 -1
- package/dist/orchestration/workflow-notify-journal.js +4 -4
- package/dist/org-memory-admission.d.ts +4 -3
- package/dist/org-memory-admission.js +6 -6
- package/dist/parked-decide.d.ts +49 -11
- package/dist/parked-decide.js +25 -26
- package/dist/parked-revive-surface.d.ts +12 -15
- package/dist/parked-revive-surface.js +3 -6
- package/dist/peer-seat.d.ts +156 -0
- package/dist/peer-seat.js +273 -0
- 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/approval-ask-store-file.d.ts +7 -0
- package/dist/plugins/approval-ask-store-file.js +11 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +6 -0
- package/dist/plugins/approval-ask-store-memory.js +12 -0
- package/dist/plugins/approval-ask-store-sql.d.ts +22 -5
- package/dist/plugins/approval-ask-store-sql.js +30 -12
- package/dist/plugins/background-agent-store-sql.js +6 -3
- package/dist/plugins/caching-session-store.d.ts +11 -2
- package/dist/plugins/caching-session-store.js +15 -3
- package/dist/plugins/checkpoint-store-sql.d.ts +21 -25
- package/dist/plugins/checkpoint-store-sql.js +13 -15
- package/dist/plugins/device-store-sql.d.ts +25 -51
- package/dist/plugins/device-store-sql.js +49 -103
- package/dist/plugins/execution-placement-sql.d.ts +151 -0
- package/dist/plugins/execution-placement-sql.js +223 -0
- package/dist/plugins/file-history-store-sql.d.ts +7 -6
- package/dist/plugins/file-history-store-sql.js +8 -7
- package/dist/plugins/file-run-store.d.ts +6 -1
- package/dist/plugins/file-run-store.js +4 -0
- package/dist/plugins/fork-routing-session-store.d.ts +6 -0
- package/dist/plugins/fork-routing-session-store.js +16 -0
- package/dist/plugins/k8s-pod-reaper.d.ts +2 -8
- package/dist/plugins/k8s-pod-reaper.js +3 -3
- package/dist/plugins/local-checkpoint-store.d.ts +1 -11
- package/dist/plugins/local-checkpoint-store.js +0 -1
- package/dist/plugins/local-session-store.d.ts +183 -45
- package/dist/plugins/local-session-store.js +412 -105
- package/dist/plugins/mailbox-store-sql.d.ts +11 -3
- package/dist/plugins/mailbox-store-sql.js +103 -15
- package/dist/plugins/memory-key-guards.d.ts +4 -0
- package/dist/plugins/memory-key-guards.js +1 -0
- package/dist/plugins/memory-run-store.d.ts +1 -1
- 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 +117 -6
- package/dist/plugins/one-time-migrations.js +383 -14
- package/dist/plugins/outcome-ledger-sql.d.ts +2 -2
- package/dist/plugins/permission-rule-store-sql.d.ts +13 -15
- package/dist/plugins/permission-rule-store-sql.js +34 -29
- package/dist/plugins/pg-pool.d.ts +7 -3
- package/dist/plugins/pg-session-storage.d.ts +41 -22
- package/dist/plugins/pg-session-storage.js +136 -55
- package/dist/plugins/remote-env-adb.d.ts +22 -4
- package/dist/plugins/remote-env-adb.js +70 -62
- package/dist/plugins/remote-env-device.d.ts +32 -12
- package/dist/plugins/remote-env-device.js +18 -17
- package/dist/plugins/remote-env-e2b.d.ts +19 -3
- package/dist/plugins/remote-env-e2b.js +41 -42
- package/dist/plugins/remote-env-file-error.d.ts +2 -0
- package/dist/plugins/remote-env-file-error.js +1 -1
- package/dist/plugins/remote-env-host.d.ts +23 -8
- package/dist/plugins/remote-env-host.js +66 -70
- package/dist/plugins/remote-env-k8s.d.ts +13 -16
- package/dist/plugins/remote-env-k8s.js +61 -54
- package/dist/plugins/remote-env-local-docker.d.ts +30 -5
- package/dist/plugins/remote-env-local-docker.js +46 -59
- package/dist/plugins/remote-env-ssh.d.ts +18 -4
- package/dist/plugins/remote-env-ssh.js +72 -56
- package/dist/plugins/remote-shell.d.ts +100 -3
- package/dist/plugins/remote-shell.js +166 -2
- package/dist/plugins/retention-store-sql.d.ts +23 -8
- package/dist/plugins/retention-store-sql.js +13 -1
- package/dist/plugins/run-store-sql.d.ts +13 -3
- package/dist/plugins/run-store-sql.js +5 -0
- package/dist/plugins/schema-consistency.d.ts +15 -5
- package/dist/plugins/schema-consistency.js +14 -8
- package/dist/plugins/schema-drift-sentence.d.ts +27 -0
- package/dist/plugins/schema-drift-sentence.js +38 -0
- package/dist/plugins/session-fork.d.ts +63 -12
- package/dist/plugins/session-fork.js +38 -21
- package/dist/plugins/session-ownership.d.ts +7 -0
- package/dist/plugins/session-ownership.js +5 -0
- package/dist/plugins/session-row-sql.d.ts +22 -0
- package/dist/plugins/session-row-sql.js +81 -0
- package/dist/plugins/session-store.d.ts +1 -1
- package/dist/plugins/session-workspace-cell.d.ts +17 -0
- package/dist/plugins/session-workspace-cell.js +38 -0
- package/dist/plugins/store-backend.d.ts +1 -1
- package/dist/plugins/store-backend.js +26 -14
- package/dist/plugins/store-contracts.d.ts +25 -5
- package/dist/plugins/tidb-pool.d.ts +12 -7
- package/dist/plugins/tidb-pool.js +15 -3
- package/dist/plugins/tidb-session-store.d.ts +74 -28
- package/dist/plugins/tidb-session-store.js +132 -53
- package/dist/plugins/tool-result-store-sql.d.ts +16 -8
- package/dist/plugins/tool-result-store-sql.js +26 -17
- 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/project-memory.d.ts +9 -15
- package/dist/project-memory.js +5 -4
- package/dist/request-key-closure.js +1 -1
- package/dist/request-value-closure.d.ts +6 -7
- package/dist/request-value-closure.js +1 -3
- package/dist/rules-consent.js +6 -4
- package/dist/run-local.d.ts +6 -0
- package/dist/run-local.js +36 -26
- package/dist/runs.d.ts +9 -2
- package/dist/runs.js +9 -2
- package/dist/sandbox-git-plane.d.ts +2 -2
- package/dist/security.d.ts +38 -12
- package/dist/security.js +8 -2
- package/dist/server-secret-env.d.ts +15 -8
- package/dist/server-secret-env.js +4 -2
- package/dist/session-children-retire.d.ts +27 -9
- package/dist/session-children-retire.js +9 -5
- package/dist/session-incarnation.d.ts +19 -10
- package/dist/session-incarnation.js +5 -3
- package/dist/session-row.d.ts +114 -5
- package/dist/session-row.js +55 -5
- package/dist/session-titler.d.ts +2 -2
- package/dist/session-workspace.d.ts +130 -0
- package/dist/session-workspace.js +83 -0
- package/dist/spec-fields.d.ts +1 -1
- package/dist/standing-answer-grant.d.ts +2 -13
- package/dist/standing-answer-grant.js +0 -7
- package/dist/task-a2a.d.ts +44 -14
- package/dist/task-a2a.js +46 -20
- package/dist/task-cwd.d.ts +6 -1
- package/dist/task-mcp.d.ts +33 -20
- package/dist/task-mcp.js +46 -22
- package/dist/tool-approval.d.ts +38 -8
- package/dist/tool-approval.js +57 -13
- package/dist/trace/core-keyset-guard.d.ts +33 -18
- package/dist/trace/engine-notice-wire.d.ts +1 -1
- package/dist/trace/engine-notice-wire.js +2 -0
- package/dist/trace/exit-seat.d.ts +20 -1
- package/dist/trace/exit-seat.js +3 -0
- package/dist/trace/extension-call-face.d.ts +33 -0
- package/dist/trace/extension-call-face.js +39 -0
- package/dist/trace/project.d.ts +26 -7
- package/dist/trace/project.js +30 -3
- package/dist/trace/redact.js +42 -13
- package/dist/trace/self-minted-wire.d.ts +240 -12
- package/dist/trace/self-minted-wire.js +100 -4
- package/dist/trace/wire-projection-faces.d.ts +6 -6
- package/dist/trace/wire-projection-faces.js +6 -5
- package/dist/url-refusal.d.ts +1 -1
- package/dist/user-authored-text.d.ts +2 -2
- package/dist/user-authored-text.js +16 -1
- package/dist/web-admin-client/apply-effective.d.ts +17 -3
- package/dist/web-admin-client/apply-effective.js +20 -10
- package/dist/web-admin-client/center-request.d.ts +3 -2
- package/dist/web-admin-client/center-request.js +2 -3
- package/dist/web-admin-client/skills-mcp.d.ts +8 -4
- package/dist/web-admin-client/skills-mcp.js +32 -18
- package/dist/web-admin-client/types.d.ts +11 -0
- package/package.json +3 -3
- package/wire-changes/server@7.138.0.json +446 -0
- package/wire-changes/server@7.139.0.json +348 -0
- package/dist/http/device-placement.d.ts +0 -175
- package/dist/http/device-placement.js +0 -145
- package/dist/http/mcp-remote-text.d.ts +0 -5
- package/dist/http/mcp-remote-text.js +0 -7
|
@@ -52,8 +52,8 @@ export declare function sandboxGitPlanePremisesOf(config: ServiceConfig, reading
|
|
|
52
52
|
}): SandboxGitPlanePremises;
|
|
53
53
|
/**
|
|
54
54
|
* Wiring point — the effective `sandboxGit` block (the origins this deployment routes through the broker, canonical form, ≤ 16). Its shape
|
|
55
|
-
* and its canonical-form judge belong to the settings-schema contract package (14.7.0
|
|
56
|
-
*
|
|
55
|
+
* and its canonical-form judge belong to the settings-schema contract package (`SandboxGitConfig`, 14.7.0 — picked up: the block rides the effective
|
|
56
|
+
* wire verbatim); this reader is not wired to it yet ⇒ `null` (the plane stays off, `no_origins`). To be replaced by the package reader — no local copy of the shape.
|
|
57
57
|
*/
|
|
58
58
|
export declare function readSandboxGitConfig(_config: ServiceConfig): {
|
|
59
59
|
readonly origins: readonly string[];
|
package/dist/security.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { IncomingMessage } from "node:http";
|
|
2
|
-
import { type SessionPlacementRecord, type SessionStore, type SessionTreeEntry } from "@sema-agent/core";
|
|
2
|
+
import { type SessionHead, type SessionPlacementRecord, type SessionStore, type SessionTreeEntry } from "@sema-agent/core";
|
|
3
3
|
import type { ServiceConfig } from "./config-types.js";
|
|
4
4
|
import { type DeploymentShapeInput } from "./deployment-shape.js";
|
|
5
5
|
import type { TaskRequestBody } from "./http/wire-types.js";
|
|
6
6
|
import type { StagingHandle } from "./session-sync-kernel.js";
|
|
7
|
-
import {
|
|
8
|
-
import type {
|
|
7
|
+
import type { ClientSessionRowWrite, ReplaySessionRowWrite, ReplaySessionRowWriteOutcome, SessionRowPatch, SessionRowWriteOutcome } from "./session-row.js";
|
|
8
|
+
import type { ExecutionPlacementSeat } from "./execution-placement.js";
|
|
9
|
+
import type { ForkTarget, ForkToOutcome } from "./plugins/session-fork.js";
|
|
9
10
|
import { type OwnerlessClaim } from "./delegated-session-owner.js";
|
|
10
11
|
/** One row of the session-list projection (CC /resume picker) — the durable session abstraction's enumeration
|
|
11
12
|
* output (§0.5). Mirrors {@link RunStore}'s shipped `SessionSummary` shape so the wire response is unchanged. */
|
|
@@ -32,6 +33,19 @@ export interface SessionListItem {
|
|
|
32
33
|
/** Pinned by the user (`PATCH /v1/sessions/:id`). ALWAYS present — `false` by default (a session's state, not a capability);
|
|
33
34
|
* a lister face with no session_meta answers `false` (nothing there can pin it). */
|
|
34
35
|
pinned: boolean;
|
|
36
|
+
/** The row tag (`src/session-row.ts` `sessionRowTagOf`): an opaque one-way digest of this occupant's writable cells — the precondition a
|
|
37
|
+
* `PATCH /v1/sessions/:id` carries back as `expectedRowTag`. Present-iff the row can be written conditionally (the store has the row write
|
|
38
|
+
* primitive ∧ the row has an occupant token); additive key, passed through unprojected (`sessions-list.ts`). Same name and meaning as
|
|
39
|
+
* `SessionSummary.rowTag` in `plugins/store-contracts.ts`. */
|
|
40
|
+
rowTag?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 会话店的行格写原语(规则与判序:`session-row.ts` 头注「写原语」)—— 按入口分两只重载:客户端写(PATCH)的结局闭集四员;行重放(2c 导入落定后的那一笔)
|
|
44
|
+
* 只有 `written` / `absent`(`changed` / `mirror` 对它不可达)。
|
|
45
|
+
*/
|
|
46
|
+
export interface SessionRowCellsWriter {
|
|
47
|
+
(sessionId: string, cells: SessionRowPatch, how: ClientSessionRowWrite): Promise<SessionRowWriteOutcome<SessionListItem>>;
|
|
48
|
+
(sessionId: string, cells: SessionRowPatch, how: ReplaySessionRowWrite): Promise<ReplaySessionRowWriteOutcome<SessionListItem>>;
|
|
35
49
|
}
|
|
36
50
|
/** A SessionStore that may additionally expose tenant-ownership ops (the TiDB store does) AND the
|
|
37
51
|
* `SessionRepo` enumeration/lifecycle seam (§0.5: list/fork/delete homed on the session abstraction's own
|
|
@@ -187,17 +201,24 @@ export type OwnerAwareSessionStore = SessionStore & {
|
|
|
187
201
|
* row of the list face (no such session, or a placed / delegation-transcript session, which never lists). Reader: the 2c
|
|
188
202
|
* manifest (`title` / `pinned`). */
|
|
189
203
|
sessionSummaryOf?: (sessionId: string) => Promise<SessionListItem | undefined>;
|
|
190
|
-
/** The session row's writable
|
|
191
|
-
* to the automatic title; the auto-titler's `setTitleIfNull` fills a NULL title only; the law of the two writers
|
|
192
|
-
* `session-row.ts`).
|
|
193
|
-
* the caller's gate
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
|
|
204
|
+
/** The session row's write primitive for its writable cells (`title` / `pinned`) — the ONLY writer of a user-set title or pin (`title: null`
|
|
205
|
+
* clears it back to the automatic title; the auto-titler's `setTitleIfNull` fills a NULL title only; the law of the two writers and of this
|
|
206
|
+
* primitive is written in `session-row.ts`). Judged under the row's lock by one judge (`judgeSessionRowWrite`): the row expectation
|
|
207
|
+
* (core `SessionRowExpectation` — the occupant the caller's gate read, owner + incarnation, judged by core `sessionRowMatches`) → the writer
|
|
208
|
+
* (a client write on a read-only mirror ⇒ `mirror`) → the row tag (a client's `rowTag` that the locked row no longer carries ⇒ `changed`) → write.
|
|
209
|
+
* `written` / `changed` carry the list row read after the commit / rollback ({@link sessionSummaryOf}'s projection, with its new `rowTag`);
|
|
210
|
+
* `absent` = no list row for that occupant (deleted, re-registered, owner restamped, or a placed session) — nothing was written. A failed write throws. */
|
|
211
|
+
writeSessionRowCells?: SessionRowCellsWriter;
|
|
198
212
|
/** E17 — fork a session's whole history to a NEW session; null if the source is unknown. The fork row records `owner` when it is a
|
|
199
|
-
* string, else (`null`) the SOURCE row's owner — a copy of an owned history is never anonymous (core `SessionStore.fork`, 7.55.0 S2).
|
|
213
|
+
* string, else (`null`) the SOURCE row's owner — a copy of an owned history is never anonymous (core `SessionStore.fork`, 7.55.0 S2).
|
|
214
|
+
* On the three stores it is the projection `forkTo(…, { id: uuidv7() })` of {@link forkTo} (one private body). */
|
|
200
215
|
fork?: (sourceId: string, owner: string | null) => Promise<string | null>;
|
|
216
|
+
/** fork 续写的店契约(三店同一只私有体;规则与结果闭集在 `plugins/session-fork.ts`):把源会话整份历史拷进调用方给的目标 id;`target.key` 存进新行那一格 fork 键。
|
|
217
|
+
* `null` = 源不在;`created` / `replayed`(同属主同键)/ `occupied{sameOwner}`(撞上别的行)。目标行原子新建(SQL 主键排他、meta 先;local 两把写锁 + 格先)。 */
|
|
218
|
+
forkTo?: (sourceId: string, owner: string | null, target: ForkTarget) => Promise<ForkToOutcome | null>;
|
|
219
|
+
/** 执行席(规则在 `execution-placement.ts`):根会话行上这一位住客的那一格的唯一读口(`read`)与 place / markMirror 两只写口。三店都有;两只包装原样转发。
|
|
220
|
+
* 缺席 = 会话店没有执行放置(只有不带它的测试走廊 / 嵌入形),调用方各按自己的缺席臂处置。 */
|
|
221
|
+
executionPlacement?: ExecutionPlacementSeat;
|
|
201
222
|
/** E21 — purge a session's conversation history (session_meta/session_event); idempotent (false if absent).
|
|
202
223
|
* `owner` is the single-DB-fleet null-safe SQL owner guard on `session_meta.owner` (defense-in-depth — the
|
|
203
224
|
* route already owner-gates; this pins the DELETE to the authenticated tenant so even a buggy gate can't purge
|
|
@@ -285,6 +306,11 @@ export interface AuthContext {
|
|
|
285
306
|
principal?: string;
|
|
286
307
|
/** The session to run against (resolved + ownership-checked here, then returned to the caller). */
|
|
287
308
|
sessionId: string;
|
|
309
|
+
/**
|
|
310
|
+
* 属主门判的那一读(会话店 `headOf` 的整只头;现铸 / 未知 id 臂是登记后那一读)—— 执行上下文解析器的 `judged`:解析器读到的行头住客与它不同 ⇒ 404(门与解析之间会话被删并同 id 重登记)。
|
|
311
|
+
* 缺 = 店没有 `headOf`(读不出头的店;只一元车道表、无执行席的形可达)。
|
|
312
|
+
*/
|
|
313
|
+
head?: SessionHead;
|
|
288
314
|
/** Long-term memory scope, derived from the principal (not the body). Undefined disables memory. */
|
|
289
315
|
memoryScope?: string;
|
|
290
316
|
/** 142-S4:the request's SHAPE-VALIDATED **且已归一(小写)** 的 projectId(body.projectId 过 core
|
package/dist/security.js
CHANGED
|
@@ -84,7 +84,11 @@ export function createAuthorizer(config, sessionStore) {
|
|
|
84
84
|
}
|
|
85
85
|
const requireExisting = body.requireExistingSession === true;
|
|
86
86
|
const headOf = headReadOf(sessionStore);
|
|
87
|
-
|
|
87
|
+
let head;
|
|
88
|
+
const readOwner = headOf === undefined ? undefined : async (id) => {
|
|
89
|
+
head = await headOf(id);
|
|
90
|
+
return head?.owner;
|
|
91
|
+
};
|
|
88
92
|
const register = sessionStore.register?.bind(sessionStore);
|
|
89
93
|
const requested = typeof body.sessionId === "string" && body.sessionId ? body.sessionId : undefined;
|
|
90
94
|
let sessionId;
|
|
@@ -126,8 +130,10 @@ export function createAuthorizer(config, sessionStore) {
|
|
|
126
130
|
sessionId = uuidv7();
|
|
127
131
|
if (register)
|
|
128
132
|
await register(sessionId, principal ?? null);
|
|
133
|
+
if (readOwner)
|
|
134
|
+
await readOwner(sessionId);
|
|
129
135
|
}
|
|
130
|
-
return { principal, sessionId, memoryScope: memoryScopeFor(config, principal, projectId), resolvedProjectId: projectId };
|
|
136
|
+
return { principal, sessionId, memoryScope: memoryScopeFor(config, principal, projectId), resolvedProjectId: projectId, ...(head === undefined ? {} : { head }) };
|
|
131
137
|
};
|
|
132
138
|
}
|
|
133
139
|
export const PRINCIPAL_MAX_LENGTH = 190;
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* 剥掉的键经一个登记过的 `SecretEnvScrubSite` 留痕(现场按**腿**命名);git 腿再叠 git 自己的两件({@link gitSubprocessEnv})。射程 = **每一条**宿主腿:
|
|
14
14
|
* src 里每一只值引 `node:child_process` 的文件都是登记腿、其中每一次起子进程都显式交组合出的 env(普查门在 `test/secret-env-scrub-host-legs.test.ts`)。
|
|
15
15
|
* 腿的继承词是调用点的事实,按「子进程里跑的是谁选的代码」定:模型命令(host shell,交任务自己的词)/ 仓里的钩子与凭据助手(三条 git 腿)/ 执行仓代码的
|
|
16
|
-
* 语言服务器 / 配方脚本 ⇒ 形状剥 `"scrub"`;请求带来的 settings hooks 命令 ⇒ 严格名单(
|
|
16
|
+
* 语言服务器 / 配方脚本 ⇒ 形状剥 `"scrub"`;请求带来的 settings hooks 命令 ⇒ 严格名单(十二名基础名单,`[names]` 臂;请求的继承词只给工具 shell、对 hook 不作用)、请求的有效环境层作授予叠在继承结果之上(引擎的 `hostChildEnv`);部署方装在宿主上的 CLI(`docker` / `adb`,命令本身
|
|
17
17
|
* 在容器 / 设备里跑、那边的 env 由 `-e` 显式给)⇒ `"all"` —— 只扣本服务自有凭据,CLI 与它的凭据助手 / 插件要读的生态变量照交(形状剥会剥
|
|
18
18
|
* `ADB_VENDOR_KEYS` / `AWS_SECRET_ACCESS_KEY` 一类,实测)。三个继承词只在引擎一处判:
|
|
19
19
|
* · `"all"` = 整份环境 **减** 本进程声明的自有凭据名;`"scrub"`(缺省)= 形状剥 ∪ 该名单;`[names]` = 严格白名单,点到名单中的名 ⇒ 引擎响亮拒
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
* **机器派生**、不手抄、不按「归谁消费」切({@link serverWithheldEnvNames} 一处)。声明两个时机、同一只 {@link declareServerWithheldEnv}:起服第一步(三个进程入口:
|
|
24
24
|
* `boot/stage-01-config.ts` / `run-local.ts` / `bake-runner/main.ts`,在任何执行环境构造与 spawn 之前 —— 声明先于构造才有构造时拒;此时没有生效配置 = 空表),
|
|
25
25
|
* 与每次生效配置换代(`web-admin-client/apply-effective.ts` 本体:CAS 之后、Runner 换装与 commit 之前 —— 声明先于席位,旧世代不声明)。名单只随**落地**的世代
|
|
26
|
-
* 增长(本进程 env 是 boot 期输入:一个名字一旦指过本进程的凭据,条目改名 / 删掉之后它的值仍在 env 里 ⇒ 落地过的名不退出;没落地的候选不留痕 —— 换装拒 ⇒
|
|
26
|
+
* 增长(本进程 env 是 boot 期输入:一个名字一旦指过本进程的凭据,条目改名 / 删掉之后它的值仍在 env 里 ⇒ 落地过的名不退出;没落地的候选不留痕 —— 名单重判命中 / 换装拒 ⇒
|
|
27
27
|
* {@link withdrawServerWithheldEnv} 撤回到换代前的集合)。声明失败(坏形名 / 运行时回填名)⇒ 引擎抛且声明保持原状:起服那次 = 拒启,换代那次 = 候选整拒(与 stage
|
|
28
28
|
* 抛同路)。能力词 `inherit_env.own_credentials_withheld` 在本进程的事实 =
|
|
29
29
|
* {@link ownCredentialsWithheld}:最近一次成功声明的集合 ⊇ 当前生效配置应声明的集合(活配置经 {@link bindOwnCredentialsConfig} 在 `loadConfig()` 之后绑一次;
|
|
@@ -38,10 +38,13 @@
|
|
|
38
38
|
* {@link allowlistedEnv} 是本仓「一张名单点到哪些 env 键,就把它们从源 env **原样**交给沙箱」的唯一实现。调用:沙箱带外 env 的 `E2B_SANDBOX_ENV` / `DOCKER_SANDBOX_ENV` /
|
|
39
39
|
* `K8S_SANDBOX_ENV`(`config.ts`)与名单解析器的「在不在」判。宿主子进程的剥后放回(`LSP_ENV_ALLOW` / `BAKE_ENV_ALLOW`)不经它 —— 那是引擎的严格名单臂(上一段)。
|
|
40
40
|
* host shell 的 `inheritEnv:[names]`(hermetic 形)7.129.0 起由引擎读(与 core `NodeExecutionEnv` 同名选项同义,点到自有凭据名即拒),不经本谓词。
|
|
41
|
-
* 名单型旋钮的**名单**另由 `config.ts` 的同一只解析器 `parseEnvNameAllowlist` 判形(
|
|
41
|
+
* 名单型旋钮的**名单**另由 `config.ts` 的同一只解析器 `parseEnvNameAllowlist` 判形(形错 / 点名名单型旋钮 / 点名本服务自有凭据名 ⇒ 拒启;源里没有的名按序号 warn),本函数只管取值。
|
|
42
42
|
* 「点名」在各处同义:点到的键原样带值(空串值照带),密钥形也照过(点名 = 部署方显式承担);源里没有的名不产生条目。
|
|
43
43
|
* 剥后放回形(`LSP_ENV_ALLOW` / `BAKE_ENV_ALLOW`)的放回本身也经引擎:{@link composeHostSubprocessEnv} 把名单交引擎的严格名单臂(`inheritedHostEnv([names])`)叠在
|
|
44
|
-
* 继承结果之上 ⇒ 点到本服务自有凭据名 =
|
|
44
|
+
* 继承结果之上 ⇒ 点到本服务自有凭据名 = 引擎在**组合这一刻**抛(语言服务器在构造时组合一次、之后 spawn 用那份静态记录;bake-runner 每次 spawn 组合;
|
|
45
|
+
* 起服时解析器 `parseEnvNameAllowlist` 已用同一只判 `inheritEnvPolicyProblem` 拒过 —— 解析器对五只名单一律拒,点到**解析时已声明**的自有凭据名的沙箱名单因此
|
|
46
|
+
* 到不了 {@link allowlistedEnv} 取值这一步;声明之后增长(中心 / config.d 模型条目的 `apiKeyEnv` 换代并进)时,换代声明对活配置里每只名单此刻交出去的名用同一只判
|
|
47
|
+
* 重判一次 —— 命中 ⇒ 撤回这次增长、候选整拒,已装好的沙箱 env / 语言服务器 env 不变成本服务的凭据,`config.ts` `ownCredentialHitsInForce`),
|
|
45
48
|
* 点到的变量值是本服务凭据的副本 = 引擎扣下。本仓不另判。
|
|
46
49
|
*/
|
|
47
50
|
import { type InheritEnvPolicy, type SecretEnvFinding } from "@sema-agent/core";
|
|
@@ -64,7 +67,7 @@ export declare function serverCredentialValueSources(modelApiKeyEnv?: ModelApiKe
|
|
|
64
67
|
/**
|
|
65
68
|
* 🔴 **唯一声明点**:把本进程自有凭据向引擎声明(core 7.52.0 `declareWithheldEnv({ names, values })`;重声明即整表替换,从下一次 spawn 起生效)。`modelApiKeyEnv` = 这一次要并进的
|
|
66
69
|
* 模型条目表(起服第一步 = 空表;换代 = 候选表)。两臂都只随**落地**的世代增长(落地过的名 / 值来源不退出:本进程 env 是 boot 期输入;没落地的候选不留痕 ——
|
|
67
|
-
* 换装拒 ⇒ {@link withdrawServerWithheldEnv})。
|
|
70
|
+
* 名单重判命中 / 换装拒 ⇒ {@link withdrawServerWithheldEnv})。
|
|
68
71
|
* · **名臂**:此前声明过的 ∪ 这张表的 {@link serverWithheldEnvNames}。引擎对坏形名 / 运行时回填名(`PATH` / `HOME` …)响亮抛且声明保持原状 —— 本函数不接住:
|
|
69
72
|
* 起服那次抛 = 拒启;换代那次抛 = 候选整拒(`applyEffective` 抛,与 stage 抛同路)。第一次交表带着名臂与**此前已收下的值**(引擎收过、env 不变 ⇒ 同值照收),
|
|
70
73
|
* 所以这一次抛只可能是名的问题。
|
|
@@ -76,7 +79,8 @@ export declare function serverCredentialValueSources(modelApiKeyEnv?: ModelApiKe
|
|
|
76
79
|
*/
|
|
77
80
|
export declare function declareServerWithheldEnv(modelApiKeyEnv?: ModelApiKeyEnvTable): readonly string[];
|
|
78
81
|
/**
|
|
79
|
-
*
|
|
82
|
+
* 候选没落地 ⇒ 撤回最近一次声明(两臂一起回到它之前的那一份),两个调用点都紧跟着那一次 {@link declareServerWithheldEnv}、同步无 await:换代声明 helper 在名单重判命中时调,
|
|
83
|
+
* `applyEffective` 在 Runner 换装抛时调 —— 没落地的候选不留痕。
|
|
80
84
|
* 退回去的那一份是引擎之前接受过的(名确定、值来源的值随 env 不变)⇒ 不抛;连撤两次是同一个结果(幂等)。
|
|
81
85
|
*/
|
|
82
86
|
export declare function withdrawServerWithheldEnv(): void;
|
|
@@ -94,18 +98,21 @@ export declare function ownCredentialsWithheld(): boolean;
|
|
|
94
98
|
export declare function ownCredentialValuesWithheld(): boolean;
|
|
95
99
|
/** 测试缝:撤回声明(引擎侧重声明为空表)、忘掉两份声明镜像、点名记账与活配置;生产代码从不调它。 */
|
|
96
100
|
export declare function __resetServerWithheldEnvForTest(): void;
|
|
97
|
-
/** 一条宿主腿要什么:现场(留痕)、继承策略(缺省 `"scrub"`;按头注「腿的继承词」一条由调用点定)
|
|
101
|
+
/** 一条宿主腿要什么:现场(留痕)、继承策略(缺省 `"scrub"`;按头注「腿的继承词」一条由调用点定)、部署方点名放回的键、调用方显式交的授予(按序叠在继承之上,后者赢)。 */
|
|
98
102
|
export interface HostSubprocessEnvRequest {
|
|
99
103
|
readonly site: SecretEnvScrubSite;
|
|
100
104
|
readonly policy?: InheritEnvPolicy | undefined;
|
|
101
105
|
readonly allow: readonly string[];
|
|
106
|
+
/** 调用方显式交给子进程的变量(今天只有 settings hooks:有效环境层 = 请求 `settings.env` + hook 自己的变量)。引擎判形:名字空 / 带 `=` / NUL / 孤代理项、
|
|
107
|
+
* 值不是串或带 NUL / 孤代理项 ⇒ 组合**抛**,拒句点名授予与变量(不带值、不回显坏名);调用点按「起不来」处置。 */
|
|
108
|
+
readonly grants?: readonly Readonly<Record<string, string>>[] | undefined;
|
|
102
109
|
}
|
|
103
110
|
/**
|
|
104
111
|
* 🔴 **宿主子进程 env 的唯一组合**:{@link composeHostSubprocessEnv} + 留痕。**没有按原样交给子进程**的名字(剥掉的)经 `site` 留痕;点名放回的键取回源值,
|
|
105
112
|
* 不是剥除,不计数、不披露。源 env 恒为本进程 env(引擎只读 `process.env`,本仓没有第二个源)。
|
|
106
113
|
*
|
|
107
114
|
* 九条宿主腿都只经它(直接或经 {@link gitSubprocessEnv}):host shell(三个继承词原样交给 `policy`)、project-memory / center-plugins / leader 三条 git 腿、
|
|
108
|
-
* 本地语言服务器、bake-runner 的每一只子进程组、local-docker 与 adb 两条 CLI 腿(`"all"`)、settings hooks 的命令腿(
|
|
115
|
+
* 本地语言服务器、bake-runner 的每一只子进程组、local-docker 与 adb 两条 CLI 腿(`"all"`)、settings hooks 的命令腿(十二名严格名单 + 有效环境层作授予)。`allow` 只在**有部署级出路**的现场非空(今天 = `LSP_ENV_ALLOW` / `BAKE_ENV_ALLOW`,
|
|
109
116
|
* 它们的现场在 `SECRET_ENV_SCRUB_SITES` 里登记了 `remedy`,披露行因此是 warn + 放行名单 + 出路句);其余现场传 `[]`。
|
|
110
117
|
* 返回 `NodeJS.ProcessEnv` 形(值可能是 `undefined` 的键本来就不会进子进程);调用方显式要交的键(`LC_ALL`、`cfg.env` …)叠在它之上。
|
|
111
118
|
* 调用时机 = 每次要交 env 时现算一次(`process.env` 在本仓是 boot 期输入,各次同值;计数因此是「每组合一次」)。
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { declareWithheldEnv, inheritedHostEnv } from "@sema-agent/core";
|
|
1
|
+
import { declareWithheldEnv, hostChildEnv, inheritedHostEnv } from "@sema-agent/core";
|
|
2
2
|
import { CONFIG_CATALOG } from "./config-catalog.js";
|
|
3
3
|
import { ENV_NAME_ALLOWLIST_KNOB_NAMES } from "./env-name-allowlist-knobs.js";
|
|
4
4
|
import { recordSecretEnvScrub } from "./observability/secret-env-scrub.js";
|
|
@@ -84,7 +84,9 @@ export function hostSubprocessEnv(o) {
|
|
|
84
84
|
}
|
|
85
85
|
export function composeHostSubprocessEnv(o, findings = []) {
|
|
86
86
|
const putBack = o.allow.length > 0 ? inheritedHostEnv([...o.allow], findings) : {};
|
|
87
|
-
|
|
87
|
+
const child = hostChildEnv(o.policy ?? "scrub", putBack, ...(o.grants ?? []));
|
|
88
|
+
findings.push(...child.withheld);
|
|
89
|
+
return child.env;
|
|
88
90
|
}
|
|
89
91
|
export function withheldFromHostSubprocess(o, regranted) {
|
|
90
92
|
const findings = [];
|
|
@@ -27,6 +27,13 @@
|
|
|
27
27
|
* (修复验证轮两条 opus 腿同命中:修前预检看的是内存句柄的**状态**(不是 running / pending ⇒ 够不着),本副本刚停、写在飞的子代因此被答成
|
|
28
28
|
* 「在别的副本上」的 409 —— 同一个「这只子代在不在本进程」的判断有两个写者。)
|
|
29
29
|
*
|
|
30
|
+
* ## 一只预检、一只协调器、一个 scope(树活性的子代半)
|
|
31
|
+
* 能在树活着时改根放置 / 住客的三门 —— 删除(`boot/session-faces.ts`)、换绑(`routes/devices.ts`)、导入(`routes/session-sync.ts`)—— 与显式结清口
|
|
32
|
+
* `POST /v1/sessions/:id/children/retire`(`routes/background.ts`)都只经这里:**观察**只有 {@link probeSessionChildren}(同一次枚举交出活子代句柄
|
|
33
|
+
* `liveChildren` 与不可达的那几只),**结清**只有 {@link retireSessionChildren}(结果交首轮观察到的句柄 `observed`);scope 只有一处取
|
|
34
|
+
* {@link sessionChildrenScope}(会话属主 `owner ?? "default"`)。wire 上的 `children` / `remaining` 一律经名册的 id 投影出门。
|
|
35
|
+
* 子代半是**写前一次观察**:子代登记在 core 的后台子代店,写者的事务装不进这一读(认领半才是写事务内那一读,`execution-placement-sql.ts` 头注)。
|
|
36
|
+
*
|
|
30
37
|
* ## 循环(有上界)
|
|
31
38
|
* 作废 / 停止与一次并发的 `/decide` 可能交错:expire 的 CAS 输给了决定腿的 resolve ⇒ 那只子代被唤醒成 running ⇒ 下一轮枚举看见
|
|
32
39
|
* 它、停掉它。循环到「枚举不出活的子代」为止,轮数有上界({@link RETIRE_MAX_ROUNDS});本进程 kill 的耐久写是 core 的异步写链,
|
|
@@ -51,26 +58,37 @@ export interface RetireSessionChildrenDeps extends ChildrenSource {
|
|
|
51
58
|
registry: Pick<TaskRegistry, "stopTask" | "reconcileParkedAgents" | "activeDelegationHandles">;
|
|
52
59
|
sleep?: (ms: number) => Promise<void>;
|
|
53
60
|
}
|
|
54
|
-
/**
|
|
61
|
+
/**
|
|
62
|
+
* 可达性预检的结果(零写)。`liveChildren` = 这一次枚举观察到的全部活子代句柄(running / parked;换绑 / 导入两门的 409 体 `children` 就是它);
|
|
63
|
+
* `unreachableHandles` 只含其中本进程结束不了的那几只(删除门与结清口的 409 `remaining`);可达的子代不在那里。
|
|
64
|
+
*/
|
|
55
65
|
export type SessionChildrenReachability = {
|
|
56
66
|
readonly reachable: true;
|
|
57
|
-
readonly
|
|
67
|
+
readonly liveChildren: readonly string[];
|
|
58
68
|
} | {
|
|
59
69
|
readonly reachable: false;
|
|
60
|
-
readonly
|
|
70
|
+
readonly liveChildren: readonly string[];
|
|
61
71
|
readonly unreachableHandles: readonly string[];
|
|
62
72
|
};
|
|
63
|
-
/**
|
|
73
|
+
/**
|
|
74
|
+
* 结束子代的结果。`observed` = 首轮枚举观察到的活子代句柄(成功形 `all` 下它们已全部结清 —— 结清口应答的 `children`)。
|
|
75
|
+
* `incomplete` = 时序失败(本进程的停止还没落盘 / 预检之后冒出来的子代),不是可达性。
|
|
76
|
+
*/
|
|
64
77
|
export type RetireSessionChildrenOutcome = {
|
|
65
78
|
readonly stopped: "all";
|
|
66
|
-
readonly
|
|
79
|
+
readonly observed: readonly string[];
|
|
67
80
|
readonly rounds: number;
|
|
68
81
|
} | {
|
|
69
82
|
readonly stopped: "incomplete";
|
|
70
|
-
readonly
|
|
83
|
+
readonly observed: readonly string[];
|
|
71
84
|
readonly rounds: number;
|
|
72
85
|
readonly remainingHandles: readonly string[];
|
|
73
86
|
};
|
|
87
|
+
/**
|
|
88
|
+
* 以一只根会话为根的后台子代在哪个 scope 分区里枚举 —— **唯一一处取**:会话属主 `owner ?? "default"`(删除门、换绑 / 导入两门、结清口同读;
|
|
89
|
+
* 子代按 run 的 principal 登记、与会话属主不同源的那一形是既有缺陷,修在这里一处)。
|
|
90
|
+
*/
|
|
91
|
+
export declare function sessionChildrenScope(owner: string | null): string;
|
|
74
92
|
/**
|
|
75
93
|
* **可达性预检**(零写;协调器在任何破坏性步骤之前调)。parked 行在有 checkpoint 店时可达(expire + reconcile 在任何副本上都成);
|
|
76
94
|
* running 行除非 {@link runsOnAnotherReplica} 都可达(`getAccessibleTask` / `agentStore.get` 都是纯读,不动任何东西)。
|
|
@@ -79,9 +97,9 @@ export declare function probeSessionChildren(deps: ProbeSessionChildrenDeps, roo
|
|
|
79
97
|
/** 以 `rootSessionId` 为根、在 `scope` 分区里的后台子代:作废 parked、停掉 running,重新枚举到没有活的为止(有上界)。 */
|
|
80
98
|
export declare function retireSessionChildren(deps: RetireSessionChildrenDeps, rootSessionId: string, scope: string): Promise<RetireSessionChildrenOutcome>;
|
|
81
99
|
/**
|
|
82
|
-
* 结束子代这一步的**时序**失败(可达性已在预检过了)
|
|
83
|
-
* session_meta 不删(E21「子腿失败 ⇒ 不删 meta ⇒ 幂等重试收敛」的既有契约),账本那一腿此时已经删了 ——
|
|
84
|
-
*
|
|
100
|
+
* 结束子代这一步的**时序**失败(可达性已在预检过了):本进程发出的停止在上界内没有全部落地。两只调用方(删除协调器、结清口)抛它 ⇒ 路由通用 500;
|
|
101
|
+
* 删除:session_meta 不删(E21「子腿失败 ⇒ 不删 meta ⇒ 幂等重试收敛」的既有契约),账本那一腿此时已经删了 —— 与任何一条子腿中途失败同形;
|
|
102
|
+
* 结清口:重试同一请求收敛。文案不带句柄(句柄进运维 warn)。
|
|
85
103
|
*/
|
|
86
104
|
export declare class SessionChildrenStopIncompleteError extends Error {
|
|
87
105
|
readonly sessionId: string;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export const RETIRE_MAX_ROUNDS = 6;
|
|
2
2
|
const RETIRE_BACKOFF_MS = [0, 25, 50, 100, 200, 400];
|
|
3
|
+
export function sessionChildrenScope(owner) {
|
|
4
|
+
return owner ?? "default";
|
|
5
|
+
}
|
|
3
6
|
async function liveChildren(deps, rootSessionId, scope) {
|
|
4
7
|
const out = new Map();
|
|
5
8
|
if (deps.agentStore !== undefined) {
|
|
@@ -22,7 +25,8 @@ export async function probeSessionChildren(deps, rootSessionId, scope) {
|
|
|
22
25
|
if (unreachable)
|
|
23
26
|
unreachableHandles.push(child.handle);
|
|
24
27
|
}
|
|
25
|
-
|
|
28
|
+
const handles = live.map((c) => c.handle);
|
|
29
|
+
return unreachableHandles.length === 0 ? { reachable: true, liveChildren: handles } : { reachable: false, liveChildren: handles, unreachableHandles };
|
|
26
30
|
}
|
|
27
31
|
async function runsOnAnotherReplica(deps, handle, rootSessionId, scope) {
|
|
28
32
|
if (deps.registry.getAccessibleTask(handle, { scope, sessionId: rootSessionId }) !== undefined)
|
|
@@ -35,7 +39,7 @@ async function runsOnAnotherReplica(deps, handle, rootSessionId, scope) {
|
|
|
35
39
|
export async function retireSessionChildren(deps, rootSessionId, scope) {
|
|
36
40
|
const sleep = deps.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
37
41
|
let live = await liveChildren(deps, rootSessionId, scope);
|
|
38
|
-
const
|
|
42
|
+
const observed = live.map((c) => c.handle);
|
|
39
43
|
let rounds = 0;
|
|
40
44
|
while (live.length > 0 && rounds < RETIRE_MAX_ROUNDS) {
|
|
41
45
|
rounds++;
|
|
@@ -56,8 +60,8 @@ export async function retireSessionChildren(deps, rootSessionId, scope) {
|
|
|
56
60
|
live = await liveChildren(deps, rootSessionId, scope);
|
|
57
61
|
}
|
|
58
62
|
return live.length === 0
|
|
59
|
-
? { stopped: "all",
|
|
60
|
-
: { stopped: "incomplete",
|
|
63
|
+
? { stopped: "all", observed, rounds }
|
|
64
|
+
: { stopped: "incomplete", observed, rounds, remainingHandles: live.map((c) => c.handle) };
|
|
61
65
|
}
|
|
62
66
|
async function expireParkedCard(deps, handle, scope) {
|
|
63
67
|
if (deps.agentStore === undefined || deps.checkpointStore === undefined)
|
|
@@ -76,7 +80,7 @@ export class SessionChildrenStopIncompleteError extends Error {
|
|
|
76
80
|
remaining;
|
|
77
81
|
constructor(sessionId, remaining) {
|
|
78
82
|
super(`session ${sessionId}: ${remaining} background agent(s) this replica stopped had not settled within ${RETIRE_MAX_ROUNDS} rounds — ` +
|
|
79
|
-
`the
|
|
83
|
+
`the operation stopped before its next step (a delete keeps the session record) so it can be retried (it converges once they settle)`);
|
|
80
84
|
this.sessionId = sessionId;
|
|
81
85
|
this.remaining = remaining;
|
|
82
86
|
this.name = "SessionChildrenStopIncompleteError";
|
|
@@ -29,11 +29,14 @@
|
|
|
29
29
|
* 要拿令牌去**写**(带化身条件的 UPDATE、认领、空间分区键)或要响亮区分「行坏了」的读者经它;只**比较**两头的读者用 `compareOccupants`。
|
|
30
30
|
* 空值只可能来自没铸化身的写腿、人为改库,或跳过了 7.104.0–7.135.x(那几版的起服迁移给存量行铸令牌,窗关后已删码)直接升上来的库 ——
|
|
31
31
|
* 把它当「通配」就是让任何人都能和这一行比成同一位住客。
|
|
32
|
-
* · **不上 wire、不进模型上下文、不进日志正文**:日志里要点名时只打 {@link incarnationLogPrefix}(前 8 位)
|
|
32
|
+
* · **不上 wire、不进模型上下文、不进日志正文**:日志里要点名时只打 {@link incarnationLogPrefix}(前 8 位)。值本身不出进程;唯一出进程的形是
|
|
33
|
+
* **单向摘要** —— 它折进会话列表行的行标签(`session-row.ts` 的 `sessionRowTagOf`,与会话 id、属主、可写格一起 SHA-256),摘要不可逆
|
|
34
|
+
* (令牌是 v4 随机串),只让「住客换了」在标签上看得见。
|
|
33
35
|
*
|
|
34
36
|
* ## 谁读它(全部派生自那一只头读)
|
|
35
|
-
* · `/decide` 的 parked 赎回腿(`parked-decide.ts`)
|
|
36
|
-
*
|
|
37
|
+
* · `/decide` 的 parked 赎回腿(`parked-decide.ts`):对根会话一读一判 —— 认领之前执行上下文解析器那一次执行席行读(与头读同一行、同一列)是唯一一读,
|
|
38
|
+
* 认领之后唯一写口按那一读的住客定址判一次(化身 ∧ 属主;不在或不是那一位 ⇒ 回滚认领、答既有的 `409 decide.not_parked`);
|
|
39
|
+
* 赎回面(`parked-revive-surface.ts`)只收写口放行的那一位,属主 = 卡的 principal 时交继承座。
|
|
37
40
|
* · core 的记忆引擎:Runner 读**它取到的那只会话**的 `getMetadata().incarnation`(SQL 两店的 wake 带出这一列;local 店交出的会话
|
|
38
41
|
* 在元数据上答边档那一格),不再有宿主座。
|
|
39
42
|
* · 没取会话的那一侧(k8s 工作区空间的分区,`boot/execution-env.ts`):会话店的 `headOf`,经 {@link sessionFaceOfHead} 拿令牌;缓存包装层原样转发。
|
|
@@ -75,7 +78,7 @@ export declare class SessionIncarnationMissingError extends Error {
|
|
|
75
78
|
*/
|
|
76
79
|
export type EmptyIncarnationReading = "refuse" | "absent";
|
|
77
80
|
/**
|
|
78
|
-
* 行上化身那一格的**唯一解码**(店读出的头、活住客的投影、SQL 两店 wake
|
|
81
|
+
* 行上化身那一格的**唯一解码**(店读出的头、活住客的投影、SQL 两店 wake 带出的会话元数据、留存删除的空间键、整段换装的沿用判据({@link carriedRowCells})都经它 ——
|
|
79
82
|
* 「是不是一只令牌」只判这一处)。非空字符串 ⇒ 那只令牌;否则按 `empty`({@link EmptyIncarnationReading}):缺省 `refuse` ⇒
|
|
80
83
|
* {@link SessionIncarnationMissingError},`absent` ⇒ `undefined`。
|
|
81
84
|
*/
|
|
@@ -116,15 +119,21 @@ export declare function sessionFaceOfHead(sessionId: string, head: SessionHead |
|
|
|
116
119
|
* 委派继承律读的都是这一只返回值。缺席 = 店没有实装 `headOf`(读不出属主 / 住客 / 叶子,调用方各按自己的 fail-closed 臂处置)。
|
|
117
120
|
*/
|
|
118
121
|
export declare function headReadOf(store: object | undefined): HeadRead | undefined;
|
|
122
|
+
/** 换装沿用的行格(化身 + fork 键):{@link carriedRowCells} 的答案。`forkKey: null` = 没有可沿用的键(新建行 / 行上本来没有)。 */
|
|
123
|
+
export interface CarriedRowCells {
|
|
124
|
+
readonly incarnation: string;
|
|
125
|
+
readonly forkKey: string | null;
|
|
126
|
+
}
|
|
119
127
|
/**
|
|
120
|
-
* session-sync
|
|
121
|
-
* (
|
|
122
|
-
*
|
|
128
|
+
* session-sync **换装**(整段换装 / 暂存提交)时行格的去留 —— 三只店共用的一句判据:换装只换内容,换的是**同一行**
|
|
129
|
+
* ⇒ 行在且那一格里有一只令牌(唯一解码 {@link incarnationFromCell} 的 `absent` 读法)⇒ 化身与 fork 键(`fork_key` / local `forkKey`:建这一行的那次 fork
|
|
130
|
+
* 请求的键,只由 fork 创建点写、此后每个写携带)**一起沿用**(属主重戳与否不改这一判:同一行 = 同一位住客);行不在(这是一次新建)或还是空的存量形 ⇒
|
|
131
|
+
* 铸一只新化身、没有 fork 键。属主不在这里判:每只店在自己的属主门上判过被换的那一行(SQL 孪生的 replace 只交「属主门删得到的那一行」),读不中的换装一个字节不写。
|
|
123
132
|
*/
|
|
124
|
-
export declare function
|
|
125
|
-
owner?: unknown;
|
|
133
|
+
export declare function carriedRowCells(sessionId: string, prior: {
|
|
126
134
|
incarnation?: unknown;
|
|
127
|
-
|
|
135
|
+
forkKey?: unknown;
|
|
136
|
+
} | undefined): CarriedRowCells;
|
|
128
137
|
/**
|
|
129
138
|
* `session_meta.incarnation` 的列定义 —— 两方言各一句,**唯一属主**:中央 DDL(`tidb-pool.ts` / `pg-session-storage.ts` 的
|
|
130
139
|
* `CREATE TABLE session_meta`)内插这同一串;存量库缺这一列时,起服列册探针(`schema-consistency.ts`)拒启,拒句里的 `ALTER TABLE … ADD COLUMN …`
|
|
@@ -67,9 +67,11 @@ export function headReadOf(store) {
|
|
|
67
67
|
const read = store?.headOf;
|
|
68
68
|
return typeof read === "function" ? read.bind(store) : undefined;
|
|
69
69
|
}
|
|
70
|
-
export function
|
|
71
|
-
const held = prior
|
|
72
|
-
|
|
70
|
+
export function carriedRowCells(sessionId, prior) {
|
|
71
|
+
const held = prior === undefined ? undefined : incarnationFromCell(sessionId, prior.incarnation, "absent");
|
|
72
|
+
if (held === undefined)
|
|
73
|
+
return { incarnation: mintSessionIncarnation(), forkKey: null };
|
|
74
|
+
return { incarnation: held, forkKey: typeof prior?.forkKey === "string" && prior.forkKey !== "" ? prior.forkKey : null };
|
|
73
75
|
}
|
|
74
76
|
export const SESSION_META_INCARNATION_COLUMN = {
|
|
75
77
|
name: "incarnation",
|
package/dist/session-row.d.ts
CHANGED
|
@@ -1,10 +1,114 @@
|
|
|
1
|
+
import { type SessionLogMark, type SessionRowExpectation } from "@sema-agent/core";
|
|
1
2
|
/** `title` 列的宽度(字符)= 用户标题的上界。两方言 DDL 内插它。 */
|
|
2
3
|
export declare const SESSION_TITLE_MAX_CHARS = 120;
|
|
3
|
-
/** 会话行的可写位(体闭集;两键至少一键)
|
|
4
|
+
/** 会话行的可写位(体闭集;两键至少一键)。会话店唯一行格写口 `writeSessionRowCells` 的格参。`title: null` = 清回自动标题(列写 NULL)。 */
|
|
4
5
|
export interface SessionRowPatch {
|
|
5
6
|
readonly title?: string | null;
|
|
6
7
|
readonly pinned?: boolean;
|
|
7
8
|
}
|
|
9
|
+
/** 一行可写格的整组当前值(每格必在;没被写过的格 = 它的缺省值)。 */
|
|
10
|
+
export type SessionRowCells = {
|
|
11
|
+
readonly [K in keyof SessionRowPatch]-?: Exclude<SessionRowPatch[K], undefined>;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* 可写格的闭集与每格缺省值 —— **一只记录**(头注「格的闭集与缺省值是一只记录」):PATCH 体闭集的键表与 {@link sessionRowTagOf} 的取格都读它;
|
|
15
|
+
* 映射型把它与 {@link SessionRowPatch} 双向绑住(漏一键 / 多一键 = 编译红)。
|
|
16
|
+
*/
|
|
17
|
+
export declare const SESSION_ROW_CELL_DEFAULTS: SessionRowCells;
|
|
18
|
+
/** 行标签的形:SHA-256 的 base64url(无填充)= 43 个 `[A-Za-z0-9_-]` 字符。体读者对 `expectedRowTag` 判的就是它。 */
|
|
19
|
+
export declare const SESSION_ROW_TAG_SHAPE: RegExp;
|
|
20
|
+
/** 算一只行标签要的四样:会话 id、属主、这一位住客的化身(非空)、可写格的整组当前值。 */
|
|
21
|
+
export interface SessionRowTagInput {
|
|
22
|
+
readonly sessionId: string;
|
|
23
|
+
readonly owner: string | null;
|
|
24
|
+
readonly incarnation: string;
|
|
25
|
+
readonly cells: SessionRowCells;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 行标签 —— 唯一一只(头注「行标签」):纯函数、无进程密钥,多副本对同一行算出同一个串。格按 {@link SESSION_ROW_CELL_DEFAULTS} 的键取、
|
|
29
|
+
* 值等于缺省的不入、按键名升序成 `[[键, 值], …]`。化身只以这只单向摘要的形式出进程(`session-incarnation.ts` 头注)。
|
|
30
|
+
*/
|
|
31
|
+
export declare function sessionRowTagOf(row: SessionRowTagInput): string;
|
|
32
|
+
/**
|
|
33
|
+
* 列表行上的 `rowTag` 键(present-iff 这一行可被条件写 = 店有行写口 ∧ 行上有化身):三只店的列表行映射都经它,化身那一格由调用方经
|
|
34
|
+
* `incarnationFromCell(…, "absent")` 解码好交进来(`undefined` = 行上没有令牌 ⇒ 键缺席,不铸)。
|
|
35
|
+
*/
|
|
36
|
+
export declare function sessionRowTagKey(row: {
|
|
37
|
+
readonly sessionId: string;
|
|
38
|
+
readonly owner: string | null;
|
|
39
|
+
readonly incarnation: string | undefined;
|
|
40
|
+
readonly cells: SessionRowCells;
|
|
41
|
+
}): {
|
|
42
|
+
readonly rowTag?: string;
|
|
43
|
+
};
|
|
44
|
+
/** 客户端写(PATCH):行期望 + 可选的行标签(只有 PATCH 入口给)。 */
|
|
45
|
+
export interface ClientSessionRowWrite {
|
|
46
|
+
readonly writer: "client";
|
|
47
|
+
readonly row: SessionRowExpectation;
|
|
48
|
+
readonly rowTag?: string;
|
|
49
|
+
}
|
|
50
|
+
/** 行重放(2c 导入落定后的那一笔):只有行期望 —— 它是镜像行的名写者,不判镜像、不带标签。 */
|
|
51
|
+
export interface ReplaySessionRowWrite {
|
|
52
|
+
readonly writer: "replay";
|
|
53
|
+
readonly row: SessionRowExpectation;
|
|
54
|
+
}
|
|
55
|
+
/** 写原语的写法(写者身份闭集两员)。 */
|
|
56
|
+
export type SessionRowWrite = ClientSessionRowWrite | ReplaySessionRowWrite;
|
|
57
|
+
/**
|
|
58
|
+
* 写原语的结局(闭集四员):`written` / `changed` 带提交(回滚)之后另读的那一行(列表行投影,含新 `rowTag`);`mirror`(客户端写在只读镜像上)/
|
|
59
|
+
* `absent`(行期望不中 / 没有行 / 委派分区行 / 应答行已不是判过的那一位住客)一个字节没写。
|
|
60
|
+
*/
|
|
61
|
+
export type SessionRowWriteOutcome<Row> = {
|
|
62
|
+
readonly kind: "written";
|
|
63
|
+
readonly row: Row;
|
|
64
|
+
} | {
|
|
65
|
+
readonly kind: "changed";
|
|
66
|
+
readonly row: Row;
|
|
67
|
+
} | {
|
|
68
|
+
readonly kind: "mirror";
|
|
69
|
+
} | {
|
|
70
|
+
readonly kind: "absent";
|
|
71
|
+
};
|
|
72
|
+
/** 行重放的结局:`changed` / `mirror` 对它不可达(判官对 `replay` 不判标签、不判镜像)。 */
|
|
73
|
+
export type ReplaySessionRowWriteOutcome<Row> = Extract<SessionRowWriteOutcome<Row>, {
|
|
74
|
+
readonly kind: "written" | "absent";
|
|
75
|
+
}>;
|
|
76
|
+
/** 写原语在锁下读到的那一行 —— 三店各自读成这一形,交同一只判官 {@link judgeSessionRowWrite}。 */
|
|
77
|
+
export interface LockedSessionRow {
|
|
78
|
+
readonly owner: string | null;
|
|
79
|
+
/** 化身那一格(`incarnationFromCell(…, "absent")` 解码:空 / 非串 ⇒ `undefined` = 住客未知,与 core 同读)。 */
|
|
80
|
+
readonly incarnation: string | undefined;
|
|
81
|
+
/** 委派分区行(SQL `placement_kind` 非空;local 没有)—— 不在列表面上,不写。 */
|
|
82
|
+
readonly placed: boolean;
|
|
83
|
+
/** 执行格是 `mirror`(写者在别处,本处只读)。 */
|
|
84
|
+
readonly mirror: boolean;
|
|
85
|
+
readonly cells: SessionRowCells;
|
|
86
|
+
}
|
|
87
|
+
/** 判官的四答(`write` = 可以写;其余三答 = 一个字节不写)。 */
|
|
88
|
+
export type SessionRowVerdict = "write" | "changed" | "mirror" | "absent";
|
|
89
|
+
/**
|
|
90
|
+
* 写原语的**唯一判官**(头注「写原语」):三店在各自的锁下读出那一行、交这一只,判序因此逐字同形 ——
|
|
91
|
+
* ① **行期望**:core 的 `sessionRowMatches(how.row, 锁住的行, logNow)`;不中、没有行(`undefined`)、委派分区行 ⇒ `absent`;
|
|
92
|
+
* ② **写者身份**:`client` ∧ 执行格为 `mirror` ⇒ `mirror`(镜像在本处只读;`replay` 是镜像的名写者,照写);
|
|
93
|
+
* ③ **标签**:`client` 带 `rowTag` ∧ 锁住的行算出的标签({@link sessionRowTagOf})≠ 它 ⇒ `changed`(行上没有化身 ⇒ 算不出标签 ⇒ 任何标签都不中);
|
|
94
|
+
* ④ `write`。
|
|
95
|
+
* 没有「已生效 ⇒ 写」的豁免:标签不中一律 `changed` —— 整体摘要分不出「住客换了」还是「格变了」,豁免会让恰好已有目标值的新住客拿到写。
|
|
96
|
+
* `logNow` 只在行期望带 `log` 时被调(调用方在同一把锁下先读好那只 mark)。
|
|
97
|
+
*/
|
|
98
|
+
export declare function judgeSessionRowWrite(sessionId: string, how: SessionRowWrite, locked: LockedSessionRow | undefined, logNow: () => SessionLogMark): SessionRowVerdict;
|
|
99
|
+
/** 应答行:提交 / 回滚之后另读的那一行 + 读到它时行上的住客(属主 + 化身那一格)。 */
|
|
100
|
+
export interface SessionRowAnswer<Row> {
|
|
101
|
+
readonly row: Row;
|
|
102
|
+
readonly occupant: {
|
|
103
|
+
readonly owner: string | null;
|
|
104
|
+
readonly incarnation: string | undefined;
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* 判官答 `write` / `changed` 之后的结局 —— 三店同一只:应答行(提交 / 回滚之后另读)仍是判过的那一位住客(同一只 core 判官 `sessionRowMatches`,只比行期望的住客半,
|
|
109
|
+
* 不比日志 mark —— 那一维判的是写之前)⇒ `written` / `changed` 带它;读不到、或已换了住客 / 属主 ⇒ `absent`(不把另一位住客的行答给这位调用方)。
|
|
110
|
+
*/
|
|
111
|
+
export declare function settleSessionRowWrite<Row>(how: SessionRowWrite, verdict: "write" | "changed", answer: SessionRowAnswer<Row> | undefined): SessionRowWriteOutcome<Row>;
|
|
8
112
|
/** 一条已分类的拒:码 + 不回显输入的句子。 */
|
|
9
113
|
export interface SessionRowProblem {
|
|
10
114
|
readonly code: "request.body_shape" | "request.field_invalid";
|
|
@@ -27,13 +131,18 @@ export declare function readSessionPinned(v: unknown): {
|
|
|
27
131
|
} | {
|
|
28
132
|
readonly problem: SessionRowProblem;
|
|
29
133
|
};
|
|
134
|
+
/** PATCH 体读出来的东西:要写的格 + 可选的前置条件(客户端读到的行标签)。 */
|
|
135
|
+
export interface SessionRowPatchRequest {
|
|
136
|
+
readonly patch: SessionRowPatch;
|
|
137
|
+
/** 在场 = 「这一行仍是我读到的那一份才写」(写原语在锁住的那一行上比 {@link sessionRowTagOf});缺席 = 无条件写。 */
|
|
138
|
+
readonly expectedRowTag?: string;
|
|
139
|
+
}
|
|
30
140
|
/**
|
|
31
|
-
* `PATCH /v1/sessions/:id` 体的**唯一**读者。形不对(非对象 /
|
|
141
|
+
* `PATCH /v1/sessions/:id` 体的**唯一**读者。形不对(非对象 / 表外键 / 一格可写位都没有 —— 只带 `expectedRowTag` 也算)⇒ `request.body_shape`;
|
|
142
|
+
* 各格走自己那一格的读者;`expectedRowTag` 不是 {@link SESSION_ROW_TAG_SHAPE} ⇒ `request.field_invalid`。先形后值,值的判序:`title` → `pinned` → `expectedRowTag`。
|
|
32
143
|
* 拒句不回显调用方的键名或值。
|
|
33
144
|
*/
|
|
34
|
-
export declare function readSessionRowPatch(body: unknown): {
|
|
35
|
-
readonly patch: SessionRowPatch;
|
|
36
|
-
} | {
|
|
145
|
+
export declare function readSessionRowPatch(body: unknown): SessionRowPatchRequest | {
|
|
37
146
|
readonly problem: SessionRowProblem;
|
|
38
147
|
};
|
|
39
148
|
//# sourceMappingURL=session-row.d.ts.map
|