@jungjaehoon/mama-core 2.4.1 → 4.0.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 (371) hide show
  1. package/README.md +76 -239
  2. package/db/migrations/030-case-first-memory-substrate.sql +13 -98
  3. package/db/migrations/034-add-connector-event-scope-columns.sql +9 -13
  4. package/db/migrations/039-add-connector-event-operator-ingest-seq.sql +9 -95
  5. package/db/migrations/062-refresh-connector-event-sequences.sql +9 -113
  6. package/db/migrations/063-refresh-legacy-connector-event-updates.sql +9 -32
  7. package/db/migrations/067-add-connector-event-source-entity-id.sql +9 -13
  8. package/db/migrations/069-create-registry-nodes.sql +52 -0
  9. package/db/migrations/070-record-identity.sql +35 -0
  10. package/db/migrations/071-service-operation-origins.sql +187 -0
  11. package/db/migrations/072-observation-versions.sql +29 -0
  12. package/db/migrations/073-registry-corrections.sql +45 -0
  13. package/db/migrations/074-work-graph-ref-kinds.sql +39 -0
  14. package/db/migrations/075-agent-judgments.sql +58 -0
  15. package/db/migrations/076-scoped-checkpoint-bindings.sql +15 -0
  16. package/db/migrations/077-legacy-record-kind.sql +6 -0
  17. package/db/migrations/078-source-ingest-commands.sql +18 -0
  18. package/db/migrations/079-twin-edge-relations.sql +43 -0
  19. package/db/migrations/080-restore-duration-days.sql +7 -0
  20. package/db/migrations/081-mailbox.sql +61 -0
  21. package/db/migrations/082-commitments-row-id.sql +12 -0
  22. package/db/migrations/083-observation-is-the-evidence.sql +49 -0
  23. package/db/migrations/084-scope-kind-is-not-the-cores-to-list.sql +34 -0
  24. package/db/migrations/085-a-migration-has-a-source.sql +37 -0
  25. package/db/migrations/086-the-mailbox-is-generic.sql +110 -0
  26. package/db/migrations/087-mailbox-payload.sql +5 -0
  27. package/db/migrations/088-native-input-journal.sql +14 -0
  28. package/db/migrations/089-native-turn-receipt-lookup.sql +3 -0
  29. package/db/migrations/090-model-run-native-inputs.sql +29 -0
  30. package/db/migrations/091-native-turn-results.sql +11 -0
  31. package/db/migrations/092-restore-decision-fts.sql +34 -0
  32. package/db/migrations/093-native-turn-primary-kind.sql +14 -0
  33. package/db/migrations/094-commitment-run-provenance.sql +9 -0
  34. package/db/migrations/095-model-run-native-input-identity.sql +39 -0
  35. package/db/migrations/096-drop-connector-event-index-fts.sql +9 -0
  36. package/db/migrations/097-native-input-json-validity.sql +37 -0
  37. package/db/migrations/098-workflow-memory-kind.sql +105 -0
  38. package/dist/action-contracts.d.ts +212 -0
  39. package/dist/action-contracts.js +10 -0
  40. package/dist/api/catalog.d.ts +118 -0
  41. package/dist/api/catalog.js +1756 -0
  42. package/dist/api/dispatch.d.ts +76 -0
  43. package/dist/api/dispatch.js +372 -0
  44. package/dist/canonicalize.d.ts +2 -2
  45. package/dist/canonicalize.js +3 -3
  46. package/dist/client/client.d.ts +33 -0
  47. package/dist/client/client.js +123 -0
  48. package/dist/client/ipc.d.ts +81 -0
  49. package/dist/client/ipc.js +314 -0
  50. package/dist/db-adapter/base-adapter.d.ts +6 -66
  51. package/dist/db-adapter/base-adapter.js +6 -6
  52. package/dist/db-adapter/index.d.ts +5 -5
  53. package/dist/db-adapter/index.js +2 -5
  54. package/dist/db-adapter/node-sqlite-adapter.d.ts +85 -15
  55. package/dist/db-adapter/node-sqlite-adapter.js +1968 -570
  56. package/dist/db-manager.d.ts +53 -97
  57. package/dist/db-manager.js +121 -603
  58. package/dist/embedding/embedder.d.ts +132 -0
  59. package/dist/embedding/embedder.js +299 -0
  60. package/dist/identity/principal-repository.d.ts +2 -2
  61. package/dist/index.d.ts +43 -58
  62. package/dist/index.js +97 -145
  63. package/dist/{context-compile/channel-grant.d.ts → knowledge/access.d.ts} +12 -17
  64. package/dist/knowledge/access.js +663 -0
  65. package/dist/knowledge/case-errors.d.ts +31 -0
  66. package/dist/knowledge/case-errors.js +40 -0
  67. package/dist/{cases/search-rollup.d.ts → knowledge/case-search-rollup.d.ts} +5 -4
  68. package/dist/{cases/search-rollup.js → knowledge/case-search-rollup.js} +6 -8
  69. package/dist/{cases/store.d.ts → knowledge/case-store.d.ts} +3 -6
  70. package/dist/{cases/store.js → knowledge/case-store.js} +7 -42
  71. package/dist/{cases/timeline-range.d.ts → knowledge/case-timeline-range.d.ts} +3 -3
  72. package/dist/{cases/timeline-range.js → knowledge/case-timeline-range.js} +47 -25
  73. package/dist/{cases/types.d.ts → knowledge/case-types.d.ts} +8 -2
  74. package/dist/{cases/types.js → knowledge/case-types.js} +1 -1
  75. package/dist/knowledge/commitments.d.ts +188 -0
  76. package/dist/knowledge/commitments.js +370 -0
  77. package/dist/knowledge/decision-edges.d.ts +70 -0
  78. package/dist/knowledge/decision-edges.js +123 -0
  79. package/dist/{agent-graph/types.d.ts → knowledge/graph-query.d.ts} +80 -70
  80. package/dist/knowledge/graph-query.js +1585 -0
  81. package/dist/knowledge/identity.d.ts +16 -0
  82. package/dist/knowledge/identity.js +22 -0
  83. package/dist/knowledge/index.d.ts +47 -0
  84. package/dist/knowledge/index.js +90 -0
  85. package/dist/knowledge/judgments.d.ts +118 -0
  86. package/dist/knowledge/judgments.js +808 -0
  87. package/dist/knowledge/observations.d.ts +160 -0
  88. package/dist/knowledge/observations.js +449 -0
  89. package/dist/knowledge/question-type.d.ts +34 -0
  90. package/dist/knowledge/question-type.js +70 -0
  91. package/dist/{search → knowledge}/ranker-features.js +1 -1
  92. package/dist/{search → knowledge}/search-quality.d.ts +0 -1
  93. package/dist/knowledge/search.d.ts +38 -0
  94. package/dist/knowledge/search.js +91 -0
  95. package/dist/knowledge/source-ingest.d.ts +65 -0
  96. package/dist/knowledge/source-ingest.js +174 -0
  97. package/dist/{edges/types.d.ts → knowledge/twin-edge-types.d.ts} +31 -4
  98. package/dist/{edges/types.js → knowledge/twin-edge-types.js} +13 -2
  99. package/dist/knowledge/work-dates.d.ts +49 -0
  100. package/dist/knowledge/work-dates.js +120 -0
  101. package/dist/mama-api.d.ts +114 -778
  102. package/dist/mama-api.js +313 -2461
  103. package/dist/memory/api.d.ts +264 -24
  104. package/dist/memory/api.js +1633 -843
  105. package/dist/memory/bootstrap-builder.d.ts +2 -1
  106. package/dist/memory/bootstrap-builder.js +5 -5
  107. package/dist/memory/channel-summary-state-store.d.ts +3 -2
  108. package/dist/memory/channel-summary-state-store.js +53 -51
  109. package/dist/memory/channel-summary-store.d.ts +5 -3
  110. package/dist/memory/channel-summary-store.js +3 -8
  111. package/dist/memory/dashboard-read.d.ts +46 -0
  112. package/dist/memory/dashboard-read.js +94 -0
  113. package/dist/memory/event-store.d.ts +3 -3
  114. package/dist/memory/event-store.js +3 -10
  115. package/dist/memory/finding-store.d.ts +3 -2
  116. package/dist/memory/finding-store.js +2 -7
  117. package/dist/memory/graph-read.d.ts +52 -0
  118. package/dist/memory/graph-read.js +130 -0
  119. package/dist/memory/judgment-types.d.ts +394 -0
  120. package/dist/memory/judgment-types.js +16 -0
  121. package/dist/memory/provenance-audit.d.ts +5 -2
  122. package/dist/memory/provenance-audit.js +8 -14
  123. package/dist/memory/provenance-live.d.ts +141 -0
  124. package/dist/memory/provenance-live.js +409 -0
  125. package/dist/memory/provenance-query.d.ts +5 -4
  126. package/dist/memory/provenance-query.js +21 -29
  127. package/dist/memory/provenance-resolver.d.ts +191 -0
  128. package/dist/memory/provenance-resolver.js +155 -0
  129. package/dist/memory/provenance.d.ts +1 -11
  130. package/dist/memory/provenance.js +2 -33
  131. package/dist/memory/recall-sanitize.d.ts +55 -0
  132. package/dist/memory/recall-sanitize.js +144 -0
  133. package/dist/memory/secret-filter.d.ts +32 -0
  134. package/dist/memory/secret-filter.js +126 -0
  135. package/dist/memory/truth-store.d.ts +2 -1
  136. package/dist/memory/truth-store.js +1 -4
  137. package/dist/memory/types.d.ts +74 -24
  138. package/dist/memory/types.js +75 -5
  139. package/dist/memory/write-adapters.d.ts +98 -0
  140. package/dist/memory/write-adapters.js +242 -0
  141. package/dist/operations/owner-action-effects.d.ts +53 -0
  142. package/dist/operations/owner-action-effects.js +96 -0
  143. package/dist/provenance/source-ref.d.ts +1 -1
  144. package/dist/provenance/source-ref.js +0 -2
  145. package/dist/registry/corrections.d.ts +31 -0
  146. package/dist/registry/corrections.js +332 -0
  147. package/dist/registry/record-identity.d.ts +49 -0
  148. package/dist/registry/record-identity.js +133 -0
  149. package/dist/registry/store.d.ts +101 -0
  150. package/dist/registry/store.js +395 -0
  151. package/dist/registry/types.d.ts +28 -0
  152. package/dist/registry/types.js +5 -0
  153. package/dist/relevance-scorer.js +2 -2
  154. package/dist/runtime/agent-event-bus.d.ts +50 -0
  155. package/dist/runtime/agent-event-bus.js +101 -0
  156. package/dist/runtime/drivers/claude-cli-wrapper.d.ts +155 -0
  157. package/dist/runtime/drivers/claude-cli-wrapper.js +392 -0
  158. package/dist/runtime/drivers/cli-arg-redaction.d.ts +2 -0
  159. package/dist/runtime/drivers/cli-arg-redaction.js +18 -0
  160. package/dist/runtime/drivers/cli-secret-redaction.d.ts +17 -0
  161. package/dist/runtime/drivers/cli-secret-redaction.js +126 -0
  162. package/dist/runtime/drivers/codex-app-server-process.d.ts +277 -0
  163. package/dist/runtime/drivers/codex-app-server-process.js +2342 -0
  164. package/dist/runtime/drivers/codex-auxiliary-tools.d.ts +17 -0
  165. package/dist/runtime/drivers/codex-auxiliary-tools.js +267 -0
  166. package/dist/runtime/drivers/codex-home.d.ts +20 -0
  167. package/dist/runtime/drivers/codex-home.js +674 -0
  168. package/dist/runtime/drivers/codex-thread-registry.d.ts +63 -0
  169. package/dist/runtime/drivers/codex-thread-registry.js +433 -0
  170. package/dist/runtime/drivers/persistent-cli-adapter.d.ts +160 -0
  171. package/dist/runtime/drivers/persistent-cli-adapter.js +396 -0
  172. package/dist/runtime/drivers/persistent-cli-process.d.ts +424 -0
  173. package/dist/runtime/drivers/persistent-cli-process.js +1543 -0
  174. package/dist/runtime/drivers/types.d.ts +456 -0
  175. package/dist/runtime/drivers/types.js +110 -0
  176. package/dist/runtime/mailbox.d.ts +223 -0
  177. package/dist/runtime/mailbox.js +582 -0
  178. package/dist/runtime/model-run-store.d.ts +28 -0
  179. package/dist/{model-runs/store.js → runtime/model-run-store.js} +81 -41
  180. package/dist/{model-runs/types.d.ts → runtime/model-run-types.d.ts} +33 -4
  181. package/dist/{model-runs/types.js → runtime/model-run-types.js} +1 -1
  182. package/dist/runtime/native-effect-observer.d.ts +22 -0
  183. package/dist/runtime/native-effect-observer.js +103 -0
  184. package/dist/runtime/native-input-journal.d.ts +46 -0
  185. package/dist/runtime/native-input-journal.js +308 -0
  186. package/dist/runtime/native-prompt.d.ts +118 -0
  187. package/dist/runtime/native-prompt.js +496 -0
  188. package/dist/runtime/native-session.d.ts +10 -0
  189. package/dist/{agent-graph/index.js → runtime/native-session.js} +9 -6
  190. package/dist/runtime/native-tool-trace-observer.d.ts +5 -0
  191. package/dist/runtime/native-tool-trace-observer.js +65 -0
  192. package/dist/runtime/native-turn.d.ts +272 -0
  193. package/dist/runtime/native-turn.js +1041 -0
  194. package/dist/runtime/operations.d.ts +236 -0
  195. package/dist/runtime/operations.js +565 -0
  196. package/dist/runtime/post-tool-handler.d.ts +74 -0
  197. package/dist/runtime/post-tool-handler.js +137 -0
  198. package/dist/runtime/prompt-layers.d.ts +126 -0
  199. package/dist/runtime/prompt-layers.js +239 -0
  200. package/dist/runtime/runtime-process.d.ts +102 -0
  201. package/dist/runtime/runtime-process.js +206 -0
  202. package/dist/runtime/runtime.d.ts +278 -0
  203. package/dist/runtime/runtime.js +563 -0
  204. package/dist/runtime/session-pool.d.ts +176 -0
  205. package/dist/runtime/session-pool.js +369 -0
  206. package/dist/runtime/stimulus-payload.d.ts +5 -0
  207. package/dist/runtime/stimulus-payload.js +50 -0
  208. package/dist/runtime/subagent-bridge.d.ts +24 -0
  209. package/dist/{agent-graph/types.js → runtime/subagent-bridge.js} +1 -1
  210. package/dist/runtime/text-completion.d.ts +22 -0
  211. package/dist/{agent-situation/types.js → runtime/text-completion.js} +1 -1
  212. package/dist/runtime/token-estimator.d.ts +25 -0
  213. package/dist/runtime/token-estimator.js +75 -0
  214. package/dist/runtime/tool-trace-store.d.ts +22 -0
  215. package/dist/{model-runs → runtime}/tool-trace-store.js +46 -27
  216. package/dist/runtime/trace-summary.d.ts +5 -0
  217. package/dist/runtime/trace-summary.js +74 -0
  218. package/dist/runtime/turn-text.d.ts +23 -0
  219. package/dist/runtime/turn-text.js +41 -0
  220. package/dist/storage/database.d.ts +67 -0
  221. package/dist/storage/database.js +158 -0
  222. package/package.json +20 -34
  223. package/dist/agent-graph/alias-write.d.ts +0 -3
  224. package/dist/agent-graph/alias-write.js +0 -234
  225. package/dist/agent-graph/entity-resolve.d.ts +0 -3
  226. package/dist/agent-graph/entity-resolve.js +0 -271
  227. package/dist/agent-graph/errors.d.ts +0 -4
  228. package/dist/agent-graph/errors.js +0 -11
  229. package/dist/agent-graph/graph-query.d.ts +0 -5
  230. package/dist/agent-graph/graph-query.js +0 -360
  231. package/dist/agent-graph/index.d.ts +0 -6
  232. package/dist/agent-situation/builder.d.ts +0 -8
  233. package/dist/agent-situation/builder.js +0 -239
  234. package/dist/agent-situation/cache-key.d.ts +0 -4
  235. package/dist/agent-situation/cache-key.js +0 -64
  236. package/dist/agent-situation/index.d.ts +0 -7
  237. package/dist/agent-situation/index.js +0 -28
  238. package/dist/agent-situation/packet-store.d.ts +0 -27
  239. package/dist/agent-situation/packet-store.js +0 -228
  240. package/dist/agent-situation/ranking-policy.d.ts +0 -18
  241. package/dist/agent-situation/ranking-policy.js +0 -75
  242. package/dist/agent-situation/source-readers.d.ts +0 -52
  243. package/dist/agent-situation/source-readers.js +0 -300
  244. package/dist/agent-situation/types.d.ts +0 -195
  245. package/dist/cases/wiki-page-index.d.ts +0 -37
  246. package/dist/cases/wiki-page-index.js +0 -201
  247. package/dist/config-loader.d.ts +0 -68
  248. package/dist/config-loader.js +0 -239
  249. package/dist/connectors/event-index.d.ts +0 -24
  250. package/dist/connectors/event-index.js +0 -245
  251. package/dist/connectors/raw-query.d.ts +0 -40
  252. package/dist/connectors/raw-query.js +0 -412
  253. package/dist/connectors/types.d.ts +0 -117
  254. package/dist/connectors/types.js +0 -3
  255. package/dist/context-compile/boundary-defaults.d.ts +0 -12
  256. package/dist/context-compile/boundary-defaults.js +0 -105
  257. package/dist/context-compile/channel-grant.js +0 -66
  258. package/dist/context-compile/compiler-policy.d.ts +0 -39
  259. package/dist/context-compile/compiler-policy.js +0 -147
  260. package/dist/context-compile/compiler.d.ts +0 -18
  261. package/dist/context-compile/compiler.js +0 -404
  262. package/dist/context-compile/index.d.ts +0 -10
  263. package/dist/context-compile/index.js +0 -26
  264. package/dist/context-compile/packet-store.d.ts +0 -8
  265. package/dist/context-compile/packet-store.js +0 -239
  266. package/dist/context-compile/ref.d.ts +0 -7
  267. package/dist/context-compile/ref.js +0 -102
  268. package/dist/context-compile/source-readers.d.ts +0 -70
  269. package/dist/context-compile/source-readers.js +0 -840
  270. package/dist/context-compile/types.d.ts +0 -155
  271. package/dist/context-compile/types.js +0 -11
  272. package/dist/context-compile/visibility.d.ts +0 -21
  273. package/dist/context-compile/visibility.js +0 -224
  274. package/dist/decision-tracker.d.ts +0 -206
  275. package/dist/decision-tracker.js +0 -481
  276. package/dist/edges/ref-validation.d.ts +0 -7
  277. package/dist/edges/ref-validation.js +0 -321
  278. package/dist/edges/store.d.ts +0 -8
  279. package/dist/edges/store.js +0 -129
  280. package/dist/embedding-client.d.ts +0 -28
  281. package/dist/embedding-client.js +0 -53
  282. package/dist/embedding-server/index.d.ts +0 -67
  283. package/dist/embedding-server/index.js +0 -405
  284. package/dist/embedding-server/mobile/auth.d.ts +0 -44
  285. package/dist/embedding-server/mobile/auth.js +0 -150
  286. package/dist/embedding-server/mobile/daemon.d.ts +0 -129
  287. package/dist/embedding-server/mobile/daemon.js +0 -313
  288. package/dist/embedding-server/mobile/output-parser.d.ts +0 -115
  289. package/dist/embedding-server/mobile/output-parser.js +0 -241
  290. package/dist/embedding-server/mobile/session-api.d.ts +0 -57
  291. package/dist/embedding-server/mobile/session-api.js +0 -261
  292. package/dist/embedding-server/mobile/session-manager.d.ts +0 -138
  293. package/dist/embedding-server/mobile/session-manager.js +0 -378
  294. package/dist/embedding-server/mobile/websocket-handler.d.ts +0 -137
  295. package/dist/embedding-server/mobile/websocket-handler.js +0 -486
  296. package/dist/embeddings.d.ts +0 -68
  297. package/dist/embeddings.js +0 -244
  298. package/dist/entities/audit-metrics.d.ts +0 -68
  299. package/dist/entities/audit-metrics.js +0 -124
  300. package/dist/entities/candidate-generator.d.ts +0 -8
  301. package/dist/entities/candidate-generator.js +0 -24
  302. package/dist/entities/entity-linked-decision-counts.d.ts +0 -2
  303. package/dist/entities/entity-linked-decision-counts.js +0 -29
  304. package/dist/entities/entity-list.d.ts +0 -22
  305. package/dist/entities/entity-list.js +0 -3
  306. package/dist/entities/entity-orphan-list.d.ts +0 -17
  307. package/dist/entities/entity-orphan-list.js +0 -3
  308. package/dist/entities/entity-search.d.ts +0 -20
  309. package/dist/entities/entity-search.js +0 -3
  310. package/dist/entities/errors.d.ts +0 -55
  311. package/dist/entities/errors.js +0 -100
  312. package/dist/entities/lineage-store.d.ts +0 -28
  313. package/dist/entities/lineage-store.js +0 -204
  314. package/dist/entities/normalization.d.ts +0 -14
  315. package/dist/entities/normalization.js +0 -63
  316. package/dist/entities/policy-store.d.ts +0 -8
  317. package/dist/entities/policy-store.js +0 -75
  318. package/dist/entities/policy-types.d.ts +0 -72
  319. package/dist/entities/policy-types.js +0 -59
  320. package/dist/entities/projection.d.ts +0 -8
  321. package/dist/entities/projection.js +0 -82
  322. package/dist/entities/provenance-query.d.ts +0 -32
  323. package/dist/entities/provenance-query.js +0 -3
  324. package/dist/entities/read-identity.d.ts +0 -31
  325. package/dist/entities/read-identity.js +0 -264
  326. package/dist/entities/recall-bridge.d.ts +0 -5
  327. package/dist/entities/recall-bridge.js +0 -171
  328. package/dist/entities/resolution-engine.d.ts +0 -8
  329. package/dist/entities/resolution-engine.js +0 -3
  330. package/dist/entities/rollback-preview.d.ts +0 -35
  331. package/dist/entities/rollback-preview.js +0 -3
  332. package/dist/entities/source-locator.d.ts +0 -3
  333. package/dist/entities/source-locator.js +0 -32
  334. package/dist/entities/store.d.ts +0 -69
  335. package/dist/entities/store.js +0 -544
  336. package/dist/entities/types.d.ts +0 -166
  337. package/dist/entities/types.js +0 -30
  338. package/dist/memory/extraction-prompt.d.ts +0 -4
  339. package/dist/memory/extraction-prompt.js +0 -89
  340. package/dist/memory/scope-backfill.d.ts +0 -14
  341. package/dist/memory/scope-backfill.js +0 -3
  342. package/dist/memory/scope-store.d.ts +0 -4
  343. package/dist/memory/scope-store.js +0 -9
  344. package/dist/memory-store.d.ts +0 -87
  345. package/dist/memory-store.js +0 -78
  346. package/dist/model-runs/store.d.ts +0 -13
  347. package/dist/model-runs/tool-trace-store.d.ts +0 -8
  348. package/dist/notification-manager.d.ts +0 -7
  349. package/dist/notification-manager.js +0 -12
  350. package/dist/outcome-tracker.d.ts +0 -151
  351. package/dist/outcome-tracker.js +0 -271
  352. package/dist/query-intent.d.ts +0 -23
  353. package/dist/query-intent.js +0 -114
  354. package/dist/runtime/trusted-provenance.d.ts +0 -3
  355. package/dist/runtime/trusted-provenance.js +0 -6
  356. package/dist/search/question-type.d.ts +0 -5
  357. package/dist/search/question-type.js +0 -41
  358. package/dist/test-utils.d.ts +0 -80
  359. package/dist/test-utils.js +0 -218
  360. package/dist/tier-validator.d.ts +0 -43
  361. package/dist/tier-validator.js +0 -159
  362. package/dist/time-formatter.d.ts +0 -25
  363. package/dist/time-formatter.js +0 -93
  364. /package/dist/{search → knowledge}/feedback-store.d.ts +0 -0
  365. /package/dist/{search → knowledge}/feedback-store.js +0 -0
  366. /package/dist/{search → knowledge}/ranker-features.d.ts +0 -0
  367. /package/dist/{search → knowledge}/ranker-rescore.d.ts +0 -0
  368. /package/dist/{search → knowledge}/ranker-rescore.js +0 -0
  369. /package/dist/{search → knowledge}/ranker-trainer.d.ts +0 -0
  370. /package/dist/{search → knowledge}/ranker-trainer.js +0 -0
  371. /package/dist/{search → knowledge}/search-quality.js +0 -0
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Action dispatch — input validation, exactly one exec call, one result shape.
3
+ *
4
+ * §4.2: dispatch never retries, never guesses sameness, and never turns a thrown
5
+ * error into an empty success. Knowledge-boundary errors keep their own code so
6
+ * the caller can tell a bad call from a denied one from a broken store.
7
+ */
8
+ import type { ActionCall, ActionContract, ActionResult, ActionSchemaObject } from '../action-contracts.js';
9
+ import { type ActionCatalog, type ActionContext } from './catalog.js';
10
+ export type ActionDispatcher = ((call: ActionCall, context: ActionContext) => Promise<ActionResult>) & {
11
+ /**
12
+ * The actions this dispatcher serves, as their contracts. Not a grant: a fact
13
+ * about the catalog it was built from, which an in-process caller with no
14
+ * stated grant of its own stands on. A caller arriving over the socket is a
15
+ * principal and is compared against the grant its credential resolves to.
16
+ *
17
+ * The contracts and not just the names, because a caller that must tell a model
18
+ * what it may call needs to say what each one is for, and deriving that from a
19
+ * second list is how the two stop agreeing.
20
+ */
21
+ readonly contracts: readonly ActionContract[];
22
+ };
23
+ export interface DispatcherOptions {
24
+ /**
25
+ * Called when a recallable write carries instruction-shaped content that is
26
+ * not secret-shaped enough to refuse. Observation, never a gate: the write
27
+ * proceeds and the host records what it saw. Absent means nobody is
28
+ * watching, which is honest rather than silently safe.
29
+ */
30
+ observeWriteWarning?: (input: {
31
+ action: string;
32
+ principalId: string;
33
+ warnings: readonly string[];
34
+ }) => void;
35
+ /**
36
+ * The receipt for one call: what was asked, what came back, how long it took.
37
+ *
38
+ * This ran in the gateway tool executor, which meant a call arriving any other
39
+ * way -- a program over the socket, a scheduled run -- left no row at all,
40
+ * while lane verification reads exactly those rows to decide whether a lane
41
+ * did what it claimed. One call, one receipt, written where every caller
42
+ * passes.
43
+ *
44
+ * It may return a reference to the receipt it wrote; dispatch hands that back
45
+ * to the caller as the result's `experienceRef` so an agent can read its own
46
+ * run. A
47
+ * thrown observer never turns a completed call into a failed one -- the
48
+ * receipt is bookkeeping and the answer is the answer -- but it is not
49
+ * swallowed silently either: the host states what it does with it.
50
+ */
51
+ observeCall?: (input: {
52
+ action: string;
53
+ /** The command id the caller issued, when it issued one. */
54
+ operationId: string | undefined;
55
+ input: unknown;
56
+ result: ActionResult;
57
+ durationMs: number;
58
+ context: ActionContext;
59
+ }) => Promise<string | undefined> | string | undefined;
60
+ }
61
+ export declare function createDispatcher(catalog: ActionCatalog, options?: DispatcherOptions): ActionDispatcher;
62
+ /**
63
+ * Time one call and hand its receipt's reference back on the result.
64
+ *
65
+ * Exported because a caller that composes its own dispatch -- a test standing a
66
+ * spy where the catalog would be -- must observe through the SAME wrapper. Two
67
+ * copies of "when is a receipt written and where does its ref land" is two
68
+ * answers to one question.
69
+ */
70
+ export declare function withCallReceipt<D extends (call: ActionCall, context: ActionContext) => Promise<ActionResult>>(dispatch: D, observeCall: NonNullable<DispatcherOptions['observeCall']>): D;
71
+ /**
72
+ * Structural validation against the contract schema — the deep semantic rules
73
+ * (ref existence, history/direction legality per view) still belong to exec.
74
+ */
75
+ export declare function validateInput(schema: ActionSchemaObject, value: unknown, path: string): string | null;
76
+ //# sourceMappingURL=dispatch.d.ts.map
@@ -0,0 +1,372 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createDispatcher = createDispatcher;
4
+ exports.withCallReceipt = withCallReceipt;
5
+ exports.validateInput = validateInput;
6
+ const judgments_js_1 = require("../knowledge/judgments.js");
7
+ const access_js_1 = require("../knowledge/access.js");
8
+ const graph_query_js_1 = require("../knowledge/graph-query.js");
9
+ const operations_js_1 = require("../runtime/operations.js");
10
+ const store_js_1 = require("../registry/store.js");
11
+ const catalog_js_1 = require("./catalog.js");
12
+ const secret_filter_js_1 = require("../memory/secret-filter.js");
13
+ function createDispatcher(catalog, options = {}) {
14
+ const runCall = async (call, context) => {
15
+ let registration;
16
+ try {
17
+ registration = catalog.entry(call.action);
18
+ }
19
+ catch (error) {
20
+ if (error instanceof catalog_js_1.UnknownActionError) {
21
+ return fail(call, 'unknown_action', 'unknown_action', error.message);
22
+ }
23
+ throw error;
24
+ }
25
+ const invalid = validateInput(registration.contract.inputSchema, call.input, 'input');
26
+ if (invalid !== null) {
27
+ return fail(call, 'invalid_input', 'invalid_input', invalid);
28
+ }
29
+ // Authority is compared here, before exec, so an ungranted action never
30
+ // reaches an action body. The grant is the principal's configured list —
31
+ // the call cannot widen it, and there is no wildcard to widen it with.
32
+ const granted = context.access.actions;
33
+ if (!Array.isArray(granted)) {
34
+ return fail(call, 'denied', 'action_grant_missing', `principal ${context.access.principalId} states no action grant`);
35
+ }
36
+ if (!granted.includes(registration.contract.name)) {
37
+ return fail(call, 'denied', 'action_not_granted', `principal ${context.access.principalId} may not call ${call.action}`);
38
+ }
39
+ const readsConnector = registration.contract.readsConnector;
40
+ if (readsConnector !== undefined) {
41
+ const named = 'fixed' in readsConnector
42
+ ? readsConnector.fixed
43
+ : call.input?.[readsConnector.fromInput];
44
+ if (typeof named !== 'string' || named === '') {
45
+ return fail(call, 'invalid_input', 'connector_unnamed', `${call.action} reads a connector but its ${'fromInput' in readsConnector ? readsConnector.fromInput : 'connector'} names none`);
46
+ }
47
+ // Absent is NO connector read, never all of them - the same fail-closed
48
+ // reading allowanceFromAccess gives the memory window below.
49
+ const grantedConnectors = context.access.connectors ?? [];
50
+ if (!grantedConnectors.includes(named)) {
51
+ // Return the caller's own connector grant to that caller, so it can correct
52
+ // the source name without exposing another principal's grant.
53
+ return fail(call, 'denied', 'connector_out_of_scope', `principal ${context.access.principalId} may not read ${named}; readable connectors: ${[...grantedConnectors].sort().join(', ') || 'none'}`);
54
+ }
55
+ }
56
+ if (registration.contract.recallableWrite === true) {
57
+ const scan = (0, secret_filter_js_1.scanMemoryWriteInput)((call.input ?? {}));
58
+ if (scan.warnings.length > 0) {
59
+ options.observeWriteWarning?.({
60
+ action: call.action,
61
+ principalId: context.access.principalId,
62
+ warnings: scan.warnings,
63
+ });
64
+ }
65
+ if (!scan.clean) {
66
+ // The matched pattern NAMES are safe to return; the matched text is not.
67
+ return fail(call, 'invalid_input',
68
+ // The label operators already grep for. The check moved; its name
69
+ // did not.
70
+ 'secret_material_refused', `refusing to persist content matching ${scan.matches.join(', ')} — a secret written here comes back through recall`);
71
+ }
72
+ }
73
+ try {
74
+ const data = await registration.exec(call.input, {
75
+ ...context,
76
+ readAllowance: readAllowanceFor(context),
77
+ operationId: call.operationId,
78
+ });
79
+ const result = { status: 'completed', data };
80
+ if (call.operationId !== undefined) {
81
+ result.operationId = call.operationId;
82
+ }
83
+ return result;
84
+ }
85
+ catch (error) {
86
+ return fail(call, failureKind(error), errorCode(error), errorMessage(error));
87
+ }
88
+ };
89
+ const dispatch = options.observeCall === undefined ? runCall : withCallReceipt(runCall, options.observeCall);
90
+ return Object.assign(dispatch, { contracts: catalog.list() });
91
+ }
92
+ /**
93
+ * Time one call and hand its receipt's reference back on the result.
94
+ *
95
+ * Exported because a caller that composes its own dispatch -- a test standing a
96
+ * spy where the catalog would be -- must observe through the SAME wrapper. Two
97
+ * copies of "when is a receipt written and where does its ref land" is two
98
+ * answers to one question.
99
+ */
100
+ function withCallReceipt(dispatch, observeCall) {
101
+ const observed = async (call, context) => {
102
+ const startedAt = Date.now();
103
+ let result;
104
+ try {
105
+ result = await dispatch(call, context);
106
+ }
107
+ catch (error) {
108
+ // One call, one receipt. A dispatch that throws instead of failing is the
109
+ // call most worth a row, not the one exempt from it, so the throw is
110
+ // written as the failure it is and then continues on its way.
111
+ try {
112
+ await observeCall({
113
+ action: call.action,
114
+ operationId: call.operationId,
115
+ input: call.input,
116
+ result: {
117
+ status: 'failed',
118
+ error: {
119
+ kind: failureKind(error),
120
+ code: thrownCode(error),
121
+ message: errorMessage(error),
122
+ },
123
+ },
124
+ durationMs: Date.now() - startedAt,
125
+ context,
126
+ });
127
+ }
128
+ catch {
129
+ // The call's own throw is the answer; a receipt that also fails must
130
+ // not replace it with a different cause.
131
+ }
132
+ throw error;
133
+ }
134
+ const ref = await observeCall({
135
+ action: call.action,
136
+ operationId: call.operationId,
137
+ input: call.input,
138
+ result,
139
+ durationMs: Date.now() - startedAt,
140
+ context,
141
+ });
142
+ // The receipt points at itself, so the agent that made the call can read
143
+ // what its own run recorded. On the envelope, never inside `data`: the
144
+ // action owns that shape, and a refusal -- the call most worth reading back
145
+ // -- has no `data` to put it in.
146
+ return ref === undefined ? result : { ...result, experienceRef: ref };
147
+ };
148
+ // Whatever the wrapped dispatch declares about itself -- `contracts`, which a
149
+ // caller with no grant of its own stands on -- survives the wrapping. A
150
+ // wrapper that drops it silently narrows the caller's authority.
151
+ return Object.assign(observed, dispatch);
152
+ }
153
+ /**
154
+ * The read window a principal's own grant states.
155
+ *
156
+ * A citation must not out-read reading. That rule used to hold only where a host
157
+ * assembled the window from a verified envelope, which meant a call arriving
158
+ * without one -- a program over the socket, a scheduled run -- got no window at
159
+ * all. The grant already says which connectors, channels and projects this
160
+ * principal may read; the same four fields ARE the window.
161
+ *
162
+ * A host that composed a narrower window still wins: this fills in only when the
163
+ * context carries none. And it fails closed the same way -- a principal whose
164
+ * grant names no connectors gets `connectors: []`, which is no raw events.
165
+ */
166
+ function allowanceFromAccess(access) {
167
+ const connectors = access.connectors ?? [];
168
+ const wideConnectors = (access.connectorWideRead ?? []).filter((name) => connectors.includes(name));
169
+ // An ordinary connector grant without a tenant is not a raw read window.
170
+ // An explicit connector-wide read is different: the owner stored-source
171
+ // reader already admits that connector across its retained channels. Keep
172
+ // only that exact intersection, never an unrelated narrow connector.
173
+ if (connectors.length > 0 && (access.tenantId ?? null) === null && wideConnectors.length === 0) {
174
+ return { connectors: [], tenantId: null };
175
+ }
176
+ return {
177
+ connectors: (access.tenantId ?? null) === null ? wideConnectors : connectors,
178
+ ...(wideConnectors.length === 0 ? {} : { wideConnectors }),
179
+ ...(access.channels ? { channels: access.channels } : {}),
180
+ ...(access.projectRefs === undefined
181
+ ? {}
182
+ : { projectIds: access.projectRefs.map((ref) => ref.id) }),
183
+ tenantId: access.tenantId ?? null,
184
+ maxObservedMs: access.maxObservedMs ?? null,
185
+ };
186
+ }
187
+ function readAllowanceFor(context) {
188
+ const allowance = context.readAllowance ?? allowanceFromAccess(context.access);
189
+ const ceiling = context.session?.replaySourceEndMs;
190
+ if (ceiling === undefined)
191
+ return allowance;
192
+ if (!Number.isSafeInteger(ceiling) || ceiling < 0) {
193
+ throw new judgments_js_1.JudgmentError('REPLAY_SOURCE_CEILING_INVALID', 'Replay source ceiling must be a nonnegative epoch millisecond integer');
194
+ }
195
+ const stated = allowance.maxSourceMs;
196
+ if (stated === undefined || stated === null) {
197
+ return { ...allowance, maxSourceMs: ceiling };
198
+ }
199
+ if (!Number.isSafeInteger(stated) || stated < 0) {
200
+ throw new judgments_js_1.JudgmentError('REPLAY_SOURCE_CEILING_INVALID', 'Read allowance source ceiling must be a nonnegative epoch millisecond integer');
201
+ }
202
+ return { ...allowance, maxSourceMs: Math.min(stated, ceiling) };
203
+ }
204
+ function fail(call, kind, code, message) {
205
+ const result = {
206
+ status: 'failed',
207
+ error: { kind, code, message },
208
+ };
209
+ if (call.operationId !== undefined) {
210
+ result.operationId = call.operationId;
211
+ }
212
+ return result;
213
+ }
214
+ function failureKind(error) {
215
+ if (error instanceof access_js_1.TwinRefNotVisibleError || thrownCode(error) === 'denied') {
216
+ return 'denied';
217
+ }
218
+ if (error instanceof graph_query_js_1.AgentGraphValidationError ||
219
+ error instanceof secret_filter_js_1.SecretMaterialRefusedError ||
220
+ thrownCode(error) === 'invalid_input') {
221
+ return 'invalid_input';
222
+ }
223
+ if (error instanceof judgments_js_1.JudgmentError ||
224
+ error instanceof operations_js_1.OperationError ||
225
+ error instanceof store_js_1.RegistryError) {
226
+ return 'failed';
227
+ }
228
+ return 'internal';
229
+ }
230
+ /**
231
+ * A thrown value's own `code`, when it states one.
232
+ *
233
+ * `errorCode` answers with the class NAME for a custom Error, which is what a
234
+ * failure result wants. A receipt wants the cause, and a thrower that carries a
235
+ * structured `code` has already named it.
236
+ */
237
+ function thrownCode(error) {
238
+ const stated = error?.code;
239
+ return typeof stated === 'string' && stated !== '' ? stated : errorCode(error);
240
+ }
241
+ function errorCode(error) {
242
+ if (error instanceof judgments_js_1.JudgmentError ||
243
+ error instanceof operations_js_1.OperationError ||
244
+ error instanceof store_js_1.RegistryError) {
245
+ return error.code;
246
+ }
247
+ if (error instanceof Error && error.name !== 'Error') {
248
+ return error.name;
249
+ }
250
+ return 'internal_error';
251
+ }
252
+ function errorMessage(error) {
253
+ return error instanceof Error ? error.message : String(error);
254
+ }
255
+ /**
256
+ * Structural validation against the contract schema — the deep semantic rules
257
+ * (ref existence, history/direction legality per view) still belong to exec.
258
+ */
259
+ function validateInput(schema, value, path) {
260
+ if (schema.const !== undefined && value !== schema.const) {
261
+ return `${path} must be ${JSON.stringify(schema.const)}.`;
262
+ }
263
+ if (schema.enum !== undefined && !schema.enum.includes(value)) {
264
+ return `${path} must be one of ${schema.enum.map(String).join(', ')}.`;
265
+ }
266
+ if (schema.type !== undefined) {
267
+ const mismatch = typeMismatch(schema.type, value);
268
+ if (mismatch !== null) {
269
+ return `${path} ${mismatch}.`;
270
+ }
271
+ }
272
+ if (schema.oneOf !== undefined) {
273
+ const matches = schema.oneOf.filter((sub) => validateInput(sub, value, path) === null).length;
274
+ if (matches !== 1) {
275
+ return `${path} must match exactly one allowed shape (${matches} matched).`;
276
+ }
277
+ }
278
+ if (typeof value === 'number') {
279
+ if (schema.minimum !== undefined && value < schema.minimum) {
280
+ return `${path} must be >= ${schema.minimum}.`;
281
+ }
282
+ if (schema.maximum !== undefined && value > schema.maximum) {
283
+ return `${path} must be <= ${schema.maximum}.`;
284
+ }
285
+ }
286
+ if (typeof value === 'string' &&
287
+ schema.minLength !== undefined &&
288
+ value.length < schema.minLength) {
289
+ return `${path} must be at least ${schema.minLength} characters.`;
290
+ }
291
+ if (typeof value === 'string' &&
292
+ schema.maxLength !== undefined &&
293
+ value.length > schema.maxLength) {
294
+ return `${path} must be at most ${schema.maxLength} characters.`;
295
+ }
296
+ if (typeof value === 'string' &&
297
+ schema.pattern !== undefined &&
298
+ !new RegExp(schema.pattern).test(value)) {
299
+ return `${path} must match ${schema.pattern}.`;
300
+ }
301
+ if (schema.type === 'object' &&
302
+ typeof value === 'object' &&
303
+ value !== null &&
304
+ !Array.isArray(value)) {
305
+ const objectValue = value;
306
+ for (const key of schema.required ?? []) {
307
+ if (objectValue[key] === undefined) {
308
+ return `${path}.${key} is required.`;
309
+ }
310
+ }
311
+ const properties = schema.properties ?? {};
312
+ for (const [key, propertyValue] of Object.entries(objectValue)) {
313
+ // undefined is absent — JSON cannot carry it
314
+ if (propertyValue === undefined) {
315
+ continue;
316
+ }
317
+ const propertySchema = properties[key];
318
+ if (propertySchema === undefined) {
319
+ if (schema.additionalProperties === false) {
320
+ return `${path}.${key} is not an allowed property.`;
321
+ }
322
+ continue;
323
+ }
324
+ const nested = validateInput(propertySchema, propertyValue, `${path}.${key}`);
325
+ if (nested !== null) {
326
+ return nested;
327
+ }
328
+ }
329
+ }
330
+ if (schema.type === 'array' &&
331
+ Array.isArray(value) &&
332
+ schema.minItems !== undefined &&
333
+ value.length < schema.minItems) {
334
+ return `${path} must carry at least ${schema.minItems} item(s).`;
335
+ }
336
+ if (schema.type === 'array' &&
337
+ Array.isArray(value) &&
338
+ schema.maxItems !== undefined &&
339
+ value.length > schema.maxItems) {
340
+ return `${path} must carry at most ${schema.maxItems} item(s).`;
341
+ }
342
+ if (schema.type === 'array' && Array.isArray(value) && schema.items !== undefined) {
343
+ for (let i = 0; i < value.length; i += 1) {
344
+ const nested = validateInput(schema.items, value[i], `${path}[${i}]`);
345
+ if (nested !== null) {
346
+ return nested;
347
+ }
348
+ }
349
+ }
350
+ return null;
351
+ }
352
+ function typeMismatch(type, value) {
353
+ switch (type) {
354
+ case 'object':
355
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
356
+ ? null
357
+ : 'must be an object';
358
+ case 'array':
359
+ return Array.isArray(value) ? null : 'must be an array';
360
+ case 'string':
361
+ return typeof value === 'string' ? null : 'must be a string';
362
+ case 'number':
363
+ return typeof value === 'number' && Number.isFinite(value) ? null : 'must be a number';
364
+ case 'integer':
365
+ return typeof value === 'number' && Number.isInteger(value) ? null : 'must be an integer';
366
+ case 'boolean':
367
+ return typeof value === 'boolean' ? null : 'must be a boolean';
368
+ case 'null':
369
+ return value === null ? null : 'must be null';
370
+ }
371
+ }
372
+ //# sourceMappingURL=dispatch.js.map
@@ -12,8 +12,8 @@
12
12
  * - serialize normalized value via JSON.stringify (after normalization)
