@agentshouse/mdruntime-adapter 0.1.0-cf22c8563f9f4 → 0.1.0-cf9ab9b7cbbca

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 (50) hide show
  1. package/AGENTS.md +269 -214
  2. package/dist/actions.d.ts +62 -1
  3. package/dist/actions.d.ts.map +1 -1
  4. package/dist/actions.js +153 -133
  5. package/dist/adapter.d.ts +1 -0
  6. package/dist/adapter.d.ts.map +1 -1
  7. package/dist/adapter.js +286 -91
  8. package/dist/discovery.d.ts +3 -1
  9. package/dist/discovery.d.ts.map +1 -1
  10. package/dist/discovery.js +18 -3
  11. package/dist/gather.d.ts +1 -0
  12. package/dist/gather.d.ts.map +1 -1
  13. package/dist/gather.js +11 -6
  14. package/dist/handed.d.ts +15 -0
  15. package/dist/handed.d.ts.map +1 -0
  16. package/dist/handed.js +38 -0
  17. package/dist/index.d.ts +2 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +1 -0
  20. package/dist/model.d.ts +1 -1
  21. package/dist/model.d.ts.map +1 -1
  22. package/dist/model.js +21 -7
  23. package/dist/read.d.ts +35 -7
  24. package/dist/read.d.ts.map +1 -1
  25. package/dist/read.js +160 -79
  26. package/dist/referrer.d.ts +7 -0
  27. package/dist/referrer.d.ts.map +1 -0
  28. package/dist/referrer.js +35 -0
  29. package/dist/refusal.d.ts +2 -5
  30. package/dist/refusal.d.ts.map +1 -1
  31. package/dist/refusal.js +6 -9
  32. package/dist/site.d.ts +1 -1
  33. package/dist/site.d.ts.map +1 -1
  34. package/dist/site.js +165 -48
  35. package/dist/stream.d.ts +6 -4
  36. package/dist/stream.d.ts.map +1 -1
  37. package/dist/stream.js +308 -16
  38. package/dist/transport.d.ts +54 -11
  39. package/dist/transport.d.ts.map +1 -1
  40. package/dist/transport.js +3 -0
  41. package/dist/version.d.ts +1 -0
  42. package/dist/version.d.ts.map +1 -1
  43. package/dist/version.js +1 -1
  44. package/dist/write.d.ts +3 -9
  45. package/dist/write.d.ts.map +1 -1
  46. package/dist/write.js +92 -14
  47. package/package.json +3 -4
  48. package/dist/links.d.ts +0 -20
  49. package/dist/links.d.ts.map +0 -1
  50. package/dist/links.js +0 -104
package/dist/write.js CHANGED
@@ -1,4 +1,5 @@
1
- import { parseOriginals } from './read.js';
1
+ import { departure, } from '@agentshouse/mdruntime';
2
+ import { binaryFileOf, headChange, identities } from './read.js';
2
3
  import { sha256Hex, textBytes } from './digest.js';
3
4
  import { nativePath, roomLocalPath } from './map.js';
4
5
  import { classifyDoor, doorRefusal, scopedRefusal } from './refusal.js';
@@ -73,6 +74,25 @@ function operationOf(batch, change, handle) {
73
74
  const operation = created(change, path);
74
75
  return operation === null ? { rule: 'type-missing' } : { operation };
75
76
  }
77
+ if (change.kind === 'binary') {
78
+ const written = {
79
+ op: 'upload',
80
+ path,
81
+ local_id: change.localId,
82
+ bytes: change.byteLength,
83
+ sha256: change.sha256,
84
+ media_type: change.mediaType,
85
+ };
86
+ const from = departure(batch.changes, batch.changes.indexOf(change));
87
+ if (from === change.path && priorAbsence(batch, change.path) !== undefined)
88
+ return { operation: written };
89
+ const replaced = priorExistence(batch, from);
90
+ if (replaced === undefined)
91
+ return { rule: 'precondition-missing' };
92
+ if (!('base' in replaced))
93
+ return { rule: 'presence-base-unrepresentable' };
94
+ return { operation: { ...written, base: replaced.base } };
95
+ }
76
96
  const existence = priorExistence(batch, change.path);
77
97
  if (existence === undefined)
78
98
  return { rule: 'precondition-missing' };
@@ -138,6 +158,12 @@ function material(value, handle) {
138
158
  return null;
139
159
  if (file.revision !== null && file.revision !== undefined && typeof file.revision !== 'string')
140
160
  return null;
161
+ const binary = binaryFileOf(file);
162
+ if (binary === null)
163
+ return null;
164
+ const head = headChange(file);
165
+ if (head === null)
166
+ return null;
141
167
  let path;
142
168
  try {
143
169
  path = roomLocalPath(file.path, handle);
@@ -149,6 +175,8 @@ function material(value, handle) {
149
175
  path,
150
176
  content: file.content,
151
177
  revision: typeof file.revision === 'string' ? file.revision : null,
178
+ ...(binary === undefined ? {} : { binary }),
179
+ ...(head === undefined ? {} : { head }),
152
180
  });
153
181
  }
