@astrosheep/keiyaku 4.5.11 → 4.5.13

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 (272) hide show
  1. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +135 -377
  2. package/build/integrations/pi/keiyaku.ts +11 -116
  3. package/build/src/akuma/akuma-errors.d.ts +1 -0
  4. package/build/src/akuma/akuma-errors.js +1 -0
  5. package/build/src/akuma/akuma-handle.d.ts +1 -0
  6. package/build/src/akuma/akuma-handle.js +6 -7
  7. package/build/src/akuma/akuma-product.d.ts +6 -8
  8. package/build/src/akuma/akuma-product.js +141 -57
  9. package/build/src/akuma/akuma.d.ts +5 -7
  10. package/build/src/akuma/akuma.js +1 -22
  11. package/build/src/akuma/archetype.d.ts +6 -5
  12. package/build/src/akuma/archetype.js +137 -38
  13. package/build/src/akuma/body.d.ts +5 -5
  14. package/build/src/akuma/body.js +223 -63
  15. package/build/src/akuma/call-input.d.ts +4 -0
  16. package/build/src/akuma/call-input.js +21 -0
  17. package/build/src/akuma/call-request.d.ts +5 -8
  18. package/build/src/akuma/call-request.js +28 -73
  19. package/build/src/akuma/fleet-execution.d.ts +26 -0
  20. package/build/src/akuma/fleet-execution.js +109 -0
  21. package/build/src/{library/fleet-result.d.ts → akuma/fleet-observation.d.ts} +13 -57
  22. package/build/src/{library/fleet-result.js → akuma/fleet-observation.js} +4 -25
  23. package/build/src/akuma/fleet-request.d.ts +122 -0
  24. package/build/src/akuma/fleet-request.js +168 -0
  25. package/build/src/akuma/heart/facts.d.ts +23 -0
  26. package/build/src/akuma/heart/facts.js +7 -0
  27. package/build/src/akuma/heart/index.d.ts +43 -4
  28. package/build/src/akuma/heart/index.js +107 -7
  29. package/build/src/akuma/heart/request-authority.d.ts +2 -0
  30. package/build/src/akuma/heart/request-authority.js +28 -3
  31. package/build/src/akuma/heart/request-rows.d.ts +2 -0
  32. package/build/src/akuma/heart/request-rows.js +24 -5
  33. package/build/src/akuma/heart/rows.d.ts +4 -1
  34. package/build/src/akuma/heart/rows.js +46 -19
  35. package/build/src/akuma/heart/schema.d.ts +1 -1
  36. package/build/src/akuma/heart/schema.js +28 -6
  37. package/build/src/akuma/heart/storage.d.ts +1 -1
  38. package/build/src/akuma/heart/tells.d.ts +29 -0
  39. package/build/src/akuma/heart/tells.js +136 -5
  40. package/build/src/akuma/heart/timeline.js +9 -3
  41. package/build/src/akuma/projection-read.js +36 -3
  42. package/build/src/akuma/projection.js +3 -4
  43. package/build/src/akuma/provider.d.ts +4 -0
  44. package/build/src/akuma/provider.js +56 -3
  45. package/build/src/akuma/providers/claude/index.js +3 -0
  46. package/build/src/akuma/providers/codex-app-server/index.js +14 -12
  47. package/build/src/akuma/providers/pi/index.js +7 -1
  48. package/build/src/akuma/publication.js +65 -49
  49. package/build/src/akuma/request-lifecycle.d.ts +5 -4
  50. package/build/src/akuma/request-lifecycle.js +29 -16
  51. package/build/src/akuma/request-rendezvous.d.ts +15 -12
  52. package/build/src/akuma/request-rendezvous.js +80 -51
  53. package/build/src/akuma/request-serve.d.ts +1 -2
  54. package/build/src/akuma/request-serve.js +94 -39
  55. package/build/src/akuma/request-wire.d.ts +57 -26
  56. package/build/src/akuma/request-wire.js +64 -25
  57. package/build/src/akuma/turn-drive.d.ts +5 -4
  58. package/build/src/akuma/turn-drive.js +27 -11
  59. package/build/src/akuma-body.d.ts +4 -6
  60. package/build/src/akuma-body.js +19 -17
  61. package/build/src/bounded-list.d.ts +8 -0
  62. package/build/src/bounded-list.js +14 -0
  63. package/build/src/cli/accepted.d.ts +1 -1
  64. package/build/src/cli/accepted.js +1 -0
  65. package/build/src/cli/commands/akuma-invoke.js +1 -25
  66. package/build/src/cli/commands/contract-help.d.ts +5 -2
  67. package/build/src/cli/commands/contract-help.js +62 -12
  68. package/build/src/cli/commands/contract-invoke.d.ts +5 -0
  69. package/build/src/cli/commands/contract-invoke.js +26 -1
  70. package/build/src/cli/commands/contract.js +50 -18
  71. package/build/src/cli/commands/task-invoke.js +10 -2
  72. package/build/src/cli/commands/task-query.js +3 -4
  73. package/build/src/cli/coordinates.d.ts +13 -0
  74. package/build/src/cli/coordinates.js +38 -24
  75. package/build/src/cli/draft.d.ts +1 -1
  76. package/build/src/cli/invoke.js +14 -1
  77. package/build/src/cli/render/akuma-activity.d.ts +0 -1
  78. package/build/src/cli/render/akuma-activity.js +5 -38
  79. package/build/src/cli/render/akuma.js +4 -1
  80. package/build/src/cli/render/audit.js +4 -1
  81. package/build/src/cli/render/catalog.js +13 -39
  82. package/build/src/cli/render/contract.js +4 -14
  83. package/build/src/cli/render/kanshi-akuma.js +3 -8
  84. package/build/src/cli/render/kanshi.js +8 -34
  85. package/build/src/cli/render/nuke.js +7 -3
  86. package/build/src/cli/render/receipt.d.ts +1 -0
  87. package/build/src/cli/render/receipt.js +8 -0
  88. package/build/src/cli/render/refusal.js +4 -3
  89. package/build/src/cli/render/task.js +4 -37
  90. package/build/src/cli/render/terminal.d.ts +2 -6
  91. package/build/src/cli/render/terminal.js +4 -9
  92. package/build/src/cli/result.d.ts +2 -1
  93. package/build/src/contract-guidance.js +13 -3
  94. package/build/src/contract-worktree.d.ts +1 -0
  95. package/build/src/contract-worktree.js +26 -2
  96. package/build/src/core/facts/codec.d.ts +2 -1
  97. package/build/src/core/facts/codec.js +3 -0
  98. package/build/src/core/facts/gate.d.ts +2 -1
  99. package/build/src/core/facts/gate.js +63 -0
  100. package/build/src/core/verbs/abandon.d.ts +2 -1
  101. package/build/src/core/verbs/abandon.js +16 -0
  102. package/build/src/core/verbs/amend.d.ts +2 -1
  103. package/build/src/core/verbs/amend.js +20 -0
  104. package/build/src/core/verbs/arc.d.ts +2 -1
  105. package/build/src/core/verbs/arc.js +16 -0
  106. package/build/src/core/verbs/attestation.d.ts +2 -1
  107. package/build/src/core/verbs/attestation.js +16 -0
  108. package/build/src/core/verbs/bind.d.ts +2 -1
  109. package/build/src/core/verbs/bind.js +16 -0
  110. package/build/src/core/verbs/deliver.d.ts +2 -1
  111. package/build/src/core/verbs/deliver.js +16 -0
  112. package/build/src/core/verbs/placement.d.ts +2 -1
  113. package/build/src/core/verbs/placement.js +58 -1
  114. package/build/src/dispatch/association.d.ts +13 -0
  115. package/build/src/dispatch/association.js +20 -0
  116. package/build/src/dispatch/index.d.ts +6 -0
  117. package/build/src/dispatch/index.js +27 -3
  118. package/build/src/git/hooks.d.ts +9 -1
  119. package/build/src/git/hooks.js +79 -1
  120. package/build/src/git/nuke.d.ts +2 -1
  121. package/build/src/git/nuke.js +6 -11
  122. package/build/src/git/private-state-seat.d.ts +26 -1
  123. package/build/src/git/private-state-seat.js +78 -13
  124. package/build/src/git/process.d.ts +2 -0
  125. package/build/src/git/reconcile.d.ts +1 -2
  126. package/build/src/git/reconcile.js +0 -6
  127. package/build/src/git/repository.d.ts +0 -2
  128. package/build/src/git/repository.js +27 -25
  129. package/build/src/git/result-codec.d.ts +29 -0
  130. package/build/src/git/result-codec.js +306 -0
  131. package/build/src/git/target-placement.js +2 -8
  132. package/build/src/git/workspace.d.ts +2 -0
  133. package/build/src/git/workspace.js +4 -0
  134. package/build/src/index.d.ts +1 -0
  135. package/build/src/kanshi/fleet.js +1 -1
  136. package/build/src/kanshi/read.js +55 -28
  137. package/build/src/kanshi/report.d.ts +4 -3
  138. package/build/src/kanshi/select.js +14 -1
  139. package/build/src/library/address.d.ts +1 -0
  140. package/build/src/library/address.js +4 -7
  141. package/build/src/library/akuma-creation.d.ts +5 -3
  142. package/build/src/library/akuma-creation.js +90 -33
  143. package/build/src/library/audit.js +2 -1
  144. package/build/src/library/catalog.d.ts +10 -2
  145. package/build/src/library/catalog.js +65 -25
  146. package/build/src/library/composition.d.ts +1 -0
  147. package/build/src/library/composition.js +1 -0
  148. package/build/src/library/configuration.d.ts +4 -21
  149. package/build/src/library/configuration.js +2 -158
  150. package/build/src/library/continuation.d.ts +20 -1
  151. package/build/src/library/continuation.js +36 -0
  152. package/build/src/library/contract-bind.d.ts +1 -0
  153. package/build/src/library/contract-bind.js +16 -5
  154. package/build/src/library/contract-forwarding.d.ts +2 -2
  155. package/build/src/library/contract-forwarding.js +18 -4
  156. package/build/src/library/contract-handle.js +4 -3
  157. package/build/src/library/contract-operations.d.ts +5 -9
  158. package/build/src/library/contract-operations.js +34 -47
  159. package/build/src/library/contract.d.ts +11 -2
  160. package/build/src/library/contract.js +21 -1
  161. package/build/src/library/delivery.d.ts +4 -1
  162. package/build/src/library/delivery.js +47 -0
  163. package/build/src/library/fleet.d.ts +4 -136
  164. package/build/src/library/fleet.js +31 -315
  165. package/build/src/library/keiyaku.d.ts +7 -3
  166. package/build/src/library/keiyaku.js +1 -0
  167. package/build/src/library/mutation.d.ts +431 -3
  168. package/build/src/library/mutation.js +192 -19
  169. package/build/src/library/nuke.d.ts +7 -1
  170. package/build/src/library/nuke.js +18 -4
  171. package/build/src/library/reconcile.d.ts +14 -0
  172. package/build/src/library/reconcile.js +22 -8
  173. package/build/src/library/refusal.d.ts +9 -1
  174. package/build/src/library/refusal.js +76 -0
  175. package/build/src/library/region.d.ts +0 -8
  176. package/build/src/library/region.js +1 -29
  177. package/build/src/library/result-codec.d.ts +2 -0
  178. package/build/src/library/result-codec.js +12 -0
  179. package/build/src/markdown/lex.js +9 -2
  180. package/build/src/markdown/types.d.ts +2 -1
  181. package/build/src/markdown/types.js +3 -1
  182. package/build/src/plugin/akuma-signals.d.ts +12 -0
  183. package/build/src/plugin/akuma-signals.js +14 -0
  184. package/build/src/plugin/public.d.ts +51 -0
  185. package/build/src/plugin/public.js +1 -0
  186. package/build/src/plugin/runtime.d.ts +14 -0
  187. package/build/src/plugin/runtime.js +357 -0
  188. package/build/src/protocol/amend.js +3 -3
  189. package/build/src/protocol/attempt.d.ts +2 -1
  190. package/build/src/protocol/attempt.js +1 -1
  191. package/build/src/protocol/audit.d.ts +1 -1
  192. package/build/src/protocol/audit.js +1 -1
  193. package/build/src/protocol/bind.d.ts +3 -1
  194. package/build/src/protocol/bind.js +26 -0
  195. package/build/src/protocol/completion.js +0 -1
  196. package/build/src/protocol/deliver.d.ts +1 -1
  197. package/build/src/protocol/deliver.js +136 -57
  198. package/build/src/protocol/intent.d.ts +0 -1
  199. package/build/src/protocol/intent.js +0 -1
  200. package/build/src/protocol/operations.d.ts +9 -2
  201. package/build/src/protocol/operations.js +16 -1
  202. package/build/src/protocol/outcome.d.ts +3 -0
  203. package/build/src/protocol/outcome.js +17 -1
  204. package/build/src/protocol/placement.js +10 -3
  205. package/build/src/protocol/read/status.d.ts +8 -0
  206. package/build/src/protocol/read/status.js +49 -0
  207. package/build/src/protocol/reintegrate.js +10 -3
  208. package/build/src/protocol/result-codec.d.ts +22 -0
  209. package/build/src/protocol/result-codec.js +442 -0
  210. package/build/src/protocol/review.d.ts +1 -1
  211. package/build/src/protocol/review.js +81 -46
  212. package/build/src/protocol/run.d.ts +22 -2
  213. package/build/src/protocol/run.js +119 -29
  214. package/build/src/runtime/proc/lifecycle.js +1 -1
  215. package/build/src/runtime/proc/line-rpc.d.ts +7 -1
  216. package/build/src/runtime/proc/line-rpc.js +49 -9
  217. package/build/src/runtime/proc/run.d.ts +0 -1
  218. package/build/src/runtime/proc/run.js +1 -11
  219. package/build/src/runtime/proc/termination.d.ts +1 -0
  220. package/build/src/runtime/proc/termination.js +63 -18
  221. package/build/src/runtime/proc/windows-launch.exe +0 -0
  222. package/build/src/settings.d.ts +10 -0
  223. package/build/src/settings.js +88 -2
  224. package/build/src/settlement/result-codec.d.ts +2 -0
  225. package/build/src/settlement/result-codec.js +56 -0
  226. package/build/src/settlement/settle.d.ts +5 -12
  227. package/build/src/settlement/settle.js +60 -55
  228. package/build/src/task/board.d.ts +3 -0
  229. package/build/src/task/board.js +22 -4
  230. package/build/src/task/catalog.d.ts +13 -2
  231. package/build/src/task/catalog.js +59 -5
  232. package/build/src/task/compose.d.ts +4 -2
  233. package/build/src/task/compose.js +56 -30
  234. package/build/src/task/created-observation.d.ts +39 -0
  235. package/build/src/task/created-observation.js +26 -0
  236. package/build/src/task/identity.d.ts +6 -0
  237. package/build/src/task/identity.js +48 -7
  238. package/build/src/task/index.d.ts +4 -3
  239. package/build/src/task/index.js +19 -16
  240. package/build/src/task/input.d.ts +3 -1
  241. package/build/src/task/input.js +7 -4
  242. package/build/src/task/lifecycle-operations.d.ts +6 -0
  243. package/build/src/task/lifecycle-operations.js +116 -0
  244. package/build/src/task/mutation-result.d.ts +762 -20
  245. package/build/src/task/mutation-result.js +34 -9
  246. package/build/src/task/mutation.d.ts +4 -9
  247. package/build/src/task/mutation.js +17 -52
  248. package/build/src/task/operation-types.d.ts +114 -0
  249. package/build/src/task/operation-types.js +1 -0
  250. package/build/src/task/operations.d.ts +6 -113
  251. package/build/src/task/operations.js +75 -117
  252. package/build/src/task/query.d.ts +8 -11
  253. package/build/src/task/query.js +7 -14
  254. package/build/src/task/store.d.ts +11 -1
  255. package/build/src/task/store.js +169 -55
  256. package/build/src/task/view.d.ts +4 -0
  257. package/build/src/task/view.js +7 -0
  258. package/build/src/verification/declaration.d.ts +1 -0
  259. package/build/src/verification/declaration.js +18 -1
  260. package/build/src/verification/execution.d.ts +0 -1
  261. package/build/src/verification/execution.js +5 -5
  262. package/build/src/world.d.ts +0 -2
  263. package/build/src/world.js +3 -7
  264. package/package.json +17 -5
  265. package/build/src/cli/square-edge.d.ts +0 -7
  266. package/build/src/cli/square-edge.js +0 -159
  267. package/build/src/git/ref-migration.d.ts +0 -22
  268. package/build/src/git/ref-migration.js +0 -55
  269. package/build/src/library/contract-forwarding-reconciliation-result.d.ts +0 -102
  270. package/build/src/library/contract-forwarding-reconciliation-result.js +0 -92
  271. package/build/src/library/contract-forwarding-result.d.ts +0 -4270
  272. package/build/src/library/contract-forwarding-result.js +0 -521
