@agentshouse/mdruntime-adapter 0.1.0-ce3ced044cab5 → 0.1.0-ce3f1a73f440b

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/adapter.js CHANGED
@@ -1,19 +1,17 @@
1
1
  import { stepped } from '@agentshouse/mdruntime';
2
- import { DISCOVER_PREFIXES, capabilities, discoveredRoom, mapDiscovery, parseDiscovery, trackedFrom, } from './discovery.js';
3
- import { streamedModels, viewModels } from './model.js';
4
- import { gathered, selections } from './gather.js';
2
+ import { capabilities, discoveredRoom, mapDiscovery, parseAuthorityChange, parseDiscovery, trackedFrom, } from './discovery.js';
5
3
  import { createSiteAdapter } from './site.js';
6
- import { authorityRoot, bootstrapping, parseEnumeration, parseFileAddress, parseGrant, refreshFrom, viewOf, wholeView, } from './read.js';
4
+ import { authorityRoot, bootstrapping, parseFileAddress, parseGrant, } from './read.js';
7
5
  import { roomStreams } from './room-stream.js';
8
6
  import { sha256Hex } from './digest.js';
9
7
  import { finishedUpload, houseUpload } from './upload.js';
10
8
  import { houseAction } from './actions.js';
11
- import { classifyDoor, classifyRead, discoveryFailure, doorRefusal } from './refusal.js';
12
- import { houseNotifications } from './stream.js';
13
- import { DOOR_BATCH, DOOR_BATCH_UPLOAD, DOOR_BOOTSTRAP, DOOR_DISCOVER, DOOR_ENUMERATE, DOOR_FILES_ATTACH, DOOR_FILES_GET, DOOR_REVISIONS, } from './transport.js';
9
+ import { classifyDoor, doorRefusal } from './refusal.js';
10
+ import { houseNotifications, } from './stream.js';
11
+ import { houseDoorRoute, } from './transport.js';
14
12
  import { batchPaths, deltaBody, deltaBytes, deltaDigest, historyOutcome, houseChanges, houseMove, mutationOutcome, operationHead, rejectedMapping, revisionBody, uploadable, } from './write.js';
15
13
  import { HOUSE_NAMEABLE_ROOM_TYPES, HOUSE_ROOM_TYPES } from './room-types.js';
16
- import { followsVersion, logPosition, presented, reachedVersion, roomVersion, } from './version.js';
14
+ import { followsVersion, logPosition, presented, reachedVersion, roomVersion } from './version.js';
17
15
  const UNCERTAIN = { kind: 'transport-uncertainty' };
18
16
  const UNCERTAIN_READ = { kind: 'transport-uncertainty' };
19
17
  const OCTET_STREAM = 'application/octet-stream';
