@sema-agent/server 7.144.0 → 7.146.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.
Files changed (305) hide show
  1. package/MIGRATION.md +621 -0
  2. package/README.md +3 -0
  3. package/README.zh-CN.md +1 -0
  4. package/USAGE.md +233 -54
  5. package/deploy/facts/CHANGES.json +25 -0
  6. package/deploy/facts/README.md +57 -0
  7. package/deploy/facts/lanes.json +54 -0
  8. package/deploy/facts/lanes.schema.json +57 -0
  9. package/deploy/facts/sandbox-rbac.json +113 -0
  10. package/deploy/facts/sandbox-rbac.schema.json +74 -0
  11. package/deploy/facts/sealed-key.json +9 -0
  12. package/deploy/facts/sealed-key.schema.json +52 -0
  13. package/deploy/sema-up/chart/templates/_helpers.tpl +19 -0
  14. package/deploy/sema-up/chart/templates/sandbox-rbac.yaml +47 -7
  15. package/deploy/sema-up/chart/templates/server-v4pro.yaml +4 -0
  16. package/deploy/sema-up/chart/templates/server.yaml +4 -0
  17. package/deploy/sema-up/chart/values.yaml +7 -0
  18. package/deploy/sema-up/stack/sema-stack-cluster.yaml +30 -14
  19. package/dist/adoption/import-limits.d.ts +6 -0
  20. package/dist/adoption/import-limits.js +7 -0
  21. package/dist/adoption/import.d.ts +62 -0
  22. package/dist/adoption/import.js +107 -0
  23. package/dist/adoption/wire.d.ts +52 -0
  24. package/dist/adoption/wire.js +9 -0
  25. package/dist/approval-ask-machine.d.ts +2 -2
  26. package/dist/approval-card.d.ts +3 -12
  27. package/dist/approval-card.js +0 -4
  28. package/dist/approval-gate-currency.d.ts +1 -1
  29. package/dist/approval-gate-currency.js +1 -1
  30. package/dist/approval-reconciler.d.ts +1 -1
  31. package/dist/audit.d.ts +2 -21
  32. package/dist/audit.js +0 -9
  33. package/dist/boot/deployment-mods.d.ts +11 -1
  34. package/dist/boot/deployment-mods.js +15 -2
  35. package/dist/boot/device-lane.js +2 -0
  36. package/dist/boot/engine-lease.d.ts +193 -21
  37. package/dist/boot/engine-lease.js +146 -20
  38. package/dist/boot/execution-env.d.ts +4 -0
  39. package/dist/boot/execution-env.js +12 -0
  40. package/dist/boot/exit-boundary.d.ts +50 -0
  41. package/dist/boot/exit-boundary.js +32 -0
  42. package/dist/boot/exit-last.d.ts +20 -4
  43. package/dist/boot/exit-last.js +21 -4
  44. package/dist/boot/governance-seams.js +1 -0
  45. package/dist/boot/memory-consolidation.d.ts +29 -17
  46. package/dist/boot/memory-consolidation.js +26 -15
  47. package/dist/boot/reapers.d.ts +12 -4
  48. package/dist/boot/reapers.js +39 -15
  49. package/dist/boot/resolve-spec.d.ts +2 -0
  50. package/dist/boot/resolve-spec.js +38 -15
  51. package/dist/boot/runner-deps.js +1 -1
  52. package/dist/boot/session-faces.d.ts +1 -1
  53. package/dist/boot/session-faces.js +6 -4
  54. package/dist/boot/shutdown.js +27 -9
  55. package/dist/boot/stage-01-config.js +1 -1
  56. package/dist/boot/stage-03-store-backend.d.ts +1 -0
  57. package/dist/boot/stage-03-store-backend.js +2 -2
  58. package/dist/boot/stage-04-stores.d.ts +1 -0
  59. package/dist/boot/stage-05-execution-env.d.ts +3 -0
  60. package/dist/boot/stage-05-execution-env.js +3 -3
  61. package/dist/boot/stage-06-runners.d.ts +3 -0
  62. package/dist/boot/stage-06-runners.js +11 -10
  63. package/dist/boot/stage-07-capability-layer.d.ts +3 -0
  64. package/dist/boot/stage-07-capability-layer.js +7 -2
  65. package/dist/boot/stage-08-reapers.d.ts +3 -0
  66. package/dist/boot/stage-08-reapers.js +3 -3
  67. package/dist/boot/stage-09-leader.d.ts +4 -1
  68. package/dist/boot/stage-10-http-server.d.ts +4 -1
  69. package/dist/boot/stage-10-http-server.js +4 -3
  70. package/dist/boot/stores.d.ts +1 -0
  71. package/dist/boot/stores.js +35 -19
  72. package/dist/boot/workflow-orchestration.d.ts +1 -1
  73. package/dist/boot/workflow-orchestration.js +2 -1
  74. package/dist/capabilities/composite-members.d.ts +3 -1
  75. package/dist/capabilities/composite-members.js +3 -1
  76. package/dist/capabilities/scenarios.d.ts +2 -2
  77. package/dist/capability-facts.d.ts +18 -1
  78. package/dist/capability-facts.js +25 -7
  79. package/dist/checkpoint-ctx-seal-m28.d.ts +1 -1
  80. package/dist/config-catalog.js +13 -4
  81. package/dist/config-d-migration.d.ts +3 -2
  82. package/dist/config-provider.d.ts +2 -2
  83. package/dist/config-types.d.ts +43 -4
  84. package/dist/config.d.ts +6 -1
  85. package/dist/config.js +67 -11
  86. package/dist/deleted-session-ids.d.ts +19 -0
  87. package/dist/deleted-session-ids.js +26 -0
  88. package/dist/deploy-facts.d.ts +155 -0
  89. package/dist/deploy-facts.js +94 -0
  90. package/dist/device-ws-hub.d.ts +48 -3
  91. package/dist/device-ws-hub.js +48 -2
  92. package/dist/error-code-family.d.ts +35 -0
  93. package/dist/error-code-family.js +26 -0
  94. package/dist/fleet/drain-entry.d.ts +39 -3
  95. package/dist/fleet/drain-entry.js +6 -0
  96. package/dist/fleet/fleet-bus.d.ts +15 -4
  97. package/dist/fleet/fleet-bus.js +17 -3
  98. package/dist/hooks/branch-transcript.d.ts +1 -1
  99. package/dist/hooks/branch-transcript.js +1 -0
  100. package/dist/hooks/classic-stations.d.ts +25 -8
  101. package/dist/hooks/classic-stations.js +29 -3
  102. package/dist/hooks/hook-runner.d.ts +33 -16
  103. package/dist/hooks/hook-runner.js +166 -73
  104. package/dist/hooks/hook-source.d.ts +14 -2
  105. package/dist/hooks/hook-source.js +8 -0
  106. package/dist/http/active-run-conflict.d.ts +1 -1
  107. package/dist/http/active-run-conflict.js +1 -1
  108. package/dist/http/admission.js +13 -2
  109. package/dist/http/checkpoint-ctx.d.ts +60 -71
  110. package/dist/http/checkpoint-ctx.js +35 -40
  111. package/dist/http/dispatch.js +18 -2
  112. package/dist/http/durable-run-leg.d.ts +5 -0
  113. package/dist/http/durable-run-leg.js +8 -6
  114. package/dist/http/execution-context.d.ts +4 -0
  115. package/dist/http/execution-context.js +9 -0
  116. package/dist/http/health-self-report.d.ts +6 -2
  117. package/dist/http/health-self-report.js +3 -2
  118. package/dist/http/memory-compliance-failure-reply.d.ts +1 -1
  119. package/dist/http/memory-compliance-failure-reply.js +2 -15
  120. package/dist/http/memory-control-plane-corrupt-reply.d.ts +25 -0
  121. package/dist/http/memory-control-plane-corrupt-reply.js +19 -0
  122. package/dist/http/principal-gate.d.ts +35 -12
  123. package/dist/http/principal-gate.js +16 -12
  124. package/dist/http/request-guards.d.ts +1 -1
  125. package/dist/http/request-guards.js +5 -5
  126. package/dist/http/resume-legs.d.ts +22 -0
  127. package/dist/http/resume-legs.js +31 -20
  128. package/dist/http/route-ctx.d.ts +26 -10
  129. package/dist/http/route-table.js +2 -0
  130. package/dist/http/routes/adoption.d.ts +11 -0
  131. package/dist/http/routes/adoption.js +80 -6
  132. package/dist/http/routes/agents-roster.js +1 -0
  133. package/dist/http/routes/approvals-assistant.d.ts +20 -1
  134. package/dist/http/routes/approvals-assistant.js +29 -7
  135. package/dist/http/routes/background.js +1 -0
  136. package/dist/http/routes/capabilities.js +4 -1
  137. package/dist/http/routes/diagnostics.d.ts +9 -14
  138. package/dist/http/routes/diagnostics.js +10 -20
  139. package/dist/http/routes/engine.d.ts +31 -0
  140. package/dist/http/routes/engine.js +81 -0
  141. package/dist/http/routes/memory-bundle.js +3 -0
  142. package/dist/http/routes/memory-consolidation.js +3 -5
  143. package/dist/http/routes/memory-origin.d.ts +1 -1
  144. package/dist/http/routes/memory-origin.js +2 -4
  145. package/dist/http/routes/memory-policy.js +5 -1
  146. package/dist/http/routes/observability.js +3 -6
  147. package/dist/http/routes/rules.d.ts +1 -1
  148. package/dist/http/routes/rules.js +5 -2
  149. package/dist/http/routes/runs.js +7 -3
  150. package/dist/http/routes/session-sync.js +24 -25
  151. package/dist/http/routes/sessions-list.d.ts +1 -1
  152. package/dist/http/routes/sessions.js +4 -0
  153. package/dist/http/routes/tasks.js +35 -14
  154. package/dist/http/routes/trace-usage.js +1 -1
  155. package/dist/http/run-concurrency-cap.d.ts +86 -0
  156. package/dist/http/run-concurrency-cap.js +54 -0
  157. package/dist/http/run-meta.d.ts +14 -7
  158. package/dist/http/run-meta.js +5 -2
  159. package/dist/http/server.d.ts +27 -16
  160. package/dist/http/server.js +21 -3
  161. package/dist/http/stored-body-replay.d.ts +9 -6
  162. package/dist/http/stored-body-replay.js +19 -5
  163. package/dist/http/submit-ctx.d.ts +12 -0
  164. package/dist/http/submit-ctx.js +23 -0
  165. package/dist/http/wire-types.d.ts +8 -3
  166. package/dist/json-body-limit.d.ts +8 -0
  167. package/dist/json-body-limit.js +2 -0
  168. package/dist/leader/diffout.d.ts +1 -1
  169. package/dist/local-data-root.d.ts +2 -2
  170. package/dist/memory-operator-faces.d.ts +9 -4
  171. package/dist/memory-scope-stores.d.ts +9 -7
  172. package/dist/memory-scope-stores.js +3 -14
  173. package/dist/memory-scope.d.ts +36 -0
  174. package/dist/memory-scope.js +32 -1
  175. package/dist/net-address.d.ts +53 -0
  176. package/dist/net-address.js +111 -0
  177. package/dist/observability/fail-open.d.ts +28 -12
  178. package/dist/observability/fail-open.js +28 -12
  179. package/dist/orchestration/workflow-notify-journal.js +2 -3
  180. package/dist/org-delivery-gate.js +1 -1
  181. package/dist/peer-directory.d.ts +6 -12
  182. package/dist/peer-directory.js +5 -1
  183. package/dist/plugins/approval-ask-store-file.d.ts +16 -2
  184. package/dist/plugins/approval-ask-store-file.js +21 -1
  185. package/dist/plugins/approval-ask-store-memory.d.ts +8 -2
  186. package/dist/plugins/approval-ask-store-memory.js +11 -8
  187. package/dist/plugins/caching-session-store.d.ts +6 -1
  188. package/dist/plugins/caching-session-store.js +6 -0
  189. package/dist/plugins/checkpoint-store-face.d.ts +426 -0
  190. package/dist/plugins/checkpoint-store-face.js +152 -0
  191. package/dist/plugins/file-run-store.d.ts +13 -7
  192. package/dist/plugins/file-run-store.js +12 -13
  193. package/dist/plugins/fork-routing-session-store.d.ts +6 -2
  194. package/dist/plugins/fork-routing-session-store.js +2 -2
  195. package/dist/plugins/imported-layer-root-retirement.d.ts +10 -8
  196. package/dist/plugins/local-checkpoint-store.d.ts +16 -5
  197. package/dist/plugins/local-checkpoint-store.js +25 -6
  198. package/dist/plugins/local-session-store.d.ts +80 -21
  199. package/dist/plugins/local-session-store.js +79 -22
  200. package/dist/plugins/memory-engine-pg.d.ts +29 -6
  201. package/dist/plugins/memory-engine-pg.js +96 -214
  202. package/dist/plugins/memory-engine-sql-apply.d.ts +121 -0
  203. package/dist/plugins/memory-engine-sql-apply.js +358 -0
  204. package/dist/plugins/memory-engine-tidb.d.ts +35 -9
  205. package/dist/plugins/memory-engine-tidb.js +97 -227
  206. package/dist/plugins/memory-key-guards.d.ts +1 -1
  207. package/dist/plugins/memory-origin-law.d.ts +3 -3
  208. package/dist/plugins/memory-run-store.d.ts +2 -0
  209. package/dist/plugins/memory-run-store.js +6 -0
  210. package/dist/plugins/one-time-migrations.d.ts +32 -56
  211. package/dist/plugins/one-time-migrations.js +27 -119
  212. package/dist/plugins/permission-rule-store-file.d.ts +17 -3
  213. package/dist/plugins/permission-rule-store-file.js +8 -1
  214. package/dist/plugins/pg-pool.js +1 -1
  215. package/dist/plugins/pg-session-storage.d.ts +17 -4
  216. package/dist/plugins/pg-session-storage.js +8 -4
  217. package/dist/plugins/run-store-sql.d.ts +4 -0
  218. package/dist/plugins/run-store-sql.js +5 -2
  219. package/dist/plugins/schema-ensure-legs.js +2 -2
  220. package/dist/plugins/session-fork.d.ts +31 -9
  221. package/dist/plugins/session-fork.js +3 -2
  222. package/dist/plugins/session-placement.d.ts +4 -2
  223. package/dist/plugins/session-store.d.ts +1 -1
  224. package/dist/plugins/sql-json-column.d.ts +5 -1
  225. package/dist/plugins/store-backend.d.ts +11 -8
  226. package/dist/plugins/store-backend.js +8 -7
  227. package/dist/plugins/store-contracts.d.ts +1 -11
  228. package/dist/plugins/store-contracts.js +0 -9
  229. package/dist/plugins/store-sweep.d.ts +63 -0
  230. package/dist/plugins/store-sweep.js +48 -0
  231. package/dist/plugins/tidb-pool.js +1 -1
  232. package/dist/plugins/tidb-session-store.d.ts +16 -3
  233. package/dist/plugins/tidb-session-store.js +8 -4
  234. package/dist/prompt-screen.d.ts +18 -0
  235. package/dist/prompt-screen.js +5 -0
  236. package/dist/rules-consent.d.ts +56 -51
  237. package/dist/rules-consent.js +86 -14
  238. package/dist/run-acceptance.d.ts +40 -10
  239. package/dist/run-acceptance.js +38 -5
  240. package/dist/run-cancel-context.d.ts +4 -1
  241. package/dist/run-cancel-context.js +2 -1
  242. package/dist/runs.js +2 -2
  243. package/dist/sandbox-egress-policy.js +6 -11
  244. package/dist/sandbox-rbac-rules.d.ts +88 -0
  245. package/dist/sandbox-rbac-rules.js +80 -0
  246. package/dist/sealed-key-layout.d.ts +17 -0
  247. package/dist/sealed-key-layout.js +4 -0
  248. package/dist/sealed-key.js +5 -5
  249. package/dist/security.d.ts +48 -9
  250. package/dist/security.js +9 -2
  251. package/dist/session-agent.d.ts +39 -0
  252. package/dist/session-agent.js +16 -0
  253. package/dist/session-error-wire.d.ts +4 -4
  254. package/dist/session-notify-door.d.ts +5 -3
  255. package/dist/session-resident-background.d.ts +57 -0
  256. package/dist/session-resident-background.js +20 -0
  257. package/dist/session-sync-kernel.d.ts +53 -14
  258. package/dist/session-sync-kernel.js +70 -1
  259. package/dist/session-sync.d.ts +5 -3
  260. package/dist/session-workspace.d.ts +1 -0
  261. package/dist/session-workspace.js +1 -0
  262. package/dist/sighup-idle.d.ts +9 -7
  263. package/dist/sighup-idle.js +4 -5
  264. package/dist/spec-fields.d.ts +16 -0
  265. package/dist/spec-fields.js +7 -0
  266. package/dist/stored-request-env-credentials-m38.d.ts +3 -0
  267. package/dist/stored-request-env-credentials-m38.js +8 -0
  268. package/dist/stored-request-prompt-profile-m30.d.ts +1 -1
  269. package/dist/{plugins → stores-sql}/checkpoint-store-sql.d.ts +33 -429
  270. package/dist/{plugins → stores-sql}/checkpoint-store-sql.js +70 -209
  271. package/dist/{plugins → stores-sql}/mailbox-store-sql.d.ts +2 -2
  272. package/dist/{plugins → stores-sql}/mailbox-store-sql.js +4 -4
  273. package/dist/{plugins → stores-sql}/roster-store-sql.d.ts +2 -2
  274. package/dist/{plugins → stores-sql}/roster-store-sql.js +1 -1
  275. package/dist/{plugins → stores-sql}/tool-result-store-sql.d.ts +2 -2
  276. package/dist/{plugins → stores-sql}/tool-result-store-sql.js +6 -6
  277. package/dist/{plugins → stores-sql}/workflow-journal-store-sql.d.ts +7 -12
  278. package/dist/{plugins → stores-sql}/workflow-journal-store-sql.js +3 -8
  279. package/dist/task-settings.d.ts +59 -4
  280. package/dist/task-settings.js +50 -4
  281. package/dist/tool-approval.d.ts +2 -2
  282. package/dist/trace/core-keyset-guard.d.ts +8 -7
  283. package/dist/trace/engine-notice-wire.d.ts +1 -1
  284. package/dist/trace/engine-notice-wire.js +2 -0
  285. package/dist/trace/exit-seat.d.ts +6 -0
  286. package/dist/trace/exit-seat.js +1 -0
  287. package/dist/trace/model-segment.d.ts +3 -2
  288. package/dist/trace/model-segment.js +16 -8
  289. package/dist/trace/project.js +9 -0
  290. package/dist/trace/redact.d.ts +79 -4
  291. package/dist/trace/redact.js +523 -123
  292. package/dist/trace/self-minted-wire.d.ts +391 -1
  293. package/dist/trace/self-minted-wire.js +145 -0
  294. package/dist/trace/wire-projection-faces.d.ts +1 -1
  295. package/dist/trace/wire-projection-faces.js +1 -1
  296. package/dist/usage-analytics.d.ts +4 -0
  297. package/package.json +12 -4
  298. package/scripts/drain-check-local.mjs +8 -29
  299. package/scripts/drain-check.mysql.sql +3 -24
  300. package/scripts/drain-check.pg.sql +3 -24
  301. package/skills/update-config.md +1 -1
  302. package/wire-changes/server@7.145.0.json +146 -0
  303. package/wire-changes/server@7.146.0.json +3221 -0
  304. package/dist/approval-batch-census.d.ts +0 -27
  305. package/dist/approval-batch-census.js +0 -27
