@agentshouse/mdruntime-adapter 0.1.0-ceda7e87cc6e8 → 0.1.0-cedb8e57837a7

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.d.ts CHANGED
@@ -10,6 +10,7 @@ export type ChangeMapping = {
10
10
  rule: string;
11
11
  };
12
12
  export declare function houseChanges(batch: ChangeBatch, handle: string): ChangeMapping;
13
+ export declare function houseMove(batch: ChangeBatch, source: string, destination: string): ChangeMapping;
13
14
  export type OperationHead = {
14
15
  readonly operation_id: string;
15
16
  readonly app_ref?: string;
@@ -21,7 +22,17 @@ export declare function deltaBody(changes: readonly HouseOperation[]): string;
21
22
  export declare function deltaBytes(delta: string): number;
22
23
  export declare function uploadable(inline: Readonly<Record<string, unknown>>, bytes: number, bounds: Pick<HouseBounds, 'max_inline_body_bytes' | 'max_upload_bytes'>): boolean;
23
24
  export declare function deltaDigest(delta: string): Promise<string>;
24
- export declare function mutationOutcome(status: number, body: unknown, locator: string, handle: string): MutationResult;
25
+ export type MoveAuthorities = {
26
+ readonly source: {
27
+ readonly authority: string;
28
+ readonly handle: string;
29
+ };
30
+ readonly destination: {
31
+ readonly authority: string;
32
+ readonly handle: string;
33
+ };
34
+ };
35
+ export declare function mutationOutcome(status: number, body: unknown, locator: string, handle: string, move?: MoveAuthorities): Generator<number, MutationResult, void>;
25
36
  export declare function rejectedMapping(mapping: Extract<ChangeMapping, {
26
37
  kind: 'unmapped';
27
38
  }>): {
@@ -1 +1 @@
1
- {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../src/write.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,WAAW,EAEhB,KAAK,aAAa,EAElB,KAAK,cAAc,EAEpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAOlD,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAE/D,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,SAAS,cAAc,EAAE,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAwHrD,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,CAQ9E;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,aAAa,CAK/D;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS,MAAM,EAAE,CAQhF;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,GAAG,MAAM,CAEpE;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,UAAU,CACxB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACzC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,uBAAuB,GAAG,kBAAkB,CAAC,GACtE,OAAO,CAKT;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE1D;AAiDD,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GACb,cAAc,CA8EhB;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,aAAa,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;IAEjF,IAAI,EAAE,UAAU;IAChB,QAAQ;IACR,IAAI;IACJ,MAAM;QAAI,IAAI;;IACd,SAAS;EAEZ;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAM1B;AA4BD,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3C,aAAa,CAyDf"}
1
+ {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../src/write.ts"],"names":[],"mappings":"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"}
package/dist/write.js CHANGED
@@ -1,5 +1,5 @@
1
- import { departure, } from '@agentshouse/mdruntime';
2
- import { binaryFileOf, headChange } from './read.js';
1
+ import { departure, ROW_WEIGHT, } from '@agentshouse/mdruntime';
2
+ import { answered, answering, binaryFileOf, headChange, revised } from './read.js';
3
3
  import { sha256Hex, textBytes } from './digest.js';
4
4
  import { nativePath, roomLocalPath } from './map.js';
5
5
  import { classifyDoor, doorRefusal, scopedRefusal } from './refusal.js';
@@ -120,6 +120,24 @@ export function houseChanges(batch, handle) {
120
120
  }
121
121
  return { kind: 'changes', changes };
122
122
  }
123
+ export function houseMove(batch, source, destination) {
124
+ const changes = [];
125
+ for (const { path, to } of batch.between?.moves ?? []) {
126
+ const existence = priorExistence(batch, path);
127
+ if (existence === undefined)
128
+ return { kind: 'unmapped', path, rule: 'precondition-missing' };
129
+ if (!('base' in existence)) {
130
+ return { kind: 'unmapped', path, rule: 'presence-base-unrepresentable' };
131
+ }
132
+ changes.push({
133
+ op: 'rename',
134
+ path: nativePath(path, source),
135
+ to: nativePath(to, destination),
136
+ base: existence.base,
137
+ });
138
+ }
139
+ return { kind: 'changes', changes };
140
+ }
123
141
  export function operationHead(batch) {
124
142
  const writer = batch.writtenBy;
125
143
  return writer === undefined
@@ -129,7 +147,7 @@ export function operationHead(batch) {
129
147
  export function batchPaths(changes) {
130
148
  return [
131
149
  ...new Set(changes.flatMap((change) => change.op === 'rename' ? [String(change.path), String(change.to)] : [String(change.path)])),
132
- ].sort();
150
+ ];
133
151
  }
134
152
  export function deltaBody(changes) {
135
153
  return JSON.stringify({ changes });
@@ -144,16 +162,19 @@ export function uploadable(inline, bytes, bounds) {
144
162
  export function deltaDigest(delta) {
145
163
  return sha256Hex(delta);
146
164
  }
147
- function material(value, handle) {
165
+ function* material(value, handle, within = () => true) {
148
166
  if (!Array.isArray(value))
149
167
  return null;
150
168
  const held = [];
151
169
  for (const entry of value) {
170
+ yield ROW_WEIGHT;
152
171
  if (typeof entry !== 'object' || entry === null)
153
172
  return null;
154
173
  const file = entry;
155
174
  if (typeof file.path !== 'string')
156
175
  return null;
176
+ if (!within(file.path))
177
+ continue;
157
178
  if (file.content !== null && typeof file.content !== 'string')
158
179
  return null;
159
180
  if (file.revision !== null && file.revision !== undefined && typeof file.revision !== 'string')
@@ -181,27 +202,74 @@ function material(value, handle) {
181
202
  }
182
203
  return held;
183
204
  }
184
- function affectedOf(held) {
205
+ function* affectedOf(held) {
185
206
  const affected = {};
186
207
  for (const entry of held) {
187
208
  if (entry.content !== null)
188
209
  affected[entry.path] = entry.content;
210
+ yield ROW_WEIGHT;
189
211
  }
190
212
  return affected;
191
213
  }
192
- export function mutationOutcome(status, body, locator, handle) {
214
+ function* acceptedOf(at, contents) {
215
+ const answer = answering();
216
+ for (const entry of contents) {
217
+ yield ROW_WEIGHT + (entry.content?.length ?? 0);
218
+ if (entry.revision === null) {
219
+ answer.removals.add(entry.path);
220
+ continue;
221
+ }
222
+ if (entry.content !== null)
223
+ answer.documents.set(entry.path, entry.content);
224
+ if (entry.binary !== undefined)
225
+ answer.binaryFiles.set(entry.path, entry.binary);
226
+ revised(answer, entry.path, entry.revision);
227
+ if (entry.head !== undefined)
228
+ answer.changes.set(entry.path, entry.head);
229
+ }
230
+ const unbinaried = answer.binaryFiles.size === 0;
231
+ const { binaryFiles, ...room } = yield* answered(answer);
232
+ return { roomVersion: roomVersion(at), ...room, ...(unbinaried ? {} : { binaryFiles }) };
233
+ }
234
+ function* movedOutcome(held, move) {
235
+ const authorities = Array.isArray(held.authorities) ? held.authorities : [];
236
+ const at = (authority) => {
237
+ const entry = authorities.find((one) => typeof one === 'object' &&
238
+ one !== null &&
239
+ one.authority === authority);
240
+ return entry === undefined ? null : readPosition(entry);
241
+ };
242
+ const left = at(move.source.authority);
243
+ const arrived = at(move.destination.authority);
244
+ if (left === null || arrived === null)
245
+ return { kind: 'transport-uncertainty' };
246
+ const under = (handle) => (path) => path.startsWith(`/rooms/${handle}/`);
247
+ const leaving = yield* material(held.contents, move.source.handle, under(move.source.handle));
248
+ const arriving = yield* material(held.contents, move.destination.handle, under(move.destination.handle));
249
+ if (leaving === null || arriving === null)
250
+ return { kind: 'transport-uncertainty' };
251
+ return {
252
+ kind: 'accepted',
253
+ ...(yield* acceptedOf(left, leaving)),
254
+ destination: yield* acceptedOf(arrived, arriving),
255
+ };
256
+ }
257
+ export function* mutationOutcome(status, body, locator, handle, move) {
193
258
  const refusal = doorRefusal(body);
194
259
  if (refusal !== null && refusal.code === 'service_mode_write_halted') {
195
260
  return { kind: 'write-halted' };
196
261
  }
197
- if (refusal !== null && refusal.code === 'expired')
198
- return { kind: 'expired' };
262
+ if (refusal !== null && refusal.code === 'expired') {
263
+ return refusal.fields.restored === true
264
+ ? { kind: 'expired', restored: true }
265
+ : { kind: 'expired' };
266
+ }
199
267
  if (refusal !== null && refusal.code === 'edit_conflict') {
200
268
  const { current, ...fields } = refusal.fields;
201
- const held = material(current, handle) ?? [];
269
+ const held = (yield* material(current, handle)) ?? [];
202
270
  return {
203
271
  kind: 'conflicted',
204
- affected: affectedOf(held),
272
+ affected: yield* affectedOf(held),
205
273
  code: refusal.code,
206
274
  fields,
207
275
  retryable: refusal.retryable,
@@ -225,8 +293,9 @@ export function mutationOutcome(status, body, locator, handle) {
225
293
  }
226
294
  if (classified !== null && classified.kind !== 'scoped-refusal')
227
295
  return classified;
228
- if (classified !== null && status === 403)
296
+ if (classified !== null && status === 403 && refusal?.code === 'operation_denied') {
229
297
  return classified;
298
+ }
230
299
  if (refusal !== null && status >= 400) {
231
300
  return {
232
301
  kind: 'rejected',
@@ -240,39 +309,15 @@ export function mutationOutcome(status, body, locator, handle) {
240
309
  return { kind: 'transport-uncertainty' };
241
310
  }
242
311
  const held = body;
312
+ if (move !== undefined)
313
+ return yield* movedOutcome(held, move);
243
314
  const at = readPosition(held);
244
315
  if (at === null)
245
316
  return { kind: 'transport-uncertainty' };
246
- const contents = material(held.contents, handle);
317
+ const contents = yield* material(held.contents, handle);
247
318
  if (contents === null)
248
319
  return { kind: 'transport-uncertainty' };
249
- const documents = {};
250
- const revisions = {};
251
- const changes = {};
252
- const binaryFiles = {};
253
- const removals = [];
254
- for (const entry of contents) {
255
- if (entry.revision === null) {
256
- removals.push(entry.path);
257
- continue;
258
- }
259
- if (entry.content !== null)
260
- documents[entry.path] = entry.content;
261
- if (entry.binary !== undefined)
262
- binaryFiles[entry.path] = entry.binary;
263
- revisions[entry.path] = entry.revision;
264
- if (entry.head !== undefined)
265
- changes[entry.path] = entry.head;
266
- }
267
- return {
268
- kind: 'accepted',
269
- roomVersion: roomVersion(at),
270
- documents,
271
- revisions,
272
- changes,
273
- removals: removals.sort(),
274
- ...(Object.keys(binaryFiles).length === 0 ? {} : { binaryFiles }),
275
- };
320
+ return { kind: 'accepted', ...(yield* acceptedOf(at, contents)) };
276
321
  }
277
322
  export function rejectedMapping(mapping) {
278
323
  return {
@@ -337,7 +382,7 @@ export function historyOutcome(status, body, locator, request) {
337
382
  return {
338
383
  kind: 'scoped-refusal',
339
384
  locator,
340
- scope: 'content',
385
+ scope: 'operation',
341
386
  code: 'retained_history_unavailable',
342
387
  fields: { path: request.path, revision: request.revision },
343
388
  retryable: false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentshouse/mdruntime-adapter",
3
- "version": "0.1.0-ceda7e87cc6e8",
3
+ "version": "0.1.0-cedb8e57837a7",
4
4
  "description": "Agents House Adapter for the MD Runtime",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -25,7 +25,6 @@
25
25
  "LICENSE"
26
26
  ],
27
27
  "dependencies": {
28
- "@agentshouse/mdmodel": "0.1.0-c6e675bb19980",
29
- "@agentshouse/mdruntime": "0.1.0-c16fc8caac7ff"
28
+ "@agentshouse/mdruntime": "0.1.0-c450c0a30a409"
30
29
  }
31
30
  }