154
182
  return held;
@@ -166,12 +194,21 @@ export function mutationOutcome(status, body, locator, handle) {
166
194
  if (refusal !== null && refusal.code === 'service_mode_write_halted') {
167
195
  return { kind: 'write-halted' };
168
196
  }
169
- if (refusal !== null && refusal.code === 'expired')
170
- return { kind: 'expired' };
197
+ if (refusal !== null && refusal.code === 'expired') {
198
+ return refusal.fields.restored === true
199
+ ? { kind: 'expired', restored: true }
200
+ : { kind: 'expired' };
201
+ }
171
202
  if (refusal !== null && refusal.code === 'edit_conflict') {
172
203
  const { current, ...fields } = refusal.fields;
173
204
  const held = material(current, handle) ?? [];
174
- return { kind: 'conflicted', affected: affectedOf(held), code: refusal.code, fields };
205
+ return {
206
+ kind: 'conflicted',
207
+ affected: affectedOf(held),
208
+ code: refusal.code,
209
+ fields,
210
+ retryable: refusal.retryable,
211
+ };
175
212
  }
176
213
  if (refusal !== null && status === 404) {
177
214
  return scopedRefusal(locator, 'undisclosed', refusal);
@@ -181,14 +218,26 @@ export function mutationOutcome(status, body, locator, handle) {
181
218
  if (refusal?.retryable === true &&
182
219
  typeof reset === 'string' &&
183
220
  classified?.kind === 'transport-uncertainty') {
184
- return { kind: 'retryable-refusal', code: refusal.code, fields: refusal.fields, reset };
221
+ return {
222
+ kind: 'retryable-refusal',
223
+ code: refusal.code,
224
+ fields: refusal.fields,
225
+ retryable: true,
226
+ reset,
227
+ };
185
228
  }
186
229
  if (classified !== null && classified.kind !== 'scoped-refusal')
187
230
  return classified;
188
231
  if (classified !== null && status === 403)
189
232
  return classified;
190
233
  if (refusal !== null && status >= 400) {
191
- return { kind: 'rejected', affected: {}, code: refusal.code, fields: refusal.fields };
234
+ return {
235
+ kind: 'rejected',
236
+ affected: {},
237
+ code: refusal.code,
238
+ fields: refusal.fields,
239
+ retryable: refusal.retryable,
240
+ };
192
241
  }
193
242
  if (status !== 200 || typeof body !== 'object' || body === null) {
194
243
  return { kind: 'transport-uncertainty' };
@@ -200,27 +249,33 @@ export function mutationOutcome(status, body, locator, handle) {
200
249
  const contents = material(held.contents, handle);
201
250
  if (contents === null)
202
251
  return { kind: 'transport-uncertainty' };
203
- const originals = parseOriginals(held.originals);
204
- if (originals === null)
205
- return { kind: 'transport-uncertainty' };
206
252
  const documents = {};
207
253
  const revisions = {};
254
+ const changes = {};
255
+ const binaryFiles = {};
208
256
  const removals = [];
209
257
  for (const entry of contents) {
210
- if (entry.content === null || entry.revision === null) {
258
+ if (entry.revision === null) {
211
259
  removals.push(entry.path);
212
260
  continue;
213
261
  }
214
- documents[entry.path] = entry.content;
262
+ if (entry.content !== null)
263
+ documents[entry.path] = entry.content;
264
+ if (entry.binary !== undefined)
265
+ binaryFiles[entry.path] = entry.binary;
215
266
  revisions[entry.path] = entry.revision;
267
+ if (entry.head !== undefined)
268
+ changes[entry.path] = entry.head;
216
269
  }
217
270
  return {
218
271
  kind: 'accepted',
219
272
  roomVersion: roomVersion(at),
220
273
  documents,
221
274
  revisions,
275
+ ...identities(revisions),
276
+ changes,
222
277
  removals: removals.sort(),
223
- originals,
278
+ ...(Object.keys(binaryFiles).length === 0 ? {} : { binaryFiles }),
224
279
  };
225
280
  }
226
281
  export function rejectedMapping(mapping) {
@@ -229,6 +284,7 @@ export function rejectedMapping(mapping) {
229
284
  affected: {},
230
285
  code: mapping.rule,
231
286
  fields: { path: mapping.path },
287
+ retryable: false,
232
288
  };
233
289
  }
234
290
  export function revisionBody(input) {
@@ -250,6 +306,17 @@ function revisionAuthor(entry) {
250
306
  }
251
307
  return null;
252
308
  }
309
+ function historyBinary(entry) {
310
+ if (entry.file === undefined)
311
+ return undefined;
312
+ const { file, bytes, media_type: mediaType, sha256 } = entry;
313
+ if (typeof file !== 'string' ||
314
+ typeof bytes !== 'number' ||
315
+ typeof mediaType !== 'string' ||
316
+ typeof sha256 !== 'string')
317
+ return null;
318
+ return { fileRef: file, byteLength: bytes, mediaType, sha256 };
319
+ }
253
320
  export function historyOutcome(status, body, locator, request) {
254
321
  const classified = classifyDoor(status, body, locator);
255
322
  if (classified !== null)
@@ -274,11 +341,14 @@ export function historyOutcome(status, body, locator, request) {
274
341
  return {
275
342
  kind: 'scoped-refusal',
276
343
  locator,
277
- scope: 'content',
344
+ scope: 'operation',
278
345
  code: 'retained_history_unavailable',
279
346
  fields: { path: request.path, revision: request.revision },
347
+ retryable: false,
280
348
  };
281
349
  }
350
+ if (typeof named.file === 'string')
351
+ return { kind: 'no-history' };
282
352
  if (typeof named.content !== 'string')
283
353
  return { kind: 'transport-uncertainty' };
284
354
  return { kind: 'revision', content: named.content };
@@ -293,7 +363,15 @@ export function historyOutcome(status, body, locator, request) {
293
363
  typeof entry.created_at !== 'string') {
294
364
  return { kind: 'transport-uncertainty' };
295
365
  }
296
- revisions.push({ revision: entry.revision, author, time: entry.created_at });
366
+ const binaryFile = historyBinary(entry);
367
+ if (binaryFile === null)
368
+ return { kind: 'transport-uncertainty' };
369
+ revisions.push({
370
+ revision: entry.revision,
371
+ author,
372
+ time: entry.created_at,
373
+ ...(binaryFile === undefined ? {} : { binaryFile }),
374
+ });
297
375
  }
298
376
  const next = held.next_before;
299
377
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentshouse/mdruntime-adapter",
3
- "version": "0.1.0-cf22c8563f9f4",
3
+ "version": "0.1.0-cf9ab9b7cbbca",
4
4
  "description": "Agents House Adapter for the MD Runtime",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -14,7 +14,7 @@
14
14
  "exports": {
15
15
  ".": {
16
16
  "types": "./dist/index.d.ts",
17
- "import": "./dist/index.js"
17
+ "default": "./dist/index.js"
18
18
  },
19
19
  "./package.json": "./package.json"
20
20
  },
@@ -25,7 +25,6 @@
25
25
  "LICENSE"
26
26
  ],
27
27
  "dependencies": {
28
- "@agentshouse/mdmodel": "0.1.0-c3d58cb8652e6",
29
- "@agentshouse/mdruntime": "0.1.0-cebcd51f70ed1"
28
+ "@agentshouse/mdruntime": "0.1.0-c2682496ef6d0"
30
29
  }
31
30
  }
package/dist/links.d.ts DELETED
@@ -1,20 +0,0 @@
1
- import type { HeldRoom, MutationResult, RoomAttachment } from '@agentshouse/mdruntime';
2
- import type { HouseScope, HouseView } from './read.js';
3
- import type { StreamedAdvancement } from './stream.js';
4
- export type RoomLinks = {
5
- roomVersion: string;
6
- handed: ReadonlyMap<string, RoomAttachment>;
7
- paths: ReadonlyMap<string, ReadonlySet<string>>;
8
- revisions: ReadonlyMap<string, string>;
9
- };
10
- export declare function scopeLinks(scope: HouseScope): RoomLinks;
11
- export declare function heldLinks(held: HeldRoom): RoomLinks;
12
- export declare function acceptedLinks(held: RoomLinks, accepted: Extract<MutationResult, {
13
- kind: 'accepted';
14
- }>, roomVersion: string, originals: readonly RoomAttachment[]): {
15
- links: RoomLinks;
16
- attachments?: readonly RoomAttachment[];
17
- };
18
- export declare function enumeratedLinks(view: HouseView, earlier: RoomLinks | undefined): RoomLinks;
19
- export declare function streamedLinks(held: RoomLinks, advanced: StreamedAdvancement): RoomLinks | null;
20
- //# sourceMappingURL=links.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"links.d.ts","sourceRoot":"","sources":["../src/links.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACvF,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAOvD,MAAM,MAAM,SAAS,GAAG;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC5C,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;IAChD,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC,CAAC;AAcF,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,CAWvD;AAOD,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,CAOnD;AAED,wBAAgB,aAAa,CAC3B,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,OAAO,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,EACvD,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,SAAS,cAAc,EAAE,GACnC;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,WAAW,CAAC,EAAE,SAAS,cAAc,EAAE,CAAA;CAAE,CA2B/D;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAgB1F;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,mBAAmB,GAAG,SAAS,GAAG,IAAI,CAoB9F"}
package/dist/links.js DELETED
@@ -1,104 +0,0 @@
1
- import { roomVersion } from './version.js';
2
- const ATTACHMENT_REFERENCE = /at_[1-9a-hjkmnp-tv-z][0-9a-hjkmnp-tv-z]*\.[0-9a-hjkmnp-tv-z]/g;
3
- const NONE = new Set();
4
- function linkedBy(text) {
5
- if (text === null)
6
- return NONE;
7
- const references = new Set(Array.from(text.matchAll(ATTACHMENT_REFERENCE), ([found]) => found));
8
- return references.size === 0 ? NONE : references;
9
- }
10
- function handedOf(attachments) {
11
- return new Map((attachments ?? []).map((attachment) => [attachment.reference, attachment]));
12
- }
13
- export function scopeLinks(scope) {
14
- return {
15
- roomVersion: roomVersion(scope),
16
- handed: handedOf(scope.attachments),
17
- paths: new Map(scope.contents.map(({ path, content }) => [path, linkedBy(content)])),
18
- revisions: new Map(scope.files.flatMap(({ path, revision }) => revision === undefined ? [] : [[path, revision]])),
19
- };
20
- }
21
- function revised(revisions, path, revision) {
22
- if (revision === undefined)
23
- revisions.delete(path);
24
- else
25
- revisions.set(path, revision);
26
- }
27
- export function heldLinks(held) {
28
- return {
29
- roomVersion: held.roomVersion,
30
- handed: handedOf(held.attachments),
31
- paths: new Map(Object.entries(held.documents).map(([path, text]) => [path, linkedBy(text)])),
32
- revisions: new Map(Object.entries(held.revisions)),
33
- };
34
- }
35
- export function acceptedLinks(held, accepted, roomVersion, originals) {
36
- const paths = new Map(held.paths);
37
- const revisions = new Map(held.revisions);
38
- const handed = new Map(held.handed);
39
- const answered = handedOf(originals);
40
- for (const [path, text] of Object.entries(accepted.documents)) {
41
- const linked = linkedBy(text);
42
- for (const reference of linked) {
43
- const original = answered.get(reference);
44
- if (!handed.has(reference) && original !== undefined)
45
- handed.set(reference, original);
46
- }
47
- paths.set(path, linked);
48
- }
49
- for (const [path, revision] of Object.entries(accepted.revisions))
50
- revisions.set(path, revision);
51
- for (const path of accepted.removals) {
52
- paths.delete(path);
53
- revisions.delete(path);
54
- }
55
- const linked = new Set([...paths.values()].flatMap((references) => [...references]));
56
- for (const reference of held.handed.keys()) {
57
- const before = [...held.paths.values()].some((references) => references.has(reference));
58
- if (before && !linked.has(reference))
59
- handed.delete(reference);
60
- }
61
- const links = { roomVersion, handed, paths, revisions };
62
- const changed = handed.size !== held.handed.size || [...handed.keys()].some((key) => !held.handed.has(key));
63
- return changed ? { links, attachments: [...handed.values()] } : { links };
64
- }
65
- export function enumeratedLinks(view, earlier) {
66
- const paths = new Map(earlier?.paths);
67
- const revisions = new Map(earlier?.revisions);
68
- for (const change of view.changes) {
69
- paths.set(change.path, linkedBy('content' in change ? change.content : null));
70
- revised(revisions, change.path, 'removed' in change
71
- ? undefined
72
- : 'reference' in change
73
- ? change.reference.revision
74
- : change.revision);
75
- }
76
- return { roomVersion: roomVersion(view), handed: handedOf(view.attachments), paths, revisions };
77
- }
78
- export function streamedLinks(held, advanced) {
79
- const paths = new Map(held.paths);
80
- const revisions = new Map(held.revisions);
81
- const dropped = new Set();
82
- for (const entry of advanced.entries) {
83
- revised(revisions, entry.path, entry.kind === 'removed' ? undefined : entry.revision);
84
- const text = entry.kind === 'removed' ? null : entry.text;
85
- if (text === undefined)
86
- return null;
87
- const linked = linkedBy(text);
88
- for (const reference of linked)
89
- if (!held.handed.has(reference))
90
- return null;
91
- for (const reference of paths.get(entry.path) ?? held.handed.keys()) {
92
- if (held.handed.has(reference) && !linked.has(reference))
93
- dropped.add(reference);
94
- }
95
- paths.set(entry.path, linked);
96
- }
97
- for (const references of paths.values()) {
98
- for (const reference of references)
99
- dropped.delete(reference);
100
- }
101
- if (dropped.size > 0)
102
- return null;
103
- return { roomVersion: advanced.page.roomVersion, handed: held.handed, paths, revisions };
104
- }