@@ -1,23 +1,18 @@
1
1
  import { parkedApprovalCard } from "../approval-content-kind.js";
2
2
  import { createHash } from "node:crypto";
3
- import { CHECKPOINT_FACET_SQL, CHECKPOINT_SWEEP_ORDER_SQL, CheckpointIndexRefusedError, judgeCheckpointIndexCells } from "./checkpoint-index-columns.js";
4
- import { CheckpointError, isGateKind, MAX_RULE_TEXT_CHARS, validatePendingSteer, appendPendingSteer, winnerFromOutcome, summarizeCheckpoint, checkpointRevOf, judgeCheckpointRow, CONTRACT_KIT_ENGINE_VERSION, ExecutionOutcomeConflictError, executionRecordDisposition, executionVerdict, } from "@sema-agent/core";
5
- import { redactDeep, redactSecrets } from "../trace/redact.js";
6
- import { MAX_RULE_OFFERS, MAX_RULE_OFFER_BATCH_MEMBERS, countKindlessBatchOffers, parkRowFacts, readRuleOfferList, skillCardFacts } from "../approval-card.js";
7
- import { assertJsonColumnWritable, createObjectColumnReader, decodeJsonColumn, decodeNullableJsonColumn, foldJsonColumn, isJsonColumnBodyProblem, jsonColumnText, jsonColumnTextExpr, jsonColumnTextSha256, readJsonArrayColumn, readJsonColumnTextSha256, readJsonObjectColumn, readNonNullJsonValueColumn, } from "./sql-json-column.js";
3
+ import { CHECKPOINT_FACET_SQL, CHECKPOINT_SWEEP_ORDER_SQL, CheckpointIndexRefusedError, judgeCheckpointIndexCells } from "../plugins/checkpoint-index-columns.js";
4
+ import { CheckpointError, validatePendingSteer, appendPendingSteer, winnerFromOutcome, summarizeCheckpoint, checkpointRevOf, judgeCheckpointRow, CONTRACT_KIT_ENGINE_VERSION, ExecutionOutcomeConflictError, executionRecordDisposition, executionVerdict, } from "@sema-agent/core";
5
+ import { parkRowFacts, skillCardFacts } from "../approval-card.js";
6
+ import { assertJsonColumnWritable, createObjectColumnReader, decodeJsonColumn, decodeNullableJsonColumn, foldJsonColumn, isJsonColumnBodyProblem, jsonColumnText, jsonColumnTextSha256, readJsonArrayColumn, readJsonColumnTextSha256, readNonNullJsonValueColumn, StoreCorruptError, } from "../plugins/sql-json-column.js";
8
7
  import { recordFailOpen } from "../observability/fail-open.js";