@@ -1,4 +1,4 @@
1
- const HEART_SCHEMA_VERSION = 21;
1
+ const HEART_SCHEMA_VERSION = 24;
2
2
  const LEASH_SCHEMA_VERSION = 4;
3
3
  function assertSchemaVersion(database, table, expected) {
4
4
  const row = database.prepare(`SELECT version FROM ${table} WHERE singleton = 1`).get();
@@ -53,16 +53,23 @@ export const HEART_SCHEMA = `
53
53
  body_sequence INTEGER NOT NULL REFERENCES bodies(sequence),
54
54
  started_at TEXT NOT NULL,
55
55
  end_sequence INTEGER UNIQUE REFERENCES timeline(sequence) ON DELETE SET NULL,
56
- outcome TEXT CHECK (outcome IN ('answered', 'failed')),
56
+ outcome TEXT CHECK (outcome IN ('answered', 'failed', 'invalid-output')),
57
57
  history_id TEXT UNIQUE,
58
58
  session_json TEXT CHECK (session_json IS NULL OR json_valid(session_json)),
59
59
  answer TEXT,
60
+ answer_json TEXT CHECK (answer_json IS NULL OR json_valid(answer_json)),
61
+ schema_json TEXT CHECK (schema_json IS NULL OR json_valid(schema_json)),
60
62
  diagnostic TEXT,
61
63
  completed_at TEXT,
62
64
  CHECK (
63
- (outcome = 'answered' AND session_json IS NOT NULL AND answer IS NOT NULL AND diagnostic IS NULL)
64
- OR (outcome = 'failed' AND history_id IS NULL AND session_json IS NULL AND answer IS NULL AND diagnostic IS NOT NULL)
65
- OR (outcome IS NULL AND end_sequence IS NULL AND history_id IS NULL AND session_json IS NULL AND answer IS NULL AND diagnostic IS NULL AND completed_at IS NULL)
65
+ (outcome = 'answered' AND session_json IS NOT NULL AND answer IS NOT NULL AND diagnostic IS NULL
66
+ AND ((schema_json IS NULL AND answer_json IS NULL) OR (schema_json IS NOT NULL AND answer_json IS NOT NULL)))
67
+ OR (outcome = 'failed' AND history_id IS NULL AND session_json IS NULL AND answer IS NULL
68
+ AND answer_json IS NULL AND diagnostic IS NOT NULL)
69
+ OR (outcome = 'invalid-output' AND answer IS NOT NULL AND answer_json IS NULL
70
+ AND diagnostic IS NOT NULL AND schema_json IS NOT NULL)
71
+ OR (outcome IS NULL AND end_sequence IS NULL AND history_id IS NULL AND session_json IS NULL
72
+ AND answer IS NULL AND answer_json IS NULL AND diagnostic IS NULL AND completed_at IS NULL)
66
73
  )
67
74
  ) STRICT;
68
75
  CREATE TABLE IF NOT EXISTS timeline (
@@ -85,8 +92,14 @@ export const HEART_SCHEMA = `
85
92
  id TEXT PRIMARY KEY,
86
93
  sequence INTEGER NOT NULL UNIQUE REFERENCES timeline(sequence) ON DELETE CASCADE,
87
94
  body TEXT NOT NULL,
95
+ schema_json TEXT CHECK (schema_json IS NULL OR json_valid(schema_json)),
88
96
  recorded_at TEXT NOT NULL
89
97
  ) STRICT;
