@agentshouse/mdruntime 0.1.0-ce531b51ff088 → 0.1.0-ce6bc9239a3ee

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 (253) hide show
  1. package/README.md +25 -12
  2. package/dist/acceptance.d.ts +26 -0
  3. package/dist/acceptance.d.ts.map +1 -0
  4. package/dist/acceptance.js +384 -0
  5. package/dist/adapter.d.ts +218 -62
  6. package/dist/adapter.d.ts.map +1 -1
  7. package/dist/adapter.js +1 -9
  8. package/dist/attached-model.d.ts +8 -0
  9. package/dist/attached-model.d.ts.map +1 -0
  10. package/dist/attached-model.js +46 -0
  11. package/dist/attempt.d.ts +16 -0
  12. package/dist/attempt.d.ts.map +1 -0
  13. package/dist/attempt.js +70 -0
  14. package/dist/binary.d.ts +18 -0
  15. package/dist/binary.d.ts.map +1 -0
  16. package/dist/binary.js +8 -0
  17. package/dist/bootstrap.d.ts +40 -6
  18. package/dist/bootstrap.d.ts.map +1 -1
  19. package/dist/bootstrap.js +336 -51
  20. package/dist/chain.d.ts +12 -0
  21. package/dist/chain.d.ts.map +1 -0
  22. package/dist/chain.js +64 -0
  23. package/dist/change-set.d.ts +9 -14
  24. package/dist/change-set.d.ts.map +1 -1
  25. package/dist/change-set.js +11 -56
  26. package/dist/change.d.ts +46 -0
  27. package/dist/change.d.ts.map +1 -1
  28. package/dist/change.js +34 -0
  29. package/dist/chat-types.d.ts +3 -0
  30. package/dist/chat-types.d.ts.map +1 -0
  31. package/dist/chat-types.js +2 -0
  32. package/dist/client.d.ts +50 -18
  33. package/dist/client.d.ts.map +1 -1
  34. package/dist/client.js +162 -30
  35. package/dist/collection.d.ts +13 -14
  36. package/dist/collection.d.ts.map +1 -1
  37. package/dist/collection.js +52 -56
  38. package/dist/compile.d.ts +16 -0
  39. package/dist/compile.d.ts.map +1 -0
  40. package/dist/compile.js +717 -0
  41. package/dist/connection.d.ts +63 -48
  42. package/dist/connection.d.ts.map +1 -1
  43. package/dist/connection.js +2487 -1575
  44. package/dist/context.d.ts +2 -0
  45. package/dist/context.d.ts.map +1 -0
  46. package/dist/context.js +7 -0
  47. package/dist/conversation-row.d.ts +33 -0
  48. package/dist/conversation-row.d.ts.map +1 -0
  49. package/dist/conversation-row.js +47 -0
  50. package/dist/conversation.d.ts +72 -22
  51. package/dist/conversation.d.ts.map +1 -1
  52. package/dist/conversation.js +1008 -273
  53. package/dist/digest.d.ts +7 -0
  54. package/dist/digest.d.ts.map +1 -0
  55. package/dist/digest.js +113 -0
  56. package/dist/durability.d.ts +10 -1
  57. package/dist/durability.d.ts.map +1 -1
  58. package/dist/durability.js +5 -0
  59. package/dist/entry.d.ts +20 -0
  60. package/dist/entry.d.ts.map +1 -0
  61. package/dist/entry.js +161 -0
  62. package/dist/expectation.d.ts +21 -0
  63. package/dist/expectation.d.ts.map +1 -0
  64. package/dist/expectation.js +70 -0
  65. package/dist/failure.d.ts +13 -0
  66. package/dist/failure.d.ts.map +1 -0
  67. package/dist/failure.js +19 -0
  68. package/dist/figures.d.ts +48 -0
  69. package/dist/figures.d.ts.map +1 -0
  70. package/dist/figures.js +197 -0
  71. package/dist/file.d.ts +2 -19
  72. package/dist/file.d.ts.map +1 -1
  73. package/dist/file.js +7 -122
  74. package/dist/host.d.ts +18 -2
  75. package/dist/host.d.ts.map +1 -1
  76. package/dist/host.js +164 -50
  77. package/dist/identity.d.ts +3 -0
  78. package/dist/identity.d.ts.map +1 -1
  79. package/dist/identity.js +13 -1
  80. package/dist/index.d.ts +31 -10
  81. package/dist/index.d.ts.map +1 -1
  82. package/dist/index.js +13 -0
  83. package/dist/install.d.ts +86 -0
  84. package/dist/install.d.ts.map +1 -0
  85. package/dist/install.js +537 -0
  86. package/dist/job.d.ts +33 -0
  87. package/dist/job.d.ts.map +1 -0
  88. package/dist/job.js +54 -0
  89. package/dist/live.d.ts +23 -0
  90. package/dist/live.d.ts.map +1 -0
  91. package/dist/live.js +165 -0
  92. package/dist/log.d.ts +1 -0
  93. package/dist/log.d.ts.map +1 -1
  94. package/dist/media.d.ts +8 -0
  95. package/dist/media.d.ts.map +1 -0
  96. package/dist/media.js +218 -0
  97. package/dist/memory.d.ts +30 -9
  98. package/dist/memory.d.ts.map +1 -1
  99. package/dist/memory.js +337 -86
  100. package/dist/messages.d.ts +52 -0
  101. package/dist/messages.d.ts.map +1 -0
  102. package/dist/messages.js +168 -0
  103. package/dist/model.d.ts +17 -16
  104. package/dist/model.d.ts.map +1 -1
  105. package/dist/model.js +9 -9
  106. package/dist/name.d.ts +4 -0
  107. package/dist/name.d.ts.map +1 -0
  108. package/dist/name.js +122 -0
  109. package/dist/observation.d.ts +22 -2
  110. package/dist/observation.d.ts.map +1 -1
  111. package/dist/observation.js +133 -17
  112. package/dist/open.d.ts +2 -0
  113. package/dist/open.d.ts.map +1 -0
  114. package/dist/open.js +1 -0
  115. package/dist/opened.d.ts +22 -0
  116. package/dist/opened.d.ts.map +1 -0
  117. package/dist/opened.js +107 -0
  118. package/dist/outcome.d.ts +73 -5
  119. package/dist/outcome.d.ts.map +1 -1
  120. package/dist/outcome.js +84 -1
  121. package/dist/overlay.d.ts +16 -5
  122. package/dist/overlay.d.ts.map +1 -1
  123. package/dist/overlay.js +147 -180
  124. package/dist/parts.d.ts +59 -0
  125. package/dist/parts.d.ts.map +1 -0
  126. package/dist/parts.js +118 -0
  127. package/dist/paths.d.ts +1 -1
  128. package/dist/paths.d.ts.map +1 -1
  129. package/dist/paths.js +4 -16
  130. package/dist/query.d.ts +56 -180
  131. package/dist/query.d.ts.map +1 -1
  132. package/dist/query.js +3 -422
  133. package/dist/questions.d.ts +32 -0
  134. package/dist/questions.d.ts.map +1 -0
  135. package/dist/questions.js +118 -0
  136. package/dist/reach.d.ts +54 -0
  137. package/dist/reach.d.ts.map +1 -0
  138. package/dist/reach.js +494 -0
  139. package/dist/react.d.ts +46 -0
  140. package/dist/react.d.ts.map +1 -0
  141. package/dist/react.js +54 -0
  142. package/dist/read.d.ts +7 -0
  143. package/dist/read.d.ts.map +1 -0
  144. package/dist/read.js +17 -0
  145. package/dist/readiness.d.ts +50 -0
  146. package/dist/readiness.d.ts.map +1 -0
  147. package/dist/readiness.js +27 -0
  148. package/dist/reads.d.ts +36 -0
  149. package/dist/reads.d.ts.map +1 -0
  150. package/dist/reads.js +136 -0
  151. package/dist/recovery.d.ts +26 -0
  152. package/dist/recovery.d.ts.map +1 -0
  153. package/dist/recovery.js +232 -0
  154. package/dist/refresh.d.ts +21 -7
  155. package/dist/refresh.d.ts.map +1 -1
  156. package/dist/refresh.js +155 -55
  157. package/dist/replica.d.ts +58 -33
  158. package/dist/replica.d.ts.map +1 -1
  159. package/dist/replica.js +355 -158
  160. package/dist/room-draft.d.ts +62 -11
  161. package/dist/room-draft.d.ts.map +1 -1
  162. package/dist/room-draft.js +281 -83
  163. package/dist/room-drafts.d.ts +29 -0
  164. package/dist/room-drafts.d.ts.map +1 -0
  165. package/dist/room-drafts.js +216 -0
  166. package/dist/rows.d.ts +32 -34
  167. package/dist/rows.d.ts.map +1 -1
  168. package/dist/rows.js +65 -87
  169. package/dist/save.d.ts +74 -6
  170. package/dist/save.d.ts.map +1 -1
  171. package/dist/save.js +902 -182
  172. package/dist/saves.d.ts +96 -0
  173. package/dist/saves.d.ts.map +1 -0
  174. package/dist/saves.js +999 -0
  175. package/dist/search.d.ts +15 -54
  176. package/dist/search.d.ts.map +1 -1
  177. package/dist/search.js +10 -121
  178. package/dist/seed.d.ts +30 -0
  179. package/dist/seed.d.ts.map +1 -0
  180. package/dist/seed.js +141 -0
  181. package/dist/shared.d.ts +15 -0
  182. package/dist/shared.d.ts.map +1 -0
  183. package/dist/shared.js +421 -0
  184. package/dist/socket/admission.d.ts +7 -0
  185. package/dist/socket/admission.d.ts.map +1 -0
  186. package/dist/socket/admission.js +39 -0
  187. package/dist/socket/answers.d.ts +6 -0
  188. package/dist/socket/answers.d.ts.map +1 -0
  189. package/dist/socket/answers.js +20 -0
  190. package/dist/socket/reads.d.ts +10 -0
  191. package/dist/socket/reads.d.ts.map +1 -0
  192. package/dist/socket/reads.js +31 -0
  193. package/dist/socket.d.ts +43 -0
  194. package/dist/socket.d.ts.map +1 -0
  195. package/dist/socket.js +96 -0
  196. package/dist/source.d.ts +61 -0
  197. package/dist/source.d.ts.map +1 -0
  198. package/dist/source.js +81 -0
  199. package/dist/status.d.ts +7 -4
  200. package/dist/status.d.ts.map +1 -1
  201. package/dist/status.js +3 -15
  202. package/dist/store/fences.d.ts +16 -0
  203. package/dist/store/fences.d.ts.map +1 -0
  204. package/dist/store/fences.js +26 -0
  205. package/dist/store/installs.d.ts +30 -0
  206. package/dist/store/installs.d.ts.map +1 -0
  207. package/dist/store/installs.js +34 -0
  208. package/dist/store/records.d.ts +212 -0
  209. package/dist/store/records.d.ts.map +1 -0
  210. package/dist/store/records.js +408 -0
  211. package/dist/store/room-held.d.ts +8 -0
  212. package/dist/store/room-held.d.ts.map +1 -0
  213. package/dist/store/room-held.js +17 -0
  214. package/dist/store/watchers.d.ts +15 -0
  215. package/dist/store/watchers.d.ts.map +1 -0
  216. package/dist/store/watchers.js +36 -0
  217. package/dist/store/writes.d.ts +24 -0
  218. package/dist/store/writes.d.ts.map +1 -0
  219. package/dist/store/writes.js +125 -0
  220. package/dist/store.d.ts +77 -94
  221. package/dist/store.d.ts.map +1 -1
  222. package/dist/store.js +118 -389
  223. package/dist/stored.d.ts +156 -0
  224. package/dist/stored.d.ts.map +1 -0
  225. package/dist/stored.js +637 -0
  226. package/dist/tables.d.ts +407 -0
  227. package/dist/tables.d.ts.map +1 -0
  228. package/dist/tables.js +724 -0
  229. package/dist/tallies.d.ts +18 -0
  230. package/dist/tallies.d.ts.map +1 -0
  231. package/dist/tallies.js +129 -0
  232. package/dist/transfer.d.ts +0 -5
  233. package/dist/transfer.d.ts.map +1 -1
  234. package/dist/turn.d.ts +9 -0
  235. package/dist/turn.d.ts.map +1 -0
  236. package/dist/turn.js +75 -0
  237. package/dist/validation.d.ts +29 -0
  238. package/dist/validation.d.ts.map +1 -0
  239. package/dist/validation.js +104 -0
  240. package/dist/windows.d.ts +11 -0
  241. package/dist/windows.d.ts.map +1 -0
  242. package/dist/windows.js +16 -0
  243. package/dist/wire.d.ts +205 -19
  244. package/dist/wire.d.ts.map +1 -1
  245. package/dist/wire.js +95 -61
  246. package/package.json +33 -10
  247. package/AGENTS.md +0 -207
  248. package/dist/attachment.d.ts +0 -3
  249. package/dist/attachment.d.ts.map +0 -1
  250. package/dist/attachment.js +0 -8
  251. package/dist/read-side.d.ts +0 -14
  252. package/dist/read-side.d.ts.map +0 -1
  253. package/dist/read-side.js +0 -371