9
8
  import { durableRowIdentity, withoutCheckpointToken } from "../checkpoint-identity.js";
10
- import { mysqlDriver, pgDriver, dialectProtocolJsonEncoder } from "./sql-driver.js";
11
- import { isDupKeyError, isMissingColumnError, rowTooLargeOrSelf, StoreRowTooLargeError } from "./sql-errors.js";
12
- import { describeProbedTableDrift } from "./schema-drift-sentence.js";
13
- import { MANAGED_RETENTION, UNMANAGED_RETENTION } from "./retention-store-sql.js";
14
- import { approvalPayloadFingerprint } from "./approval-payload-fingerprint.js";
9
+ import { mysqlDriver, pgDriver, dialectProtocolJsonEncoder } from "../plugins/sql-driver.js";
10
+ import { isDupKeyError, isMissingColumnError, rowTooLargeOrSelf, StoreRowTooLargeError } from "../plugins/sql-errors.js";
11
+ import { describeProbedTableDrift } from "../plugins/schema-drift-sentence.js";
12
+ import { MANAGED_RETENTION, UNMANAGED_RETENTION } from "../plugins/retention-store-sql.js";
13
+ import { approvalPayloadFingerprint } from "../plugins/approval-payload-fingerprint.js";
14
+ import { approvalDecisionOfWinner, boundedRuleOffers, boundedToolInput, candidateIdentityOf, DECIDED_REPLAY_SCAN_CAP, queueRowGateKind, TERMINAL_BACKSTOP_MS, TERMINAL_GRACE_MS, UnreadableCheckpointRowError, } from "../plugins/checkpoint-store-face.js";
15
15
  const CTX_REWRITE_PAGE = 500;