98
+ CREATE TABLE IF NOT EXISTS tell_bindings (
99
+ tell_id TEXT PRIMARY KEY REFERENCES tells(id) ON DELETE CASCADE,
100
+ turn_sequence INTEGER NOT NULL REFERENCES turns(sequence) ON DELETE CASCADE,
101
+ bound_at TEXT NOT NULL
102
+ ) STRICT;
90
103
  CREATE TABLE IF NOT EXISTS tell_deliveries (
91
104
  sequence INTEGER PRIMARY KEY AUTOINCREMENT,
92
105
  tell_id TEXT NOT NULL REFERENCES tells(id) ON DELETE CASCADE,
@@ -115,6 +128,13 @@ export const HEART_SCHEMA = `
115
128
  ON tell_receipts(tell_id, kind) WHERE evidence = 'exact';
116
129
  CREATE UNIQUE INDEX IF NOT EXISTS tell_receipts_fence
117
130
  ON tell_receipts(turn_sequence, fence, kind) WHERE evidence = 'fence';
131
+ CREATE TABLE IF NOT EXISTS tell_dispositions (
132
+ body_sequence INTEGER NOT NULL REFERENCES bodies(sequence),
133
+ tell_id TEXT NOT NULL REFERENCES tells(id),
134
+ decided_at TEXT NOT NULL,
135
+ resolved_at TEXT,
136
+ PRIMARY KEY (body_sequence, tell_id)
137
+ ) STRICT;
118
138
  CREATE TABLE IF NOT EXISTS requests (
119
139
  sequence INTEGER PRIMARY KEY AUTOINCREMENT,
120
140
  id TEXT NOT NULL UNIQUE,
@@ -122,7 +142,7 @@ export const HEART_SCHEMA = `
122
142
  action TEXT NOT NULL,
123
143
  payload_json TEXT NOT NULL CHECK (json_valid(payload_json)),
124
144
  admitted_at TEXT NOT NULL,
125
- state TEXT NOT NULL CHECK (state IN ('admitted', 'reserved', 'served', 'refused', 'voided')),
145
+ state TEXT NOT NULL CHECK (state IN ('admitted', 'reserved', 'begun', 'served', 'refused', 'voided', 'unproven')),
126
146
  child TEXT,
127
147
  service_json TEXT CHECK (service_json IS NULL OR json_valid(service_json)),
128
148
  diagnostic TEXT,
@@ -131,12 +151,14 @@ export const HEART_SCHEMA = `
131
151
  (state = 'admitted' AND child IS NULL AND service_json IS NULL AND diagnostic IS NULL AND evidence IS NULL)
132
152
  OR (state = 'reserved' AND child IS NOT NULL AND service_json IS NULL
133
153
  AND diagnostic IS NULL AND evidence IS NULL)
154
+ OR (state = 'begun' AND child IS NULL AND service_json IS NULL AND diagnostic IS NULL AND evidence IS NULL)
134
155
  OR (state = 'served'
135
156
  AND ((child IS NOT NULL AND service_json IS NULL)
136
157
  OR (child IS NULL AND service_json IS NOT NULL))
137
158
  AND diagnostic IS NULL AND evidence IS NULL)
138
159
  OR (state = 'refused' AND child IS NULL AND service_json IS NULL AND diagnostic IS NOT NULL AND evidence IS NULL)
139
160
  OR (state = 'voided' AND child IS NULL AND service_json IS NULL AND diagnostic IS NULL AND evidence IS NOT NULL)
161
+ OR (state = 'unproven' AND child IS NULL AND service_json IS NULL AND diagnostic IS NULL AND evidence IS NOT NULL)
140
162
  )
141
163
  ) STRICT;
142
164
  CREATE TABLE IF NOT EXISTS control (
@@ -39,7 +39,7 @@ export declare class HeldAkumaLeash {
39
39
  target: StopFact;
40
40
  result: "recorded" | "already-killed";
41
41
  }> | null>;
42
- recordInterruptTell(paths: AkumaPaths, tell: Omit<TellFact, "sequence" | "state" | "deliveries">): Promise<Readonly<{
42
+ recordInterruptTell(paths: AkumaPaths, tell: Omit<TellFact, "sequence" | "state" | "deliveries" | "binding">): Promise<Readonly<{
43
43
  kind: "not-born";
44
44
  } | {
45
45
  kind: "recorded";
@@ -10,3 +10,32 @@ export declare function insertTellDeliveryFact(database: DatabaseSync, input: Te
10
10
  export declare function insertTellReceiptFact(database: DatabaseSync, input: TellReceiptInput): void;
11
11
  export declare function tellIdsForFence(database: DatabaseSync, turnSequence: number, fence: string): readonly string[];
12
12
  export declare function pendingTellFacts(database: DatabaseSync): readonly TellFact[];
13
+ export declare function openTellDispositionIds(database: DatabaseSync, bodySequence: number): readonly string[] | null;
14
+ export declare function latestOpenTellDisposition(database: DatabaseSync): Readonly<{
15
+ bodySequence: number;
16
+ tellIds: readonly string[];
17
+ }> | null;
18
+ export declare function insertTellDispositionSnapshot(database: DatabaseSync, bodySequence: number, tellIds: readonly string[], at: string): void;
19
+ export declare function resolveTellDispositionSnapshot(database: DatabaseSync, bodySequence: number, at: string): void;
20
+ /** Heart proof that a disposition snapshot is held: every frozen Tell-id left pending. */
21
+ export declare function dispositionSnapshotProven(database: DatabaseSync, disposition: Readonly<{
22
+ tellIds: readonly string[];
23
+ }>): boolean;
24
+ /**
25
+ * Identify the successor Body that took a disposition snapshot by delivery.
26
+ * Returns that Body sequence when every frozen Tell-id has a delivery on a
27
+ * turn owned by one Body after `bodySequence`; otherwise null. An unqualified
28
+ * newer Body or held leash is not proof. A missing Tell row is Heart corruption.
29
+ */
30
+ export declare function successorBodyHoldingDisposition(database: DatabaseSync, disposition: Readonly<{
31
+ bodySequence: number;
32
+ tellIds: readonly string[];
33
+ }>): number | null;
34
+ export declare function insertUndeliveredTellReceipts(database: DatabaseSync, tellIds: readonly string[], at: string): void;
35
+ export declare function insertTellBindingFact(database: DatabaseSync, input: Readonly<{
36
+ tellId: string;
37
+ turnSequence: number;
38
+ boundAt: string;
39
+ }>): void;
40
+ export declare function drainPendingTells(pending: readonly TellFact[]): readonly TellFact[];
41
+ export declare function openBoundTurns(database: DatabaseSync, bodySequence: number): readonly number[];
@@ -1,3 +1,4 @@
1
+ import { AuthorityCorruptionError } from "../../core/facts/errors.js";
1
2
  export const tellStateSql = `CASE
2
3
  WHEN EXISTS (
3
4
  SELECT 1 FROM tell_deliveries d
@@ -23,20 +24,29 @@ function tellDeliveries(database, id) {
23
24
  ? { turnSequence: row.turn_sequence, route: row.route, deliveredAt: row.delivered_at }
24
25
  : { turnSequence: row.turn_sequence, route: row.route, receipt: row.receipt, deliveredAt: row.delivered_at });
25
26
  }
27
+ function tellBinding(database, id) {
28
+ const row = database
29
+ .prepare("SELECT turn_sequence, bound_at FROM tell_bindings WHERE tell_id = ?")
30
+ .get(id);
31
+ return row === undefined ? undefined : { turnSequence: row.turn_sequence, boundAt: row.bound_at };
32
+ }
26
33
  function decodeTellRow(database, row) {
34
+ const binding = tellBinding(database, row.id);
27
35
  return {
28
36
  kind: "tell",
29
37
  sequence: row.sequence,
30
38
  id: row.id,
31
39
  body: row.body,
40
+ ...(row.schema_json === null ? {} : { schemaJson: row.schema_json }),
32
41
  state: row.state,
33
42
  recordedAt: row.recorded_at,
34
43
  deliveries: tellDeliveries(database, row.id),
44
+ ...(binding === undefined ? {} : { binding }),
35
45
  };
36
46
  }
37
47
  export function decodeTellAtSequence(database, sequence) {
38
48
  const row = database
39
- .prepare(`SELECT sequence, id, body, recorded_at, ${tellStateSql} AS state
49
+ .prepare(`SELECT sequence, id, body, schema_json, recorded_at, ${tellStateSql} AS state
40
50
  FROM tells WHERE sequence = ?`)
41
51
  .get(sequence);
42
52
  if (row === undefined)
@@ -46,13 +56,13 @@ export function decodeTellAtSequence(database, sequence) {
46
56
  export function insertTellFact(database, tell) {
47
57
  const sequence = Number(database.prepare("INSERT INTO timeline(kind) VALUES ('tell')").run().lastInsertRowid);
48
58
  database
49
- .prepare("INSERT INTO tells(id, sequence, body, recorded_at) VALUES (?, ?, ?, ?)")
50
- .run(tell.id, sequence, tell.body, tell.recordedAt);
59
+ .prepare("INSERT INTO tells(id, sequence, body, schema_json, recorded_at) VALUES (?, ?, ?, ?, ?)")
60
+ .run(tell.id, sequence, tell.body, tell.schemaJson ?? null, tell.recordedAt);
51
61
  return sequence;
52
62
  }
53
63
  export function tellFact(database, id) {
54
64
  const row = database
55
- .prepare(`SELECT sequence, id, body, recorded_at, ${tellStateSql} AS state
65
+ .prepare(`SELECT sequence, id, body, schema_json, recorded_at, ${tellStateSql} AS state
56
66
  FROM tells WHERE id = ?`)
57
67
  .get(id);
58
68
  return row === undefined ? null : decodeTellRow(database, row);
@@ -89,8 +99,129 @@ export function tellIdsForFence(database, turnSequence, fence) {
89
99
  }
90
100
  export function pendingTellFacts(database) {
91
101
  const rows = database
92
- .prepare(`SELECT sequence, id, body, recorded_at, ${tellStateSql} AS state FROM tells
102
+ .prepare(`SELECT sequence, id, body, schema_json, recorded_at, ${tellStateSql} AS state FROM tells
93
103
  WHERE ${tellStateSql} = 'pending' ORDER BY sequence`)
94
104
  .all();
95
105
  return rows.map((row) => decodeTellRow(database, row));
96
106
  }
107
+ export function openTellDispositionIds(database, bodySequence) {
108
+ const rows = database
109
+ .prepare(`SELECT tell_id FROM tell_dispositions
110
+ WHERE body_sequence = ? AND resolved_at IS NULL ORDER BY tell_id`)
111
+ .all(bodySequence);
112
+ return rows.length === 0 ? null : rows.map((row) => row.tell_id);
113
+ }
114
+ export function latestOpenTellDisposition(database) {
115
+ const row = database
116
+ .prepare(`SELECT body_sequence FROM tell_dispositions
117
+ WHERE resolved_at IS NULL ORDER BY body_sequence DESC LIMIT 1`)
118
+ .get();
119
+ if (row === undefined)
120
+ return null;
121
+ const tellIds = openTellDispositionIds(database, row.body_sequence);
122
+ return tellIds === null ? null : { bodySequence: row.body_sequence, tellIds };
123
+ }
124
+ export function insertTellDispositionSnapshot(database, bodySequence, tellIds, at) {
125
+ const insert = database.prepare(`INSERT OR IGNORE INTO tell_dispositions(body_sequence, tell_id, decided_at)
126
+ VALUES (?, ?, ?)`);
127
+ for (const tellId of tellIds)
128
+ insert.run(bodySequence, tellId, at);
129
+ }
130
+ export function resolveTellDispositionSnapshot(database, bodySequence, at) {
131
+ database
132
+ .prepare(`UPDATE tell_dispositions SET resolved_at = ?
133
+ WHERE body_sequence = ? AND resolved_at IS NULL`)
134
+ .run(at, bodySequence);
135
+ }
136
+ function requireDispositionTell(database, tellId) {
137
+ const tell = tellFact(database, tellId);
138
+ if (tell === null) {
139
+ throw new AuthorityCorruptionError(`Akuma disposition references missing tell ${tellId}`);
140
+ }
141
+ return tell;
142
+ }
143
+ /** Heart proof that a disposition snapshot is held: every frozen Tell-id left pending. */
144
+ export function dispositionSnapshotProven(database, disposition) {
145
+ for (const tellId of disposition.tellIds) {
146
+ if (requireDispositionTell(database, tellId).state === "pending")
147
+ return false;
148
+ }
149
+ return true;
150
+ }
151
+ /**
152
+ * Identify the successor Body that took a disposition snapshot by delivery.
153
+ * Returns that Body sequence when every frozen Tell-id has a delivery on a
154
+ * turn owned by one Body after `bodySequence`; otherwise null. An unqualified
155
+ * newer Body or held leash is not proof. A missing Tell row is Heart corruption.
156
+ */
157
+ export function successorBodyHoldingDisposition(database, disposition) {
158
+ let successor = null;
159
+ for (const tellId of disposition.tellIds) {
160
+ const tell = requireDispositionTell(database, tellId);
161
+ if (tell.state === "pending")
162
+ return null;
163
+ const row = database
164
+ .prepare(`SELECT t.body_sequence AS body_sequence
165
+ FROM tell_deliveries d
166
+ JOIN turns t ON t.sequence = d.turn_sequence
167
+ WHERE d.tell_id = ? AND t.body_sequence > ?
168
+ ORDER BY t.body_sequence ASC LIMIT 1`)
169
+ .get(tellId, disposition.bodySequence);
170
+ if (row === undefined) {
171
+ // Terminal witness without successor delivery (e.g. undelivered) is not successor custody.
172
+ return null;
173
+ }
174
+ if (successor === null)
175
+ successor = row.body_sequence;
176
+ else if (successor !== row.body_sequence)
177
+ return null;
178
+ }
179
+ return successor;
180
+ }
181
+ export function insertUndeliveredTellReceipts(database, tellIds, at) {
182
+ for (const tellId of tellIds) {
183
+ const current = requireDispositionTell(database, tellId);
184
+ if (current.state !== "pending")
185
+ continue;
186
+ insertTellReceiptFact(database, {
187
+ evidence: "exact",
188
+ tellId,
189
+ kind: "undelivered",
190
+ receivedAt: at,
191
+ });
192
+ }
193
+ }
194
+ export function insertTellBindingFact(database, input) {
195
+ const result = database
196
+ .prepare("INSERT OR IGNORE INTO tell_bindings(tell_id, turn_sequence, bound_at) VALUES (?, ?, ?)")
197
+ .run(input.tellId, input.turnSequence, input.boundAt);
198
+ const row = database
199
+ .prepare("SELECT turn_sequence FROM tell_bindings WHERE tell_id = ?")
200
+ .get(input.tellId);
201
+ if (row === undefined || (result.changes === 0 && row.turn_sequence !== input.turnSequence)) {
202
+ throw new Error(`tell ${input.tellId} is already bound to a different Turn`);
203
+ }
204
+ }
205
+ export function drainPendingTells(pending) {
206
+ const unbound = pending.filter((tell) => tell.binding === undefined);
207
+ if (unbound.length === 0)
208
+ return [];
209
+ const first = unbound[0];
210
+ const drained = [first];
211
+ for (const tell of unbound.slice(1)) {
212
+ if (tell.schemaJson !== undefined)
213
+ break;
214
+ drained.push(tell);
215
+ }
216
+ return drained;
217
+ }
218
+ export function openBoundTurns(database, bodySequence) {
219
+ return database
220
+ .prepare(`SELECT DISTINCT turns.sequence AS sequence
221
+ FROM turns
222
+ JOIN tell_bindings ON tell_bindings.turn_sequence = turns.sequence
223
+ WHERE turns.body_sequence = ? AND turns.end_sequence IS NULL
224
+ ORDER BY turns.sequence`)
225
+ .all(bodySequence)
226
+ .map((row) => row.sequence);
227
+ }
@@ -49,7 +49,7 @@ export function pruneActivityFacts(database, limit) {
49
49
  function turn(database, sequence) {
50
50
  const row = database
51
51
  .prepare(`SELECT sequence, body_sequence, started_at, end_sequence, outcome,
52
- history_id, session_json, answer, diagnostic, completed_at FROM turns WHERE sequence = ?`)
52
+ history_id, session_json, answer, answer_json, schema_json, diagnostic, completed_at FROM turns WHERE sequence = ?`)
53
53
  .get(sequence);
54
54
  if (row === undefined)
55
55
  throw new Error(`Akuma timeline references missing Turn ${sequence}`);
@@ -57,11 +57,17 @@ function turn(database, sequence) {
57
57
  }
58
58
  function turnStart(database, sequence) {
59
59
  const row = database
60
- .prepare("SELECT sequence, body_sequence, started_at FROM turns WHERE sequence = ?")
60
+ .prepare("SELECT sequence, body_sequence, started_at, schema_json FROM turns WHERE sequence = ?")
61
61
  .get(sequence);
62
62
  if (row === undefined)
63
63
  throw new Error(`Akuma timeline references missing Turn ${sequence}`);
64
- return { kind: "turn-start", sequence: row.sequence, bodySequence: row.body_sequence, startedAt: row.started_at };
64
+ return {
65
+ kind: "turn-start",
66
+ sequence: row.sequence,
67
+ bodySequence: row.body_sequence,
68
+ startedAt: row.started_at,
69
+ ...(row.schema_json === null ? {} : { schemaJson: row.schema_json }),
70
+ };
65
71
  }
66
72
  function decodeTimelineRow(database, row) {
67
73
  if (row.kind === "turn-start")
@@ -48,11 +48,44 @@ function flattenReportedChanges(rows) {
48
48
  }));
49
49
  });
50
50
  }
