@agentshouse/mdruntime-adapter 0.1.0-cacce09fc82c6 → 0.1.0-cb42b23b5d2fb

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.
package/dist/write.js CHANGED
@@ -1,4 +1,5 @@
1
- import { headChange, parseOriginals } from './read.js';
1
+ import { departure, } from '@agentshouse/mdruntime';
2
+ import { binaryFileOf, headChange } 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,9 @@ 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;
141
164
  const head = headChange(file);
142
165
  if (head === null)
143
166
  return null;
@@ -152,6 +175,7 @@ function material(value, handle) {
152
175
  path,
153
176
  content: file.content,
154
177
  revision: typeof file.revision === 'string' ? file.revision : null,
178
+ ...(binary === undefined ? {} : { binary }),
155
179
  ...(head === undefined ? {} : { head }),
156
180
  });
157
181
  }
@@ -175,7 +199,13 @@ export function mutationOutcome(status, body, locator, handle) {
175
199
  if (refusal !== null && refusal.code === 'edit_conflict') {
176
200
  const { current, ...fields } = refusal.fields;
177
201
  const held = material(current, handle) ?? [];
178
- return { kind: 'conflicted', affected: affectedOf(held), code: refusal.code, fields };
202
+ return {
203
+ kind: 'conflicted',
204
+ affected: affectedOf(held),
205
+ code: refusal.code,
206
+ fields,
207
+ retryable: refusal.retryable,
208
+ };
179
209
  }
180
210
  if (refusal !== null && status === 404) {
181
211
  return scopedRefusal(locator, 'undisclosed', refusal);
@@ -185,14 +215,26 @@ export function mutationOutcome(status, body, locator, handle) {
185
215
  if (refusal?.retryable === true &&
186
216
  typeof reset === 'string' &&
187
217
  classified?.kind === 'transport-uncertainty') {
188
- return { kind: 'retryable-refusal', code: refusal.code, fields: refusal.fields, reset };
218
+ return {
219
+ kind: 'retryable-refusal',
220
+ code: refusal.code,
221
+ fields: refusal.fields,
222
+ retryable: true,
223
+ reset,
224
+ };
189
225
  }
190
226
  if (classified !== null && classified.kind !== 'scoped-refusal')
191
227
  return classified;
192
228
  if (classified !== null && status === 403)
193
229
  return classified;
194
230
  if (refusal !== null && status >= 400) {
195
- return { kind: 'rejected', affected: {}, code: refusal.code, fields: refusal.fields };
231
+ return {
232
+ kind: 'rejected',
233
+ affected: {},
234
+ code: refusal.code,
235
+ fields: refusal.fields,
236
+ retryable: refusal.retryable,
237
+ };
196
238
  }
197
239
  if (status !== 200 || typeof body !== 'object' || body === null) {
198
240
  return { kind: 'transport-uncertainty' };
@@ -204,19 +246,20 @@ export function mutationOutcome(status, body, locator, handle) {
204
246
  const contents = material(held.contents, handle);
205
247
  if (contents === null)
206
248
  return { kind: 'transport-uncertainty' };
207
- const originals = parseOriginals(held.originals);
208
- if (originals === null)
209
- return { kind: 'transport-uncertainty' };
210
249
  const documents = {};
211
250
  const revisions = {};
212
251
  const changes = {};
252
+ const binaryFiles = {};
213
253
  const removals = [];
214
254
  for (const entry of contents) {
215
- if (entry.content === null || entry.revision === null) {
255
+ if (entry.revision === null) {
216
256
  removals.push(entry.path);
217
257
  continue;
218
258
  }
219
- documents[entry.path] = entry.content;
259
+ if (entry.content !== null)
260
+ documents[entry.path] = entry.content;
261
+ if (entry.binary !== undefined)
262
+ binaryFiles[entry.path] = entry.binary;
220
263
  revisions[entry.path] = entry.revision;
221
264
  if (entry.head !== undefined)
222
265
  changes[entry.path] = entry.head;
@@ -228,7 +271,7 @@ export function mutationOutcome(status, body, locator, handle) {
228
271
  revisions,
229
272
  changes,
230
273
  removals: removals.sort(),
231
- originals,
274
+ ...(Object.keys(binaryFiles).length === 0 ? {} : { binaryFiles }),
232
275
  };
233
276
  }
234
277
  export function rejectedMapping(mapping) {
@@ -237,6 +280,7 @@ export function rejectedMapping(mapping) {
237
280
  affected: {},
238
281
  code: mapping.rule,
239
282
  fields: { path: mapping.path },
283
+ retryable: false,
240
284
  };
241
285
  }
242
286
  export function revisionBody(input) {
@@ -258,6 +302,17 @@ function revisionAuthor(entry) {
258
302
  }
259
303
  return null;
260
304
  }
305
+ function historyBinary(entry) {
306
+ if (entry.file === undefined)
307
+ return undefined;
308
+ const { file, bytes, media_type: mediaType, sha256 } = entry;
309
+ if (typeof file !== 'string' ||
310
+ typeof bytes !== 'number' ||
311
+ typeof mediaType !== 'string' ||
312
+ typeof sha256 !== 'string')
313
+ return null;
314
+ return { fileRef: file, byteLength: bytes, mediaType, sha256 };
315
+ }
261
316
  export function historyOutcome(status, body, locator, request) {
262
317
  const classified = classifyDoor(status, body, locator);
263
318
  if (classified !== null)
@@ -285,8 +340,11 @@ export function historyOutcome(status, body, locator, request) {
285
340
  scope: 'content',
286
341
  code: 'retained_history_unavailable',
287
342
  fields: { path: request.path, revision: request.revision },
343
+ retryable: false,
288
344
  };
289
345
  }
346
+ if (typeof named.file === 'string')
347
+ return { kind: 'no-history' };
290
348
  if (typeof named.content !== 'string')
291
349
  return { kind: 'transport-uncertainty' };
292
350
  return { kind: 'revision', content: named.content };
@@ -301,7 +359,15 @@ export function historyOutcome(status, body, locator, request) {
301
359
  typeof entry.created_at !== 'string') {
302
360
  return { kind: 'transport-uncertainty' };
303
361
  }
304
- revisions.push({ revision: entry.revision, author, time: entry.created_at });
362
+ const binaryFile = historyBinary(entry);
363
+ if (binaryFile === null)
364
+ return { kind: 'transport-uncertainty' };
365
+ revisions.push({
366
+ revision: entry.revision,
367
+ author,
368
+ time: entry.created_at,
369
+ ...(binaryFile === undefined ? {} : { binaryFile }),
370
+ });
305
371
  }
306
372
  const next = held.next_before;
307
373
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentshouse/mdruntime-adapter",
3
- "version": "0.1.0-cacce09fc82c6",
3
+ "version": "0.1.0-cb42b23b5d2fb",
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,7 @@
25
25
  "LICENSE"
26
26
  ],
27
27
  "dependencies": {
28
- "@agentshouse/mdmodel": "0.1.0-c896b3d9398b1",
29
- "@agentshouse/mdruntime": "0.1.0-c389df724fd2f"
28
+ "@agentshouse/mdmodel": "0.1.0-c6e675bb19980",
29
+ "@agentshouse/mdruntime": "0.1.0-c0cea65344137"
30
30
  }
31
31
  }
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
- }