@agentshouse/mdruntime 0.1.0-cdf82f77fae68 → 0.1.0-ce06b735d6c6d

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 (383) hide show
  1. package/README.md +24 -19
  2. package/dist/acceptance.d.ts +3 -0
  3. package/dist/acceptance.d.ts.map +1 -0
  4. package/dist/acceptance.js +299 -0
  5. package/dist/act-lanes.d.ts +30 -0
  6. package/dist/act-lanes.d.ts.map +1 -0
  7. package/dist/act-lanes.js +225 -0
  8. package/dist/actions.d.ts +26 -0
  9. package/dist/actions.d.ts.map +1 -0
  10. package/dist/actions.js +302 -0
  11. package/dist/adapter.d.ts +187 -97
  12. package/dist/adapter.d.ts.map +1 -1
  13. package/dist/attached-model.d.ts +6 -10
  14. package/dist/attached-model.d.ts.map +1 -1
  15. package/dist/attached-model.js +35 -41
  16. package/dist/binary.d.ts +0 -5
  17. package/dist/binary.d.ts.map +1 -1
  18. package/dist/binary.js +1 -1
  19. package/dist/bootstrap.d.ts +31 -11
  20. package/dist/bootstrap.d.ts.map +1 -1
  21. package/dist/bootstrap.js +311 -89
  22. package/dist/cell.d.ts +6 -0
  23. package/dist/cell.d.ts.map +1 -0
  24. package/dist/cell.js +9 -0
  25. package/dist/chain.d.ts +12 -0
  26. package/dist/chain.d.ts.map +1 -0
  27. package/dist/chain.js +64 -0
  28. package/dist/change-set.d.ts +13 -14
  29. package/dist/change-set.d.ts.map +1 -1
  30. package/dist/change-set.js +17 -63
  31. package/dist/change.d.ts +32 -1
  32. package/dist/change.d.ts.map +1 -1
  33. package/dist/change.js +14 -3
  34. package/dist/chat-types.d.ts +3 -0
  35. package/dist/chat-types.d.ts.map +1 -0
  36. package/dist/chat-types.js +11 -0
  37. package/dist/client.d.ts +48 -29
  38. package/dist/client.d.ts.map +1 -1
  39. package/dist/client.js +131 -28
  40. package/dist/collection.d.ts +31 -9
  41. package/dist/collection.d.ts.map +1 -1
  42. package/dist/collection.js +49 -80
  43. package/dist/compile.d.ts +18 -0
  44. package/dist/compile.d.ts.map +1 -0
  45. package/dist/compile.js +724 -0
  46. package/dist/connection.d.ts +8 -116
  47. package/dist/connection.d.ts.map +1 -1
  48. package/dist/connection.js +112 -2412
  49. package/dist/context.d.ts +2 -0
  50. package/dist/context.d.ts.map +1 -0
  51. package/dist/{chat/context.js → context.js} +1 -4
  52. package/dist/conversation-live.d.ts +150 -0
  53. package/dist/conversation-live.d.ts.map +1 -0
  54. package/dist/conversation-live.js +259 -0
  55. package/dist/conversation-row.d.ts +35 -0
  56. package/dist/conversation-row.d.ts.map +1 -0
  57. package/dist/conversation-row.js +55 -0
  58. package/dist/conversation.d.ts +82 -45
  59. package/dist/conversation.d.ts.map +1 -1
  60. package/dist/conversation.js +1116 -584
  61. package/dist/declaration.d.ts +10 -0
  62. package/dist/declaration.d.ts.map +1 -0
  63. package/dist/declaration.js +24 -0
  64. package/dist/digest.d.ts +7 -0
  65. package/dist/digest.d.ts.map +1 -0
  66. package/dist/digest.js +113 -0
  67. package/dist/discovery.d.ts +10 -0
  68. package/dist/discovery.d.ts.map +1 -0
  69. package/dist/discovery.js +150 -0
  70. package/dist/durability.d.ts +23 -1
  71. package/dist/durability.d.ts.map +1 -1
  72. package/dist/durability.js +9 -0
  73. package/dist/entry.d.ts +20 -0
  74. package/dist/entry.d.ts.map +1 -0
  75. package/dist/entry.js +161 -0
  76. package/dist/expectation.d.ts +26 -13
  77. package/dist/expectation.d.ts.map +1 -1
  78. package/dist/expectation.js +72 -19
  79. package/dist/failure.d.ts +3 -0
  80. package/dist/failure.d.ts.map +1 -1
  81. package/dist/failure.js +6 -0
  82. package/dist/figures.d.ts +49 -0
  83. package/dist/figures.d.ts.map +1 -0
  84. package/dist/figures.js +199 -0
  85. package/dist/file.d.ts +2 -19
  86. package/dist/file.d.ts.map +1 -1
  87. package/dist/file.js +8 -122
  88. package/dist/holdings.d.ts +29 -0
  89. package/dist/holdings.d.ts.map +1 -0
  90. package/dist/holdings.js +95 -0
  91. package/dist/host.d.ts +29 -4
  92. package/dist/host.d.ts.map +1 -1
  93. package/dist/host.js +177 -27
  94. package/dist/index.d.ts +41 -13
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.js +19 -2
  97. package/dist/install.d.ts +60 -0
  98. package/dist/install.d.ts.map +1 -0
  99. package/dist/install.js +537 -0
  100. package/dist/lifecycle.d.ts +7 -0
  101. package/dist/lifecycle.d.ts.map +1 -0
  102. package/dist/lifecycle.js +278 -0
  103. package/dist/listing.d.ts +52 -0
  104. package/dist/listing.d.ts.map +1 -0
  105. package/dist/listing.js +152 -0
  106. package/dist/live.d.ts +25 -0
  107. package/dist/live.d.ts.map +1 -0
  108. package/dist/live.js +206 -0
  109. package/dist/locks.d.ts +7 -0
  110. package/dist/locks.d.ts.map +1 -0
  111. package/dist/locks.js +32 -0
  112. package/dist/lost.d.ts +5 -0
  113. package/dist/lost.d.ts.map +1 -0
  114. package/dist/lost.js +49 -0
  115. package/dist/media.d.ts +8 -0
  116. package/dist/media.d.ts.map +1 -0
  117. package/dist/media.js +215 -0
  118. package/dist/memory.d.ts +24 -6
  119. package/dist/memory.d.ts.map +1 -1
  120. package/dist/memory.js +291 -101
  121. package/dist/messages.d.ts +58 -0
  122. package/dist/messages.d.ts.map +1 -0
  123. package/dist/messages.js +162 -0
  124. package/dist/model.d.ts +11 -12
  125. package/dist/model.d.ts.map +1 -1
  126. package/dist/model.js +7 -15
  127. package/dist/models.d.ts +10 -0
  128. package/dist/models.d.ts.map +1 -0
  129. package/dist/models.js +153 -0
  130. package/dist/name.d.ts +4 -0
  131. package/dist/name.d.ts.map +1 -0
  132. package/dist/name.js +122 -0
  133. package/dist/observation.d.ts +42 -9
  134. package/dist/observation.d.ts.map +1 -1
  135. package/dist/observation.js +238 -33
  136. package/dist/opened.d.ts +22 -0
  137. package/dist/opened.d.ts.map +1 -0
  138. package/dist/opened.js +107 -0
  139. package/dist/opening.d.ts +4 -0
  140. package/dist/opening.d.ts.map +1 -0
  141. package/dist/opening.js +53 -0
  142. package/dist/outcome.d.ts +60 -8
  143. package/dist/outcome.d.ts.map +1 -1
  144. package/dist/outcome.js +64 -0
  145. package/dist/overlay.d.ts +8 -4
  146. package/dist/overlay.d.ts.map +1 -1
  147. package/dist/overlay.js +136 -192
  148. package/dist/page-metadata.d.ts +8 -0
  149. package/dist/page-metadata.d.ts.map +1 -0
  150. package/dist/page-metadata.js +19 -0
  151. package/dist/parts.d.ts +4 -0
  152. package/dist/parts.d.ts.map +1 -0
  153. package/dist/parts.js +13 -0
  154. package/dist/paths.d.ts +2 -0
  155. package/dist/paths.d.ts.map +1 -1
  156. package/dist/paths.js +26 -0
  157. package/dist/preparation.d.ts +41 -0
  158. package/dist/preparation.d.ts.map +1 -0
  159. package/dist/preparation.js +314 -0
  160. package/dist/presence.d.ts +58 -0
  161. package/dist/presence.d.ts.map +1 -0
  162. package/dist/presence.js +233 -0
  163. package/dist/queries.d.ts +16 -0
  164. package/dist/queries.d.ts.map +1 -0
  165. package/dist/queries.js +308 -0
  166. package/dist/query.d.ts +49 -183
  167. package/dist/query.d.ts.map +1 -1
  168. package/dist/query.js +3 -464
  169. package/dist/{chat/questions.d.ts → questions.d.ts} +5 -7
  170. package/dist/questions.d.ts.map +1 -0
  171. package/dist/{chat/questions.js → questions.js} +11 -7
  172. package/dist/queue.d.ts +40 -0
  173. package/dist/queue.d.ts.map +1 -0
  174. package/dist/queue.js +450 -0
  175. package/dist/reach.d.ts +20 -7
  176. package/dist/reach.d.ts.map +1 -1
  177. package/dist/reach.js +353 -98
  178. package/dist/react.d.ts +23 -7
  179. package/dist/react.d.ts.map +1 -1
  180. package/dist/react.js +40 -18
  181. package/dist/{chat/read.d.ts → read.d.ts} +2 -0
  182. package/dist/read.d.ts.map +1 -0
  183. package/dist/{chat/read.js → read.js} +4 -0
  184. package/dist/readiness.d.ts +55 -0
  185. package/dist/readiness.d.ts.map +1 -0
  186. package/dist/readiness.js +25 -0
  187. package/dist/reads.d.ts +39 -0
  188. package/dist/reads.d.ts.map +1 -0
  189. package/dist/reads.js +178 -0
  190. package/dist/recovery.d.ts +28 -0
  191. package/dist/recovery.d.ts.map +1 -0
  192. package/dist/recovery.js +254 -0
  193. package/dist/refresh.d.ts +17 -14
  194. package/dist/refresh.d.ts.map +1 -1
  195. package/dist/refresh.js +145 -53
  196. package/dist/refusal.d.ts +5 -0
  197. package/dist/refusal.d.ts.map +1 -0
  198. package/dist/refusal.js +55 -0
  199. package/dist/replica.d.ts +50 -33
  200. package/dist/replica.d.ts.map +1 -1
  201. package/dist/replica.js +339 -162
  202. package/dist/retried.d.ts +30 -0
  203. package/dist/retried.d.ts.map +1 -0
  204. package/dist/retried.js +72 -0
  205. package/dist/room-draft.d.ts +39 -10
  206. package/dist/room-draft.d.ts.map +1 -1
  207. package/dist/room-draft.js +196 -120
  208. package/dist/room-drafts.d.ts +24 -0
  209. package/dist/room-drafts.d.ts.map +1 -0
  210. package/dist/room-drafts.js +217 -0
  211. package/dist/rows.d.ts +31 -37
  212. package/dist/rows.d.ts.map +1 -1
  213. package/dist/rows.js +60 -128
  214. package/dist/runtime.d.ts +34 -0
  215. package/dist/runtime.d.ts.map +1 -0
  216. package/dist/runtime.js +1 -0
  217. package/dist/save.d.ts +42 -43
  218. package/dist/save.d.ts.map +1 -1
  219. package/dist/save.js +800 -259
  220. package/dist/saves.d.ts +32 -0
  221. package/dist/saves.d.ts.map +1 -0
  222. package/dist/saves.js +410 -0
  223. package/dist/search.d.ts +15 -55
  224. package/dist/search.d.ts.map +1 -1
  225. package/dist/search.js +10 -121
  226. package/dist/seed.d.ts +25 -0
  227. package/dist/seed.d.ts.map +1 -0
  228. package/dist/seed.js +145 -0
  229. package/dist/shared.d.ts +10 -0
  230. package/dist/shared.d.ts.map +1 -0
  231. package/dist/shared.js +339 -0
  232. package/dist/shown.d.ts +33 -0
  233. package/dist/shown.d.ts.map +1 -0
  234. package/dist/shown.js +309 -0
  235. package/dist/socket/admission.d.ts +7 -0
  236. package/dist/socket/admission.d.ts.map +1 -0
  237. package/dist/socket/admission.js +39 -0
  238. package/dist/socket/answers.d.ts +6 -0
  239. package/dist/socket/answers.d.ts.map +1 -0
  240. package/dist/socket/answers.js +20 -0
  241. package/dist/socket/lanes.d.ts +28 -0
  242. package/dist/socket/lanes.d.ts.map +1 -0
  243. package/dist/socket/lanes.js +103 -0
  244. package/dist/socket/reads.d.ts +10 -0
  245. package/dist/socket/reads.d.ts.map +1 -0
  246. package/dist/socket/reads.js +31 -0
  247. package/dist/socket/session.d.ts +38 -0
  248. package/dist/socket/session.d.ts.map +1 -0
  249. package/dist/socket/session.js +23 -0
  250. package/dist/socket.d.ts +67 -0
  251. package/dist/socket.d.ts.map +1 -0
  252. package/dist/socket.js +164 -0
  253. package/dist/source.d.ts +54 -0
  254. package/dist/source.d.ts.map +1 -0
  255. package/dist/source.js +82 -0
  256. package/dist/status.d.ts +5 -2
  257. package/dist/status.d.ts.map +1 -1
  258. package/dist/status.js +3 -7
  259. package/dist/store/installs.d.ts +30 -0
  260. package/dist/store/installs.d.ts.map +1 -0
  261. package/dist/store/installs.js +40 -0
  262. package/dist/store/readiness.d.ts +11 -0
  263. package/dist/store/readiness.d.ts.map +1 -0
  264. package/dist/store/readiness.js +68 -0
  265. package/dist/store/records.d.ts +217 -0
  266. package/dist/store/records.d.ts.map +1 -0
  267. package/dist/store/records.js +464 -0
  268. package/dist/store/room-held.d.ts +8 -0
  269. package/dist/store/room-held.d.ts.map +1 -0
  270. package/dist/store/room-held.js +17 -0
  271. package/dist/store/rooms-shown.d.ts +8 -0
  272. package/dist/store/rooms-shown.d.ts.map +1 -0
  273. package/dist/store/rooms-shown.js +13 -0
  274. package/dist/store/space.d.ts +11 -0
  275. package/dist/store/space.d.ts.map +1 -0
  276. package/dist/store/space.js +41 -0
  277. package/dist/store/watchers.d.ts +17 -0
  278. package/dist/store/watchers.d.ts.map +1 -0
  279. package/dist/store/watchers.js +56 -0
  280. package/dist/store/writes.d.ts +24 -0
  281. package/dist/store/writes.d.ts.map +1 -0
  282. package/dist/store/writes.js +125 -0
  283. package/dist/store.d.ts +112 -117
  284. package/dist/store.d.ts.map +1 -1
  285. package/dist/store.js +165 -488
  286. package/dist/stored.d.ts +167 -0
  287. package/dist/stored.d.ts.map +1 -0
  288. package/dist/stored.js +703 -0
  289. package/dist/surface.d.ts +89 -0
  290. package/dist/surface.d.ts.map +1 -0
  291. package/dist/surface.js +222 -0
  292. package/dist/sync.d.ts +19 -0
  293. package/dist/sync.d.ts.map +1 -0
  294. package/dist/sync.js +535 -0
  295. package/dist/tables.d.ts +419 -0
  296. package/dist/tables.d.ts.map +1 -0
  297. package/dist/tables.js +758 -0
  298. package/dist/tallies.d.ts +18 -0
  299. package/dist/tallies.d.ts.map +1 -0
  300. package/dist/tallies.js +128 -0
  301. package/dist/transfer.d.ts +0 -5
  302. package/dist/transfer.d.ts.map +1 -1
  303. package/dist/turn.d.ts +9 -0
  304. package/dist/turn.d.ts.map +1 -0
  305. package/dist/turn.js +75 -0
  306. package/dist/validation.d.ts +29 -0
  307. package/dist/validation.d.ts.map +1 -0
  308. package/dist/validation.js +104 -0
  309. package/dist/windows.d.ts +11 -0
  310. package/dist/windows.d.ts.map +1 -0
  311. package/dist/windows.js +16 -0
  312. package/dist/wire.d.ts +221 -36
  313. package/dist/wire.d.ts.map +1 -1
  314. package/dist/wire.js +74 -33
  315. package/package.json +28 -24
  316. package/AGENTS.md +0 -318
  317. package/dist/attempt.d.ts +0 -16
  318. package/dist/attempt.d.ts.map +0 -1
  319. package/dist/attempt.js +0 -57
  320. package/dist/chat/acts.d.ts +0 -34
  321. package/dist/chat/acts.d.ts.map +0 -1
  322. package/dist/chat/acts.js +0 -36
  323. package/dist/chat/context.d.ts +0 -3
  324. package/dist/chat/context.d.ts.map +0 -1
  325. package/dist/chat/input.d.ts +0 -9
  326. package/dist/chat/input.d.ts.map +0 -1
  327. package/dist/chat/input.js +0 -99
  328. package/dist/chat/kit.d.ts +0 -60
  329. package/dist/chat/kit.d.ts.map +0 -1
  330. package/dist/chat/kit.js +0 -123
  331. package/dist/chat/lasting.d.ts +0 -6
  332. package/dist/chat/lasting.d.ts.map +0 -1
  333. package/dist/chat/lasting.js +0 -19
  334. package/dist/chat/list.d.ts +0 -20
  335. package/dist/chat/list.d.ts.map +0 -1
  336. package/dist/chat/list.js +0 -59
  337. package/dist/chat/markdown.d.ts +0 -19
  338. package/dist/chat/markdown.d.ts.map +0 -1
  339. package/dist/chat/markdown.js +0 -187
  340. package/dist/chat/message.d.ts +0 -6
  341. package/dist/chat/message.d.ts.map +0 -1
  342. package/dist/chat/message.js +0 -192
  343. package/dist/chat/messages.d.ts +0 -21
  344. package/dist/chat/messages.d.ts.map +0 -1
  345. package/dist/chat/messages.js +0 -151
  346. package/dist/chat/name.d.ts +0 -6
  347. package/dist/chat/name.d.ts.map +0 -1
  348. package/dist/chat/name.js +0 -37
  349. package/dist/chat/opened.d.ts +0 -11
  350. package/dist/chat/opened.d.ts.map +0 -1
  351. package/dist/chat/opened.js +0 -17
  352. package/dist/chat/overlay.d.ts +0 -31
  353. package/dist/chat/overlay.d.ts.map +0 -1
  354. package/dist/chat/overlay.js +0 -97
  355. package/dist/chat/parts.d.ts +0 -57
  356. package/dist/chat/parts.d.ts.map +0 -1
  357. package/dist/chat/parts.js +0 -119
  358. package/dist/chat/process.d.ts +0 -20
  359. package/dist/chat/process.d.ts.map +0 -1
  360. package/dist/chat/process.js +0 -32
  361. package/dist/chat/provider.d.ts +0 -63
  362. package/dist/chat/provider.d.ts.map +0 -1
  363. package/dist/chat/provider.js +0 -645
  364. package/dist/chat/question.d.ts +0 -9
  365. package/dist/chat/question.d.ts.map +0 -1
  366. package/dist/chat/question.js +0 -80
  367. package/dist/chat/questions.d.ts.map +0 -1
  368. package/dist/chat/read.d.ts.map +0 -1
  369. package/dist/chat/ready.d.ts +0 -33
  370. package/dist/chat/ready.d.ts.map +0 -1
  371. package/dist/chat/ready.js +0 -91
  372. package/dist/chat/style.d.ts +0 -4
  373. package/dist/chat/style.d.ts.map +0 -1
  374. package/dist/chat/style.js +0 -302
  375. package/dist/chat.d.ts +0 -14
  376. package/dist/chat.d.ts.map +0 -1
  377. package/dist/chat.js +0 -8
  378. package/dist/log.d.ts +0 -5
  379. package/dist/log.d.ts.map +0 -1
  380. package/dist/log.js +0 -14
  381. package/dist/read-side.d.ts +0 -18
  382. package/dist/read-side.d.ts.map +0 -1
  383. package/dist/read-side.js +0 -440
