@agentshouse/mdruntime-adapter 0.1.0-cd673d02b6e50 → 0.1.0-cd7e4bb187177

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,7 @@ 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'), {
93
117
  prefixes: [authorityRoot(entry.handle)],
94
118
  ...(files === null ? {} : { held: [files] }),
95
119
  }, request.signal ?? new AbortController().signal);
@@ -97,84 +121,12 @@ export function createAgentsHouseAdapter(options) {
97
121
  return classifyDoor(answered.status, answered.body, entry.locator) ?? UNCERTAIN_READ;
98
122
  return rooms.head(entry, answered.room, request.arriving, request.signal);
99
123
  }
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
124
  function held(rooms) {
148
- const kept = rooms.flatMap((room) => {
125
+ notifications.send(rooms.flatMap((room) => {
149
126
  const entry = tracked.get(room.locator);
150
127
  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;
128
+ return entry === undefined || at === null ? [] : [presented(entry.authority, at)];
129
+ }));
178
130
  }
179
131
  function authorityFor(locator) {
180
132
  return tracked.get(locator);
@@ -193,60 +145,18 @@ export function createAgentsHouseAdapter(options) {
193
145
  return result;
194
146
  return { ...result, at: { locator, roomVersion: roomVersion({ position, logEpoch }) } };
195
147
  }
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
148
  async function uploaded(head, changes, delta, bytes, entry, handed, keep) {
244
149
  const paths = batchPaths(changes);
245
150
  const sha256 = await deltaDigest(delta);
246
151
  if (handed !== undefined && handed.sha256 === sha256) {
247
152
  return { body: { ...head, paths, upload: handed, runtime: notifications.runtime } };
248
153
  }
249
- const minted = await transport.door(DOOR_BATCH_UPLOAD, { ...head, paths, bytes, sha256 });
154
+ const minted = await transport.door(houseDoorRoute('batch-upload'), {
155
+ ...head,
156
+ paths,
157
+ bytes,
158
+ sha256,
159
+ });
250
160
  if (minted.status !== 200) {
251
161
  return {
252
162
  outcome: await stepped(mutationOutcome(minted.status, minted.body, entry.locator, entry.handle)),
@@ -294,11 +204,11 @@ export function createAgentsHouseAdapter(options) {
294
204
  : { body: inline };
295
205
  if ('outcome' in prepared)
296
206
  return prepared.outcome;
297
- const answer = await transport.door(DOOR_BATCH, prepared.body);
207
+ const answer = await transport.door(houseDoorRoute('batch'), prepared.body);
298
208
  const stagedFiles = await staged(answer, request);
299
209
  if (stagedFiles === false)
300
210
  return UNCERTAIN;
301
- const settled = stagedFiles === null ? answer : await transport.door(DOOR_BATCH, prepared.body);
211
+ const settled = stagedFiles === null ? answer : await transport.door(houseDoorRoute('batch'), prepared.body);
302
212
  if (stagedFiles === true && (await staged(settled, request)) !== null)
303
213
  return UNCERTAIN;
304
214
  return stepped(mutationOutcome(settled.status, settled.body, entry.locator, entry.handle, into === undefined
@@ -366,7 +276,7 @@ export function createAgentsHouseAdapter(options) {
366
276
  const entry = authorityFor(request.locator);
367
277
  if (entry === undefined)
368
278
  return null;
369
- return () => transport.door(DOOR_FILES_GET, {
279
+ return () => transport.door(houseDoorRoute('files/get'), {
370
280
  room_ref: entry.authority,
371
281
  path: request.path,
372
282
  revision: request.revision,
@@ -378,46 +288,6 @@ export function createAgentsHouseAdapter(options) {
378
288
  async authorize() {
379
289
  return options.authorize();
380
290
  },
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
291
  async bootstrap(_authorization, request) {
422
292
  const entry = authorityFor(request.locator);
423
293
  if (entry === undefined)
@@ -426,20 +296,6 @@ export function createAgentsHouseAdapter(options) {
426
296
  ? openedRoom(entry, request)
427
297
  : streamedPage(entry, request.pageToken, request.held);
428
298
  },
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
299
  async mutate(_authorization, request, keep) {
444
300
  const entry = authorityFor(request.locator);
445
301
  if (entry === undefined)
@@ -460,17 +316,16 @@ export function createAgentsHouseAdapter(options) {
460
316
  const bytes = deltaBytes(delta);
461
317
  const handed = request.upload;
462
318
  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
319
  const outcome = await answer(handed);
465
320
  if (handed === undefined || !lapsedGrant(outcome))
466
- return settle(outcome);
467
- return settle(await answer(undefined));
321
+ return outcome;
322
+ return answer(undefined);
468
323
  },
469
324
  async history(_authorization, request) {
470
325
  const entry = authorityFor(request.locator);
471
326
  if (entry === undefined)
472
327
  return { kind: 'room-not-readable', locator: request.locator };
473
- const answer = await transport.door(DOOR_REVISIONS, revisionBody({
328
+ const answer = await transport.door(houseDoorRoute('revisions'), revisionBody({
474
329
  path: request.path,
475
330
  handle: entry.handle,
476
331
  ...(request.revision === undefined ? {} : { revision: request.revision }),
@@ -497,7 +352,7 @@ export function createAgentsHouseAdapter(options) {
497
352
  const entry = authorityFor(request.locator);
498
353
  if (entry === undefined)
499
354
  return { kind: 'room-not-readable', locator: request.locator };
500
- const declared = await transport.door(DOOR_FILES_ATTACH, {
355
+ const declared = await transport.door(houseDoorRoute('files/attach'), {
501
356
  room_ref: entry.authority,
502
357
  name: request.name,
503
358
  bytes: request.byteLength,
@@ -533,16 +388,7 @@ export function createAgentsHouseAdapter(options) {
533
388
  },
534
389
  roomStream: {
535
390
  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
- },
391
+ observe: notifications.observe,
546
392
  },
547
393
  conversations: notifications.conversations,
548
394
  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
+ }