@@ -51,18 +49,49 @@ export function createAgentsHouseAdapter(options) {
51
49
  if ('site' in options)
52
50
  return createSiteAdapter(options.site, options.snapshot === true);
53
51
  const transport = options.transport;
54
- const notifications = houseNotifications(transport, 'credential');
52
+ const notifications = houseNotifications(transport, 'credential', {
53
+ opened: async (frame) => (frame === null ? null : opened(frame)),
54
+ changed,
55
+ });
55
56
  const tracked = new Map();
56
- const handed = new Map();
57
57
  const rooms = roomStreams('credential');
58
58
  const unreused = new Set();
59
- let heldRevisions;
60
59
  let bounds;
61
60
  function declared() {
62
61
  if (bounds === undefined)
63
62
  throw new Error('no Discovery declared the bounds');
64
63
  return bounds;
65
64
  }
65
+ function opened(frame) {
66
+ const document = parseDiscovery(frame);
67
+ if (document === null)
68
+ return null;
69
+ bounds = document.bounds;
70
+ tracked.clear();
71
+ for (const entry of trackedFrom(document))
72
+ tracked.set(entry.locator, entry);
73
+ notifications.track([...tracked.values()]);
74
+ return {
75
+ ...mapDiscovery(document, document.authorities.map((authority) => discoveredRoom(authority)), capabilities(document.actions)),
76
+ member: document.member,
77
+ };
78
+ }
79
+ function changed(frame) {
80
+ const change = parseAuthorityChange(frame);
81
+ if (change === null)
82
+ return null;
83
+ for (const locator of change.left)
84
+ tracked.delete(locator);
85
+ for (const entry of trackedFrom(change))
86
+ tracked.set(entry.locator, entry);
87
+ notifications.track([...tracked.values()]);
88
+ return {
89
+ kind: 'authority-changed',
90
+ rooms: change.authorities.map((authority) => discoveredRoom(authority)),
91
+ left: change.left,
92
+ member: change.member,
93
+ };
94
+ }
66
95
  async function streamedPage(entry, token, held) {
67
96
  const part = await rooms.part(entry, token);
68
97
  if ('kind' in part)
@@ -72,11 +101,6 @@ export function createAgentsHouseAdapter(options) {
72
101
  unreused.add(entry.locator);
73
102
  return UNCERTAIN_READ;
74
103
  }
75
- if (part.first && part.ended)
76
- handed.set(entry.locator, roomVersion(scope));
77
- else
78
- handed.delete(entry.locator);
79
- notifications.reach(entry.authority, scope);
80
104
  return {
81
105
  ...(await stepped(bootstrapping(scope))),
82
106
  ...(part.models === undefined ? {} : { models: part.models }),
@@ -89,7 +113,8 @@ export function createAgentsHouseAdapter(options) {
89
113
  const files = reusing === undefined
90
114
  ? null
91
115
  : await heldFiles(entry.authority, reusing, declared().max_held_files);
92
- const answered = await transport.streamed(DOOR_BOOTSTRAP, {
116
+ const answered = await transport.streamed(houseDoorRoute('bootstrap'), {
117
+ room_ref: entry.authority,
93
118
  prefixes: [authorityRoot(entry.handle)],
94
119
  ...(files === null ? {} : { held: [files] }),
95
120
  }, request.signal ?? new AbortController().signal);
@@ -97,84 +122,12 @@ export function createAgentsHouseAdapter(options) {
97
122
  return classifyDoor(answered.status, answered.body, entry.locator) ?? UNCERTAIN_READ;
98
123
  return rooms.head(entry, answered.room, request.arriving, request.signal);
99
124
  }
100
- async function enumeratedPage(ask, page) {
101
- const answer = await transport.door(DOOR_ENUMERATE, {
102
- prefixes: [authorityRoot(ask.entry.handle)],
103
- positions: [
104
- {
105
- ...presented(ask.entry.authority, { position: page.after, logEpoch: ask.from.logEpoch }),
106
- page: { through: page.through, read: page.read },
107
- },
108
- ],
109
- });
110
- const failure = classifyRead(answer.status, answer.body, ask.entry.locator);
111
- if (failure !== null)
112
- return failure;
113
- const enumeration = parseEnumeration(answer.body, 'credential');
114
- if (enumeration === null)
115
- return UNCERTAIN_READ;
116
- return (viewOf(enumeration, ask.entry) ?? { kind: 'room-not-readable', locator: ask.entry.locator });
117
- }
118
- async function enumeratedRoom(enumeration, ask) {
119
- const first = viewOf(enumeration, ask.entry);
120
- if (first === undefined)
121
- return { kind: 'room-not-readable', locator: ask.entry.locator };
122
- const view = await wholeView(first, (page) => enumeratedPage(ask, page));
123
- if ('kind' in view)
124
- return view;
125
- notifications.reach(ask.entry.authority, view);
126
- const answer = await refreshFrom(view, ask.fromRoomVersion);
127
- if (answer.kind !== 'net-advancement')
128
- return answer;
129
- handed.set(ask.entry.locator, roomVersion(view));
130
- const models = await viewModels(view, ask.entry);
131
- return models === undefined ? answer : { ...answer, models };
132
- }
133
- async function streamed(entry, request, from) {
134
- if (handed.get(entry.locator) !== request.fromRoomVersion)
135
- return null;
136
- const asked = notifications.edited(entry, from);
137
- const kept = asked.length === 0 || heldRevisions === undefined
138
- ? new Map()
139
- : await heldRevisions(entry.locator, asked);
140
- const advanced = await stepped(notifications.advance(entry, from, (path, revision) => kept.get(path) === revision));
141
- if (advanced === null)
142
- return null;
143
- handed.set(entry.locator, advanced.page.roomVersion);
144
- const models = await streamedModels(advanced.schemas, entry, 'credential');
145
- return models === undefined ? advanced.page : { ...advanced.page, models };
146
- }
147
125
  function held(rooms) {
148
- const kept = rooms.flatMap((room) => {
126
+ notifications.send(rooms.flatMap((room) => {
149
127
  const entry = tracked.get(room.locator);
150
128
  const at = logPosition(room.roomVersion);
151
- if (entry === undefined || at === null)
152
- return [];
153
- handed.set(room.locator, room.roomVersion);
154
- notifications.reach(entry.authority, at);
155
- return [presented(entry.authority, at)];
156
- });
157
- notifications.send(kept);
158
- }
159
- async function adoptedMove(entry, into, outcome) {
160
- if (outcome.kind === 'accepted' && outcome.destination !== undefined) {
161
- await adopted(into, { kind: 'accepted', ...outcome.destination });
162
- }
163
- return adopted(entry, outcome);
164
- }
165
- async function adopted(entry, outcome) {
166
- if (outcome.kind !== 'accepted')
167
- return outcome;
168
- const held = handed.get(entry.locator);
169
- if (held === undefined)
170
- return outcome;
171
- const follows = followsVersion(held, outcome.roomVersion);
172
- if (follows)
173
- handed.set(entry.locator, outcome.roomVersion);
174
- const at = logPosition(outcome.roomVersion);
175
- if (follows && at !== null)
176
- notifications.reach(entry.authority, at);
177
- return outcome;
129
+ return entry === undefined || at === null ? [] : [presented(entry.authority, at)];
130
+ }));
178
131
  }
179
132
  function authorityFor(locator) {
180
133
  return tracked.get(locator);
@@ -193,60 +146,18 @@ export function createAgentsHouseAdapter(options) {
193
146
  return result;
194
147
  return { ...result, at: { locator, roomVersion: roomVersion({ position, logEpoch }) } };
195
148
  }
196
- function layered(asks) {
197
- const depths = new Map();
198
- const layers = [];
199
- for (const ask of asks) {
200
- const depth = depths.get(ask.ask.entry.authority) ?? 0;
201
- depths.set(ask.ask.entry.authority, depth + 1);
202
- (layers[depth] ??= []).push(ask);
203
- }
204
- return layers;
205
- }
206
- async function enumerated(asks) {
207
- const answers = [];
208
- const parts = layered(asks.map((ask, index) => ({ ask, index }))).flatMap((layer) => selections(layer, declared().max_prefixes));
209
- for (const part of parts) {
210
- let open = [...part];
211
- while (open.length > 0) {
212
- const answer = await transport.door(DOOR_ENUMERATE, {
213
- prefixes: open.map(({ ask }) => authorityRoot(ask.entry.handle)),
214
- positions: open.map(({ ask }) => presented(ask.entry.authority, ask.from)),
215
- });
216
- const classified = open.map(({ ask }) => classifyRead(answer.status, answer.body, ask.entry.locator));
217
- if (classified[0]?.kind === 'beyond-horizon') {
218
- const named = doorRefusal(answer.body)?.fields.authority;
219
- const expired = open.filter(({ ask }) => ask.entry.authority === named);
220
- const answered = expired.length === 0 ? UNCERTAIN_READ : { kind: 'beyond-horizon' };
221
- const gone = expired.length === 0 ? open : expired;
222
- for (const ask of gone)
223
- answers[ask.index] = answered;
224
- open = open.filter((ask) => !gone.includes(ask));
225
- continue;
226
- }
227
- const enumeration = classified[0] === null ? parseEnumeration(answer.body, 'credential') : null;
228
- for (const [answerIndex, { ask, index }] of open.entries()) {
229
- const failure = classified[answerIndex];
230
- if (failure !== null && failure !== undefined) {
231
- answers[index] = failure;
232
- continue;
233
- }
234
- answers[index] =
235
- enumeration === null ? UNCERTAIN_READ : await enumeratedRoom(enumeration, ask);
236
- }
237
- open = [];
238
- }
239
- }
240
- return answers;
241
- }
242
- const enumerateTogether = gathered(enumerated);
243
149
  async function uploaded(head, changes, delta, bytes, entry, handed, keep) {
244
150
  const paths = batchPaths(changes);
245
151
  const sha256 = await deltaDigest(delta);
246
152
  if (handed !== undefined && handed.sha256 === sha256) {
247
153
  return { body: { ...head, paths, upload: handed, runtime: notifications.runtime } };
248
154
  }
249
- const minted = await transport.door(DOOR_BATCH_UPLOAD, { ...head, paths, bytes, sha256 });
155
+ const minted = await transport.door(houseDoorRoute('batch-upload'), {
156
+ ...head,
157
+ paths,
158
+ bytes,
159
+ sha256,
160
+ });
250
161
  if (minted.status !== 200) {
251
162
  return {
252
163
  outcome: await stepped(mutationOutcome(minted.status, minted.body, entry.locator, entry.handle)),
@@ -294,11 +205,11 @@ export function createAgentsHouseAdapter(options) {
294
205
  : { body: inline };
295
206
  if ('outcome' in prepared)
296
207
  return prepared.outcome;
297
- const answer = await transport.door(DOOR_BATCH, prepared.body);
208
+ const answer = await transport.door(houseDoorRoute('batch'), prepared.body);
298
209
  const stagedFiles = await staged(answer, request);
299
210
  if (stagedFiles === false)
300
211
  return UNCERTAIN;
301
- const settled = stagedFiles === null ? answer : await transport.door(DOOR_BATCH, prepared.body);
212
+ const settled = stagedFiles === null ? answer : await transport.door(houseDoorRoute('batch'), prepared.body);
302
213
  if (stagedFiles === true && (await staged(settled, request)) !== null)
303
214
  return UNCERTAIN;
304
215
  return stepped(mutationOutcome(settled.status, settled.body, entry.locator, entry.handle, into === undefined
@@ -366,7 +277,7 @@ export function createAgentsHouseAdapter(options) {
366
277
  const entry = authorityFor(request.locator);
367
278
  if (entry === undefined)
368
279
  return null;
369
- return () => transport.door(DOOR_FILES_GET, {
280
+ return () => transport.door(houseDoorRoute('files/get'), {
370
281
  room_ref: entry.authority,
371
282
  path: request.path,
372
283
  revision: request.revision,
@@ -378,46 +289,6 @@ export function createAgentsHouseAdapter(options) {
378
289
  async authorize() {
379
290
  return options.authorize();
380
291
  },
381
- async discover(_authorization, scope) {
382
- const answer = await transport.door(DOOR_DISCOVER, {
383
- prefixes: [...DISCOVER_PREFIXES],
384
- ...(scope === undefined ? {} : { rooms: scope.authorities }),
385
- });
386
- const failed = discoveryFailure(answer.status, answer.body);
387
- if (failed !== null)
388
- return failed;
389
- const document = parseDiscovery(answer.body);
390
- if (document === null)
391
- return { kind: 'transport-uncertainty' };
392
- bounds = document.bounds;
393
- const entries = trackedFrom(document);
394
- const covered = scope === undefined
395
- ? null
396
- : [
397
- ...new Set([
398
- ...[...tracked.values()]
399
- .filter((entry) => scope.authorities.includes(entry.authority))
400
- .map((entry) => entry.locator),
401
- ...entries.map((entry) => entry.locator),
402
- ]),
403
- ];
404
- if (covered === null)
405
- tracked.clear();
406
- else
407
- for (const locator of covered)
408
- tracked.delete(locator);
409
- for (const entry of entries)
410
- tracked.set(entry.locator, entry);
411
- for (const locator of handed.keys())
412
- if (!tracked.has(locator))
413
- handed.delete(locator);
414
- notifications.track([...tracked.values()]);
415
- return {
416
- ...mapDiscovery(document, document.authorities.map((authority) => discoveredRoom(authority)), capabilities(document.actions, [...tracked.values()])),
417
- member: document.member,
418
- ...(covered === null ? {} : { covered }),
419
- };
420
- },
421
292
  async bootstrap(_authorization, request) {
422
293
  const entry = authorityFor(request.locator);
423
294
  if (entry === undefined)
@@ -426,20 +297,6 @@ export function createAgentsHouseAdapter(options) {
426
297
  ? openedRoom(entry, request)
427
298
  : streamedPage(entry, request.pageToken, request.held);
428
299
  },
429
- async refresh(_authorization, request) {
430
- const entry = authorityFor(request.locator);
431
- if (entry === undefined)
432
- return { kind: 'room-not-readable', locator: request.locator };
433
- if (request.pageToken !== undefined)
434
- return { kind: 'transport-uncertainty' };
435
- const from = logPosition(request.fromRoomVersion);
436
- if (from === null)
437
- return { kind: 'beyond-horizon' };
438
- const answered = await streamed(entry, request, from);
439
- if (answered !== null)
440
- return answered;
441
- return enumerateTogether({ entry, from, fromRoomVersion: request.fromRoomVersion });
442
- },
443
300
  async mutate(_authorization, request, keep) {
444
301
  const entry = authorityFor(request.locator);
445
302
  if (entry === undefined)
@@ -455,22 +312,21 @@ export function createAgentsHouseAdapter(options) {
455
312
  : houseMove(batch, entry.handle, into.handle);
456
313
  if (mapped.kind === 'unmapped')
457
314
  return rejectedMapping(mapped);
458
- const head = operationHead(batch);
315
+ const head = operationHead(batch, entry.authority);
459
316
  const delta = deltaBody(mapped.changes);
460
317
  const bytes = deltaBytes(delta);
461
318
  const handed = request.upload;
462
319
  const answer = (upload) => submit(request, head, mapped.changes, delta, bytes, entry, upload, keep, into);
463
- const settle = (outcome) => into === undefined ? adopted(entry, outcome) : adoptedMove(entry, into, outcome);
464
320
  const outcome = await answer(handed);
465
321
  if (handed === undefined || !lapsedGrant(outcome))
466
- return settle(outcome);
467
- return settle(await answer(undefined));
322
+ return outcome;
323
+ return answer(undefined);
468
324
  },
469
325
  async history(_authorization, request) {
470
326
  const entry = authorityFor(request.locator);
471
327
  if (entry === undefined)
472
328
  return { kind: 'room-not-readable', locator: request.locator };
473
- const answer = await transport.door(DOOR_REVISIONS, revisionBody({
329
+ const answer = await transport.door(houseDoorRoute('revisions'), revisionBody({
474
330
  path: request.path,
475
331
  handle: entry.handle,
476
332
  ...(request.revision === undefined ? {} : { revision: request.revision }),
@@ -497,7 +353,7 @@ export function createAgentsHouseAdapter(options) {
497
353
  const entry = authorityFor(request.locator);
498
354
  if (entry === undefined)
499
355
  return { kind: 'room-not-readable', locator: request.locator };
500
- const declared = await transport.door(DOOR_FILES_ATTACH, {
356
+ const declared = await transport.door(houseDoorRoute('files/attach'), {
501
357
  room_ref: entry.authority,
502
358
  name: request.name,
503
359
  bytes: request.byteLength,
@@ -533,16 +389,7 @@ export function createAgentsHouseAdapter(options) {
533
389
  },
534
390
  roomStream: {
535
391
  hold: held,
536
- reopen: notifications.reopen,
537
- observe(notify, receipts, revisions) {
538
- heldRevisions = revisions;
539
- return notifications.observe(notify, receipts);
540
- },
541
- published(locator, roomVersion) {
542
- const at = logPosition(roomVersion);
543
- if (at !== null)
544
- notifications.published(locator, at);
545
- },
392
+ observe: notifications.observe,
546
393
  },
547
394
  conversations: notifications.conversations,
548
395
  serviceMode: notifications.serviceMode,
@@ -1,7 +1,6 @@
1
1
  import type { Capability, DiscoveredRoom, Discovery, Member, ProviderLimit, Retention } from '@agentshouse/mdruntime';
2
2
  import { type LogPosition } from './version.js';
3
3
  export declare const PROVIDER_ACTIONS = "provider-actions";
4
- export declare const DISCOVER_PREFIXES: readonly string[];
5
4
  export type HouseBounds = {
6
5
  max_authored_file_bytes: number;
7
6
  max_batch_operations: number;
@@ -40,6 +39,11 @@ export type HouseDiscoveryDocument = {
40
39
  authorities: readonly HouseAuthority[];
41
40
  actions: readonly string[];
42
41
  };
42
+ export type HouseAuthorityChange = {
43
+ member: Member;
44
+ authorities: readonly HouseAuthority[];
45
+ left: readonly string[];
46
+ };
43
47
  export type TrackedAuthority = LogPosition & {
44
48
  locator: string;
45
49
  authority: string;
@@ -57,12 +61,13 @@ export type HouseSiteDiscovery = {
57
61
  authorities: readonly HouseSiteAuthority[];
58
62
  };
59
63
  export declare function parseDiscovery(body: unknown): HouseDiscoveryDocument | null;
64
+ export declare function parseAuthorityChange(body: unknown): HouseAuthorityChange | null;
60
65
  export declare function parseSiteDiscovery(body: unknown): HouseSiteDiscovery | null;
61
66
  export declare function siteTracked(document: HouseSiteDiscovery): TrackedAuthority[];
62
- export declare function trackedFrom(document: HouseDiscoveryDocument): TrackedAuthority[];
67
+ export declare function trackedFrom(document: Pick<HouseDiscoveryDocument, 'authorities'>): TrackedAuthority[];
63
68
  export declare function providerLimits(bounds: HouseBounds): readonly ProviderLimit[];
64
69
  export declare function declaredRetention(bounds: HouseBounds): Retention;
65
- export declare function capabilities(actions: HouseDiscoveryDocument['actions'], rooms: readonly Pick<TrackedAuthority, 'authority' | 'handle'>[]): readonly Capability[];
70
+ export declare function capabilities(actions: HouseDiscoveryDocument['actions']): readonly Capability[];
66
71
  export declare function siteCapabilities(): readonly Capability[];
67
72
  export declare function discoveredRoom(authority: HouseAuthority): DiscoveredRoom;
68
73
  export declare function mapDiscovery(document: Pick<HouseDiscoveryDocument, 'bounds'>, rooms: readonly DiscoveredRoom[], declared: readonly Capability[]): Discovery;
@@ -1 +1 @@
1
- {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"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"}
package/dist/discovery.js CHANGED
@@ -1,8 +1,7 @@
1
- import { declaredActions, houseConversationAgents, SITE_SUBMIT } from './actions.js';
1
+ import { declaredActions } from './actions.js';
2
+ import { SITE_SUBMISSION } from './transport.js';
2
3
  import { readPosition, roomVersion } from './version.js';
3
4
  export const PROVIDER_ACTIONS = 'provider-actions';
4
- export const DISCOVER_PREFIXES = ['/'];
5
- const PRIVATE_HANDLE = 'private';
6
5
  const BOUND_KEYS = [
7
6
  'max_authored_file_bytes',
8
7
  'max_batch_operations',
@@ -111,6 +110,18 @@ function parseAuthority(value) {
111
110
  ...at,
112
111
  };
113
112
  }
113
+ function parseAuthorities(value) {
114
+ if (!Array.isArray(value))
115
+ return null;
116
+ const authorities = [];
117
+ for (const entry of value) {
118
+ const authority = parseAuthority(entry);
119
+ if (authority === null)
120
+ return null;
121
+ authorities.push(authority);
122
+ }
123
+ return authorities;
124
+ }
114
125
  export function parseDiscovery(body) {
115
126
  if (typeof body !== 'object' || body === null)
116
127
  return null;
@@ -126,16 +137,19 @@ export function parseDiscovery(body) {
126
137
  new Set(actions).size !== actions.length ||
127
138
  actions.some((name) => name.length === 0))
128
139
  return null;
129
- if (!Array.isArray(held.authorities))
140
+ const authorities = parseAuthorities(held.authorities);
141
+ return authorities === null ? null : { member, bounds, authorities, actions };
142
+ }
143
+ export function parseAuthorityChange(body) {
144
+ if (typeof body !== 'object' || body === null)
130
145
  return null;
131
- const authorities = [];
132
- for (const entry of held.authorities) {
133
- const authority = parseAuthority(entry);
134
- if (authority === null)
135
- return null;
136
- authorities.push(authority);
137
- }
138
- return { member, bounds, authorities, actions };
146
+ const held = body;
147
+ const member = parseMember(held.member);
148
+ const authorities = parseAuthorities(held.authorities);
149
+ const left = stringList(held.left);
150
+ if (member === null || authorities === null || left === null)
151
+ return null;
152
+ return { member, authorities, left };
139
153
  }
140
154
  function parseSiteAuthority(value) {
141
155
  if (typeof value !== 'object' || value === null)
@@ -220,21 +234,14 @@ export function declaredRetention(bounds) {
220
234
  refreshHorizon: bounds.change_retention_seconds,
221
235
  };
222
236
  }
223
- export function capabilities(actions, rooms) {
224
- const own = rooms.find((room) => room.handle === PRIVATE_HANDLE);
225
- return [
226
- {
227
- name: PROVIDER_ACTIONS,
228
- actions: declaredActions(actions),
229
- ...(own === undefined ? {} : { conversationAgents: houseConversationAgents(own.authority) }),
230
- },
231
- ];
237
+ export function capabilities(actions) {
238
+ return [{ name: PROVIDER_ACTIONS, actions: declaredActions(actions) }];
232
239
  }
233
240
  export function siteCapabilities() {
234
241
  return [
235
242
  {
236
243
  name: PROVIDER_ACTIONS,
237
- actions: [{ name: SITE_SUBMIT, inputShape: {}, resultKind: 'house' }],
244
+ actions: [{ name: SITE_SUBMISSION, inputShape: {}, resultKind: 'house' }],
238
245
  },
239
246
  ];
240
247
  }
@@ -0,0 +1,12 @@
1
+ import type { AcceptedMessage, ActionResult, ConversationHistoryRequest } from '@agentshouse/mdruntime';
2
+ import { type HouseDoor } from './transport.js';
3
+ export declare const HISTORY_PAGE = 100;
4
+ type HistoryCursor = {
5
+ accepted_at: string;
6
+ message_id: string;
7
+ };
8
+ export declare function cursorPosition(cursor: HistoryCursor): string;
9
+ export declare function acceptedMessage(entry: unknown): AcceptedMessage | null;
10
+ export declare function houseHistory(transport: HouseDoor, request: ConversationHistoryRequest): Promise<ActionResult>;
11
+ export {};
12
+ //# sourceMappingURL=history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EAGZ,0BAA0B,EAC3B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhE,eAAO,MAAM,YAAY,MAAM,CAAC;AAIhC,KAAK,aAAa,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAkBjE,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAE5D;AAUD,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,GAAG,IAAI,CAUtE;AA8BD,wBAAsB,YAAY,CAChC,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,YAAY,CAAC,CAmBvB"}
@@ -0,0 +1,91 @@
1
+ import { actionOutcome } from './actions.js';
2
+ import { houseDoorRoute } from './transport.js';
3
+ export const HISTORY_PAGE = 100;
4
+ const HISTORY = 'conversations/history';
5
+ function record(value) {
6
+ return typeof value === 'object' && value !== null ? value : {};
7
+ }
8
+ function text(value, name) {
9
+ const held = record(value)[name];
10
+ return typeof held === 'string' ? held : undefined;
11
+ }
12
+ function historyCursor(value) {
13
+ const acceptedAt = text(value, 'accepted_at');
14
+ const messageId = text(value, 'message_id');
15
+ if (acceptedAt === undefined || messageId === undefined)
16
+ return null;
17
+ return { accepted_at: acceptedAt, message_id: messageId };
18
+ }
19
+ export function cursorPosition(cursor) {
20
+ return JSON.stringify({ accepted_at: cursor.accepted_at, message_id: cursor.message_id });
21
+ }
22
+ function positionCursor(value) {
23
+ try {
24
+ return historyCursor(JSON.parse(value));
25
+ }
26
+ catch {
27
+ return null;
28
+ }
29
+ }
30
+ export function acceptedMessage(entry) {
31
+ const cursor = historyCursor(entry);
32
+ if (cursor === null)
33
+ return null;
34
+ return {
35
+ identity: cursor.message_id,
36
+ turn: text(entry, 'turn_id') ?? cursor.message_id,
37
+ position: cursorPosition(cursor),
38
+ text: text(entry, 'text') ?? '',
39
+ message: structuredClone(record(entry)),
40
+ };
41
+ }
42
+ function historyPage(entry) {
43
+ const held = record(entry);
44
+ const conversation = text(held, 'conversation_id');
45
+ if (conversation === undefined || !Array.isArray(held.messages))
46
+ return null;
47
+ const messages = [];
48
+ for (const one of held.messages) {
49
+ const message = acceptedMessage(one);
50
+ if (message === null)
51
+ return null;
52
+ messages.push(message);
53
+ }
54
+ const next = held.next === null || held.next === undefined ? undefined : historyCursor(held.next);
55
+ if (next === null)
56
+ return null;
57
+ return { conversation, messages, ...(next === undefined ? {} : { next: cursorPosition(next) }) };
58
+ }
59
+ function historyAsks(request) {
60
+ const asks = [];
61
+ for (const { conversation, after } of request.conversations) {
62
+ const cursor = after === undefined ? undefined : positionCursor(after);
63
+ if (cursor === null)
64
+ return null;
65
+ asks.push({
66
+ conversation_id: conversation,
67
+ ...(cursor === undefined ? {} : { after: cursor }),
68
+ });
69
+ }
70
+ return asks;
71
+ }
72
+ export async function houseHistory(transport, request) {
73
+ const asks = historyAsks(request);
74
+ if (asks === null)
75
+ return { kind: 'rejected', code: 'invalid_request', fields: {}, retryable: false };
76
+ const outcome = actionOutcome(await transport.door(houseDoorRoute(HISTORY), { conversations: asks, limit: HISTORY_PAGE }), HISTORY);
77
+ if (outcome.kind !== 'action')
78
+ return outcome;
79
+ const answered = record(outcome.result).histories;
80
+ if (!Array.isArray(answered))
81
+ return { kind: 'transport-uncertainty' };
82
+ const histories = [];
83
+ for (const entry of answered) {
84
+ const page = historyPage(entry);
85
+ if (page === null)
86
+ return { kind: 'transport-uncertainty' };
87
+ histories.push(page);
88
+ }
89
+ const result = { histories };
90
+ return { kind: 'action', result };
91
+ }