16
- const KINDLESS_SCAN_PAGE = 200;
17
- export { approvalPayloadFingerprint } from "./approval-payload-fingerprint.js";
18
- const MAX_TOOL_INPUT_CHARS = 8192;
19
- export const TERMINAL_BACKSTOP_MS = Math.max(60_000, (Number.isFinite(Number(process.env.APPROVAL_TERMINAL_BACKSTOP_MS)) ? Number(process.env.APPROVAL_TERMINAL_BACKSTOP_MS) : 0) || 30 * 86_400_000);
20
- export const TERMINAL_GRACE_MS = 3_600_000;
21
16
  export function tokenFingerprint(token) {
22
17
  return "sha256:" + createHash("sha256").update(token).digest("hex").slice(0, 12);
23
18
  }
@@ -50,21 +45,6 @@ class StoredRowProjectionMemo {
50
45
  }
51
46
  const STORED_ROW_READ_BATCH = 100;
52
47
  const CHECKPOINT_SHA256_AS = "checkpoint_sha256";
53
- const GATE_KIND_IS_LIVE_RUN_PARK = {
54
- human: true,
55
- irreversible_ask: true,
56
- resource_limit: true,
57
- needs_review: true,
58
- plan_review: true,
59
- task_done: false,
60
- };
61
- export const LIVE_RUN_GATE_KINDS = Object.keys(GATE_KIND_IS_LIVE_RUN_PARK).filter((k) => GATE_KIND_IS_LIVE_RUN_PARK[k]);
62
- export const TERMINAL_PARK_GATE_KINDS = Object.keys(GATE_KIND_IS_LIVE_RUN_PARK).filter((k) => !GATE_KIND_IS_LIVE_RUN_PARK[k]);
63
- export function pendingRowPrecedes(a, b, pick) {
64
- if (pick === "oldest")
65
- return a.createdAt < b.createdAt || (a.createdAt === b.createdAt && a.token < b.token);
66
- return a.createdAt > b.createdAt || (a.createdAt === b.createdAt && a.token > b.token);
67
- }
68
48
  export const CHECKPOINT_ADDED_COLUMNS = [
69
49
  {
70
50
  column: "has_bidi_controls",
@@ -99,53 +79,6 @@ export async function assertCheckpointColumnSchema(query, dialect) {
99
79
  }
100
80
  }
101
81
  }
102
- const MAX_RULE_OFFER_SCAN = 32;
103
- function preboundBatchMembers(item) {
104
- if (typeof item !== "object" || item === null)
105
- return item;
106
- const candidate = item;
107
- if (candidate.kind !== "batch" || !Array.isArray(candidate.rules) || candidate.rules.length <= MAX_RULE_OFFER_BATCH_MEMBERS)
108
- return item;
109
- return { ...candidate, rules: candidate.rules.slice(0, MAX_RULE_OFFER_BATCH_MEMBERS) };
110
- }
111
- export function boundedReaderInput(raw) {
112
- return Array.isArray(raw) ? raw.slice(0, MAX_RULE_OFFER_SCAN).map(preboundBatchMembers) : raw;
113
- }
114
- export function boundedRuleOffers(raw, opts = {}) {
115
- const observe = opts.countRedactions ?? true;
116
- const scrub = (text) => redactSecrets(text, { observe }).slice(0, MAX_RULE_TEXT_CHARS);
117
- const read = readRuleOfferList(boundedReaderInput(raw));
118
- const out = [];
119
- for (const { offer } of read) {
120
- if (out.length >= MAX_RULE_OFFERS)
121
- break;
122
- switch (offer.kind) {
123
- case "single":
124
- out.push({ kind: "single", rule: scrub(offer.rule), match: offer.match, command: scrub(offer.command) });
125
- break;
126
- case "batch":
127
- out.push({
128
- kind: "batch",
129
- rules: offer.rules.slice(0, MAX_RULE_OFFER_BATCH_MEMBERS).map((r) => {
130
- switch (r.kind) {
131
- case "command":
132
- return { kind: "command", rule: scrub(r.rule), match: r.match, command: scrub(r.command), segment: scrub(r.segment) };
133
- case "directoryRead":
134
- return { kind: "directoryRead", rule: scrub(r.rule), directory: scrub(r.directory), segment: scrub(r.segment) };
135
- default:
136
- throw new Error(`unknown rule-offer batch member kind: ${JSON.stringify(r)}`);
137
- }
138
- }),
139
- uncoveredSegments: offer.uncoveredSegments,
140
- ...(offer.uncoveredDetail !== undefined ? { uncoveredDetail: offer.uncoveredDetail.map((d) => ({ segment: scrub(d.segment), reason: d.reason })) } : {}),
141
- });
142
- break;
143
- default:
144
- throw new Error(`unknown rule-offer kind: ${JSON.stringify(offer)}`);
145
- }
146
- }
147
- return out.length > 0 ? out : undefined;
148
- }
149
82
  const readCheckpointBlobBody = createObjectColumnReader();
150
83
  const readResumeOutcomeBody = createObjectColumnReader();
151
84
  const readGateOutcomeBody = createObjectColumnReader();