13
13
  * - hash canonical JSON string with SHA-256 over UTF-8 bytes → 32-byte Buffer
14
14
  *
15
- * No top-level await. No ESM-only runtime dependency. Safe for CJS consumers
16
- * (mcp-server, claude-code-plugin) via package export `./canonicalize`.
15
+ * No top-level await. No ESM-only runtime dependency. Safe for CJS callers via the
16
+ * package export `./canonicalize`.
17
17
  *
18
18
  * @module canonicalize
19
19
  */
@@ -13,8 +13,8 @@
13
13
  * - serialize normalized value via JSON.stringify (after normalization)
14
14
  * - hash canonical JSON string with SHA-256 over UTF-8 bytes → 32-byte Buffer
15
15
  *
16
- * No top-level await. No ESM-only runtime dependency. Safe for CJS consumers
17
- * (mcp-server, claude-code-plugin) via package export `./canonicalize`.
16
+ * No top-level await. No ESM-only runtime dependency. Safe for CJS callers via the
17
+ * package export `./canonicalize`.
18
18
  *
19
19
  * @module canonicalize
20
20
  */
@@ -62,7 +62,7 @@ function normalize(value, path = '$') {
62
62
  if (type === 'object') {
63
63
  const obj = value;
64
64
  const sortedKeys = Object.keys(obj).sort();
65
- const out = {};
65
+ const out = Object.create(null);
66
66
  for (const key of sortedKeys) {
67
67
  out[key] = normalize(obj[key], `${path}.${key}`);
68
68
  }
@@ -0,0 +1,33 @@
1
+ import type { ActionContract, ActionResult, ClientSessionFacts } from '../action-contracts.js';
2
+ export interface ClientOptions {
3
+ /** The private socket the runtime owns. No path guessing — product assembly states it. */
4
+ socketPath: string;
5
+ /**
6
+ * Append-only JSONL journal of issued operations: {at, operationId, action,
7
+ * payloadHash}. Written before send; a failed write fails the call closed,
8
+ * because an operation without a recovery record must not run.
9
+ */
10
+ journalPath: string;
11
+ /** Opaque session credential; the server resolves it to access. */
12
+ credential?: string;
13
+ /** Optional cap on one request; a timeout after connect reports `unknown`. */
14
+ timeoutMs?: number;
15
+ }
16
+ export interface ClientCall {
17
+ action: string;
18
+ input?: unknown;
19
+ session?: ClientSessionFacts;
20
+ /** Reuse this id only to retransmit the same call. */
21
+ operationId?: string;
22
+ }
23
+ export interface Client {
24
+ /** Every contract the server executes — the whole callable surface. */
25
+ describe(): Promise<ActionContract[]>;
26
+ /** One contract by name or alias. */
27
+ describe(name: string): Promise<ActionContract>;
28
+ call(call: ClientCall): Promise<ActionResult>;
29
+ /** The server's bound record of an issued operation. */
30
+ getOperation(operationId: string): Promise<ActionResult>;
31
+ }
32
+ export declare function createClient(options: ClientOptions): Client;
33
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createClient = createClient;
4
+ /**
5
+ * Client — the one caller-side library for CLI and MCP.
6
+ *
7
+ * §291: the client issues the operationId for a call and writes it to the
8
+ * journal — action plus payload hash — BEFORE the request is sent, so a retry
9
+ * always names the same id. For knowledge commands that id is the commandId;
10
+ * an input carrying a different commandId conflicts before anything writes.
11
+ *
12
+ * §297: a confirmed failure is `failed`; a transport break after the request
13
+ * may have committed is `unknown` and keeps the original operationId. A
14
+ * disconnected call is never reported as unsaved.
15
+ */
16
+ const node_crypto_1 = require("node:crypto");
17
+ const node_fs_1 = require("node:fs");
18
+ const node_path_1 = require("node:path");
19
+ const canonicalize_js_1 = require("../canonicalize.js");
20
+ const ipc_js_1 = require("./ipc.js");
21
+ function createClient(options) {
22
+ const journal = (entry) => {
23
+ (0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(options.journalPath), { recursive: true });
24
+ (0, node_fs_1.appendFileSync)(options.journalPath, `${JSON.stringify(entry)}\n`, 'utf8');
25
+ };
26
+ const payloadHash = (call, operationId) => (0, node_crypto_1.createHash)('sha256')
27
+ .update((0, canonicalize_js_1.canonicalizeJSON)(JSON.parse(JSON.stringify({ action: call.action, input: call.input ?? null, operationId }))))
28
+ .digest('hex');
29
+ const call = async (request) => {
30
+ const operationId = request.operationId ?? `op_${(0, node_crypto_1.randomUUID)()}`;
31
+ const inputCommandId = typeof request.input === 'object' && request.input !== null
32
+ ? request.input.commandId
33
+ : undefined;
34
+ if (typeof inputCommandId === 'string' && inputCommandId !== operationId) {
35
+ return {
36
+ status: 'failed',
37
+ operationId,
38
+ error: {
39
+ kind: 'invalid_input',
40
+ code: 'COMMAND_CONFLICT',
41
+ message: `input.commandId ${inputCommandId} disagrees with operationId ${operationId}: ` +
42
+ 'a call has exactly one command id — retransmit reuses it, a new call gets a new one',
43
+ },
44
+ };
45
+ }
46
+ try {
47
+ journal({
48
+ at: new Date().toISOString(),
49
+ operationId,
50
+ action: request.action,
51
+ payloadHash: payloadHash(request, operationId),
52
+ });
53
+ }
54
+ catch (error) {
55
+ return {
56
+ status: 'failed',
57
+ operationId,
58
+ error: {
59
+ kind: 'internal',
60
+ code: 'journal_write_failed',
61
+ message: `operation journal write failed before send: ${error instanceof Error ? error.message : String(error)}`,
62
+ },
63
+ };
64
+ }
65
+ let wire;
66
+ try {
67
+ wire = await (0, ipc_js_1.sendIpcRequest)(options.socketPath, {
68
+ requestId: (0, ipc_js_1.newRequestId)(),
69
+ kind: 'call',
70
+ credential: options.credential,
71
+ action: request.action,
72
+ input: request.input,
73
+ operationId,
74
+ session: request.session,
75
+ }, { timeoutMs: options.timeoutMs });
76
+ }
77
+ catch (error) {
78
+ if (error instanceof ipc_js_1.IpcTransportError && error.phase === 'connect') {
79
+ return {
80
+ status: 'failed',
81
+ operationId,
82
+ error: {
83
+ kind: 'internal',
84
+ code: 'ipc_unavailable',
85
+ message: `runtime socket unreachable: ${error.message}`,
86
+ },
87
+ };
88
+ }
89
+ return {
90
+ status: 'unknown',
91
+ operationId,
92
+ error: {
93
+ kind: 'internal',
94
+ code: 'ipc_lost_response',
95
+ message: `the answer was lost after the call may have committed — ` +
96
+ `check operation.get(${operationId}) or resend the same operationId`,
97
+ },
98
+ };
99
+ }
100
+ if (!wire.ok) {
101
+ return { status: 'failed', operationId, error: wire.error };
102
+ }
103
+ return wire.result;
104
+ };
105
+ const describe = async (name) => {
106
+ const wire = await (0, ipc_js_1.sendIpcRequest)(options.socketPath, {
107
+ requestId: (0, ipc_js_1.newRequestId)(),
108
+ kind: 'describe',
109
+ credential: options.credential,
110
+ name,
111
+ }, { timeoutMs: options.timeoutMs });
112
+ if (!wire.ok) {
113
+ throw new Error(`describe failed: [${wire.error.code}] ${wire.error.message}`);
114
+ }
115
+ return wire.result;
116
+ };
117
+ return {
118
+ describe: describe,
119
+ call,
120
+ getOperation: (operationId) => call({ action: 'operation.get', input: { operationId } }),
121
+ };
122
+ }
123
+ //# sourceMappingURL=client.js.map