package/dist/overlay.js CHANGED
@@ -1,4 +1,21 @@
1
- import { apply, parse, serialize } from '@agentshouse/mdmodel';
1
+ import { apply, frontmatterValue, parse, serialize, } from '@agentshouse/mdmodel';
2
+ import { drafted, entriesIn, settling } from './shared.js';
3
+ import { ROW_WEIGHT } from './turn.js';
4
+ export function* acceptedBinaries(files) {
5
+ for (const [path, file] of entriesIn(files))
6
+ yield [path, { state: 'accepted', ...file }];
7
+ }
8
+ export function sameBinary(left, right) {
9
+ if (left === undefined || right === undefined)
10
+ return left === right;
11
+ return (left.state === right.state &&
12
+ left.byteLength === right.byteLength &&
13
+ left.mediaType === right.mediaType &&
14
+ left.sha256 === right.sha256 &&
15
+ (left.state === 'accepted'
16
+ ? right.state === 'accepted'
17
+ : right.state === 'pending' && left.localId === right.localId));
18
+ }
2
19
  export function sameChange(left, right) {
3
20
  if (left === undefined || right === undefined)
4
21
  return left === right;
@@ -8,10 +25,13 @@ export function sameChange(left, right) {
8
25
  left.author?.name === right.author?.name);
9
26
  }