@@ -153,6 +86,22 @@ const readRiskDescriptorBody = createObjectColumnReader();
153
86
  function decodeCheckpointColumn(cell, where) {
154
87
  return decodeJsonColumn(cell, readCheckpointBlobBody, `checkpoint.checkpoint ${where}`);
155
88
  }
89
+ function verdictOfUnreadableBody(cell) {
90
+ return judgeCheckpointRow(cell);
91
+ }
92
+ const UNREADABLE_SUMMARY_MEMBERS = new Set(["token", "rowVerdict", "sessionId", "scope", "gateKind", "createdAt", "deadline"]);
93
+ function isUnreadableSummaryForm(summary) {
94
+ const names = UNREADABLE_SUMMARY_MEMBERS;
95
+ return summary.rowVerdict.kind !== "ok" && Object.keys(summary).every((member) => names.has(member));
96
+ }
97
+ function readCheckpointBodyOrRefuse(cell, where) {
98
+ try {
99
+ return refusing("a checkpoint nobody can resume", () => decodeCheckpointColumn(cell, where));
100
+ }
101
+ catch (e) {
102
+ throw e instanceof StoreCorruptError ? new UnreadableCheckpointRowError(e, verdictOfUnreadableBody(cell)) : e;
103
+ }
104
+ }
156
105
  function decodeOutcomeColumn(cell, where) {
157
106
  return decodeNullableJsonColumn(cell, readResumeOutcomeBody, `checkpoint.outcome ${where}`);
158
107
  }
@@ -225,80 +174,7 @@ function readCheckpointIdCell(cell) {
225
174
  return null;
226
175
  }
227
176
  }
228
- export function queueRowGateKind(kind) {
229
- if (isGateKind(kind))
230
- return kind;
231
- recordFailOpen("server.approvals.queue-row-gate-kind-missing", `gate_kind=${kind === null || kind === undefined ? "NULL" : redactSecrets(String(kind)).slice(0, 40)}`);
232
- return undefined;
233
- }
234
177
  const readPendingActionMemberBody = createObjectColumnReader();
