@sema-agent/server 7.139.0 → 7.141.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 +471 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/USAGE.md +94 -26
- package/dist/adoption/runner.js +1 -1
- package/dist/adoption/sql.js +1 -1
- package/dist/approval-batch-census.d.ts +27 -0
- package/dist/approval-batch-census.js +27 -0
- package/dist/approval-card.d.ts +37 -22
- package/dist/approval-card.js +6 -3
- package/dist/approval.d.ts +15 -0
- package/dist/approval.js +10 -0
- package/dist/audit.d.ts +4 -2
- package/dist/audit.js +2 -2
- package/dist/bench/s1/live-deps.js +3 -2
- package/dist/bench/s1/row.d.ts +5 -2
- package/dist/bench/s1/row.js +2 -22
- package/dist/boot/adoption.js +1 -1
- package/dist/boot/device-lane.d.ts +11 -0
- package/dist/boot/device-lane.js +16 -0
- package/dist/boot/engine-lease.d.ts +24 -3
- package/dist/boot/engine-lease.js +9 -2
- package/dist/boot/execution-env.js +18 -12
- package/dist/boot/execution-lane.d.ts +8 -0
- package/dist/boot/execution-lane.js +6 -1
- package/dist/boot/memory-boundary.d.ts +16 -53
- package/dist/boot/memory-boundary.js +10 -20
- package/dist/boot/memory-consolidation.d.ts +16 -12
- package/dist/boot/memory-consolidation.js +24 -13
- package/dist/boot/reapers.d.ts +2 -2
- package/dist/boot/resolve-spec.d.ts +3 -5
- package/dist/boot/resolve-spec.js +9 -8
- package/dist/boot/runner-deps.d.ts +3 -3
- package/dist/boot/runner-deps.js +1 -0
- package/dist/boot/session-faces.d.ts +1 -1
- package/dist/boot/session-faces.js +4 -3
- package/dist/boot/shutdown.js +5 -0
- package/dist/boot/stage-03-store-backend.d.ts +2 -6
- package/dist/boot/stage-03-store-backend.js +2 -3
- package/dist/boot/stage-04-stores.d.ts +2 -6
- package/dist/boot/stage-04-stores.js +5 -5
- package/dist/boot/stage-05-execution-env.d.ts +2 -6
- package/dist/boot/stage-05-execution-env.js +3 -1
- package/dist/boot/stage-06-runners.d.ts +2 -8
- package/dist/boot/stage-06-runners.js +3 -3
- package/dist/boot/stage-07-capability-layer.d.ts +2 -7
- package/dist/boot/stage-07-capability-layer.js +8 -10
- package/dist/boot/stage-08-reapers.d.ts +2 -7
- package/dist/boot/stage-09-leader.d.ts +2 -7
- package/dist/boot/stage-10-http-server.d.ts +2 -7
- package/dist/boot/stage-10-http-server.js +6 -4
- package/dist/boot/stores.d.ts +3 -6
- package/dist/boot/stores.js +37 -44
- package/dist/boot/task-list-lane.d.ts +1 -1
- package/dist/boot/task-list-lane.js +1 -1
- package/dist/boot/web-admin.js +36 -9
- package/dist/capabilities/execution-lane.d.ts +2 -2
- package/dist/capabilities/scenarios.d.ts +1 -1
- package/dist/capability-facts.d.ts +9 -0
- package/dist/capability-facts.js +9 -0
- package/dist/card-void.d.ts +38 -0
- package/dist/card-void.js +23 -0
- package/dist/config-catalog.js +12 -8
- package/dist/config-provider.d.ts +18 -17
- package/dist/config-provider.js +28 -36
- package/dist/config-types.d.ts +36 -9
- package/dist/config.js +56 -46
- package/dist/delegated-session-owner.d.ts +23 -20
- package/dist/delegated-session-owner.js +2 -2
- package/dist/deployment-shape.d.ts +9 -8
- package/dist/deployment-shape.js +4 -4
- package/dist/device-store.d.ts +7 -0
- package/dist/device-store.js +3 -0
- package/dist/execution-config-root.d.ts +22 -0
- package/dist/execution-config-root.js +35 -0
- package/dist/execution-lane-caps.d.ts +145 -107
- package/dist/execution-lane-caps.js +144 -83
- package/dist/execution-placement.d.ts +3 -0
- package/dist/execution-placement.js +7 -0
- package/dist/fleet/drain-entry.d.ts +3 -0
- package/dist/hosted-posture.d.ts +8 -0
- package/dist/hosted-posture.js +4 -0
- package/dist/http/admission.js +3 -3
- package/dist/http/caller-trust.d.ts +3 -2
- package/dist/http/caller-trust.js +2 -1
- package/dist/http/dispatch.js +4 -0
- package/dist/http/live-frame.d.ts +24 -0
- package/dist/http/live-frame.js +16 -0
- package/dist/http/memory-compliance-failure-reply.d.ts +3 -1
- package/dist/http/memory-compliance-failure-reply.js +5 -0
- package/dist/http/memory-layer-reply.d.ts +30 -0
- package/dist/http/memory-layer-reply.js +24 -0
- package/dist/http/resume-legs.js +49 -35
- package/dist/http/retired-service-deps.d.ts +1 -1
- package/dist/http/retired-service-deps.js +1 -1
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/adoption.js +1 -1
- package/dist/http/routes/approvals-assistant.js +1 -0
- package/dist/http/routes/capabilities.js +5 -4
- package/dist/http/routes/diagnostics.d.ts +0 -19
- package/dist/http/routes/diagnostics.js +16 -2
- package/dist/http/routes/memory-bundle.d.ts +2 -2
- package/dist/http/routes/memory-bundle.js +4 -1
- package/dist/http/routes/memory-compliance.js +9 -2
- package/dist/http/routes/memory-consolidation.js +12 -1
- package/dist/http/routes/memory-origin.js +14 -2
- package/dist/http/routes/memory-policy.js +7 -2
- package/dist/http/routes/run-permission-mode.d.ts +75 -0
- package/dist/http/routes/run-permission-mode.js +170 -0
- package/dist/http/routes/session-sync.d.ts +3 -6
- package/dist/http/routes/session-sync.js +7 -2
- package/dist/http/routes/sessions.js +33 -15
- package/dist/http/routes/tasks.js +67 -68
- package/dist/http/run-read-face.js +3 -3
- package/dist/http/send.d.ts +1 -1
- package/dist/http/send.js +2 -2
- package/dist/http/server.d.ts +14 -27
- package/dist/http/server.js +2 -2
- package/dist/http/sse-log.d.ts +3 -8
- package/dist/http/stored-body-replay.d.ts +3 -3
- package/dist/http/stored-body-replay.js +3 -1
- package/dist/identity-source.d.ts +1 -1
- package/dist/identity-source.js +1 -1
- package/dist/instruction-source-notice.d.ts +7 -0
- package/dist/instruction-source-notice.js +6 -6
- package/dist/lane-home-probe.d.ts +68 -42
- package/dist/lane-home-probe.js +53 -30
- package/dist/leader/wire.js +5 -4
- package/dist/mcp-assertion-header.d.ts +4 -0
- package/dist/mcp-assertion-header.js +5 -0
- package/dist/memory-bundle-engine.d.ts +16 -9
- package/dist/memory-bundle-engine.js +29 -6
- package/dist/memory-operator-faces.d.ts +85 -30
- package/dist/memory-operator-faces.js +136 -30
- package/dist/memory-posture.d.ts +1 -1
- package/dist/memory-project-layer.d.ts +3 -21
- package/dist/memory-project-layer.js +11 -8
- package/dist/memory-scope-stores.d.ts +73 -0
- package/dist/memory-scope-stores.js +86 -0
- package/dist/memory-scope.d.ts +33 -9
- package/dist/memory-scope.js +17 -5
- package/dist/memory-sync-client.d.ts +34 -9
- package/dist/memory-sync-client.js +108 -28
- package/dist/observability/fail-open.d.ts +30 -2
- package/dist/observability/fail-open.js +30 -2
- package/dist/observability/metrics.js +0 -1
- package/dist/observability/run-terminal.d.ts +6 -2
- package/dist/observability/run-terminal.js +25 -26
- package/dist/observability/secret-env-scrub.d.ts +20 -1
- package/dist/observability/secret-env-scrub.js +14 -0
- package/dist/orchestration/workflow-completion-inbox.d.ts +5 -2
- package/dist/orchestration/workflow-completion-inbox.js +13 -5
- package/dist/orchestration/workflow-notify-journal.d.ts +5 -3
- package/dist/orchestration/workflow-notify-journal.js +2 -1
- package/dist/permission-mode-admission.d.ts +68 -0
- package/dist/permission-mode-admission.js +23 -0
- package/dist/permission-rule-list.d.ts +55 -6
- package/dist/permission-rule-list.js +52 -5
- package/dist/plugins/adoption-log-sql.js +4 -4
- package/dist/plugins/approval-ask-store-sql.js +14 -14
- package/dist/plugins/approval-nonce-store.js +4 -4
- package/dist/plugins/blob-backend.d.ts +4 -4
- package/dist/plugins/blob-backend.js +7 -7
- package/dist/plugins/breaker-state-sql.js +2 -2
- package/dist/plugins/caching-session-store.d.ts +6 -0
- package/dist/plugins/caching-session-store.js +3 -0
- package/dist/plugins/checkpoint-index-columns.js +2 -2
- package/dist/plugins/checkpoint-store-sql.d.ts +65 -17
- package/dist/plugins/checkpoint-store-sql.js +90 -19
- package/dist/plugins/device-store-sql.d.ts +5 -2
- package/dist/plugins/device-store-sql.js +23 -20
- package/dist/plugins/ensure-index.d.ts +1 -2
- package/dist/plugins/execution-placement-sql.d.ts +19 -9
- package/dist/plugins/execution-placement-sql.js +20 -9
- package/dist/plugins/file-history-store-sql.d.ts +2 -2
- package/dist/plugins/file-history-store-sql.js +4 -4
- package/dist/plugins/file-run-store.d.ts +2 -2
- package/dist/plugins/file-run-store.js +1 -1
- package/dist/plugins/fork-routing-session-store.d.ts +10 -32
- package/dist/plugins/fork-routing-session-store.js +2 -61
- package/dist/plugins/image-bake-store-sql.js +9 -9
- package/dist/plugins/image-index-sql.js +11 -11
- package/dist/plugins/k8s-exec-protocol.d.ts +4 -1
- package/dist/plugins/k8s-exec-protocol.js +6 -1
- package/dist/plugins/leader-run-store-sql.js +4 -4
- package/dist/plugins/local-checkpoint-store.d.ts +10 -1
- package/dist/plugins/local-checkpoint-store.js +22 -0
- package/dist/plugins/local-session-store.d.ts +227 -35
- package/dist/plugins/local-session-store.js +518 -37
- package/dist/plugins/local-session-window.d.ts +17 -3
- package/dist/plugins/local-session-window.js +7 -13
- package/dist/plugins/mailbox-store-sql.d.ts +2 -1
- package/dist/plugins/mailbox-store-sql.js +4 -4
- package/dist/plugins/memory-engine-tidb.js +5 -5
- package/dist/plugins/memory-optout-grant-store-sql.js +1 -1
- package/dist/plugins/memory-run-store.d.ts +2 -2
- package/dist/plugins/memory-run-store.js +1 -1
- package/dist/plugins/memory-sync-store-tidb.js +3 -3
- package/dist/plugins/one-time-migrations.d.ts +52 -11
- package/dist/plugins/one-time-migrations.js +101 -39
- package/dist/plugins/org-delivery-quota-store.js +2 -2
- package/dist/plugins/outcome-ledger-sql.js +2 -2
- package/dist/plugins/permission-rule-store-sql.d.ts +4 -4
- package/dist/plugins/permission-rule-store-sql.js +16 -16
- package/dist/plugins/pg-pool.js +3 -2
- package/dist/plugins/pg-session-storage.d.ts +2 -0
- package/dist/plugins/pg-session-storage.js +3 -2
- package/dist/plugins/remote-env-adb.d.ts +7 -24
- package/dist/plugins/remote-env-adb.js +22 -5
- package/dist/plugins/remote-env-device.d.ts +2 -28
- package/dist/plugins/remote-env-device.js +2 -1
- package/dist/plugins/remote-env-e2b.d.ts +40 -27
- package/dist/plugins/remote-env-e2b.js +180 -20
- package/dist/plugins/remote-env-file-error.d.ts +1 -1
- package/dist/plugins/remote-env-file-error.js +8 -2
- package/dist/plugins/remote-env-host.d.ts +19 -35
- package/dist/plugins/remote-env-host.js +26 -3
- package/dist/plugins/remote-env-k8s.d.ts +22 -14
- package/dist/plugins/remote-env-k8s.js +150 -26
- package/dist/plugins/remote-env-local-docker.d.ts +27 -24
- package/dist/plugins/remote-env-local-docker.js +91 -24
- package/dist/plugins/remote-env-ssh.d.ts +4 -24
- package/dist/plugins/remote-env-ssh.js +4 -3
- package/dist/plugins/resume-anchor-store-sql.js +2 -2
- package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
- package/dist/plugins/retention-lane-store-sql.js +2 -2
- package/dist/plugins/retention-store-sql.d.ts +1 -1
- package/dist/plugins/retention-store-sql.js +6 -6
- package/dist/plugins/run-store-sql.d.ts +3 -3
- package/dist/plugins/run-store-sql.js +19 -18
- package/dist/plugins/sandbox-read-floor.d.ts +273 -0
- package/dist/plugins/sandbox-read-floor.js +608 -0
- package/dist/plugins/schema-consistency.d.ts +6 -6
- package/dist/plugins/schema-consistency.js +1 -1
- package/dist/plugins/schema-ensure-legs.d.ts +2 -3
- package/dist/plugins/schema-ensure-legs.js +2 -2
- package/dist/plugins/schema-live-columns.d.ts +1 -1
- package/dist/plugins/session-capture-record-store-sql.js +1 -1
- package/dist/plugins/session-ownership.d.ts +2 -1
- package/dist/plugins/session-placement.d.ts +17 -4
- package/dist/plugins/session-placement.js +2 -1
- package/dist/plugins/session-rules-column.d.ts +1 -1
- package/dist/plugins/session-rules-column.js +1 -1
- package/dist/plugins/session-store.d.ts +18 -20
- package/dist/plugins/session-store.js +4 -12
- package/dist/plugins/session-workspace-cell.d.ts +1 -1
- package/dist/plugins/session-workspace-cell.js +1 -1
- package/dist/plugins/shared-memory-store-sql.js +2 -2
- package/dist/plugins/sql-driver.d.ts +10 -5
- package/dist/plugins/sql-driver.js +6 -6
- package/dist/plugins/sql-errors.js +1 -1
- package/dist/plugins/store-backend.d.ts +35 -6
- package/dist/plugins/store-backend.js +27 -10
- package/dist/plugins/store-contracts.d.ts +9 -2
- package/dist/plugins/task-list-store-sql.js +11 -11
- package/dist/plugins/tidb-pool.js +7 -6
- package/dist/plugins/tidb-session-storage.js +4 -4
- package/dist/plugins/tidb-session-store.d.ts +4 -1
- package/dist/plugins/tidb-session-store.js +16 -15
- package/dist/plugins/tool-result-store-sql.d.ts +2 -2
- package/dist/plugins/tool-result-store-sql.js +3 -3
- package/dist/plugins/user-input-ledger-sql.js +2 -2
- package/dist/plugins/workflow-journal-store-sql.js +5 -5
- package/dist/plugins/workflow-run-store-sql.js +19 -19
- package/dist/plugins/write-behind-counter.d.ts +2 -3
- package/dist/plugins/write-behind-counter.js +5 -5
- package/dist/resource-suspend.d.ts +14 -12
- package/dist/resource-suspend.js +1 -1
- package/dist/resource-window.d.ts +4 -3
- package/dist/run-cancel-context.d.ts +34 -0
- package/dist/run-cancel-context.js +7 -0
- package/dist/run-local.js +14 -19
- package/dist/runs.d.ts +47 -16
- package/dist/runs.js +112 -113
- package/dist/security.d.ts +2 -2
- package/dist/server-secret-env.d.ts +2 -1
- package/dist/server-secret-env.js +2 -4
- package/dist/session-error-wire.d.ts +22 -4
- package/dist/session-error-wire.js +16 -0
- package/dist/session-incarnation.d.ts +10 -4
- package/dist/session-incarnation.js +1 -1
- package/dist/session-policy-wire.d.ts +1 -1
- package/dist/session-sync-kernel.d.ts +42 -1
- package/dist/session-sync-kernel.js +17 -0
- package/dist/session-sync.js +16 -4
- package/dist/sql-engine-coordinates.d.ts +49 -0
- package/dist/sql-engine-coordinates.js +27 -0
- package/dist/sql-engine-posture.d.ts +1 -1
- package/dist/sql-engine-posture.js +1 -1
- package/dist/standing-answer-grant.d.ts +31 -2
- package/dist/standing-answer-grant.js +14 -2
- package/dist/store-posture.d.ts +1 -1
- package/dist/{plugins → stores-sql}/background-agent-store-sql.d.ts +2 -2
- package/dist/{plugins → stores-sql}/background-agent-store-sql.js +8 -8
- package/dist/{plugins → stores-sql}/session-policy-store-sql.d.ts +7 -5
- package/dist/{plugins → stores-sql}/session-policy-store-sql.js +12 -12
- package/dist/{plugins → stores-sql}/usage-window-store-sql.d.ts +1 -1
- package/dist/{plugins → stores-sql}/usage-window-store-sql.js +3 -3
- package/dist/task-a2a.d.ts +1 -1
- package/dist/task-a2a.js +5 -6
- package/dist/task-mcp.d.ts +21 -8
- package/dist/task-mcp.js +17 -9
- package/dist/task-settings.d.ts +52 -25
- package/dist/task-settings.js +91 -28
- package/dist/terminal.d.ts +103 -19
- package/dist/terminal.js +72 -20
- package/dist/trace/core-keyset-guard.d.ts +79 -2
- package/dist/trace/exit-seat.d.ts +7 -0
- package/dist/trace/exit-seat.js +1 -0
- package/dist/trace/model-segment.d.ts +2 -2
- package/dist/trace/redact.d.ts +3 -1
- package/dist/trace/redact.js +395 -110
- package/dist/trace/self-minted-wire.d.ts +226 -2
- package/dist/trace/self-minted-wire.js +79 -0
- package/dist/verifier-pause-card.d.ts +8 -0
- package/dist/verifier-pause-card.js +19 -0
- package/dist/web-admin-client/apply-effective.d.ts +5 -7
- package/dist/web-admin-client/apply-effective.js +2 -2
- package/dist/web-admin-client/candidate-gate.d.ts +11 -7
- package/dist/web-admin-client/candidate-gate.js +1 -1
- package/dist/web-admin-client/http-client.d.ts +5 -4
- package/dist/web-admin-client/http-client.js +2 -2
- package/dist/web-admin-client/read-warnings.d.ts +7 -17
- package/dist/web-admin-client/read-warnings.js +5 -9
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +3 -2
- package/package.json +2 -2
- package/wire-changes/server@7.140.0.json +184 -0
- package/wire-changes/server@7.141.0.json +367 -0
|
@@ -68,33 +68,33 @@ export async function ensurePgTaskListSchema(q) {
|
|
|
68
68
|
)`);
|
|
69
69
|
}
|
|
70
70
|
async function ensureMeta(exec, dialect, listKey) {
|
|
71
|
-
await exec(dialect === "
|
|
71
|
+
await exec(dialect === "mysql"
|
|
72
72
|
? `INSERT INTO ${TASK_LIST_META_TABLE} (list_key, next_id, next_sort) VALUES (?, 1, 1) ON DUPLICATE KEY UPDATE list_key = list_key`
|
|
73
73
|
: `INSERT INTO ${TASK_LIST_META_TABLE} (list_key, next_id, next_sort) VALUES ($1, 1, 1) ON CONFLICT (list_key) DO NOTHING`, [listKey]);
|
|
74
74
|
}
|
|
75
75
|
async function allocateOn(exec, dialect, listKey) {
|
|
76
76
|
await ensureMeta(exec, dialect, listKey);
|
|
77
|
-
const rows = await exec(dialect === "
|
|
77
|
+
const rows = await exec(dialect === "mysql"
|
|
78
78
|
? `SELECT next_id FROM ${TASK_LIST_META_TABLE} WHERE list_key = ? FOR UPDATE`
|
|
79
79
|
: `SELECT next_id FROM ${TASK_LIST_META_TABLE} WHERE list_key = $1 FOR UPDATE`, [listKey]);
|
|
80
80
|
const id = Number(rows[0].next_id);
|
|
81
|
-
await exec(dialect === "
|
|
81
|
+
await exec(dialect === "mysql"
|
|
82
82
|
? `UPDATE ${TASK_LIST_META_TABLE} SET next_id = ? WHERE list_key = ?`
|
|
83
83
|
: `UPDATE ${TASK_LIST_META_TABLE} SET next_id = $1 WHERE list_key = $2`, [id + 1, listKey]);
|
|
84
84
|
return String(id);
|
|
85
85
|
}
|
|
86
86
|
async function setOn(exec, dialect, listKey, id, itemJson) {
|
|
87
87
|
await ensureMeta(exec, dialect, listKey);
|
|
88
|
-
const rows = await exec(dialect === "
|
|
88
|
+
const rows = await exec(dialect === "mysql"
|
|
89
89
|
? `SELECT next_sort FROM ${TASK_LIST_META_TABLE} WHERE list_key = ? FOR UPDATE`
|
|
90
90
|
: `SELECT next_sort FROM ${TASK_LIST_META_TABLE} WHERE list_key = $1 FOR UPDATE`, [listKey]);
|
|
91
91
|
const sort = Number(rows[0].next_sort);
|
|
92
|
-
await exec(dialect === "
|
|
92
|
+
await exec(dialect === "mysql"
|
|
93
93
|
? `INSERT INTO ${TASK_LIST_ITEM_TABLE} (list_key, id, id_num, sort_seq, item_json) VALUES (?, ?, ?, ?, ?)
|
|
94
94
|
ON DUPLICATE KEY UPDATE item_json = VALUES(item_json)`
|
|
95
95
|
: `INSERT INTO ${TASK_LIST_ITEM_TABLE} (list_key, id, id_num, sort_seq, item_json) VALUES ($1, $2, $3, $4, $5)
|
|
96
96
|
ON CONFLICT (list_key, id) DO UPDATE SET item_json = EXCLUDED.item_json`, [listKey, id, arrayIndexOf(id), sort, itemJson]);
|
|
97
|
-
await exec(dialect === "
|
|
97
|
+
await exec(dialect === "mysql"
|
|
98
98
|
? `UPDATE ${TASK_LIST_META_TABLE} SET next_sort = ? WHERE list_key = ?`
|
|
99
99
|
: `UPDATE ${TASK_LIST_META_TABLE} SET next_sort = $1 WHERE list_key = $2`, [sort + 1, listKey]);
|
|
100
100
|
}
|
|
@@ -160,29 +160,29 @@ export function createTiDBTaskListStore(pool, listKey) {
|
|
|
160
160
|
};
|
|
161
161
|
const build = (q, inTx) => ({
|
|
162
162
|
get: async (id) => {
|
|
163
|
-
const [rows] = (await q.query(`SELECT ${jsonColumnText("
|
|
163
|
+
const [rows] = (await q.query(`SELECT ${jsonColumnText("mysql", "item_json")} FROM ${TASK_LIST_ITEM_TABLE} WHERE list_key = ? AND id = ?${inTx ? " FOR UPDATE" : ""}`, [listKey, id]));
|
|
164
164
|
return rows.length > 0 ? parseItem(rows[0].item_json, `for list ${listKey} item ${JSON.stringify(id)}`) : undefined;
|
|
165
165
|
},
|
|
166
166
|
set: async (id, item) => {
|
|
167
167
|
if (item.metadata)
|
|
168
168
|
assertJsonMetadata(item.metadata);
|
|
169
169
|
const json = JSON.stringify(item);
|
|
170
|
-
await (inTx ? setOn(execOn(q), "
|
|
170
|
+
await (inTx ? setOn(execOn(q), "mysql", listKey, id, json) : tx((c) => setOn(execOn(c), "mysql", listKey, id, json)));
|
|
171
171
|
},
|
|
172
172
|
delete: async (id) => {
|
|
173
173
|
const [res] = (await q.query(`DELETE FROM ${TASK_LIST_ITEM_TABLE} WHERE list_key = ? AND id = ?`, [listKey, id]));
|
|
174
174
|
return res.affectedRows === 1;
|
|
175
175
|
},
|
|
176
176
|
list: async () => {
|
|
177
|
-
const [rows] = (await q.query(`SELECT ${jsonColumnText("
|
|
177
|
+
const [rows] = (await q.query(`SELECT ${jsonColumnText("mysql", "item_json")} FROM ${TASK_LIST_ITEM_TABLE} WHERE list_key = ? ORDER BY id_num IS NULL, id_num, sort_seq${inTx ? " FOR UPDATE" : ""}`, [listKey]));
|
|
178
178
|
return rows.map((r) => parseItem(r.item_json, `for list ${listKey} (enumeration)`));
|
|
179
179
|
},
|
|
180
|
-
allocateId: async () => (inTx ? allocateOn(execOn(q), "
|
|
180
|
+
allocateId: async () => (inTx ? allocateOn(execOn(q), "mysql", listKey) : tx((c) => allocateOn(execOn(c), "mysql", listKey))),
|
|
181
181
|
...(inTx
|
|
182
182
|
? {}
|
|
183
183
|
: {
|
|
184
184
|
mutate: (fn) => tx(async (c) => {
|
|
185
|
-
await ensureMeta(execOn(c), "
|
|
185
|
+
await ensureMeta(execOn(c), "mysql", listKey);
|
|
186
186
|
await c.query(`SELECT next_id FROM ${TASK_LIST_META_TABLE} WHERE list_key = ? FOR UPDATE`, [listKey]);
|
|
187
187
|
return fn(build(c, true));
|
|
188
188
|
}),
|
|
@@ -79,7 +79,7 @@ export const SCHEMA_STATEMENTS = [
|
|
|
79
79
|
-- NULL = 还没有任何腿记过;唯一写者 = 腿的记录座(src/session-workspace.ts),列属主 = src/plugins/session-workspace-cell.ts
|
|
80
80
|
-- (列定义、形读者、编解码;存量库缺这一列 ⇒ 起服列册对账拒启,拒句里给出 ALTER)。下一条腿的 TaskSpec.projectId 读它的 project.id。
|
|
81
81
|
-- 服务端元数据:不进 wire 会话面、不进模型上下文;住在会话行上 ⇒ 随会话删除 / 留存清扫一起消失,fork 出的新行为 NULL。
|
|
82
|
-
${SESSION_META_WORKSPACE_COLUMN.
|
|
82
|
+
${SESSION_META_WORKSPACE_COLUMN.mysql},
|
|
83
83
|
-- #292 C18(core 5.48.0 design/323)subagent 转录持久化 —— placement 元组,**创建时一次落行、
|
|
84
84
|
-- first-write 不可变**(register 的 ON DUPLICATE 臂永不重写这六列)。判别位 = placement_kind:
|
|
85
85
|
-- 在场 ⇒ 该会话住在 placement 分区里(不上宿主枚举、claim 形 acquire 恒拒、release=真删除、
|
|
@@ -96,12 +96,12 @@ export const SCHEMA_STATEMENTS = [
|
|
|
96
96
|
-- 无 id 创建 / fork / 导入新行),删除随行消失,同 id 重登记铸新的;'' = 没铸过,读口响亮拒。列定义的唯一属主 =
|
|
97
97
|
-- src/session-incarnation.ts 的 SESSION_META_INCARNATION_COLUMN(存量库缺这一列 ⇒ 起服列册对账拒启,拒句里的 ALTER 由本建表语句生成)。
|
|
98
98
|
-- 不上 wire、不进模型上下文、日志只打前 8 位。
|
|
99
|
-
${SESSION_META_INCARNATION_COLUMN.
|
|
99
|
+
${SESSION_META_INCARNATION_COLUMN.mysql},
|
|
100
100
|
-- 执行放置:根会话行上**这一位住客**的一格 —— execution_role('writer' | 'mirror' | NULL = absent)、execution_lane、device 车道的设备与绑定属主、
|
|
101
101
|
-- 放下时刻、换绑序号;写只按住客谓词 (session_id, incarnation, owner) ∧ placement_kind IS NULL(换了住客 = 这一格不在)。fork_key = 建这一行的那次
|
|
102
102
|
-- fork 请求的键(只由 fork 创建点写,此后每个写携带)。规则在 src/execution-placement.ts,列定义与语句的唯一属主 = src/plugins/execution-placement-sql.ts
|
|
103
103
|
-- (存量库缺这些列 ⇒ 起服列册对账拒启;加列只由一次性迁移做)。
|
|
104
|
-
${sessionMetaPlacementColumnsDdl("
|
|
104
|
+
${sessionMetaPlacementColumnsDdl("mysql")},
|
|
105
105
|
PRIMARY KEY (session_id),
|
|
106
106
|
KEY idx_session_meta_owner (owner),
|
|
107
107
|
-- listPlaced 的检索腿(kind + 租户 + 年龄升序);普通会话这三列全 NULL ⇒ 不占索引选择性。
|
|
@@ -173,7 +173,7 @@ export const SCHEMA_STATEMENTS = [
|
|
|
173
173
|
-- (rows from before these columns, unauthenticated-write acceptance, a run someone else accepted on the owner's behalf) ⇒ not
|
|
174
174
|
-- qualified. Column definitions' single owner = src/identity-source.ts RUN_IDENTITY_COLUMNS (the boot column probe derives its
|
|
175
175
|
-- ALTER suggestion from this statement). \`source\` above is attribution only, never an authentication source.
|
|
176
|
-
${RUN_IDENTITY_COLUMNS.
|
|
176
|
+
${RUN_IDENTITY_COLUMNS.mysql},
|
|
177
177
|
-- objective_preview: the list's "what is this task" glance — redacted + truncated at write.
|
|
178
178
|
objective_preview VARCHAR(160) NULL,
|
|
179
179
|
-- cancel_requested: durable cross-replica CANCEL flag. The running instance's heartbeat tick honors it
|
|
@@ -463,7 +463,7 @@ export const SCHEMA_STATEMENTS = [
|
|
|
463
463
|
principal VARCHAR(190) NULL,
|
|
464
464
|
-- 会话规则(三只桶,引擎的规则条目文法)。列定义唯一属主 = src/plugins/session-rules-column.ts 的 SESSION_RULES_COLUMN(一列一文法:
|
|
465
465
|
-- 7.128.x 及以前这一列叫 rules、按整串工具名读;存量库由一次性迁移 M17 改名,带退役命令桶的行原样留着、读回判坏并逐行点名,见那份文件与 one-time-migrations.ts)。
|
|
466
|
-
${SESSION_RULES_COLUMN.
|
|
466
|
+
${SESSION_RULES_COLUMN.mysql},
|
|
467
467
|
rev BIGINT NOT NULL,
|
|
468
468
|
-- gen (core 7.25.0 StoredSessionRules.gen, S-529 二期):这一行的**血统**。rev 只在一条血统内计数,
|
|
469
469
|
-- deleteBySession 终结血统并把下一代的号留在 session_policy_rev_mark.gen 上,于是活规则读者能把
|
|
@@ -632,7 +632,8 @@ export const SCHEMA_STATEMENTS = [
|
|
|
632
632
|
-- kind === "task_notification" vs everything-else. Do NOT "tidy" this into NOT NULL DEFAULT.
|
|
633
633
|
kind VARCHAR(24) NULL,
|
|
634
634
|
-- payload: bounded + redacted JSON extras of the entry's kind. task_notification: task_type / result / …;
|
|
635
|
-
-- workflow_complete: at most {"completionId": …} (the engine's own correlation id, verbatim;
|
|
635
|
+
-- workflow_complete: at most {"completionId": …, "diagnostics": …} (the engine's own correlation id, verbatim; the engine's diagnostic
|
|
636
|
+
-- teaching text, redacted + bounded at enqueue; each key absent when the engine minted none, NULL when neither).
|
|
636
637
|
payload TEXT NULL,
|
|
637
638
|
PRIMARY KEY (session_id, run_id),
|
|
638
639
|
UNIQUE KEY uq_wfinbox_seq (seq),
|
|
@@ -9,8 +9,8 @@ import { jsonColumnText } from "./sql-json-column.js";
|
|
|
9
9
|
import { incarnationFromCell } from "../session-incarnation.js";
|
|
10
10
|
const SESSION_EVENT_BY_TYPE_HINT = "/*+ USE_INDEX(session_event, idx_session_event_type) */";
|
|
11
11
|
export const SESSION_EVENT_LATEST_BY_TYPE_SQL = {
|
|
12
|
-
floor: `SELECT ${SESSION_EVENT_BY_TYPE_HINT} ${jsonColumnText("
|
|
13
|
-
epochAnchor: `SELECT ${SESSION_EVENT_BY_TYPE_HINT} seq, ${jsonColumnText("
|
|
12
|
+
floor: `SELECT ${SESSION_EVENT_BY_TYPE_HINT} ${jsonColumnText("mysql", "payload")} FROM session_event WHERE session_id = ? AND type = 'compaction' ORDER BY seq DESC LIMIT 1`,
|
|
13
|
+
epochAnchor: `SELECT ${SESSION_EVENT_BY_TYPE_HINT} seq, ${jsonColumnText("mysql", "payload")} FROM session_event WHERE session_id = ? AND seq < ? AND type IN ('prompt_epoch','compaction') ORDER BY seq DESC LIMIT 100`,
|
|
14
14
|
};
|
|
15
15
|
const isDupKey = isMysqlDupKeyError;
|
|
16
16
|
export class TiDBSessionStorage extends BaseSessionStorage {
|
|
@@ -35,7 +35,7 @@ export class TiDBSessionStorage extends BaseSessionStorage {
|
|
|
35
35
|
if (!meta)
|
|
36
36
|
return null;
|
|
37
37
|
const { floorEntryId, floorSeq } = await TiDBSessionStorage.computeFloor(pool, sessionId);
|
|
38
|
-
const [eventRows] = await pool.query(`SELECT seq, ${jsonColumnText("
|
|
38
|
+
const [eventRows] = await pool.query(`SELECT seq, ${jsonColumnText("mysql", "payload")} FROM session_event WHERE session_id = ? AND seq >= ? ORDER BY seq ASC`, [sessionId, floorSeq]);
|
|
39
39
|
const entries = eventRows.map((r) => decodeSessionEventPayload(r.payload, sessionId, r.seq));
|
|
40
40
|
const placement = placementFromRow(meta);
|
|
41
41
|
const metadata = { id: sessionId, createdAt: toIso(meta.created_at), incarnation: incarnationFromCell(sessionId, meta.incarnation), ...(placement !== undefined ? { placement } : {}) };
|
|
@@ -58,7 +58,7 @@ export class TiDBSessionStorage extends BaseSessionStorage {
|
|
|
58
58
|
const inMem = await super.getEntry(id);
|
|
59
59
|
if (inMem)
|
|
60
60
|
return inMem;
|
|
61
|
-
const [rows] = await this.pool.query(`SELECT ${jsonColumnText("
|
|
61
|
+
const [rows] = await this.pool.query(`SELECT ${jsonColumnText("mysql", "payload")} FROM session_event WHERE session_id = ? AND entry_id = ?`, [this.sessionId, id]);
|
|
62
62
|
if (rows[0] === undefined)
|
|
63
63
|
return undefined;
|
|
64
64
|
return decodeSessionEventPayload(rows[0].payload, this.sessionId, id);
|
|
@@ -28,13 +28,16 @@ export declare class TiDBSessionStore implements SessionStore {
|
|
|
28
28
|
* `retention-store-sql.ts` 的 {@link MANAGED_RETENTION}。 */
|
|
29
29
|
readonly retention: RetentionDeclaration;
|
|
30
30
|
/** [ref] C18(core 5.48.0 [ref]):placement **声明**。六条义务的实装点逐条见
|
|
31
|
-
* {@link
|
|
31
|
+
* {@link SESSION_PLACEMENTS} 顶注与本类的 acquire / listSessions / release / listPlaced /
|
|
32
32
|
* placementOf 各处的 `[ref]` 注。 */
|
|
33
33
|
readonly placements: {
|
|
34
34
|
readonly subagent: {
|
|
35
35
|
readonly durability: "durable";
|
|
36
36
|
};
|
|
37
37
|
};
|
|
38
|
+
/** core `SessionStore.durability`:未 placed 的会话活过进程重启(会话史落在 `session_meta` + `session_event` 两张真表,`acquire(id,{requireExisting:true})` 从事件日志重放)。
|
|
39
|
+
* 与 {@link placements} 的分区耐久是同一只常量({@link SESSION_DURABILITY}),Pg 孪生同格 —— 不声明的话 core 对缺席读 `process_local`,接线清单对真持久部署说谎。 */
|
|
40
|
+
readonly durability: "durable";
|
|
38
41
|
/** In-flight acquisitions keyed by id, so concurrent acquire(sameId) in one process share one. */
|
|
39
42
|
private readonly pending;
|
|
40
43
|
/** 委派子代孤行那一行 warn 的去处(`delegated-session-owner.ts`;装配给部署的 logger,缺席 ⇒ 缺省 logger,不静默)。 */
|
|
@@ -12,7 +12,7 @@ import { writeSessionRowCellsSql } from "./session-row-sql.js";
|
|
|
12
12
|
import { contentForkRelation, fastForwardSharedContentDiverged } from "../session-sync-content.js";
|
|
13
13
|
import { CLAIM_OWNERLESS_PLACED_SQL, claimOwnerlessParams, createPlacedSessionRow } from "../delegated-session-owner.js";
|
|
14
14
|
import { createLogger } from "../observability/logger.js";
|
|
15
|
-
import { placementCapabilityOf, LIST_PLACED_BATCH, PLACEMENT_SELECT_COLUMNS, placedRowFromRow, placementFromRow, placementInsertValues,
|
|
15
|
+
import { placementCapabilityOf, LIST_PLACED_BATCH, PLACEMENT_SELECT_COLUMNS, placedRowFromRow, placementFromRow, placementInsertValues, SESSION_DURABILITY, SESSION_PLACEMENTS, } from "./session-placement.js";
|
|
16
16
|
import { classifySyncRelationshipByIds, SyncConflictError, StagedCommitOwnerChangedError, stagingIdFor, STAGING_ID_MARKER, STAGING_GC_GRACE_MS, } from "../session-sync-kernel.js";
|
|
17
17
|
import { assertFirstOwnerWritable, forkOwnerOf, isSessionOwnerValue } from "./session-ownership.js";
|
|
18
18
|
import { selectForkRows } from "@sema-agent/core";
|
|
@@ -25,7 +25,8 @@ const rowsOnConnection = (conn) => async (sql, values) => (await conn.query(sql,
|
|
|
25
25
|
export class TiDBSessionStore {
|
|
26
26
|
pool;
|
|
27
27
|
retention;
|
|
28
|
-
placements =
|
|
28
|
+
placements = SESSION_PLACEMENTS;
|
|
29
|
+
durability = SESSION_DURABILITY;
|
|
29
30
|
pending = new Map();
|
|
30
31
|
log;
|
|
31
32
|
executionPlacement;
|
|
@@ -89,7 +90,7 @@ export class TiDBSessionStore {
|
|
|
89
90
|
}, this.log);
|
|
90
91
|
}
|
|
91
92
|
async claimOwnerless(sessionId, incarnation, owner) {
|
|
92
|
-
const [res] = await this.pool.query(CLAIM_OWNERLESS_PLACED_SQL.
|
|
93
|
+
const [res] = await this.pool.query(CLAIM_OWNERLESS_PLACED_SQL.mysql, [...claimOwnerlessParams(sessionId, incarnation, owner)]);
|
|
93
94
|
return res.affectedRows > 0;
|
|
94
95
|
}
|
|
95
96
|
async sourceFaces(ids) {
|
|
@@ -256,7 +257,7 @@ export class TiDBSessionStore {
|
|
|
256
257
|
}
|
|
257
258
|
}
|
|
258
259
|
async readSessionWorkspace(sessionId) {
|
|
259
|
-
const [rows] = await this.pool.query(`SELECT ${jsonColumnText("
|
|
260
|
+
const [rows] = await this.pool.query(`SELECT ${jsonColumnText("mysql", "workspace")} FROM session_meta WHERE session_id = ?`, [sessionId]);
|
|
260
261
|
const row = rows[0];
|
|
261
262
|
return row === undefined ? undefined : decodeSessionWorkspaceCell(row.workspace, sessionId);
|
|
262
263
|
}
|
|
@@ -284,7 +285,7 @@ export class TiDBSessionStore {
|
|
|
284
285
|
if (storage === null)
|
|
285
286
|
return null;
|
|
286
287
|
const point = await forkPointOf(storage);
|
|
287
|
-
const [allRows] = await this.pool.query(`SELECT entry_id, parent_id, type, ${jsonColumnText("
|
|
288
|
+
const [allRows] = await this.pool.query(`SELECT entry_id, parent_id, type, ${jsonColumnText("mysql", "payload")}, ts FROM session_event WHERE session_id = ? ORDER BY seq ASC`, [sourceId]);
|
|
288
289
|
const { rows: eventRows, leafId: forkLeafId } = selectForkRows(allRows, leafId, point, FORK_LOG_ROW_SHAPE);
|
|
289
290
|
const now = new Date();
|
|
290
291
|
const conn = await this.pool.getConnection();
|
|
@@ -329,7 +330,7 @@ export class TiDBSessionStore {
|
|
|
329
330
|
const [metaRows] = await this.pool.query("SELECT 1 FROM session_meta WHERE session_id = ?", [sessionId]);
|
|
330
331
|
if (!metaRows[0])
|
|
331
332
|
return null;
|
|
332
|
-
const [eventRows] = await this.pool.query(`SELECT seq, entry_id, parent_id, type, ${jsonColumnText("
|
|
333
|
+
const [eventRows] = await this.pool.query(`SELECT seq, entry_id, parent_id, type, ${jsonColumnText("mysql", "payload")}, ts FROM session_event WHERE session_id = ? ORDER BY seq ASC`, [sessionId]);
|
|
333
334
|
return eventRows.map((r) => decodeSessionEventPayload(r.payload, sessionId, r.seq));
|
|
334
335
|
}
|
|
335
336
|
async listEntryIds(sessionId) {
|
|
@@ -348,7 +349,7 @@ export class TiDBSessionStore {
|
|
|
348
349
|
async function* gen() {
|
|
349
350
|
let cursor = opts?.afterSeq ?? -1;
|
|
350
351
|
for (;;) {
|
|
351
|
-
const [rows] = await pool.query(`SELECT seq, ${jsonColumnText("
|
|
352
|
+
const [rows] = await pool.query(`SELECT seq, ${jsonColumnText("mysql", "payload")} FROM session_event WHERE session_id = ? AND seq > ? ORDER BY seq ASC LIMIT ?`, [sessionId, cursor, batchSize]);
|
|
352
353
|
for (const r of rows)
|
|
353
354
|
yield decodeSessionEventPayload(r.payload, sessionId, r.seq);
|
|
354
355
|
if (rows.length < batchSize)
|
|
@@ -431,7 +432,7 @@ export class TiDBSessionStore {
|
|
|
431
432
|
throw new SessionError("storage", `import of session ${sessionId} failed`, new Error(`session ${sessionId} already exists — importEntries only creates a session (replaceEntries rewrites one); nothing was written`));
|
|
432
433
|
}
|
|
433
434
|
}
|
|
434
|
-
const claim = await lockRootAndReadClaim(rowsOnConnection(conn), "
|
|
435
|
+
const claim = await lockRootAndReadClaim(rowsOnConnection(conn), "mysql", sessionId);
|
|
435
436
|
if (claim.activeTaskId !== null)
|
|
436
437
|
throw new SessionActiveRunError(sessionId, claim.activeTaskId);
|
|
437
438
|
if (mode === "replace")
|
|
@@ -451,7 +452,7 @@ export class TiDBSessionStore {
|
|
|
451
452
|
}
|
|
452
453
|
}
|
|
453
454
|
async readStagedEntries(stagingId) {
|
|
454
|
-
const [rows] = await this.pool.query(`SELECT seq, ${jsonColumnText("
|
|
455
|
+
const [rows] = await this.pool.query(`SELECT seq, ${jsonColumnText("mysql", "payload")} FROM session_event WHERE session_id = ? ORDER BY seq ASC`, [stagingId]);
|
|
455
456
|
return rows.map((r) => decodeSessionEventPayload(r.payload, stagingId, r.seq));
|
|
456
457
|
}
|
|
457
458
|
async sweepStagingSessions() {
|
|
@@ -470,7 +471,7 @@ export class TiDBSessionStore {
|
|
|
470
471
|
const conn = await this.pool.getConnection();
|
|
471
472
|
try {
|
|
472
473
|
await conn.beginTransaction();
|
|
473
|
-
const claim = await lockRootAndReadClaim(rowsOnConnection(conn), "
|
|
474
|
+
const claim = await lockRootAndReadClaim(rowsOnConnection(conn), "mysql", sessionId);
|
|
474
475
|
if (claim.activeTaskId !== null) {
|
|
475
476
|
await conn.rollback();
|
|
476
477
|
throw new SessionActiveRunError(sessionId, claim.activeTaskId);
|
|
@@ -553,7 +554,7 @@ class TiDBStagingHandle {
|
|
|
553
554
|
throw new StagedCommitOwnerChangedError(this.realSessionId);
|
|
554
555
|
}
|
|
555
556
|
}
|
|
556
|
-
const claim = await lockRootAndReadClaim(rowsOnConnection(conn), "
|
|
557
|
+
const claim = await lockRootAndReadClaim(rowsOnConnection(conn), "mysql", this.realSessionId);
|
|
557
558
|
if (claim.activeTaskId !== null) {
|
|
558
559
|
await conn.rollback();
|
|
559
560
|
throw new SessionActiveRunError(this.realSessionId, claim.activeTaskId);
|
|
@@ -573,8 +574,8 @@ class TiDBStagingHandle {
|
|
|
573
574
|
throw new SyncConflictError(this.realSessionId, rel);
|
|
574
575
|
}
|
|
575
576
|
if (rel.relation === "fast_forward" && opts.resolution !== "overwrite-dst" && dstIds !== null && dstIds.length > 0) {
|
|
576
|
-
const [dstFull] = await conn.query(`SELECT seq, ${jsonColumnText("
|
|
577
|
-
const [stagedFull] = await conn.query(`SELECT entry_id, ${jsonColumnText("
|
|
577
|
+
const [dstFull] = await conn.query(`SELECT seq, ${jsonColumnText("mysql", "payload")} FROM session_event WHERE session_id = ? ORDER BY seq ASC FOR UPDATE`, [this.realSessionId]);
|
|
578
|
+
const [stagedFull] = await conn.query(`SELECT entry_id, ${jsonColumnText("mysql", "payload")} FROM session_event WHERE session_id = ? ORDER BY seq ASC FOR UPDATE`, [this.stagingId]);
|
|
578
579
|
const dstSet = new Set(dstIds);
|
|
579
580
|
const dstEntries = dstFull.map((r) => decodeSessionEventPayload(r.payload, this.realSessionId, r.seq));
|
|
580
581
|
const stagedShared = stagedFull
|
|
@@ -588,13 +589,13 @@ class TiDBStagingHandle {
|
|
|
588
589
|
}
|
|
589
590
|
await conn.query("DELETE FROM session_event WHERE session_id = ?", [this.realSessionId]);
|
|
590
591
|
await conn.query("UPDATE session_event SET session_id = ? WHERE session_id = ?", [this.realSessionId, this.stagingId]);
|
|
591
|
-
const [lastRow] = await conn.query(`SELECT ${jsonColumnText("
|
|
592
|
+
const [lastRow] = await conn.query(`SELECT ${jsonColumnText("mysql", "payload")} FROM session_event WHERE session_id = ? ORDER BY seq DESC LIMIT 1 FOR UPDATE`, [this.realSessionId]);
|
|
592
593
|
let leafId = null;
|
|
593
594
|
if (lastRow[0])
|
|
594
595
|
leafId = leafIdAfterEntry(decodeSessionEventPayload(lastRow[0].payload, this.realSessionId, "last staged row"));
|
|
595
596
|
const [settle] = await conn.query(`UPDATE session_meta SET owner = ?, updated_at = ?, leaf_id = ?, leaf_seq = ?, ${MIRROR_ON_COMMIT_SET} WHERE session_id = ? AND ${MIRROR_ON_COMMIT_GUARD}`, [owner, now, leafId, srcIds.length, this.realSessionId]);
|
|
596
597
|
if (settle.affectedRows !== 1) {
|
|
597
|
-
const locked = readPlacementRowStatement("
|
|
598
|
+
const locked = readPlacementRowStatement("mysql", this.realSessionId, { lock: true });
|
|
598
599
|
const [lockedRows] = await conn.query(locked.text, [...locked.values]);
|
|
599
600
|
const cell = lockedRows[0] === undefined ? undefined : placementCellFromRow(this.realSessionId, lockedRows[0]);
|
|
600
601
|
await conn.rollback();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ToolResultProvenance, ToolResultStore, ToolResultSlice, ToolResultDeletionReport } from "@sema-agent/core";
|
|
2
2
|
import type { Pool as MySqlPool } from "mysql2/promise";
|
|
3
3
|
import type { Pool as PgPool, PoolClient as PgPoolClient } from "pg";
|
|
4
|
-
import { type SqlDriver } from "./sql-driver.js";
|
|
4
|
+
import { type SqlDriver, type SqlDialect } from "./sql-driver.js";
|
|
5
5
|
import type { RetentionDeclaration } from "@sema-agent/core";
|
|
6
6
|
import { type IndexSpec } from "./ensure-index.js";
|
|
7
7
|
/** PG schema for the tool_result table — the PG translation of tidb-pool.ts's tool_result DDL
|
|
@@ -27,7 +27,7 @@ export declare function ensureSchema(pool: PgPool | PgPoolClient): Promise<void>
|
|
|
27
27
|
*/
|
|
28
28
|
export declare function assertToolResultProvenanceSchema(query: (sql: string) => Promise<{
|
|
29
29
|
rows: Record<string, unknown>[];
|
|
30
|
-
}>, dialect:
|
|
30
|
+
}>, dialect: SqlDialect): Promise<void>;
|
|
31
31
|
/** Dual-dialect durable ToolResultStore. See the file header for the dialect-delta ledger. */
|
|
32
32
|
export declare class SqlToolResultStore implements ToolResultStore {
|
|
33
33
|
protected readonly db: SqlDriver;
|
|
@@ -24,7 +24,7 @@ export async function ensureSchema(pool) {
|
|
|
24
24
|
await ensureIndexes((t, p) => pool.query(t, p), "pg", TOOL_RESULT_INDEXES);
|
|
25
25
|
}
|
|
26
26
|
export async function assertToolResultProvenanceSchema(query, dialect) {
|
|
27
|
-
const widthRow = await query(dialect === "
|
|
27
|
+
const widthRow = await query(dialect === "mysql"
|
|
28
28
|
? "SELECT CHARACTER_MAXIMUM_LENGTH AS len FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'tool_result' AND column_name = 'ref'"
|
|
29
29
|
: "SELECT character_maximum_length AS len FROM information_schema.columns WHERE table_schema = current_schema() AND table_name = 'tool_result' AND column_name = 'ref'").catch(() => ({ rows: [] }));
|
|
30
30
|
const width = Number(widthRow.rows[0]?.len ?? NaN);
|
|
@@ -62,8 +62,8 @@ export class SqlToolResultStore {
|
|
|
62
62
|
this.db = db;
|
|
63
63
|
this.retention = opts.retention ?? UNMANAGED_RETENTION;
|
|
64
64
|
}
|
|
65
|
-
q(
|
|
66
|
-
return this.db.dialect === "
|
|
65
|
+
q(mysql, pg) {
|
|
66
|
+
return this.db.dialect === "mysql" ? mysql : pg;
|
|
67
67
|
}
|
|
68
68
|
isUnsafeRef(ref) {
|
|
69
69
|
try {
|
|
@@ -15,8 +15,8 @@ export class SqlWorkflowJournalStore {
|
|
|
15
15
|
this.db = db;
|
|
16
16
|
this.resumeClaimTtlMs = opts?.resumeClaimTtlMs ?? DEFAULT_RESUME_CLAIM_TTL_MS;
|
|
17
17
|
}
|
|
18
|
-
q(
|
|
19
|
-
return this.db.dialect === "
|
|
18
|
+
q(mysql, pg) {
|
|
19
|
+
return this.db.dialect === "mysql" ? mysql : pg;
|
|
20
20
|
}
|
|
21
21
|
async append(runId, scope, entry) {
|
|
22
22
|
assertJournalEntryFits(entry);
|
|
@@ -35,7 +35,7 @@ export class SqlWorkflowJournalStore {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
async load(runId, scope) {
|
|
38
|
-
const { rows } = await this.db.query(this.q(`SELECT call_key, ${jsonColumnText("
|
|
38
|
+
const { rows } = await this.db.query(this.q(`SELECT call_key, ${jsonColumnText("mysql", "result")} FROM workflow_journal JOIN workflow_journal_owner USING (run_id, incarnation) WHERE run_id = ? AND scope = ? ORDER BY ordinal ASC`, `SELECT call_key, ${jsonColumnText("pg", "result")} FROM workflow_journal JOIN workflow_journal_owner USING (run_id, incarnation) WHERE run_id = $1 AND scope = $2 ORDER BY ordinal ASC`), [runId, scope]);
|
|
39
39
|
return rows.map((r) => {
|
|
40
40
|
const callKey = String(r.call_key);
|
|
41
41
|
return journalEntryOfCell(runId, callKey, r.result, `workflow_journal.result for run ${runId} entry ${callKey}`);
|
|
@@ -69,10 +69,10 @@ export class SqlWorkflowJournalStore {
|
|
|
69
69
|
return row !== undefined && row.ordinal === ordinal && row.resultJson !== null ? row.resultJson : undefined;
|
|
70
70
|
}
|
|
71
71
|
async readRows(runId, scope, from, limit, inlineBytes) {
|
|
72
|
-
const params = this.db.dialect === "
|
|
72
|
+
const params = this.db.dialect === "mysql"
|
|
73
73
|
? [inlineBytes, runId, scope, from, limit]
|
|
74
74
|
: [runId, scope, inlineBytes, from, limit];
|
|
75
|
-
const { rows } = await this.db.query(this.q(`SELECT ordinal, call_key, CASE WHEN LENGTH(result) > ? THEN NULL ELSE ${jsonColumnTextExpr("
|
|
75
|
+
const { rows } = await this.db.query(this.q(`SELECT ordinal, call_key, CASE WHEN LENGTH(result) > ? THEN NULL ELSE ${jsonColumnTextExpr("mysql", "result")} END AS result_json, LENGTH(result) AS result_bytes FROM workflow_journal JOIN workflow_journal_owner USING (run_id, incarnation) WHERE run_id = ? AND scope = ? AND ordinal >= ? ORDER BY ordinal ASC LIMIT ?`, `SELECT ordinal, call_key, CASE WHEN OCTET_LENGTH(result) > $3 THEN NULL ELSE ${jsonColumnTextExpr("pg", "result")} END AS result_json, OCTET_LENGTH(result) AS result_bytes FROM workflow_journal JOIN workflow_journal_owner USING (run_id, incarnation) WHERE run_id = $1 AND scope = $2 AND ordinal >= $4 ORDER BY ordinal ASC LIMIT $5`), params);
|
|
76
76
|
return rows.map((r) => ({ ordinal: Number(r.ordinal), callKey: String(r.call_key), resultJson: r.result_json === null ? null : String(r.result_json), resultBytes: Number(r.result_bytes) }));
|
|
77
77
|
}
|
|
78
78
|
async deleteByRun(runId) {
|
|
@@ -57,8 +57,8 @@ export class SqlWorkflowRunStore {
|
|
|
57
57
|
this.db = db;
|
|
58
58
|
this.onWarn = onWarn;
|
|
59
59
|
}
|
|
60
|
-
q(
|
|
61
|
-
return this.db.dialect === "
|
|
60
|
+
q(mysql, pg) {
|
|
61
|
+
return this.db.dialect === "mysql" ? mysql : pg;
|
|
62
62
|
}
|
|
63
63
|
async put(id, run) {
|
|
64
64
|
const stored = { ...withRedactedError(run), id, rev: run.rev ?? 0 };
|
|
@@ -73,7 +73,7 @@ export class SqlWorkflowRunStore {
|
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
async get(id) {
|
|
76
|
-
const { rows } = await this.db.query(this.q(`SELECT ${jsonColumnText("
|
|
76
|
+
const { rows } = await this.db.query(this.q(`SELECT ${jsonColumnText("mysql", "run")}, rev FROM workflow_run WHERE id = ?`, `SELECT ${jsonColumnText("pg", "run")}, rev FROM workflow_run WHERE id = $1`), [id]);
|
|
77
77
|
const r = rows[0];
|
|
78
78
|
if (!r)
|
|
79
79
|
return null;
|
|
@@ -100,7 +100,7 @@ export class SqlWorkflowRunStore {
|
|
|
100
100
|
const params = [scope];
|
|
101
101
|
let where;
|
|
102
102
|
let limit = "";
|
|
103
|
-
if (this.db.dialect === "
|
|
103
|
+
if (this.db.dialect === "mysql") {
|
|
104
104
|
where = "scope = ?";
|
|
105
105
|
if (opts?.status !== undefined) {
|
|
106
106
|
where += " AND status = ?";
|
|
@@ -160,9 +160,9 @@ export class SqlWorkflowRunStore {
|
|
|
160
160
|
}
|
|
161
161
|
if (doomed.length === 0)
|
|
162
162
|
return 0;
|
|
163
|
-
const res = await this.db.query(this.q(`DELETE FROM workflow_run WHERE scope = ? AND id IN (${doomed.map(() => "?").join(",")})`, "DELETE FROM workflow_run WHERE scope = $1 AND id = ANY($2::text[])"), this.db.dialect === "
|
|
164
|
-
await this.db.query(this.q(`DELETE FROM workflow_agent_session WHERE scope = ? AND run_id IN (${doomed.map(() => "?").join(",")})`, "DELETE FROM workflow_agent_session WHERE scope = $1 AND run_id = ANY($2::text[])"), this.db.dialect === "
|
|
165
|
-
await this.db.query(this.q(`DELETE FROM workflow_park_decision WHERE run_id IN (${doomed.map(() => "?").join(",")})`, "DELETE FROM workflow_park_decision WHERE run_id = ANY($1::text[])"), this.db.dialect === "
|
|
163
|
+
const res = await this.db.query(this.q(`DELETE FROM workflow_run WHERE scope = ? AND id IN (${doomed.map(() => "?").join(",")})`, "DELETE FROM workflow_run WHERE scope = $1 AND id = ANY($2::text[])"), this.db.dialect === "mysql" ? [scope, ...doomed] : [scope, doomed]);
|
|
164
|
+
await this.db.query(this.q(`DELETE FROM workflow_agent_session WHERE scope = ? AND run_id IN (${doomed.map(() => "?").join(",")})`, "DELETE FROM workflow_agent_session WHERE scope = $1 AND run_id = ANY($2::text[])"), this.db.dialect === "mysql" ? [scope, ...doomed] : [scope, doomed]);
|
|
165
|
+
await this.db.query(this.q(`DELETE FROM workflow_park_decision WHERE run_id IN (${doomed.map(() => "?").join(",")})`, "DELETE FROM workflow_park_decision WHERE run_id = ANY($1::text[])"), this.db.dialect === "mysql" ? [...doomed] : [doomed]);
|
|
166
166
|
return res.affected;
|
|
167
167
|
}
|
|
168
168
|
}
|
|
@@ -175,8 +175,8 @@ export class SqlWorkflowCompletionInbox {
|
|
|
175
175
|
this.db = db;
|
|
176
176
|
this.onWarn = onWarn;
|
|
177
177
|
}
|
|
178
|
-
q(
|
|
179
|
-
return this.db.dialect === "
|
|
178
|
+
q(mysql, pg) {
|
|
179
|
+
return this.db.dialect === "mysql" ? mysql : pg;
|
|
180
180
|
}
|
|
181
181
|
async sweepFences(now) {
|
|
182
182
|
await this.db.query(this.q("DELETE FROM workflow_inbox_fence WHERE until_ms < ?", "DELETE FROM workflow_inbox_fence WHERE until_ms < $1"), [now]);
|
|
@@ -213,7 +213,7 @@ export class SqlWorkflowCompletionInbox {
|
|
|
213
213
|
}
|
|
214
214
|
const over = await this.db.query(this.q("SELECT seq, run_id FROM workflow_completion_inbox WHERE session_id = ? ORDER BY seq DESC LIMIT 100000 OFFSET ?", "SELECT seq, run_id FROM workflow_completion_inbox WHERE session_id = $1 ORDER BY seq DESC OFFSET $2"), [entry.sessionId, MAX_PENDING_PER_SESSION]);
|
|
215
215
|
if (over.rows.length > 0) {
|
|
216
|
-
await this.db.query(this.q(`DELETE FROM workflow_completion_inbox WHERE session_id = ? AND seq IN (${over.rows.map(() => "?").join(",")})`, "DELETE FROM workflow_completion_inbox WHERE session_id = $1 AND seq = ANY($2::bigint[])"), this.db.dialect === "
|
|
216
|
+
await this.db.query(this.q(`DELETE FROM workflow_completion_inbox WHERE session_id = ? AND seq IN (${over.rows.map(() => "?").join(",")})`, "DELETE FROM workflow_completion_inbox WHERE session_id = $1 AND seq = ANY($2::bigint[])"), this.db.dialect === "mysql" ? [entry.sessionId, ...over.rows.map((r) => r.seq)] : [entry.sessionId, over.rows.map((r) => r.seq)]);
|
|
217
217
|
for (const r of over.rows)
|
|
218
218
|
this.onWarn?.("workflow_completion_inbox_overflow", { sessionId: entry.sessionId, droppedRunId: String(r.run_id) });
|
|
219
219
|
}
|
|
@@ -243,7 +243,7 @@ export class SqlWorkflowCompletionInbox {
|
|
|
243
243
|
await this.sweepFences(now);
|
|
244
244
|
await this.db.query(this.q("INSERT INTO workflow_inbox_fence (session_id, kind, run_id, owner, owner_known, until_ms) VALUES (?,?,?,?,?,?) " +
|
|
245
245
|
"ON DUPLICATE KEY UPDATE owner = VALUES(owner), owner_known = VALUES(owner_known), until_ms = VALUES(until_ms)", "INSERT INTO workflow_inbox_fence (session_id, kind, run_id, owner, owner_known, until_ms) VALUES ($1,$2,'',$3,$4,$5) " +
|
|
246
|
-
"ON CONFLICT (session_id, kind, run_id) DO UPDATE SET owner = EXCLUDED.owner, owner_known = EXCLUDED.owner_known, until_ms = EXCLUDED.until_ms"), this.db.dialect === "
|
|
246
|
+
"ON CONFLICT (session_id, kind, run_id) DO UPDATE SET owner = EXCLUDED.owner, owner_known = EXCLUDED.owner_known, until_ms = EXCLUDED.until_ms"), this.db.dialect === "mysql"
|
|
247
247
|
? [sessionId, KIND_PURGE, "", purgedOwner ?? null, purgedOwner !== undefined ? 1 : 0, now + PURGE_FENCE_MS]
|
|
248
248
|
: [sessionId, KIND_PURGE, purgedOwner ?? null, purgedOwner !== undefined ? 1 : 0, now + PURGE_FENCE_MS]);
|
|
249
249
|
await this.db.query(this.q("DELETE FROM workflow_completion_inbox WHERE session_id = ?", "DELETE FROM workflow_completion_inbox WHERE session_id = $1"), [sessionId]);
|
|
@@ -263,8 +263,8 @@ export class SqlWorkflowNotifyJournalStore {
|
|
|
263
263
|
constructor(db) {
|
|
264
264
|
this.db = db;
|
|
265
265
|
}
|
|
266
|
-
q(
|
|
267
|
-
return this.db.dialect === "
|
|
266
|
+
q(mysql, pg) {
|
|
267
|
+
return this.db.dialect === "mysql" ? mysql : pg;
|
|
268
268
|
}
|
|
269
269
|
async record(input) {
|
|
270
270
|
await this.db.query(this.q("INSERT IGNORE INTO workflow_notify_journal (run_id, scope, acked, source_task_id, principal, created_at_ms) VALUES (?,?,0,?,?,?)", "INSERT INTO workflow_notify_journal (run_id, scope, acked, source_task_id, principal, created_at_ms) VALUES ($1,$2,0,$3,$4,$5) ON CONFLICT (run_id) DO NOTHING"), [input.runId, input.scope, input.sourceTaskId ?? null, input.principal ?? null, input.createdAt]);
|
|
@@ -308,8 +308,8 @@ export class SqlWorkflowAgentSessionIndex {
|
|
|
308
308
|
constructor(db) {
|
|
309
309
|
this.db = db;
|
|
310
310
|
}
|
|
311
|
-
q(
|
|
312
|
-
return this.db.dialect === "
|
|
311
|
+
q(mysql, pg) {
|
|
312
|
+
return this.db.dialect === "mysql" ? mysql : pg;
|
|
313
313
|
}
|
|
314
314
|
async ensurePointers(_runId, rows) {
|
|
315
315
|
for (const r of rows) {
|
|
@@ -335,8 +335,8 @@ export class SqlWorkflowParkDecisionStore {
|
|
|
335
335
|
constructor(claims) {
|
|
336
336
|
this.claims = claims;
|
|
337
337
|
}
|
|
338
|
-
q(
|
|
339
|
-
return this.claims.db.dialect === "
|
|
338
|
+
q(mysql, pg) {
|
|
339
|
+
return this.claims.db.dialect === "mysql" ? mysql : pg;
|
|
340
340
|
}
|
|
341
341
|
async record(d) {
|
|
342
342
|
const fenced = await this.claims.whileHoldingClaim(d.hostSessionId, d.deliveredTaskId, async (tx) => {
|
|
@@ -347,12 +347,12 @@ export class SqlWorkflowParkDecisionStore {
|
|
|
347
347
|
return fenced.held;
|
|
348
348
|
}
|
|
349
349
|
async get(token) {
|
|
350
|
-
const { rows } = await this.claims.db.query(this.q(`SELECT token, run_id, host_session_id, ${jsonColumnText("
|
|
350
|
+
const { rows } = await this.claims.db.query(this.q(`SELECT token, run_id, host_session_id, ${jsonColumnText("mysql", "outcome")}, fingerprint, delivered_task_id, accepted_at_ms FROM workflow_park_decision WHERE token = ?`, `SELECT token, run_id, host_session_id, ${jsonColumnText("pg", "outcome")}, fingerprint, delivered_task_id, accepted_at_ms FROM workflow_park_decision WHERE token = $1`), [token]);
|
|
351
351
|
const r = rows[0];
|
|
352
352
|
return r ? rowToParkDecision(r) : null;
|
|
353
353
|
}
|
|
354
354
|
async listByHostSession(hostSessionId) {
|
|
355
|
-
const { rows } = await this.claims.db.query(this.q(`SELECT token, run_id, host_session_id, ${jsonColumnText("
|
|
355
|
+
const { rows } = await this.claims.db.query(this.q(`SELECT token, run_id, host_session_id, ${jsonColumnText("mysql", "outcome")}, fingerprint, delivered_task_id, accepted_at_ms FROM workflow_park_decision WHERE host_session_id = ?`, `SELECT token, run_id, host_session_id, ${jsonColumnText("pg", "outcome")}, fingerprint, delivered_task_id, accepted_at_ms FROM workflow_park_decision WHERE host_session_id = $1`), [hostSessionId]);
|
|
356
356
|
return rows.map(rowToParkDecision);
|
|
357
357
|
}
|
|
358
358
|
}
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
import type { Pool as MySqlPool } from "mysql2/promise";
|
|
35
35
|
import type { Pool as PgPool } from "pg";
|
|
36
36
|
import { type AlignedWindow } from "../observability/cost-quota.js";
|
|
37
|
+
import type { SqlDialect } from "./sql-driver.js";
|
|
37
38
|
export interface CounterTable {
|
|
38
39
|
/** Table name; must have columns (<keyCol>, window_bucket BIGINT, <valCol>, updated_at). */
|
|
39
40
|
table: string;
|
|
@@ -56,7 +57,6 @@ export type CounterDegradeHook = (info: CounterDegradeInfo) => void;
|
|
|
56
57
|
* flush round forever; the stalled watchdog can then only report, not recover). The rejection lands in
|
|
57
58
|
* the existing flush/refresh catch → the S9 streak telemetry counts it; the round ENDS and retries. */
|
|
58
59
|
export declare const DEFAULT_COUNTER_QUERY_TIMEOUT_MS = 30000;
|
|
59
|
-
type CounterDialect = "tidb" | "pg";
|
|
60
60
|
/** Dual-dialect write-behind aggregating counter. See the file header for the dialect-delta ledger. */
|
|
61
61
|
export declare class SqlWriteBehindCounter {
|
|
62
62
|
private readonly dialect;
|
|
@@ -73,7 +73,7 @@ export declare class SqlWriteBehindCounter {
|
|
|
73
73
|
private flushing;
|
|
74
74
|
private flushStartedAt;
|
|
75
75
|
private failStreak;
|
|
76
|
-
constructor(dialect:
|
|
76
|
+
constructor(dialect: SqlDialect, pool: MySqlPool | PgPool, t: CounterTable,
|
|
77
77
|
/** 🔴 不再 `readonly`([ref]):`costQuotaWindowSec` 热更新经 {@link setWindowMs} 换代,语义见那里。 */
|
|
78
78
|
windowMs: number, now?: () => number, onDegraded?: CounterDegradeHook | undefined, // S9: observability tap — never affects counting
|
|
79
79
|
queryTimeoutMs?: number);
|
|
@@ -135,5 +135,4 @@ export declare class WriteBehindCounter extends SqlWriteBehindCounter {
|
|
|
135
135
|
export declare class PgWriteBehindCounter extends SqlWriteBehindCounter {
|
|
136
136
|
constructor(pool: PgPool, t: CounterTable, windowMs: number, now?: () => number, onDegraded?: CounterDegradeHook, queryTimeoutMs?: number);
|
|
137
137
|
}
|
|
138
|
-
export {};
|
|
139
138
|
//# sourceMappingURL=write-behind-counter.d.ts.map
|
|
@@ -25,7 +25,7 @@ export class SqlWriteBehindCounter {
|
|
|
25
25
|
this.queryTimeoutMs = queryTimeoutMs;
|
|
26
26
|
}
|
|
27
27
|
async exec(sql, params) {
|
|
28
|
-
if (this.dialect === "
|
|
28
|
+
if (this.dialect === "mysql") {
|
|
29
29
|
const [r] = (await this.pool.query({ sql, timeout: this.queryTimeoutMs }, params));
|
|
30
30
|
if (Array.isArray(r))
|
|
31
31
|
return { rows: r, affected: 0 };
|
|
@@ -92,7 +92,7 @@ export class SqlWriteBehindCounter {
|
|
|
92
92
|
}
|
|
93
93
|
async flushOnce() {
|
|
94
94
|
const { table, keyCol, valCol } = this.t;
|
|
95
|
-
const sql = this.dialect === "
|
|
95
|
+
const sql = this.dialect === "mysql"
|
|
96
96
|
? `INSERT INTO ${table} (${keyCol}, window_bucket, ${valCol}, updated_at) VALUES (?,?,?,?) ` +
|
|
97
97
|
`ON DUPLICATE KEY UPDATE ${valCol} = ${valCol} + VALUES(${valCol}), updated_at = VALUES(updated_at)`
|
|
98
98
|
: `INSERT INTO ${table} (${keyCol}, window_bucket, ${valCol}, updated_at) VALUES ($1,$2,$3,$4) ` +
|
|
@@ -129,7 +129,7 @@ export class SqlWriteBehindCounter {
|
|
|
129
129
|
const { table, keyCol, valCol } = this.t;
|
|
130
130
|
const b = this.bucket();
|
|
131
131
|
try {
|
|
132
|
-
const { rows } = await this.exec(this.dialect === "
|
|
132
|
+
const { rows } = await this.exec(this.dialect === "mysql"
|
|
133
133
|
? `SELECT ${keyCol}, ${valCol} FROM ${table} WHERE window_bucket = ?`
|
|
134
134
|
: `SELECT ${keyCol}, ${valCol} FROM ${table} WHERE window_bucket = $1`, [b]);
|
|
135
135
|
const next = new Map();
|
|
@@ -145,7 +145,7 @@ export class SqlWriteBehindCounter {
|
|
|
145
145
|
}
|
|
146
146
|
async reap() {
|
|
147
147
|
try {
|
|
148
|
-
const { affected } = await this.exec(this.dialect === "
|
|
148
|
+
const { affected } = await this.exec(this.dialect === "mysql"
|
|
149
149
|
? `DELETE FROM ${this.t.table} WHERE window_bucket < ?`
|
|
150
150
|
: `DELETE FROM ${this.t.table} WHERE window_bucket < $1`, [this.bucket()]);
|
|
151
151
|
this.bump("reap", false);
|
|
@@ -175,7 +175,7 @@ export class SqlWriteBehindCounter {
|
|
|
175
175
|
}
|
|
176
176
|
export class WriteBehindCounter extends SqlWriteBehindCounter {
|
|
177
177
|
constructor(pool, t, windowMs, now, onDegraded, queryTimeoutMs) {
|
|
178
|
-
super("
|
|
178
|
+
super("mysql", pool, t, windowMs, now, onDegraded, queryTimeoutMs);
|
|
179
179
|
}
|
|
180
180
|
}
|
|
181
181
|
export class PgWriteBehindCounter extends SqlWriteBehindCounter {
|