package/dist/reach.js CHANGED
@@ -1,10 +1,11 @@
1
+ import { QueryError } from '@agentshouse/mdmodel';
2
+ import { selected } from './collection.js';
1
3
  import { unheldView } from './conversation.js';
2
4
  import { modelTypes, NO_MODEL } from './model.js';
3
- import { applied, observing } from './observation.js';
4
- import { runtimeError } from './failure.js';
5
- import { failure, undeclared, } from './outcome.js';
5
+ import { changeOf, digestApplied, digestOf, observing, unchanged, } from './observation.js';
6
+ import { runtimeError, uncaught } from './failure.js';
7
+ import { failure, lockedRoom, ROOM_LOCKED, undeclared, UNREADABLE, } from './outcome.js';
6
8
  import { beneath } from './paths.js';
7
- import { reconciled } from './read-side.js';
8
9
  import { moveTarget, readParts, staleWrite, } from './room-draft.js';
9
10
  import { documentKey } from './rows.js';
10
11
  const UNHELD_TYPES = { collection: modelTypes(NO_MODEL), typedSelection: null };
@@ -14,18 +15,35 @@ function unconversed(name) {
14
15
  const NO_CONVERSATION = {
15
16
  list: () => Promise.resolve([]),
16
17
  read: (conversation) => Promise.resolve(unheldView(conversation)),
17
- create: unconversed('conversation.create'),
18
- send: unconversed('conversation.send'),
19
- answer: unconversed('conversation.answer'),
20
- interrupt: unconversed('conversation.interrupt'),
21
- kill: unconversed('conversation.kill'),
22
- cancel: unconversed('conversation.cancel'),
23
- delete: unconversed('conversation.delete'),
18
+ create: unconversed('conversations/create'),
19
+ send: unconversed('conversations/send'),
20
+ answer: unconversed('conversations/interaction/answer'),
21
+ interrupt: unconversed('conversations/interrupt'),
22
+ kill: unconversed('conversations/kill'),
23
+ delete: unconversed('conversations/delete'),
24
+ takeOut: unconversed('conversations/take-out'),
25
+ decide: unconversed('agent-functions/decide'),
26
+ rename: unconversed('conversations/rename'),
27
+ option: unconversed('conversations/option/set'),
28
+ retry: unconversed('conversations/retry'),
29
+ pin: () => Promise.resolve(),
30
+ openTurn: () => Promise.resolve(),
31
+ dismissSuggestion: () => Promise.resolve(),
24
32
  };
25
33
  const NO_CHAT_DRAFT = {
26
34
  write: () => Promise.resolve(),
35
+ prepend: () => Promise.resolve(),
36
+ append: () => Promise.resolve(),
27
37
  discard: () => Promise.resolve(),
28
38
  };
39
+ function areasOf(reach) {
40
+ return reach.areas ?? [];
41
+ }
42
+ function fenced(reach, room, path) {
43
+ return areasOf(reach).some((area) => area.room === room &&
44
+ beneath(area.path, path) &&
45
+ !area.open.some((open) => beneath(open, path)));
46
+ }
29
47
  export function holds(reach, room) {
30
48
  return (reach === null ||
31
49
  reach.rooms.includes(room) ||
@@ -38,33 +56,33 @@ export function governs(reach, room) {
38
56
  if (wholly(reach, room.locator)) {
39
57
  return { collection: true, selection: room.typedSelection !== null };
40
58
  }
41
- const selected = (path) => room.typedSelection?.roots.some((root) => beneath(root, path)) ?? false;
59
+ const within = (path) => selected({ selection: room.typedSelection }, path);
42
60
  const paths = reach.documents
43
61
  .filter((document) => document.room === room.locator)
44
62
  .map(({ path }) => path);
45
- return { collection: paths.some((path) => !selected(path)), selection: paths.some(selected) };
63
+ return { collection: paths.some((path) => !within(path)), selection: paths.some(within) };
46
64
  }
47
65
  function covers(reach, room, path) {
48
66
  return (reach === null ||
49
- reach.rooms.includes(room) ||
50
- reach.documents.some((document) => document.room === room && document.path === path));
67
+ (!fenced(reach, room, path) &&
68
+ (reach.rooms.includes(room) ||
69
+ reach.documents.some((document) => document.room === room && document.path === path))));
51
70
  }
52
71
  function conversing(reach) {
53
72
  return reach === null || reach.conversations;
54
73
  }
55
- function refers(reach, scope) {
56
- if (reach === null)
57
- return true;
58
- if (scope === null)
59
- return false;
60
- if (scope.kind === 'conversations')
61
- return reach.conversations;
62
- return scope.path === undefined
63
- ? wholly(reach, scope.locator)
64
- : covers(reach, scope.locator, scope.path);
74
+ function roomsAwaited(error, reach) {
75
+ return error.code === 'unknown-type' && reach !== null && reach.rooms.length === 0;
65
76
  }
66
- function unreachedReference(fileRef) {
67
- return { kind: 'absent', code: 'binary-file-absent', fields: { fileRef }, retryable: false };
77
+ async function planInReach(runtime, input, reach, answered) {
78
+ try {
79
+ return await runtime.plan(input, reach);
80
+ }
81
+ catch (error) {
82
+ if (error instanceof QueryError && (answered || roomsAwaited(error, reach)))
83
+ return null;
84
+ throw error;
85
+ }
68
86
  }
69
87
  export function planReach(reach) {
70
88
  return reach === null
@@ -74,11 +92,22 @@ export function planReach(reach) {
74
92
  documents: [
75
93
  ...new Set(reach.documents.map(({ room, path }) => documentKey(room, path))),
76
94
  ].sort(),
95
+ areas: areasOf(reach)
96
+ .map(({ room, path, open }) => ({ room, path, open: [...new Set(open)].sort() }))
97
+ .sort((left, right) => documentKey(left.room, left.path) < documentKey(right.room, right.path) ? -1 : 1),
77
98
  };
78
99
  }
79
100
  function roomsWithin(reach, rooms) {
80
101
  return rooms.filter((room) => wholly(reach, room.locator));
81
102
  }
103
+ function roomsChangeWithin(reach, { changed, removed, order }) {
104
+ const within = {
105
+ changed: changed.filter(([locator]) => wholly(reach, locator)),
106
+ removed,
107
+ order: order === null ? null : order.filter((locator) => wholly(reach, locator)),
108
+ };
109
+ return unchanged(within) ? null : within;
110
+ }
82
111
  function typesWithin(reach, room, types) {
83
112
  if (room === undefined)
84
113
  return structuredClone(UNHELD_TYPES);
@@ -89,7 +118,7 @@ function typesWithin(reach, room, types) {
89
118
  };
90
119
  }
91
120
  function moves(reach, room, move) {
92
- return move === undefined || covers(reach, room, moveTarget(move));
121
+ return move === undefined || covers(reach, move.room ?? room, moveTarget(move));
93
122
  }
94
123
  function draftWithin(reach, draft) {
95
124
  return covers(reach, draft.room, draft.path) && moves(reach, draft.room, draft.parts.move);
@@ -108,12 +137,13 @@ function writeWithin(reach, write) {
108
137
  function savedWithin(reach, room, result) {
109
138
  if (reach === null || result.outcome === 'saved')
110
139
  return result;
111
- const { file, location, referrers, ...refusal } = result;
140
+ const { file, location, line, referrers, ...refusal } = result;
112
141
  const hidden = file !== undefined && !covers(reach, room, file);
113
142
  return {
114
143
  ...refusal,
115
144
  ...(file === undefined || hidden ? {} : { file }),
116
145
  ...(location === undefined || hidden ? {} : { location }),
146
+ ...(line === undefined || hidden ? {} : { line }),
117
147
  ...(referrers === undefined
118
148
  ? {}
119
149
  : { referrers: referrers.filter((path) => covers(reach, room, path)) }),
@@ -123,80 +153,200 @@ function statusWithin(reach, status) {
123
153
  return {
124
154
  ...status,
125
155
  attentionRequired: status.attentionRequired.filter((entry) => covers(reach, entry.room, entry.path)),
156
+ unsent: status.unsent.filter((change) => covers(reach, change.room, change.path)),
126
157
  };
127
158
  }
128
159
  function queueWithin(reach, room, entries) {
129
- return entries.filter(({ batch }) => batch.changes.every((change) => covers(reach, room, change.path) &&
130
- (change.kind !== 'move' || covers(reach, room, change.to))));
160
+ return entries
161
+ .filter(({ batch }) => batch.changes.every((change) => covers(reach, room, change.path) &&
162
+ (change.kind !== 'move' || covers(reach, room, change.to))))
163
+ .map((entry) => {
164
+ const { between, ...batch } = entry.batch;
165
+ if (between === undefined)
166
+ return entry;
167
+ return wholly(reach, between.source.room) && wholly(reach, between.destination.room)
168
+ ? entry
169
+ : { ...entry, batch };
170
+ });
131
171
  }
132
172
  function unreached(room) {
133
- return runtimeError('room-not-held', `No Local Replica for ${room}`);
173
+ return runtimeError('unknown-room', `Unknown Room ${room}`);
174
+ }
175
+ function lockedError(room) {
176
+ return runtimeError(ROOM_LOCKED, `${room} is locked until House confirms its access`, true);
177
+ }
178
+ function deviceUnreached() {
179
+ return runtimeError('device-unreached', 'Only the panel reaches this device');
134
180
  }
135
- export function narrowed(runtime, given) {
181
+ const ATTACH_REQUIRED = 'attach-required';
182
+ function attachRequired() {
183
+ return runtimeError(ATTACH_REQUIRED, 'App code takes a file in with binaryFile.attach');
184
+ }
185
+ function carriesFile(parts) {
186
+ return parts !== null && typeof parts === 'object' && Object.hasOwn(parts, 'file');
187
+ }
188
+ export function narrowed(runtime, given, port) {
136
189
  const { md, watch } = runtime;
137
190
  let reach = given;
138
191
  const open = new Set();
139
- function following(begin) {
192
+ function following(begin, locking = false) {
140
193
  let stop = begin();
141
194
  const restart = () => {
142
195
  stop();
143
196
  stop = begin();
144
197
  };
145
198
  open.add(restart);
199
+ const unwatch = locking ? runtime.watchLocks(restart) : () => { };
146
200
  return () => {
147
201
  open.delete(restart);
202
+ unwatch();
203
+ stop();
204
+ };
205
+ }
206
+ const unlocking = (rooms, locked) => {
207
+ const held = (rooms ?? []).filter((room) => locked.includes(room));
208
+ return held.length === 0 ? null : { pending: held.map((room) => ({ room, awaits: 'unlock' })) };
209
+ };
210
+ const unlocked = (entries, locked) => entries.filter((entry) => !locked.includes(entry.room));
211
+ const intoLocked = async (held) => {
212
+ for (const move of held) {
213
+ if (move?.room !== undefined && (await runtime.locked(move.room)))
214
+ return true;
215
+ }
216
+ return false;
217
+ };
218
+ function ordered(deliver) {
219
+ let open = true;
220
+ let shown = Promise.resolve();
221
+ return {
222
+ push(making) {
223
+ shown = shown.then(() => making.then((value) => {
224
+ if (open)
225
+ deliver(value);
226
+ }, uncaught), uncaught);
227
+ },
228
+ stop() {
229
+ open = false;
230
+ },
231
+ };
232
+ }
233
+ function unlockedWatch(topic, input, deliver, fail, within) {
234
+ const shown = ordered(deliver);
235
+ const stop = watch(topic, input, (message) => {
236
+ shown.push(runtime.lockedRooms().then((locked) => within(message, locked)));
237
+ }, fail);
238
+ return () => {
239
+ shown.stop();
240
+ stop();
241
+ };
242
+ }
243
+ function lockedFirst(room, start, shut) {
244
+ let open = true;
245
+ let stop = () => { };
246
+ void (async () => {
247
+ const closed = !holds(reach, room) || (await runtime.locked(room));
248
+ if (!open)
249
+ return;
250
+ if (closed)
251
+ shut();
252
+ else
253
+ stop = start();
254
+ })();
255
+ return () => {
256
+ open = false;
148
257
  stop();
149
258
  };
150
259
  }
151
- const within = (topic, input, deliver) => {
260
+ const within = (topic, input, deliver, fail) => {
261
+ if (topic === 'read' && reach !== null) {
262
+ fail(deviceUnreached());
263
+ return () => { };
264
+ }
152
265
  if (topic === 'rooms') {
153
- return following(() => watch(topic, input, (rooms) => deliver(roomsWithin(reach, rooms))));
266
+ return following(() => watch(topic, input, (rooms) => {
267
+ const shown = Array.isArray(rooms)
268
+ ? roomsWithin(reach, rooms)
269
+ : roomsChangeWithin(reach, rooms);
270
+ if (shown !== null)
271
+ deliver(shown);
272
+ }, fail));
273
+ }
274
+ if (topic === 'readiness') {
275
+ return following(() => runtime.watchReadiness(port, reach, deliver));
154
276
  }
155
277
  if (topic === 'sync-status') {
156
- return following(() => watch(topic, input, (status) => deliver(statusWithin(reach, status))));
278
+ return following(() => unlockedWatch(topic, input, deliver, fail, (status, locked) => {
279
+ const shown = statusWithin(reach, status);
280
+ return { ...shown, attentionRequired: unlocked(shown.attentionRequired, locked) };
281
+ }), true);
157
282
  }
158
283
  if (topic === 'room-drafts') {
159
- return following(() => watch(topic, input, (drafts) => deliver(draftsWithin(reach, drafts))));
284
+ return following(() => unlockedWatch(topic, input, deliver, fail, (drafts, locked) => unlocked(draftsWithin(reach, drafts), locked)), true);
160
285
  }
161
286
  if (topic === 'queue') {
162
287
  const room = input[0];
163
- return following(() => {
164
- if (!holds(reach, room)) {
165
- deliver([]);
166
- return () => { };
167
- }
168
- return watch(topic, input, (entries) => deliver(queueWithin(reach, room, entries)));
169
- });
288
+ return following(() => lockedFirst(room, () => watch(topic, input, (entries) => deliver(queueWithin(reach, room, entries)), fail), () => deliver([])), true);
170
289
  }
171
290
  if (topic === 'query') {
172
- const plan = runtime.plan(input[0], reach);
173
291
  let held = null;
292
+ let planning = null;
293
+ const waiting = (result) => {
294
+ const answer = { result, keys: [] };
295
+ if (held === null || changeOf(held, answer) !== null)
296
+ deliver(answer);
297
+ held = digestOf(answer);
298
+ };
174
299
  return following(() => {
175
- let first = true;
176
- return runtime.watchPlan({ ...plan, reach: planReach(reach) }, (message) => {
177
- if (!first) {
178
- held = applied(held, message);
179
- deliver(message);
180
- return;
181
- }
182
- first = false;
183
- if (held === null) {
184
- held = message;
185
- deliver(message);
186
- return;
187
- }
188
- const next = reconciled(held, message);
189
- if (next === null)
300
+ let open = true;
301
+ let stop = () => { };
302
+ if (planning?.reach !== reach) {
303
+ planning = { reach, plan: planInReach(runtime, input[0], reach, held !== null) };
304
+ }
305
+ const planned = planning.plan;
306
+ void (async () => {
307
+ const plan = await planned;
308
+ const locked = await runtime.lockedRooms();
309
+ if (!open)
190
310
  return;
191
- held = next.keyed;
192
- deliver(next.change);
311
+ if (plan === null)
312
+ return waiting({ pending: [] });
313
+ const pending = unlocking(plan.rooms, locked);
314
+ if (pending !== null)
315
+ return waiting(pending);
316
+ let first = true;
317
+ const heard = (message) => {
318
+ if (!first) {
319
+ held = digestApplied(held, message);
320
+ deliver(message);
321
+ return;
322
+ }
323
+ first = false;
324
+ const change = held === null ? message : changeOf(held, message);
325
+ held = digestOf(message);
326
+ if (change !== null)
327
+ deliver(change);
328
+ };
329
+ stop = runtime.watchPlan({ ...plan, locked }, (message) => {
330
+ if (open)
331
+ heard(message);
332
+ }, (error) => {
333
+ if (open)
334
+ fail(error);
335
+ });
336
+ })().catch((error) => {
337
+ if (open)
338
+ fail(error);
193
339
  });
194
- });
340
+ return () => {
341
+ open = false;
342
+ stop();
343
+ };
344
+ }, true);
195
345
  }
196
346
  if (topic === 'conversation') {
197
347
  return following(() => {
198
348
  if (conversing(reach))
199
- return watch(topic, input, deliver);
349
+ return watch(topic, input, deliver, fail);
200
350
  deliver(unheldView(input[0]));
201
351
  return () => { };
202
352
  });
@@ -204,64 +354,160 @@ export function narrowed(runtime, given) {
204
354
  if (topic === 'conversations' || topic === 'agents') {
205
355
  return following(() => {
206
356
  if (conversing(reach))
207
- return watch(topic, input, deliver);
357
+ return watch(topic, input, deliver, fail);
208
358
  deliver([]);
209
359
  return () => { };
210
360
  });
211
361
  }
212
- return watch(topic, input, deliver);
362
+ if (topic === 'figures' || topic === 'holdings' || topic === 'listed-agents') {
363
+ if (reach === null)
364
+ return watch(topic, input, deliver, fail);
365
+ fail(deviceUnreached());
366
+ return () => { };
367
+ }
368
+ return watch(topic, input, deliver, fail);
213
369
  };
370
+ const files = new Map();
371
+ let handed = 0;
372
+ async function hand(reading) {
373
+ const answer = await reading;
374
+ if (answer.kind !== 'binary')
375
+ return answer;
376
+ handed += 1;
377
+ const file = String(handed);
378
+ files.set(file, answer.file);
379
+ return { ...answer, file };
380
+ }
214
381
  const conversation = () => (conversing(reach) ? md.conversation : NO_CONVERSATION);
215
382
  const chatDraft = () => (conversing(reach) ? md.chatDraft : NO_CHAT_DRAFT);
216
383
  const view = {
217
384
  ...md,
218
- rooms: () => roomsWithin(reach, md.rooms()),
219
- query: ((input) => runtime.query(runtime.plan(input, reach))),
385
+ rooms: () => md.rooms().then((rooms) => roomsWithin(reach, rooms)),
386
+ query: (async (input) => {
387
+ const plan = await planInReach(runtime, input, reach, false);
388
+ if (plan === null)
389
+ return { pending: [] };
390
+ const locked = await runtime.lockedRooms();
391
+ return unlocking(plan.rooms, locked) ?? runtime.query({ ...plan, locked });
392
+ }),
220
393
  search: (input) => runtime.search(input, reach),
221
- types(room) {
394
+ async types(room) {
395
+ if (holds(reach, room) && (await runtime.locked(room)))
396
+ throw lockedError(room);
222
397
  if (wholly(reach, room))
223
398
  return md.types(room);
224
399
  if (!holds(reach, room))
225
400
  return structuredClone(UNHELD_TYPES);
226
- const listed = md.rooms().find(({ locator }) => locator === room);
227
- return typesWithin(reach, listed, md.types(room));
401
+ return typesWithin(reach, await runtime.room(room), await md.types(room));
228
402
  },
229
403
  async save(room, roomDrafts, writtenBy) {
230
404
  if (!holds(reach, room))
231
405
  throw unreached(room);
232
- const outside = roomDrafts.find(({ path }) => !covers(reach, room, path) ||
233
- !moves(reach, room, md.roomDraft.read(room, path)?.parts.move));
406
+ if (await runtime.locked(room)) {
407
+ return { outcome: 'refused', code: ROOM_LOCKED, retryable: true };
408
+ }
409
+ const held = (await Promise.all(roomDrafts.map(({ path }) => md.roomDraft.read(room, path)))).map((draft) => draft?.parts.move);
410
+ const outside = roomDrafts.find(({ path }, at) => !covers(reach, room, path) || !moves(reach, room, held[at]));
234
411
  if (outside !== undefined) {
235
412
  return { outcome: 'refused', code: 'stale', retryable: false, file: outside.path };
236
413
  }
414
+ if (await intoLocked(held))
415
+ return { outcome: 'refused', code: ROOM_LOCKED, retryable: true };
237
416
  return savedWithin(reach, room, await md.save(room, roomDrafts, writtenBy));
238
417
  },
239
- history: (room, path, query) => covers(reach, room, path)
240
- ? md.history(room, path, query)
241
- : Promise.resolve(failure({ kind: 'room-not-readable', locator: room })),
418
+ async saveParts(room, parts, writtenBy) {
419
+ if (!holds(reach, room))
420
+ throw unreached(room);
421
+ const filed = reach === null ? undefined : parts.find(({ parts: one }) => carriesFile(one));
422
+ if (filed !== undefined) {
423
+ return { outcome: 'refused', code: ATTACH_REQUIRED, retryable: false, file: filed.path };
424
+ }
425
+ if (await runtime.locked(room)) {
426
+ return { outcome: 'refused', code: ROOM_LOCKED, retryable: true };
427
+ }
428
+ const held = parts.map(({ path, parts: one }) => readParts(one, path).move);
429
+ if (parts.some(({ path }, at) => !covers(reach, room, path) || !moves(reach, room, held[at]))) {
430
+ throw unreached(room);
431
+ }
432
+ if (await intoLocked(held))
433
+ return { outcome: 'refused', code: ROOM_LOCKED, retryable: true };
434
+ return savedWithin(reach, room, await md.saveParts(room, parts, writtenBy));
435
+ },
436
+ async resolve(room, path, destination) {
437
+ const at = await runtime.located(room, path, destination);
438
+ return at !== null && !covers(reach, at.room, at.path)
439
+ ? UNREADABLE
440
+ : md.resolve(room, path, destination);
441
+ },
442
+ history: async (room, path, query) => !covers(reach, room, path)
443
+ ? failure({ kind: 'room-not-readable', locator: room })
444
+ : (await runtime.locked(room))
445
+ ? lockedRoom(room)
446
+ : md.history(room, path, query),
242
447
  binaryFile: {
243
- read: (room, path, revision) => covers(reach, room, path)
244
- ? md.binaryFile.read(room, path, revision)
245
- : Promise.resolve(failure({ kind: 'room-not-readable', locator: room })),
246
- readReference: (reference) => refers(reach, runtime.referrerScope(reference.referrer))
247
- ? md.binaryFile.readReference(reference)
248
- : Promise.resolve(unreachedReference(reference.fileRef)),
448
+ read: async (room, path, revision) => !covers(reach, room, path)
449
+ ? failure({ kind: 'room-not-readable', locator: room })
450
+ : (await runtime.locked(room))
451
+ ? lockedRoom(room)
452
+ : hand(md.binaryFile.read(room, path, revision)),
453
+ link: async (room, path, revision) => !covers(reach, room, path)
454
+ ? failure({ kind: 'room-not-readable', locator: room })
455
+ : (await runtime.locked(room))
456
+ ? lockedRoom(room)
457
+ : md.binaryFile.link(room, path, revision),
458
+ show: async (room, path, revision) => !covers(reach, room, path)
459
+ ? failure({ kind: 'room-not-readable', locator: room })
460
+ : (await runtime.locked(room))
461
+ ? lockedRoom(room)
462
+ : hand(md.binaryFile.show(room, path, revision)),
463
+ attach: async (room, file) => !wholly(reach, room)
464
+ ? failure({ kind: 'room-not-readable', locator: room })
465
+ : (await runtime.locked(room))
466
+ ? lockedRoom(room)
467
+ : md.binaryFile.attach(room, file),
468
+ async part(file, part) {
469
+ const key = files.get(file);
470
+ if (key === undefined)
471
+ return null;
472
+ const bytes = await md.binaryFile.part(key, part);
473
+ if (bytes === null)
474
+ files.delete(file);
475
+ return bytes;
476
+ },
249
477
  },
250
- reached: (room, roomVersion, path) => (path === undefined ? wholly(reach, room) : covers(reach, room, path)) &&
251
- md.reached(room, roomVersion, path),
252
- log: () => (reach === null ? md.log() : ''),
478
+ reached: async (room, roomVersion, path) => (path === undefined ? wholly(reach, room) : covers(reach, room, path)) &&
479
+ !(await runtime.locked(room)) &&
480
+ (await md.reached(room, roomVersion, path)),
481
+ cleanUp: () => (reach === null ? md.cleanUp() : Promise.reject(deviceUnreached())),
482
+ unsent: () => (reach === null ? md.unsent() : Promise.reject(deviceUnreached())),
483
+ reset: () => (reach === null ? md.reset() : Promise.reject(deviceUnreached())),
484
+ readAgain: () => (reach === null ? md.readAgain() : Promise.reject(deviceUnreached())),
253
485
  roomDraft: {
254
- list: () => md.roomDraft.list().then((drafts) => draftsWithin(reach, drafts)),
255
- read: (room, path) => covers(reach, room, path) ? shownDraft(reach, md.roomDraft.read(room, path)) : null,
256
- async write(room, path, revision, parts) {
257
- if (!covers(reach, room, path) || !moves(reach, room, readParts(parts).move)) {
486
+ list: async () => unlocked(draftsWithin(reach, await md.roomDraft.list()), await runtime.lockedRooms()),
487
+ async read(room, path) {
488
+ if (!covers(reach, room, path))
489
+ return null;
490
+ if (await runtime.locked(room))
491
+ throw lockedError(room);
492
+ return shownDraft(reach, await md.roomDraft.read(room, path));
493
+ },
494
+ async write(room, path, revision, parts, next) {
495
+ if (reach !== null && carriesFile(parts))
496
+ throw attachRequired();
497
+ const move = readParts(parts, path).move;
498
+ if (!covers(reach, room, path) || !moves(reach, room, move))
258
499
  throw unreached(room);
259
- }
260
- return writeWithin(reach, await md.roomDraft.write(room, path, revision, parts));
500
+ if (await runtime.locked(room))
501
+ throw lockedError(room);
502
+ if (await intoLocked([move]))
503
+ throw lockedError(move.room);
504
+ return writeWithin(reach, await md.roomDraft.write(room, path, revision, parts, next));
261
505
  },
262
506
  async discard(room, path, revision) {
263
507
  if (!covers(reach, room, path))
264
508
  return staleWrite(null);
509
+ if (await runtime.locked(room))
510
+ throw lockedError(room);
265
511
  return writeWithin(reach, await md.roomDraft.discard(room, path, revision));
266
512
  },
267
513
  },
@@ -269,15 +515,24 @@ export function narrowed(runtime, given) {
269
515
  list: () => conversation().list(),
270
516
  read: (id, options) => conversation().read(id, options),
271
517
  create: (input) => conversation().create(input),
272
- send: (id) => conversation().send(id),
273
- answer: (id, answer) => conversation().answer(id, answer),
274
- interrupt: (id) => conversation().interrupt(id),
275
- kill: (id) => conversation().kill(id),
276
- cancel: (id, turn) => conversation().cancel(id, turn),
277
- delete: (id) => conversation().delete(id),
518
+ send: (id, operation, draft) => conversation().send(id, operation, draft),
519
+ answer: (id, answer, operation) => conversation().answer(id, answer, operation),
520
+ interrupt: (id, operation) => conversation().interrupt(id, operation),
521
+ kill: (id, operation) => conversation().kill(id, operation),
522
+ delete: (id, operation) => conversation().delete(id, operation),
523
+ takeOut: (id, message, operation) => conversation().takeOut(id, message, operation),
524
+ decide: (request, decision, operation) => conversation().decide(request, decision, operation),
525
+ rename: (id, name, operation) => conversation().rename(id, name, operation),
526
+ option: (id, option, value, operation) => conversation().option(id, option, value, operation),
527
+ retry: (id, message, operation) => conversation().retry(id, message, operation),
528
+ pin: (figures) => conversation().pin(figures),
529
+ openTurn: (id, turn) => conversation().openTurn(id, turn),
530
+ dismissSuggestion: (id, suggestion) => conversation().dismissSuggestion(id, suggestion),
278
531
  },
279
532
  chatDraft: {
280
533
  write: (id, draft, revision) => chatDraft().write(id, draft, revision),
534
+ prepend: (id, draft) => chatDraft().prepend(id, draft),
535
+ append: (id, draft) => chatDraft().append(id, draft),
281
536
  discard: (id) => chatDraft().discard(id),
282
537
  },
283
538
  observe: observing(within),