235
- export function boundedToolInput(args) {
236
- if (args === undefined)
237
- return null;
238
- const redacted = redactDeep(args);
239
- const json = JSON.stringify(redacted);
240
- if (json === undefined)
241
- return null;
242
- if (json.length > MAX_TOOL_INPUT_CHARS)
243
- return { truncated: true, bytes: json.length };
244
- return redacted;
245
- }
246
- export const DECIDED_REPLAY_SCAN_CAP = 8;
247
- export function approvalDecisionOfWinner(winner, boundCallId) {
248
- if (winner === undefined)
249
- return null;
250
- if (winner.boundCallId !== boundCallId)
251
- return null;
252
- switch (winner.decision) {
253
- case "allow":
254
- return "approve";
255
- case "deny":
256
- return "deny";
257
- case "approve":
258
- case "reject":
259
- case "edit":
260
- return null;
261
- default: {
262
- const unhandled = winner.decision;
263
- void unhandled;
264
- return null;
265
- }
266
- }
267
- }
268
- function pendingActionToolCallId(body) {
269
- if (typeof body !== "object" || body === null)
270
- return { readable: false };
271
- if ("sourceTaskId" in body)
272
- return { readable: false };
273
- const rawSource = "sourceSessionId" in body ? body.sourceSessionId : null;
274
- if (rawSource !== null && rawSource !== undefined && typeof rawSource !== "string")
275
- return { readable: false };
276
- const sourceSessionId = typeof rawSource === "string" ? rawSource : null;
277
- if (!("pendingAction" in body))
278
- return { readable: true, toolCallId: null, boundInputHash: null, kind: null, sourceSessionId };
279
- const pa = body.pendingAction;
280
- if (typeof pa !== "object" || pa === null)
281
- return { readable: false };
282
- const kind = "kind" in pa ? pa.kind : null;
283
- if (kind !== null && typeof kind !== "string")
284
- return { readable: false };
285
- if (!("toolCallId" in pa))
286
- return { readable: true, toolCallId: null, boundInputHash: null, kind, sourceSessionId };
287
- const id = pa.toolCallId;
288
- if (typeof id !== "string")
289
- return { readable: false };
290
- if (kind !== "tool_approval")
291
- return { readable: false };
292
- const bih = "boundInputHash" in pa ? pa.boundInputHash : null;
293
- if (bih !== null && typeof bih !== "string")
294
- return { readable: false };
295
- return { readable: true, toolCallId: id, boundInputHash: bih, kind, sourceSessionId };
296
- }
297
- export function candidateIdentityOf(cp) {
298
- if (judgeCheckpointRow(cp).kind === "lacking")
299
- return { readable: false };
300
- return pendingActionToolCallId(cp);
301
- }
302
178
  function candidateIdentityOfColumn(cell, where) {
303
179
  let cp;
304
180
  try {
@@ -371,7 +247,6 @@ export function readPendingSteerQueueColumn(queueRaw) {
371
247
  }
372
248
  const STEER_CAS_ATTEMPTS = 8;
373
249
  const EXECUTION_RECORD_CAS_ATTEMPTS = 8;
374
- export const CTX_CLAIM_REWRITES = ["written", "claim_released", "context_absent"];
375
250
  export class SqlCheckpointStore {
376
251
  db;
377
252
  logger;
@@ -474,7 +349,7 @@ export class SqlCheckpointStore {
474
349
  const r = rows[0];
475
350
  if (!r)
476
351
  return null;
477
- const cp = refusing("a checkpoint nobody can resume", () => decodeCheckpointColumn(r.checkpoint, `for token ${tokenFingerprint(token)}`));
352
+ const cp = readCheckpointBodyOrRefuse(r.checkpoint, `for token ${tokenFingerprint(token)}`);
478
353
  cp.status = r.status;
479
354
  const outcomeRaw = refusing("a decision record nobody can read", () => decodeOutcomeColumn(r.outcome, `for token ${tokenFingerprint(token)}`));
480
355
  if (outcomeRaw)
@@ -653,47 +528,74 @@ export class SqlCheckpointStore {
653
528
  const token = String(r.token);
654
529
  const sha256 = readJsonColumnTextSha256(r[CHECKPOINT_SHA256_AS], "checkpoint.checkpoint_sha256 (whole-row read)");
655
530
  const projection = this.projectStoredRow(r, sha256);
656
- if (projection !== undefined && sha256 === expected.get(token))
531
+ if (sha256 === expected.get(token))
657
532
  out.set(token, projection);
658
533
  }
659
534
  }
660
535
  return out;
661
536
  }
662
537
  projectStoredRow(r, sha256) {
538
+ const read = this.readStoredRow(r, "(operator queue row, whole-row read)", sha256);
539
+ return read.summary === undefined ? { rowVerdict: read.rowVerdict, skillCardFacts: {} } : { rowVerdict: read.rowVerdict, skillCardFacts: skillCardFacts(read.summary) };
540
+ }
541
+ readStoredRow(r, where, sha256, discloseFor) {
542
+ const memo = this.storedRowMemo.get(sha256);
663
543
  let cp;
664
544
  try {
665
- cp = decodeCheckpointColumn(r.checkpoint, "(operator queue row, whole-row read)");
545
+ cp = decodeCheckpointColumn(r.checkpoint, where);
666
546
  }
667
547
  catch (e) {
668
548
  if (!isJsonColumnBodyProblem(e))
669
549
  throw e;
670
550
  recordFailOpen("server.approvals.park-row-blob-unreadable");
671
- return undefined;
551
+ return { rowVerdict: verdictOfUnreadableBody(r.checkpoint) };
672
552
  }
673
553
  let summary;
554
+ const disclosed = [];
674
555
  try {
675
- summary = summarizeCheckpoint(cp);
556
+ summary = summarizeCheckpoint(cp, (sentence) => disclosed.push(sentence), memo?.rowVerdict);
676
557
  }
677
558
  catch {
678
559
  recordFailOpen("server.approvals.park-row-blob-unreadable");
679
- return { rowVerdict: judgeCheckpointRow(cp), skillCardFacts: {} };
560
+ return { rowVerdict: judgeCheckpointRow(cp) };
680
561
  }
681
- const projection = { rowVerdict: summary.rowVerdict, skillCardFacts: skillCardFacts(summary) };
682
- this.storedRowMemo.set(sha256, projection);
683
- return projection;
562
+ if (isUnreadableSummaryForm(summary)) {
563
+ recordFailOpen("server.approvals.park-row-blob-unreadable");
564
+ return { rowVerdict: summary.rowVerdict };
565
+ }
566
+ const seat = discloseFor?.(cp);
567
+ for (const sentence of disclosed)
568
+ seat?.(sentence);
569
+ if (memo === undefined)
570
+ this.storedRowMemo.set(sha256, { rowVerdict: summary.rowVerdict, skillCardFacts: skillCardFacts(summary) });
571
+ return { rowVerdict: summary.rowVerdict, summary };
684
572
  }
685
573
  async listByScope(scope) {
686
- const { rows } = await this.db.query(this.q(`SELECT ${jsonColumnText("mysql", "checkpoint")}, ${jsonColumnTextSha256("mysql", "checkpoint", CHECKPOINT_SHA256_AS)}, status FROM checkpoint WHERE status = 'pending' AND scope = ? ORDER BY created_at_ms ASC LIMIT 500`, `SELECT ${jsonColumnText("pg", "checkpoint")}, ${jsonColumnTextSha256("pg", "checkpoint", CHECKPOINT_SHA256_AS)}, status FROM checkpoint WHERE status = 'pending' AND scope = $1 ORDER BY created_at_ms ASC LIMIT 500`), [scope]);
574
+ const d = this.db.dialect;
575
+ const { rows } = await this.db.query(`SELECT ${jsonColumnText(d, "checkpoint")}, ${jsonColumnTextSha256(d, "checkpoint", CHECKPOINT_SHA256_AS)}, ${jsonColumnText(d, "checkpoint", PARK_ROW_CHECKPOINT_ID)}, ` +
576
+ `token, session_id, scope, created_at_ms, deadline, gate_kind FROM checkpoint WHERE status = 'pending' AND scope = ${this.q("?", "$1")} ORDER BY created_at_ms ASC LIMIT 500`, [scope]);
687
577
  const out = [];
688
578
  for (const r of rows) {
689
579
  const sha256 = readJsonColumnTextSha256(r[CHECKPOINT_SHA256_AS], `checkpoint.checkpoint_sha256 in the ${scope} scheduler view`);
690
- const cp = refusing("a checkpoint nobody can resume", () => decodeCheckpointColumn(r.checkpoint, `in the ${scope} scheduler view`));
691
- cp.status = r.status;
692
- const memo = this.storedRowMemo.get(sha256);
693
- const summary = summarizeCheckpoint(cp, (sentence) => recordFailOpen("server.checkpoint.inbox-risk-axes-damaged", withoutCheckpointToken(sentence, cp.token)), memo?.rowVerdict);
694
- if (memo === undefined)
695
- this.storedRowMemo.set(sha256, { rowVerdict: summary.rowVerdict, skillCardFacts: skillCardFacts(summary) });
696
- out.push(summary);
580
+ const read = this.readStoredRow(r, `in the ${scope} scheduler view`, sha256, (cp) => (sentence) => recordFailOpen("server.checkpoint.inbox-risk-axes-damaged", withoutCheckpointToken(sentence, cp.token)));
581
+ if (read.summary !== undefined) {
582
+ out.push(read.summary);
583
+ continue;
584
+ }
585
+ const gateKind = queueRowGateKind(r.gate_kind);
586
+ if (gateKind === undefined)
587
+ continue;
588
+ const checkpointId = readCheckpointIdCell(r[PARK_ROW_CHECKPOINT_ID.as]);
589
+ out.push({
590
+ token: String(r.token),
591
+ rowVerdict: read.rowVerdict,
592
+ ...(typeof checkpointId === "string" ? { checkpointId } : {}),
593
+ sessionId: String(r.session_id),
594
+ scope: String(r.scope),
595
+ gateKind,
596
+ createdAt: Number(r.created_at_ms),
597
+ ...(r.deadline == null ? {} : { deadline: Number(r.deadline) }),
598
+ });
697
599
  }
698
600
  return out;
699
601
  }
@@ -872,47 +774,6 @@ export class SqlCheckpointStore {
872
774
  }
873
775
  return out;
874
776
  }
875
- async scanKindlessBatchRows() {
876
- const out = [];
877
- let unreadableCells = 0;
878
- const tolerant = (read) => {
879
- try {
880
- return read();
881
- }
882
- catch (e) {
883
- if (!isJsonColumnBodyProblem(e))
884
- throw e;
885
- unreadableCells += 1;
886
- return undefined;
887
- }
888
- };
889
- const prefilter = (d) => `(rule_suggestions IS NOT NULL OR ${jsonColumnTextExpr(d, "checkpoint", PARK_ROW_PENDING_ACTION.key)} LIKE '%"batch"%')`;
890
- let after = "";
891
- for (;;) {
892
- const { rows } = await this.db.query(this.q(`SELECT token, ${jsonColumnText("mysql", "rule_suggestions")}, ${jsonColumnText("mysql", "checkpoint", PARK_ROW_PENDING_ACTION)} FROM checkpoint WHERE token > ? AND ${prefilter("mysql")} ORDER BY token LIMIT ${KINDLESS_SCAN_PAGE}`, `SELECT token, ${jsonColumnText("pg", "rule_suggestions")}, ${jsonColumnText("pg", "checkpoint", PARK_ROW_PENDING_ACTION)} FROM checkpoint WHERE token > $1 AND ${prefilter("pg")} ORDER BY token LIMIT ${KINDLESS_SCAN_PAGE}`), [after]);
893
- for (const row of rows) {
894
- const token = String(row.token);
895
- after = token;
896
- const carriers = [];
897
- const column = tolerant(() => decodeNullableJsonColumn(row.rule_suggestions, readJsonArrayColumn, "checkpoint.rule_suggestions (kind-less batch census)"));
898
- if (countKindlessBatchOffers(boundedReaderInput(column)) > 0)
899
- carriers.push("rule_suggestions");
900
- const pendingAction = tolerant(() => decodeNullableJsonColumn(row[PARK_ROW_PENDING_ACTION.as], readJsonObjectColumn, "checkpoint.checkpoint pendingAction member (kind-less batch census)"));
901
- if (typeof pendingAction === "object" && pendingAction !== null) {
902
- const blobOffers = Reflect.get(pendingAction, "ruleOffers");
903
- if (blobOffers !== undefined && !Array.isArray(blobOffers))
904
- unreadableCells += 1;
905
- else if (countKindlessBatchOffers(blobOffers) > 0)
906
- carriers.push("pendingAction.ruleOffers");
907
- }
908
- if (carriers.length > 0)
909
- out.push({ ref: tokenFingerprint(token), carriers });
910
- }
911
- if (rows.length < KINDLESS_SCAN_PAGE)
912
- break;
913
- }
914
- return { rows: out, unreadableCells };
915
- }
916
777
  async reapCtx(cutoff) {
917
778
  const res = await this.db.query(this.q("DELETE FROM checkpoint_ctx WHERE updated_at_ms < ? " +
918
779
  "AND session_id NOT IN (SELECT session_id FROM checkpoint WHERE status='pending') " +
@@ -1,8 +1,8 @@
1
1
  import type { Pool as MySqlPool } from "mysql2/promise";
2
2
  import type { Pool as PgPool } from "pg";
3
3
  import type { MailboxAckResult, MailboxAppendMessage, MailboxDecision, MailboxDecisionOutcome, MailboxLease, MailboxRecipientTombstone, MailboxStore } from "@sema-agent/core";
4
- import { type IndexSpec } from "./ensure-index.js";
5
- import type { SqlDialect } from "./sql-driver.js";
4
+ import { type IndexSpec } from "../plugins/ensure-index.js";
5
+ import type { SqlDialect } from "../plugins/sql-driver.js";
6
6
  export declare const MAILBOX_TABLE = "mailbox";
7
7
  export declare const MAILBOX_MSG_TABLE = "mailbox_message";
8
8
  /** [ref] 收件人墓碑表(预删除态的**唯一**真源;形与理由见 `mailbox-recipient-lifecycle.ts` 模块头)。
@@ -1,10 +1,10 @@
1
1
  import { isUtf8 } from "node:buffer";
2
2
  import { MAILBOX_CONSUMED_ID_WINDOW, MAILBOX_INVALID_PEER_META_CODE, MAILBOX_RECORD_ID_MAX_CHARS, MAILBOX_REPLAY_FACETS, MAILBOX_TOMBSTONED_RECIPIENT_CODE, MailboxStoreError, assertMailboxDecisionMove, judgeMailboxAppendById, mailboxReplayDigests, readMailboxAppend, readMailboxPeerMeta, readStoredMailboxDecision } from "@sema-agent/core";
3
- import { pgHasUnstorable, pgSanitizeText, PgUnstorableError } from "./pg-safe-json.js";
3
+ import { pgHasUnstorable, pgSanitizeText, PgUnstorableError } from "../plugins/pg-safe-json.js";
4
4
  import { isWellFormedUnicode } from "../principal-jwt.js";
5
- import { ensureIndexes } from "./ensure-index.js";
6
- import { escapeLike } from "./sql-escape.js";
7
- import { SqlJsonColumnError, decodeJsonColumn, decodeNullableJsonColumn, foldJsonColumn, isJsonColumnBodyProblem, jsonColumnText, readStringArrayColumn } from "./sql-json-column.js";
5
+ import { ensureIndexes } from "../plugins/ensure-index.js";
6
+ import { escapeLike } from "../plugins/sql-escape.js";
7
+ import { SqlJsonColumnError, decodeJsonColumn, decodeNullableJsonColumn, foldJsonColumn, isJsonColumnBodyProblem, jsonColumnText, readStringArrayColumn } from "../plugins/sql-json-column.js";
8
8
  export const MAILBOX_TABLE = "mailbox";
9
9
  export const MAILBOX_MSG_TABLE = "mailbox_message";
10
10
  export const MAILBOX_TOMBSTONE_TABLE = "mailbox_tombstone";
@@ -22,8 +22,8 @@
22
22
  */
23
23
  import type { Pool } from "mysql2/promise";
24
24
  import { type RosterStore, type RosterEntry, type RosterAccess } from "@sema-agent/core";
25
- import type { PgQueryFn } from "./pg-query.js";
26
- import { type IndexSpec } from "./ensure-index.js";
25
+ import type { PgQueryFn } from "../plugins/pg-query.js";
26
+ import { type IndexSpec } from "../plugins/ensure-index.js";
27
27
  export declare const ROSTER_TABLE = "agent_roster";
28
28
  export declare function ensureTiDBRosterSchema(pool: Pool): Promise<void>;
29
29
  /** [ref]:本 store 的索引**声明**(两方言共用一份)。PG 侧由下面的 `ensurePgRosterSchema` 应用,MySQL 侧由 `tidb-pool.ts` 的中央 `ensureSchema` 应用(那里内联 `KEY` 已在 `CREATE TABLE` 里 ⇒ 新建库探到即零 DDL,存量库缺谁补谁)。加索引以外的 schema 变更仍归运维,见 `plugins/ensure-index.ts` 头注。 */
@@ -1,5 +1,5 @@
1
1
  import { normalizeAgentName } from "@sema-agent/core";
2
- import { ensureIndexes } from "./ensure-index.js";
2
+ import { ensureIndexes } from "../plugins/ensure-index.js";
3
3
  export const ROSTER_TABLE = "agent_roster";
4
4
  function rowToEntry(r) {
5
5
  return {
@@ -1,9 +1,9 @@
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, type SqlDialect } from "./sql-driver.js";
4
+ import { type SqlDriver, type SqlDialect } from "../plugins/sql-driver.js";
5
5
  import type { RetentionDeclaration } from "@sema-agent/core";
6
- import { type IndexSpec } from "./ensure-index.js";
6
+ import { type IndexSpec } from "../plugins/ensure-index.js";
7
7
  /** PG schema for the tool_result table — the PG translation of tidb-pool.ts's tool_result DDL
8
8
  * (LONGTEXT→TEXT, DATETIME(3)→TIMESTAMPTZ(3), inline KEY→separate CREATE INDEX). Disjoint from other stores'
9
9
  * tables, so a self-contained ensureSchema is safe (central pg-pool aggregation is done separately). */
@@ -1,10 +1,10 @@
1
1
  import { MAX_MINTED_TOOL_RESULT_REF_CHARS, assertSafeToolResultRef, assertToolResultProvenanceMatch, normalizeToolResultProvenance } from "@sema-agent/core";
2
- import { pgSanitizeText } from "./pg-safe-json.js";
3
- import { mysqlDriver, pgDriver } from "./sql-driver.js";
4
- import { MANAGED_RETENTION, UNMANAGED_RETENTION } from "./retention-store-sql.js";
5
- import { ensureIndexes } from "./ensure-index.js";
6
- import { describeProbedTableDrift, schemaWaysOut } from "./schema-drift-sentence.js";
7
- import { isMissingColumnError } from "./sql-errors.js";
2
+ import { pgSanitizeText } from "../plugins/pg-safe-json.js";
3
+ import { mysqlDriver, pgDriver } from "../plugins/sql-driver.js";
4
+ import { MANAGED_RETENTION, UNMANAGED_RETENTION } from "../plugins/retention-store-sql.js";
5
+ import { ensureIndexes } from "../plugins/ensure-index.js";
6
+ import { describeProbedTableDrift, schemaWaysOut } from "../plugins/schema-drift-sentence.js";
7
+ import { isMissingColumnError } from "../plugins/sql-errors.js";
8
8
  export const PG_TOOL_RESULT_SCHEMA = [
9
9
  `CREATE TABLE IF NOT EXISTS tool_result (
10
10
  ref VARCHAR(518) COLLATE "C" NOT NULL,
@@ -8,7 +8,7 @@
8
8
  * {@link import("@sema-agent/core").InMemoryWorkflowJournalStore} (single-replica, lost on crash); this is the
9
9
  * byte-match durable twin so a workflow survives a replica crash and RESUMES (replay the longest unchanged
10
10
  * PREFIX of recorded `ctx.agent` results, run only the first changed/new call + everything after it live). The
11
- * journal is LOAD-BEARING (unlike the best-effort {@link import("./run-store-sql.js")} observation layer):
11
+ * journal is LOAD-BEARING (unlike the best-effort {@link import("../plugins/run-store-sql.js")} observation layer):
12
12
  * append/load failures MUST throw — a silently-dropped entry would silently re-run already-done work.
13
13
  *
14
14
  * Schema = two tables (DDL in tidb-pool.ts / pg-pool.ts ensureSchema), the SQL normal form of core's per-run
@@ -36,7 +36,7 @@
36
36
  * `run_id = ? AND scope = ?`.
37
37
  * Why the owner record's incarnation is in the row's PRIMARY KEY (one rule: **a row belongs to the owner record that
38
38
  * wrote it — readable only through it, overwritable only by a write made through it**): a write can outlive the owner
39
- * record it was judged against — `deleteByRun` / the GC sweep racing an append, an append stalled between its two
39
+ * record it was judged against — the GC sweep racing an append, an append stalled between its two
40
40
  * statements. Keyed and joined on run_id alone, (a) a leftover row would be adopted by the next claim of that run_id by
41
41
  * ANY scope, and (b) on PostgreSQL READ COMMITTED a stale guarded write whose SELECT still saw the old record would, via
42
42
  * the ON CONFLICT arm (which updates a row its snapshot never saw, without re-checking the source), overwrite the NEW
@@ -77,7 +77,7 @@
77
77
  import type { Pool as MySqlPool } from "mysql2/promise";
78
78
  import type { Pool as PgPool } from "pg";
79
79
  import { type WorkflowJournalEntry, type WorkflowJournalStore } from "@sema-agent/core";
80
- import { type SqlDriver } from "./sql-driver.js";
80
+ import { type SqlDriver } from "../plugins/sql-driver.js";
81
81
  /** Dual-dialect durable WorkflowJournalStore. See the file header for the dialect-delta ledger. */
82
82
  /** [ref] 租约旋钮。TTL 只是**崩溃兜底**(engine 终态 finally 显式释放;[ref]/[ref] 两层分工:
83
83
  * engine 崩了没释放 ⇒ 陈旧 claim 可被接管)。
@@ -137,11 +137,6 @@ export declare class SqlWorkflowJournalStore implements WorkflowJournalStore {
137
137
  private oversizeCellOf;
138
138
  /** 读面的**唯一**行读法(`loadPage` 的块读与超门行的单条读共用):序数 ≥ `from` 的至多 `limit` 行,字节超 `inlineBytes` 的行 `resultJson` 为 null(只回 `resultBytes`)。 */
139
139
  private readRows;
140
- /** GC — purge ALL journal entries for a run (every incarnation), then its owner row ([ref]). Scoped by run_id alone;
141
- * idempotent (returns the journal rows removed). Mirrors the resume-anchor store's deleteBySession. An append racing the
142
- * two DELETEs can leave a row behind without its owner record; it is keyed by the dead incarnation — readable and
143
- * overwritable by no one (file header) — and the GC sweep removes it by age. */
144
- deleteByRun(runId: string): Promise<number>;
145
140
  /** [ref] / WF2([ref] core 拍板 a 形,签名逐字)—— cross-replica resume admission lease。
146
141
  *
147
142
  * 语义(bake-store `idem_key UNIQUE` 先例):PK (source_run_id, scope) 上的原子赢或观察。四步,每步
@@ -165,10 +160,10 @@ export declare class SqlWorkflowJournalStore implements WorkflowJournalStore {
165
160
  newRunId: string;
166
161
  scope: string;
167
162
  }): Promise<void>;
168
- /** GC — time-based sweep: purge journal entries older than `maxAgeMs` (created_at_ms < now - maxAgeMs). The
169
- * per-run deleteByRun has no production caller (a run-store reap gives no per-run hook), so this bounded sweep
170
- * — wired into the service reaper — is what keeps the heaviest table (TaskResult-bearing) from growing without
171
- * bound. A resume of a journal older than the retention window simply re-runs live (resume is an optimization).
163
+ /** GC — time-based sweep: purge journal entries older than `maxAgeMs` (created_at_ms < now - maxAgeMs). This is the
164
+ * journal's ONE delete path (the engine's contract has no per-run delete; its File store's was retired in core 7.61.0,
165
+ * and this store's went with it) — wired into the service reaper, it is what keeps the heaviest table
166
+ * (TaskResult-bearing) from growing without bound. A resume of a journal older than the retention window simply re-runs live (resume is an optimization).
172
167
  * Idempotent; returns the journal rows purged.
173
168
  *
174
169
  * [ref]: the same cutoff then purges owner rows whose OWN clock (`appended_at_ms`, pushed by every append of the
@@ -1,9 +1,9 @@
1
1
  import { callKeyOrdinal } from "@sema-agent/core";
2
2
  import { assertJournalEntryFits } from "@sema-agent/core";
3
- import { journalEntryOfCell, journalRowPayloadOf } from "./workflow-journal-payload.js";
3
+ import { journalEntryOfCell, journalRowPayloadOf } from "../plugins/workflow-journal-payload.js";
4
4
  import { randomUUID } from "node:crypto";
5
- import { mysqlDriver, pgDriver } from "./sql-driver.js";
6
- import { jsonColumnText, jsonColumnTextExpr } from "./sql-json-column.js";
5
+ import { mysqlDriver, pgDriver } from "../plugins/sql-driver.js";
6
+ import { jsonColumnText, jsonColumnTextExpr } from "../plugins/sql-json-column.js";
7
7
  const DEFAULT_RESUME_CLAIM_TTL_MS = 60 * 60 * 1000;
8
8
  const INT_MIN = -2147483648;
9
9
  const INT_MAX = 2147483647;
@@ -75,11 +75,6 @@ export class SqlWorkflowJournalStore {
75
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
- async deleteByRun(runId) {
79
- const res = await this.db.query(this.q("DELETE FROM workflow_journal WHERE run_id = ?", "DELETE FROM workflow_journal WHERE run_id = $1"), [runId]);
80
- await this.db.query(this.q("DELETE FROM workflow_journal_owner WHERE run_id = ?", "DELETE FROM workflow_journal_owner WHERE run_id = $1"), [runId]);
81
- return res.affected;
82
- }
83
78
  async resumeClaim(input) {
84
79
  const now = Date.now();
85
80
  const ins = await this.db.query(this.q("INSERT IGNORE INTO workflow_resume_claim (source_run_id, scope, new_run_id, claimed_at_ms) VALUES (?, ?, ?, ?)", "INSERT INTO workflow_resume_claim (source_run_id, scope, new_run_id, claimed_at_ms) VALUES ($1, $2, $3, $4) ON CONFLICT (source_run_id, scope) DO NOTHING"), [input.sourceRunId, input.scope, input.newRunId, now]);