51
+ function aggregateReportedChanges(changes) {
52
+ const groups = new Map();
53
+ changes.forEach((change, index) => {
54
+ const current = groups.get(change.path);
55
+ const diffstat = change.diffstat;
56
+ if (current === undefined) {
57
+ groups.set(change.path, {
58
+ latest: change,
59
+ lastIndex: index,
60
+ added: diffstat?.added ?? 0,
61
+ removed: diffstat?.removed ?? 0,
62
+ complete: diffstat !== undefined,
63
+ });
64
+ return;
65
+ }
66
+ current.latest = change;
67
+ current.lastIndex = index;
68
+ if (diffstat === undefined)
69
+ current.complete = false;
70
+ else {
71
+ current.added += diffstat.added;
72
+ current.removed += diffstat.removed;
73
+ }
74
+ });
75
+ return [...groups.values()]
76
+ .sort((left, right) => left.lastIndex - right.lastIndex)
77
+ .map((group) => {
78
+ if (group.complete)
79
+ return { ...group.latest, diffstat: { added: group.added, removed: group.removed } };
80
+ const { sequence, at, op, path } = group.latest;
81
+ return { sequence, at, op, path };
82
+ });
83
+ }
51
84
  function summarizeReportedChanges(rows) {
52
- const eligible = flattenReportedChanges(rows);
85
+ const files = aggregateReportedChanges(flattenReportedChanges(rows));
53
86
  return {
54
- reportedChanges: eligible.slice(-REPORTED_CHANGE_LIMIT),
55
- reportedChangesOmitted: Math.max(0, eligible.length - REPORTED_CHANGE_LIMIT),
87
+ reportedChanges: files.slice(-REPORTED_CHANGE_LIMIT),
88
+ reportedChangesOmitted: Math.max(0, files.length - REPORTED_CHANGE_LIMIT),
56
89
  };
57
90
  }