10
27
  const EMPTY_FRONTMATTER = '---\n---\n';
28
+ function isPart(change) {
29
+ return change.kind === 'field' || change.kind === 'section' || change.kind === 'preamble';
30
+ }
11
31
  function at(path, name) {
12
32
  return `${path} ${name}`;
13
33
  }
14
- function priorsOf(preconditions) {
34
+ function* priorsOf(preconditions) {
15
35
  const fields = new Map();
16
36
  const sections = new Map();
17
37
  const preambles = new Map();
@@ -25,6 +45,7 @@ function priorsOf(preconditions) {
25
45
  if (precondition.kind === 'preamble') {
26
46
  preambles.set(precondition.path, precondition.value);
27
47
  }
48
+ yield ROW_WEIGHT;
28
49
  }
29
50
  return {
30
51
  field: (path, name) => fields.get(at(path, name)),
@@ -40,49 +61,50 @@ function compose(fields, sections) {
40
61
  const opened = parse(skeleton);
41
62
  if (!opened.ok)
42
63
  return skeleton;
43
- let document = opened.document;
44
- for (const [name, value] of Object.entries(fields)) {
45
- const next = apply(document, { kind: 'field', name, value, prior: undefined });
46
- if (next.outcome === 'applied')
47
- document = next.document;
48
- }
49
- return serialize(document);
64
+ const next = apply(opened.document, Object.entries(fields).flatMap(([name, value]) => frontmatterValue(value) ? [{ kind: 'field', name, value, prior: undefined }] : []));
65
+ return serialize(next.outcome === 'applied' ? next.document : opened.document);
50
66
  }
51
- function edited(document, change, priors) {
52
- if (change.kind === 'field') {
53
- return apply(document, {
67
+ function edited(change, priors) {
68
+ if (change.kind === 'field')
69
+ return {
54
70
  kind: 'field',
55
71
  name: change.name,
56
72
  value: change.value,
57
73
  prior: priors.field(change.path, change.name),
58
- });
59
- }
60
- if (change.kind === 'preamble') {
61
- return apply(document, {
62
- kind: 'preamble',
63
- value: change.value,
64
- prior: priors.preamble(change.path),
65
- });
66
- }
67
- if (change.kind !== 'section')
68
- return null;
69
- return apply(document, {
74
+ };
75
+ if (change.kind === 'preamble')
76
+ return { kind: 'preamble', value: change.value, prior: priors.preamble(change.path) };
77
+ return {
70
78
  kind: 'section',
71
79
  name: change.name,
72
80
  value: change.value,
73
81
  prior: priors.section(change.path, change.name),
74
- });
82
+ };
75
83
  }
76
- function edit(staged, change, priors) {
77
- const text = staged.documents[change.path];
84
+ function edit(staged, changes, priors) {
85
+ const path = changes[0].path;
86
+ delete staged.revisions[path];
87
+ const text = staged.documents[path];
78
88
  if (text === undefined)
79
- return;
80
- const parsed = parse(text, change.path);
89
+ return changes.length;
90
+ const parsed = parse(text, path);
81
91
  if (!parsed.ok)
82
- return;
83
- const next = edited(parsed.document, change, priors);
84
- if (next?.outcome === 'applied')
85
- staged.documents[change.path] = serialize(next.document);
92
+ return changes.length;
93
+ const wanted = changes.map((change) => edited(change, priors));
94
+ const first = apply(parsed.document, wanted);
95
+ if (first.outcome === 'refuse')
96
+ return changes.length;
97
+ if (first.outcome === 'applied') {
98
+ staged.documents[path] = serialize(first.document);
99
+ return 0;
100
+ }
101
+ const stale = new Set(first.stale);
102
+ const kept = wanted.filter((_, at) => !stale.has(at));
103
+ const rest = apply(parsed.document, kept);
104
+ if (rest.outcome !== 'applied')
105
+ return changes.length;
106
+ staged.documents[path] = serialize(rest.document);
107
+ return first.stale.length;
86
108
  }
87
109
  function relocate(staged, from, to) {
88
110
  const text = staged.documents[from];
@@ -90,194 +112,139 @@ function relocate(staged, from, to) {
90
112
  delete staged.documents[from];
91
113
  staged.documents[to] = text;
92
114
  }
93
- else if (staged.binaryTargets.delete(from)) {
94
- staged.binaryTargets.add(to);
115
+ else if (staged.binaries[from] !== undefined) {
116
+ staged.binaries[to] = staged.binaries[from];
117
+ delete staged.binaries[from];
95
118
  }
96
119
  else {
97
- return;
120
+ return false;
98
121
  }
99
122
  moveHead(staged, from, to);
123
+ return true;
100
124
  }
101
125
  function moveHead(heads, from, to) {
102
126
  const revision = heads.revisions[from];
127
+ const fileId = heads.fileIds[from];
128
+ const created = heads.created[from];
103
129
  const change = heads.changes[from];
104
130
  delete heads.revisions[from];
131
+ delete heads.fileIds[from];
132
+ delete heads.created[from];
105
133
  delete heads.changes[from];
134
+ delete heads.fileIds[to];
135
+ delete heads.created[to];
106
136
  delete heads.changes[to];
107
137
  if (revision !== undefined)
108
138
  heads.revisions[to] = revision;
139
+ if (fileId !== undefined)
140
+ heads.fileIds[to] = fileId;
141
+ if (created !== undefined)
142
+ heads.created[to] = created;
109
143
  if (change !== undefined)
110
144
  heads.changes[to] = change;
111
145
  }
112
146
  function erase(staged, path) {
113
147
  delete staged.documents[path];
114
148
  delete staged.revisions[path];
149
+ delete staged.fileIds[path];
150
+ delete staged.created[path];
115
151
  delete staged.changes[path];
116
- staged.binaryTargets.delete(path);
152
+ delete staged.binaries[path];
117
153
  }
118
- function stage(staged, change, priors) {
119
- if (change.kind === 'field' || change.kind === 'section' || change.kind === 'preamble') {
120
- edit(staged, change, priors);
121
- return;
122
- }
154
+ function stage(staged, change) {
123
155
  if (change.kind === 'create') {
124
156
  staged.documents[change.path] =
125
157
  'content' in change ? change.content : compose(change.fields, change.sections);
158
+ delete staged.fileIds[change.path];
159
+ delete staged.created[change.path];
126
160
  delete staged.changes[change.path];
127
- return;
161
+ return true;
128
162
  }
129
163
  if (change.kind === 'replace') {
164
+ delete staged.revisions[change.path];
130
165
  if (staged.documents[change.path] === undefined)
131
- return;
166
+ return false;
132
167
  staged.documents[change.path] = change.content;
133
- return;
168
+ return true;
169
+ }
170
+ if (change.kind === 'binary') {
171
+ if (staged.documents[change.path] !== undefined)
172
+ return false;
173
+ staged.binaries[change.path] = {
174
+ state: 'pending',
175
+ localId: change.localId,
176
+ byteLength: change.byteLength,
177
+ mediaType: change.mediaType,
178
+ sha256: change.sha256,
179
+ };
180
+ delete staged.revisions[change.path];
181
+ delete staged.changes[change.path];
182
+ return true;
134
183
  }
135
184
  if (change.kind === 'move') {
136
- relocate(staged, change.path, change.to);
137
- return;
185
+ return relocate(staged, change.path, change.to);
186
+ }
187
+ if (change.kind === 'arrival') {
188
+ erase(staged, change.path);
189
+ if ('content' in change)
190
+ staged.documents[change.path] = change.content;
191
+ else
192
+ staged.binaries[change.path] = { state: 'accepted', ...change.binary };
193
+ arrive(staged, change);
194
+ return true;
138
195
  }
139
196
  erase(staged, change.path);
197
+ return true;
198
+ }
199
+ function arrive(heads, change) {
200
+ if (change.revision !== undefined)
201
+ heads.revisions[change.path] = change.revision;
202
+ if (change.fileId !== undefined)
203
+ heads.fileIds[change.path] = change.fileId;
204
+ if (change.created !== undefined)
205
+ heads.created[change.path] = change.created;
206
+ if (change.change !== undefined)
207
+ heads.changes[change.path] = change.change;
140
208
  }
141
- export function overlay(base, queue) {
209
+ export function* overlaying(base, queue, unapplied) {
142
210
  const staged = {
143
- documents: { ...base.documents },
144
- binaryTargets: new Set(base.binaryTargets),
145
- revisions: { ...base.revisions },
146
- changes: { ...base.changes },
147
- };
148
- for (const batch of queue) {
149
- const priors = priorsOf(batch.preconditions);
150
- for (const change of batch.changes)
151
- stage(staged, change, priors);
152
- }
153
- return {
154
- documents: staged.documents,
155
- binaryTargets: [...staged.binaryTargets].sort(),
156
- revisions: staged.revisions,
157
- changes: staged.changes,
211
+ documents: drafted(base.documents),
212
+ binaries: drafted(base.binaries),
213
+ revisions: drafted(base.revisions),
214
+ fileIds: drafted(base.fileIds),
215
+ created: drafted(base.created),
216
+ changes: drafted(base.changes),
158
217
  };
159
- }
160
- function pathsOf(batch) {
161
- return batch.changes.flatMap((change) => change.kind === 'move' ? [change.path, change.to] : [change.path]);
162
- }
163
- export function sameLayerText(left, right) {
164
- const paths = Object.keys(left.documents);
165
- return (paths.length === Object.keys(right.documents).length &&
166
- paths.every((path) => left.documents[path] === right.documents[path]) &&
167
- left.binaryTargets.length === right.binaryTargets.length &&
168
- left.binaryTargets.every((path) => right.binaryTargets.includes(path)));
169
- }
170
- function replayHeads(base, queue) {
171
- const heads = { revisions: { ...base.revisions }, changes: { ...base.changes } };
172
218
  for (const batch of queue) {
173
- for (const change of batch.changes) {
174
- if (change.kind === 'remove') {
175
- delete heads.revisions[change.path];
176
- delete heads.changes[change.path];
177
- }
178
- else if (change.kind === 'create') {
179
- delete heads.changes[change.path];
180
- }
181
- else if (change.kind === 'move') {
182
- moveHead(heads, change.path, change.to);
183
- }
184
- }
185
- }
186
- return heads;
187
- }
188
- export function overlayChanged(base, queue, previousBase, previousQueue, previousVisible) {
189
- const before = previousQueue.map((batch) => JSON.stringify(batch));
190
- const after = queue.map((batch) => JSON.stringify(batch));
191
- if (before.length === after.length &&
192
- before.every((id, index) => id === after[index]) &&
193
- sameLayerText(base, previousBase)) {
194
- return {
195
- documents: previousVisible.documents,
196
- binaryTargets: previousVisible.binaryTargets,
197
- ...replayHeads(base, queue),
198
- };
199
- }
200
- const affected = new Set();
201
- const paths = new Set([
202
- ...Object.keys(base.documents),
203
- ...Object.keys(previousBase.documents),
204
- ...Object.keys(base.revisions),
205
- ...Object.keys(previousBase.revisions),
206
- ...Object.keys(base.changes),
207
- ...Object.keys(previousBase.changes),
208
- ...base.binaryTargets,
209
- ...previousBase.binaryTargets,
210
- ]);
211
- for (const path of paths) {
212
- if (base.documents[path] !== previousBase.documents[path] ||
213
- base.revisions[path] !== previousBase.revisions[path] ||
214
- !sameChange(base.changes[path], previousBase.changes[path]) ||
215
- base.binaryTargets.includes(path) !== previousBase.binaryTargets.includes(path))
216
- affected.add(path);
217
- }
218
- const oldIds = new Set(before);
219
- const newIds = new Set(after);
220
- for (const batch of previousQueue) {
221
- if (!newIds.has(JSON.stringify(batch)))
222
- for (const path of pathsOf(batch))
223
- affected.add(path);
224
- }
225
- for (const batch of queue) {
226
- if (!oldIds.has(JSON.stringify(batch)))
227
- for (const path of pathsOf(batch))
228
- affected.add(path);
229
- }
230
- let expanded = true;
231
- while (expanded) {
232
- expanded = false;
233
- for (const batch of queue) {
234
- const touched = pathsOf(batch);
235
- if (!touched.some((path) => affected.has(path)))
219
+ const priors = yield* priorsOf(batch.preconditions);
220
+ for (let index = 0; index < batch.changes.length; index += 1) {
221
+ const change = batch.changes[index];
222
+ if (!isPart(change)) {
223
+ if (!stage(staged, change))
224
+ unapplied?.();
225
+ yield ROW_WEIGHT;
236
226
  continue;
237
- for (const path of touched) {
238
- if (affected.has(path))
239
- continue;
240
- affected.add(path);
241
- expanded = true;
242
227
  }
228
+ const run = [change];
229
+ while (index + 1 < batch.changes.length) {
230
+ const next = batch.changes[index + 1];
231
+ if (!isPart(next) || next.path !== change.path)
232
+ break;
233
+ run.push(next);
234
+ index += 1;
235
+ }
236
+ const text = staged.documents[change.path] ?? '';
237
+ for (let left = edit(staged, run, priors); left > 0; left -= 1)
238
+ unapplied?.();
239
+ yield ROW_WEIGHT + text.length;
243
240
  }
244
241
  }
245
- const documents = {};
246
- const revisions = {};
247
- const changes = {};
248
- for (const path of affected) {
249
- if (base.documents[path] !== undefined)
250
- documents[path] = base.documents[path];
251
- if (base.revisions[path] !== undefined)
252
- revisions[path] = base.revisions[path];
253
- if (base.changes[path] !== undefined)
254
- changes[path] = base.changes[path];
255
- }
256
- const staged = overlay({
257
- documents,
258
- revisions,
259
- changes,
260
- binaryTargets: base.binaryTargets.filter((path) => affected.has(path)),
261
- }, queue.filter((batch) => pathsOf(batch).some((path) => affected.has(path))));
262
- const mergedDocuments = { ...previousVisible.documents };
263
- const mergedRevisions = { ...previousVisible.revisions };
264
- const mergedChanges = { ...previousVisible.changes };
265
- const mergedTargets = new Set(previousVisible.binaryTargets);
266
- for (const path of affected) {
267
- delete mergedDocuments[path];
268
- delete mergedRevisions[path];
269
- delete mergedChanges[path];
270
- mergedTargets.delete(path);
271
- }
272
- Object.assign(mergedDocuments, staged.documents);
273
- Object.assign(mergedRevisions, staged.revisions);
274
- Object.assign(mergedChanges, staged.changes);
275
- for (const path of staged.binaryTargets)
276
- mergedTargets.add(path);
277
242
  return {
278
- documents: mergedDocuments,
279
- revisions: mergedRevisions,
280
- changes: mergedChanges,
281
- binaryTargets: [...mergedTargets].sort(),
243
+ documents: yield* settling(staged.documents),
244
+ binaries: yield* settling(staged.binaries),
245
+ revisions: yield* settling(staged.revisions),
246
+ fileIds: yield* settling(staged.fileIds),
247
+ created: yield* settling(staged.created),
248
+ changes: yield* settling(staged.changes),
282
249
  };
283
250
  }
@@ -0,0 +1,59 @@
1
+ import type { RunningSubagent, TurnContext } from './adapter.js';
2
+ import { type JobMarker, type OpenJob } from './job.js';
3
+ export type PlanStep = {
4
+ readonly content: string;
5
+ readonly status: string;
6
+ };
7
+ export type Marker = 'mode' | 'compaction' | 'retry' | 'model' | 'job';
8
+ export type Part = {
9
+ readonly type: 'text';
10
+ readonly text: string;
11
+ } | {
12
+ readonly type: 'reasoning';
13
+ readonly text: string;
14
+ } | {
15
+ readonly type: 'commands';
16
+ readonly count: number;
17
+ } | {
18
+ readonly type: 'subagent';
19
+ readonly description: string;
20
+ readonly done: boolean;
21
+ readonly result: string | null;
22
+ } | {
23
+ readonly type: 'message';
24
+ readonly command: string;
25
+ readonly target: string | null;
26
+ } | {
27
+ readonly type: 'image';
28
+ readonly path: string;
29
+ readonly name: string;
30
+ readonly mediaType: string;
31
+ } | {
32
+ readonly type: 'marker';
33
+ readonly marker: Marker;
34
+ readonly text: string;
35
+ } | {
36
+ readonly type: 'plan';
37
+ readonly steps: readonly PlanStep[];
38
+ };
39
+ export declare function partsOf(raw: readonly unknown[]): readonly Part[];
40
+ export declare function contextIn(raw: unknown): TurnContext | null;
41
+ export type Turn = {
42
+ readonly turn: string;
43
+ readonly parts: readonly Part[];
44
+ readonly ended: boolean;
45
+ };
46
+ export type ChatWork = {
47
+ readonly kind: 'job' | 'schedule' | 'subagent';
48
+ readonly title: string;
49
+ readonly next: string | null;
50
+ readonly activity: string | null;
51
+ };
52
+ export declare function counted(count: number): string;
53
+ export declare function runningLine(raw: readonly unknown[]): string | null;
54
+ export declare function jobsOf(markers: readonly JobMarker[], turn: {
55
+ readonly started: string | null;
56
+ readonly parts: readonly unknown[];
57
+ } | null): readonly OpenJob[];
58
+ export declare function stillRunning(turns: readonly Turn[], subagents: readonly RunningSubagent[]): ReadonlyMap<string, readonly ChatWork[]>;
59
+ //# sourceMappingURL=parts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parts.d.ts","sourceRoot":"","sources":["../src/parts.ts"],"names":[],"mappings":"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"}
package/dist/parts.js ADDED
@@ -0,0 +1,118 @@
1
+ import { closeLast, markerMoved, openJobs } from './job.js';
2
+ import { excerpt, list, record, text } from './read.js';
3
+ const MARKERS = ['mode', 'compaction', 'retry', 'model', 'job'];
4
+ function partOf(raw) {
5
+ const part = record(raw);
6
+ switch (text(part, 'type')) {
7
+ case 'text':
8
+ case 'reasoning': {
9
+ const said = text(part, 'text');
10
+ return said === null ? null : { type: part.type, text: said };
11
+ }
12
+ case 'commands':
13
+ return typeof part.count === 'number' ? { type: 'commands', count: part.count } : null;
14
+ case 'subagent':
15
+ return {
16
+ type: 'subagent',
17
+ description: text(part, 'description') ?? '',
18
+ done: part.status === 'done',
19
+ result: text(part, 'result'),
20
+ };
21
+ case 'message': {
22
+ const command = text(part, 'command');
23
+ return command === null ? null : { type: 'message', command, target: text(part, 'target') };
24
+ }
25
+ case 'image': {
26
+ const path = text(part, 'file');
27
+ const name = text(part, 'name');
28
+ return path === null || name === null
29
+ ? null
30
+ : { type: 'image', path, name, mediaType: text(part, 'media_type') ?? '' };
31
+ }
32
+ case 'marker': {
33
+ const marker = text(part, 'marker');
34
+ return marker === null || !MARKERS.includes(marker)
35
+ ? null
36
+ : { type: 'marker', marker: marker, text: text(part, 'text') ?? '' };
37
+ }
38
+ case 'plan':
39
+ return {
40
+ type: 'plan',
41
+ steps: list(part, 'entries').flatMap((entry) => {
42
+ const step = record(entry);
43
+ const content = text(step, 'content');
44
+ return content === null ? [] : [{ content, status: text(step, 'status') ?? '' }];
45
+ }),
46
+ };
47
+ default:
48
+ return null;
49
+ }
50
+ }
51
+ export function partsOf(raw) {
52
+ return raw.flatMap((one) => partOf(one) ?? []);
53
+ }
54
+ export function contextIn(raw) {
55
+ const held = record(raw);
56
+ return typeof held.used === 'number' && typeof held.window === 'number' && held.window > 0
57
+ ? { used: held.used, window: held.window }
58
+ : null;
59
+ }
60
+ export function counted(count) {
61
+ return count === 1 ? '1 command' : `${count} commands`;
62
+ }
63
+ export function runningLine(raw) {
64
+ const parts = partsOf(raw);
65
+ const note = [...parts].reverse().find((part) => part.type === 'text' && part.text.trim() !== '');
66
+ if (note?.type === 'text')
67
+ return excerpt(note.text);
68
+ const commands = parts.reduce((sum, part) => (part.type === 'commands' ? sum + part.count : sum), 0);
69
+ return commands === 0 ? null : counted(commands);
70
+ }
71
+ export function jobsOf(markers, turn) {
72
+ const running = (turn === null ? [] : partsOf(turn.parts)).flatMap((part) => part.type === 'marker' && part.marker === 'job'
73
+ ? [{ said: part.text, at: turn?.started ?? null }]
74
+ : []);
75
+ return openJobs([...markers, ...running]);
76
+ }
77
+ export function stillRunning(turns, subagents) {
78
+ const open = [];
79
+ for (const { turn, parts, ended } of turns) {
80
+ for (const part of parts) {
81
+ if (part.type === 'subagent') {
82
+ const key = `subagent\u0000${part.description}`;
83
+ if (part.done)
84
+ closeLast(open, key);
85
+ else if (ended) {
86
+ open.push({
87
+ turn,
88
+ key,
89
+ work: { kind: 'subagent', title: part.description, next: null, activity: null },
90
+ });
91
+ }
92
+ continue;
93
+ }
94
+ if (part.type !== 'marker' || part.marker !== 'job')
95
+ continue;
96
+ markerMoved(open, part.text, (job, key) => ended
97
+ ? {
98
+ turn,
99
+ key,
100
+ work: {
101
+ kind: job.kind === 'started' ? 'job' : 'schedule',
102
+ title: job.label,
103
+ next: job.next,
104
+ activity: null,
105
+ },
106
+ }
107
+ : null);
108
+ }
109
+ }
110
+ const doing = [...subagents];
111
+ const under = new Map();
112
+ for (const { turn, work } of open) {
113
+ const at = work.kind === 'subagent' ? doing.findIndex((one) => one.description === work.title) : -1;
114
+ const shown = at === -1 ? work : { ...work, activity: doing.splice(at, 1)[0].activity };
115
+ under.set(turn, [...(under.get(turn) ?? []), shown]);
116
+ }
117
+ return under;
118
+ }
package/dist/paths.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export declare function normalize(path: string): string | null;
2
- export declare function relative(from: string, target: string): string;
3
2
  export declare function beneath(prefix: string, path: string): boolean;
4
3
  export declare function covered(prefixes: readonly string[], path: string): boolean;
4
+ export declare function ancestors(path: string): readonly string[];
5
5
  //# sourceMappingURL=paths.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAKA,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYrD;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAW7D;AAED,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED,wBAAgB,OAAO,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAK1E"}
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYrD;AAED,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED,wBAAgB,OAAO,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAK1E;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAGzD"}
package/dist/paths.js CHANGED
@@ -1,7 +1,3 @@
1
- function dirname(path) {
2
- const index = path.lastIndexOf('/');
3
- return index === -1 ? '' : path.slice(0, index);
4
- }
5
1
  export function normalize(path) {
6
2
  const parts = [];
7
3
  for (const part of path.split('/')) {
@@ -17,18 +13,6 @@ export function normalize(path) {
17
13
  }
18
14
  return parts.join('/');
19
15
  }
20
- export function relative(from, target) {
21
- const base = dirname(from)
22
- .split('/')
23
- .filter((part) => part !== '');
24
- const parts = target.split('/');
25
- let shared = 0;
26
- while (shared < base.length && shared + 1 < parts.length && base[shared] === parts[shared]) {
27
- shared += 1;
28
- }
29
- const up = Array.from({ length: base.length - shared }, () => '..');
30
- return [...up, ...parts.slice(shared)].join('/');
31
- }
32
16
  export function beneath(prefix, path) {
33
17
  return path === prefix || path.startsWith(`${prefix}/`);
34
18
  }
@@ -38,3 +22,7 @@ export function covered(prefixes, path) {
38
22
  return normalized !== null && (normalized === '' || beneath(normalized, path));
39
23
  });
40
24
  }
25
+ export function ancestors(path) {
26
+ const parts = path.split('/');
27
+ return parts.slice(1).map((_, at) => parts.slice(0, at + 1).join('/'));
28
+ }