58
91
  function frontierReportedChanges(ledger) {
@@ -1,4 +1,3 @@
1
- /* eslint-disable max-lines -- Akuma owns one coherent activity projection and strict boundary schema. */
2
1
  import { decodeAgentEvent } from "./provider.js";
3
2
  import { projectTell } from "./heart/facts.js";
4
3
  import { z } from "zod";
@@ -193,9 +192,9 @@ export const activitySnapshotSchema = z.union([
193
192
  ]);
194
193
  function publicOutcome(turnSequence, outcome) {
195
194
  const historyId = `turn/${turnSequence}`;
196
- return outcome.kind === "answered"
197
- ? { kind: "answered", historyId, answer: outcome.answer }
198
- : { kind: "failed", historyId, diagnostic: outcome.diagnostic };
195
+ if (outcome.kind === "answered")
196
+ return { kind: "answered", historyId, answer: outcome.answer };
197
+ return { kind: "failed", historyId, diagnostic: outcome.diagnostic };
199
198
  }
200
199
  export function selectExactHistory(rows, id) {
201
200
  const outcome = rows.find((row) => row.kind === "outcome" && row.outcome.historyId === id);
@@ -4,6 +4,7 @@ export type { ResumeCoordinate } from "./coordinate.js";
4
4
  export declare const AKUMA_REQUESTS_ENV = "AKUMA_REQUESTS";
5
5
  export declare const AGENT_EVENT_TEXT_LIMIT = 16384;
6
6
  export declare const AGENT_THOUGHT_TEXT_LIMIT = 4000;
7
+ export declare const AGENT_EVENT_QUEUE_LIMIT = 256;
7
8
  export type SearchScope = "content" | "files" | "web";
8
9
  export type ToolCall = Readonly<{
9
10
  kind: "run";
@@ -85,6 +86,8 @@ export declare function unknownEvent(kind: string): Extract<AgentEvent, {
85
86
  export declare class AgentEventChannel implements AsyncIterable<AgentEvent> {
86
87
  private readonly queued;
87
88
  private readonly waiters;
89
+ private overflowMarker;
90
+ private overflowCount;
88
91
  private ended;
89
92
  emit(event: AgentEvent): void;
90
93
  end(): void;
@@ -169,6 +172,7 @@ export type DriveInput = Readonly<{
169
172
  requests: Readonly<{
170
173
  dir: string;
171
174
  }>;
175
+ schemaJson?: string;
172
176
  }>;
173
177
  export type ProviderOptionAdmission = Readonly<{
174
178
  kind: "admitted";
@@ -2,6 +2,7 @@ import { decodeResumeCoordinate, encodeResumeCoordinate } from "./coordinate.js"
2
2
  export const AKUMA_REQUESTS_ENV = "AKUMA_REQUESTS";
3
3
  export const AGENT_EVENT_TEXT_LIMIT = 16_384;
4
4
  export const AGENT_THOUGHT_TEXT_LIMIT = 4_000;
5
+ export const AGENT_EVENT_QUEUE_LIMIT = 256;
5
6
  const AGENT_EVENT_TYPES = {
6
7
  session: true,
7
8
  assistant: true,
@@ -313,16 +314,64 @@ export function noteEvent(note) {
313
314
  export function unknownEvent(kind) {
314
315
  return { type: "unknown", kind };
315
316
  }
317
+ // Slow consumers may lose reconstructible narration, but session coordinates,
318
+ // notes, and error events stay observable. A full protected queue replaces one
319
+ // protected item with a bounded aggregate note; `end` ignores later emission.
320
+ function isErrorEvent(event) {
321
+ if (event.type === "note")
322
+ return true;
323
+ if (event.type === "tool" && event.phase === "completed")
324
+ return event.result.status === "error";
325
+ return event.type === "unknown" && /(?:error|fail|abort|cancel|stop|terminal)/iu.test(event.kind);
326
+ }
327
+ function isReconstructibleEvent(event) {
328
+ return event.type !== "session" && !isErrorEvent(event);
329
+ }
330
+ const AGENT_EVENT_OVERFLOW_PREFIX = "Agent event queue overflow";
331
+ function overflowEvent(count) {
332
+ return { type: "note", text: `${AGENT_EVENT_OVERFLOW_PREFIX}: ${count} terminal/error events coalesced` };
333
+ }
316
334
  export class AgentEventChannel {
317
335
  queued = [];
318
336
  waiters = [];
337
+ overflowMarker;
338
+ overflowCount = 0;
319
339
  ended = false;
320
340
  emit(event) {
341
+ if (this.ended)
342
+ return;
321
343
  const waiter = this.waiters.shift();
322
- if (waiter === undefined)
323
- this.queued.push(event);
324
- else
344
+ if (waiter !== undefined) {
325
345
  waiter.resolve({ done: false, value: event });
346
+ return;
347
+ }
348
+ if (this.queued.length >= AGENT_EVENT_QUEUE_LIMIT) {
349
+ const reconstructible = this.queued.findIndex(isReconstructibleEvent);
350
+ if (reconstructible === -1) {
351
+ if (isReconstructibleEvent(event))
352
+ return;
353
+ this.overflowCount += 1;
354
+ if (this.overflowMarker !== undefined) {
355
+ const marker = overflowEvent(this.overflowCount);
356
+ const markerIndex = this.queued.indexOf(this.overflowMarker);
357
+ if (markerIndex !== -1) {
358
+ this.queued[markerIndex] = marker;
359
+ this.overflowMarker = marker;
360
+ return;
361
+ }
362
+ this.overflowMarker = undefined;
363
+ }
364
+ const protectedIndex = this.queued.findIndex((queued) => queued.type !== "session");
365
+ const replacement = protectedIndex === -1 ? 0 : protectedIndex;
366
+ this.overflowCount += 1;
367
+ const marker = overflowEvent(this.overflowCount);
368
+ this.queued[replacement] = marker;
369
+ this.overflowMarker = marker;
370
+ return;
371
+ }
372
+ this.queued.splice(reconstructible, 1);
373
+ }
374
+ this.queued.push(event);
326
375
  }
327
376
  end() {
328
377
  if (this.ended)
@@ -335,6 +384,10 @@ export class AgentEventChannel {
335
384
  return {
336
385
  next: () => {
337
386
  const event = this.queued.shift();
387
+ if (event === this.overflowMarker) {
388
+ this.overflowMarker = undefined;
389
+ this.overflowCount = 0;
390
+ }
338
391
  if (event !== undefined)
339
392
  return Promise.resolve({ done: false, value: event });
340
393
  if (this.ended)
@@ -86,6 +86,9 @@ function claudeQueryOptions(input, execution, abortController) {
86
86
  : { type: "preset", preset: "claude_code", append: input.options.systemPrompt },
87
87
  }),
88
88
  ...(input.session.kind === "fresh" ? {} : { resume: claudeSessionId(input.session.coordinate) }),
89
+ ...(input.schemaJson === undefined
90
+ ? {}
91
+ : { outputFormat: { type: "json_schema", schema: JSON.parse(input.schemaJson) } }),
89
92
  };
90
93
  }
91
94
  async function forkClaude(load, execution, input) {
@@ -95,6 +95,7 @@ async function admitTurn(server, input, state, events, config) {
95
95
  ...(input.options.effort === undefined ? {} : { effort: input.options.effort }),
96
96
  approvalPolicy: "never",
97
97
  sandboxPolicy: sandbox(input.cwd, input.options, input.requests),
98
+ ...(input.schemaJson === undefined ? {} : { outputSchema: JSON.parse(input.schemaJson) }),
98
99
  }));
99
100
  }
100
101
  async function forkCodex(execution, input, custody) {
@@ -152,11 +153,8 @@ async function startCodex(execution, input, custody) {
152
153
  const events = new AgentEventChannel();
153
154
  const server = codexServer(execution, input);
154
155
  const closed = new Promise((resolve) => server.onExit(() => resolve()));
155
- custody.own({
156
- closed,
157
- abort: async () => await server.close(true),
158
- forceDispose: async () => await server.close(true),
159
- });
156
+ const close = async () => await server.close(true);
157
+ custody.own({ closed, abort: close, forceDispose: close });
160
158
  const state = { settled: false, tools: new Map() };
161
159
  let settle;
162
160
  const completion = new Promise((resolve) => {
@@ -168,13 +166,11 @@ async function startCodex(execution, input, custody) {
168
166
  return;
169
167
  terminal = result;
170
168
  state.settled = true;
171
- void server.endInputAndDrain().then(() => {
172
- events.end();
173
- settle(result);
174
- }, () => {
169
+ const done = () => {
175
170
  events.end();
176
171
  settle(result);
177
- });
172
+ };
173
+ void server.endInputAndDrain().then(done, done);
178
174
  };
179
175
  server.onNotification((notification) => {
180
176
  const result = codexNotificationResult(notification, state, events);
@@ -202,13 +198,19 @@ async function startCodex(execution, input, custody) {
202
198
  await server.close(true);
203
199
  throw signal.reason;
204
200
  }
205
- finish({ kind: "failed", diagnostic: diagnostic(error) });
201
+ const message = diagnostic(error);
202
+ finish({ kind: "failed", diagnostic: message });
203
+ await server.close(true);
204
+ throw error instanceof Error ? error : new Error(message);
206
205
  }
207
206
  finally {
208
207
  signal.removeEventListener("abort", abortSetup);
209
208
  }
210
- if (state.turnId === undefined)
209
+ if (state.turnId === undefined) {
210
+ if (terminal?.kind === "failed" && terminal.diagnostic.length > 0)
211
+ throw new Error(terminal.diagnostic);
211
212
  throw new Error("codex app-server did not admit a turn");
213
+ }
212
214
  return {
213
215
  admission: { fence: state.turnId },
214
216
  events,
@@ -79,7 +79,13 @@ async function createPiSession(sdk, execution, input) {
79
79
  }
80
80
  async function runPiPrompt(native, input, events, state, settle) {
81
81
  try {
82
- await native.prompt([input.body, ...input.launchTells.map((tell) => tell.text)].join("\n\n"));
82
+ const prompt = [input.body, ...input.launchTells.map((tell) => tell.text)].filter((part) => part.length > 0).join("\n\n");
83
+ const schemaPrompt = input.schemaJson === undefined
84
+ ? prompt
85
+ : [prompt, "Respond with JSON matching this JSON Schema and no other text:", input.schemaJson]
86
+ .filter((part) => part.length > 0)
87
+ .join("\n\n");
88
+ await native.prompt(schemaPrompt);
83
89
  let result;
84
90
  if (state.aborting)
85
91
  result = { kind: "failed", diagnostic: "Pi session aborted" };