@agentshouse/mdruntime-adapter 0.1.0-alpha.1 → 0.1.0-alpha.10

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 (58) hide show
  1. package/AGENTS.md +82 -0
  2. package/dist/actions.d.ts +16 -0
  3. package/dist/actions.d.ts.map +1 -0
  4. package/dist/actions.js +454 -0
  5. package/dist/actions.js.map +1 -0
  6. package/dist/adapter.d.ts +10 -0
  7. package/dist/adapter.d.ts.map +1 -0
  8. package/dist/adapter.js +285 -0
  9. package/dist/adapter.js.map +1 -0
  10. package/dist/digest.d.ts +3 -0
  11. package/dist/digest.d.ts.map +1 -0
  12. package/dist/digest.js +11 -0
  13. package/dist/digest.js.map +1 -0
  14. package/dist/discovery.d.ts +87 -0
  15. package/dist/discovery.d.ts.map +1 -0
  16. package/dist/discovery.js +347 -0
  17. package/dist/discovery.js.map +1 -0
  18. package/dist/index.d.ts +3 -1
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +2 -1
  21. package/dist/index.js.map +1 -1
  22. package/dist/map.d.ts +3 -0
  23. package/dist/map.d.ts.map +1 -0
  24. package/dist/map.js +15 -0
  25. package/dist/map.js.map +1 -0
  26. package/dist/model.d.ts +19 -0
  27. package/dist/model.d.ts.map +1 -0
  28. package/dist/model.js +64 -0
  29. package/dist/model.js.map +1 -0
  30. package/dist/read.d.ts +73 -0
  31. package/dist/read.d.ts.map +1 -0
  32. package/dist/read.js +326 -0
  33. package/dist/read.js.map +1 -0
  34. package/dist/refusal.d.ts +11 -0
  35. package/dist/refusal.d.ts.map +1 -0
  36. package/dist/refusal.js +78 -0
  37. package/dist/refusal.js.map +1 -0
  38. package/dist/site.d.ts +4 -0
  39. package/dist/site.d.ts.map +1 -0
  40. package/dist/site.js +200 -0
  41. package/dist/site.js.map +1 -0
  42. package/dist/stream.d.ts +12 -0
  43. package/dist/stream.d.ts.map +1 -0
  44. package/dist/stream.js +298 -0
  45. package/dist/stream.js.map +1 -0
  46. package/dist/transport.d.ts +88 -0
  47. package/dist/transport.d.ts.map +1 -0
  48. package/dist/transport.js +12 -0
  49. package/dist/transport.js.map +1 -0
  50. package/dist/version.d.ts +14 -0
  51. package/dist/version.d.ts.map +1 -0
  52. package/dist/version.js +29 -0
  53. package/dist/version.js.map +1 -0
  54. package/dist/write.d.ts +47 -0
  55. package/dist/write.d.ts.map +1 -0
  56. package/dist/write.js +389 -0
  57. package/dist/write.js.map +1 -0
  58. package/package.json +7 -2
package/dist/site.js ADDED
@@ -0,0 +1,200 @@
1
+ import { mapDiscovery, parseSiteDiscovery, siteCapabilities, siteSlots, siteTracked } from './discovery.js';
2
+ import { MODEL_ABSENT, failedModel, heldModel, modelKey, modelShelf } from './model.js';
3
+ import { advancedScope, authorityRoot, bootstrapOf, definitionsOf, parseEnumeration, parseSiteBootstrap, refreshFrom, selectionRoots } from './read.js';
4
+ import { classifyDoor, discoveryFailure } from './refusal.js';
5
+ import { houseNotifications } from './stream.js';
6
+ import { PRIVATE_AUTHORITY, SITE_DOOR_BOOTSTRAP, SITE_DOOR_DISCOVER, SITE_DOOR_ENUMERATE } from './transport.js';
7
+ import { logPosition, presented, roomVersion } from './version.js';
8
+ const UNCERTAIN = {
9
+ kind: 'transport-uncertainty'
10
+ };
11
+ function siteRoom(tracked, attachedModel) {
12
+ const read = selectionRoots(tracked);
13
+ return {
14
+ name: tracked.handle,
15
+ locator: tracked.locator,
16
+ collectionRoot: tracked.collectionRoot,
17
+ roomVersion: roomVersion(tracked),
18
+ operations: {
19
+ read: [
20
+ ...read
21
+ ],
22
+ sync: [
23
+ ...read
24
+ ],
25
+ write: [],
26
+ delete: []
27
+ },
28
+ replica: {
29
+ selection: tracked.locator,
30
+ admission: 'admitted'
31
+ },
32
+ attachedModel,
33
+ providerOwnedPaths: []
34
+ };
35
+ }
36
+ function settled(refused) {
37
+ return refused.kind === 'beyond-horizon' ? UNCERTAIN : refused;
38
+ }
39
+ export function createSiteAdapter(transport) {
40
+ const notifications = houseNotifications(transport, 'site');
41
+ const tracked = new Map();
42
+ const models = modelShelf();
43
+ const acquired = new Map();
44
+ let caught = new Map();
45
+ async function enumeration(entry, from) {
46
+ const answer = await transport.door(SITE_DOOR_ENUMERATE, {
47
+ positions: [
48
+ presented(entry.authority, from)
49
+ ]
50
+ });
51
+ const classified = classifyDoor(answer.status, answer.body, entry.locator);
52
+ if (classified !== null) return classified;
53
+ return parseEnumeration(answer.body, 'site') ?? UNCERTAIN;
54
+ }
55
+ async function caughtUp(entry) {
56
+ const answer = await transport.read(`${SITE_DOOR_BOOTSTRAP}${entry.authority}`);
57
+ const classified = classifyDoor(answer.status, answer.body, entry.locator);
58
+ if (classified !== null) return {
59
+ failure: settled(classified)
60
+ };
61
+ const scope = parseSiteBootstrap(answer.body);
62
+ if (scope === null) return {
63
+ failure: UNCERTAIN
64
+ };
65
+ if (roomVersion(scope) === roomVersion(entry)) return {
66
+ scope
67
+ };
68
+ const found = await enumeration(entry, scope);
69
+ if ('kind' in found) return {
70
+ failure: settled(found)
71
+ };
72
+ const view = found.authorities.find((held)=>held.authority === entry.authority);
73
+ if (view === undefined) return {
74
+ failure: {
75
+ kind: 'room-not-readable',
76
+ locator: entry.locator
77
+ }
78
+ };
79
+ return {
80
+ scope: advancedScope(scope, view)
81
+ };
82
+ }
83
+ async function refreshed(entry, fromRoomVersion) {
84
+ const from = logPosition(fromRoomVersion);
85
+ if (from === null) return {
86
+ kind: 'beyond-horizon'
87
+ };
88
+ const streamed = notifications.advance(entry, from);
89
+ if (streamed !== null) return streamed;
90
+ const found = await enumeration(entry, from);
91
+ if ('kind' in found) return found;
92
+ return refreshFrom(found, entry, fromRoomVersion);
93
+ }
94
+ async function acquire(entry, held) {
95
+ if ('failure' in held) return {
96
+ snapshot: failedModel(held.failure),
97
+ identity: null
98
+ };
99
+ const model = await heldModel(definitionsOf(held.scope, entry.modelRoot), `${authorityRoot(entry.handle)}/${entry.modelRoot}`, MODEL_ABSENT);
100
+ acquired.set(entry.authority, {
101
+ roomVersion: roomVersion(held.scope),
102
+ model
103
+ });
104
+ return model;
105
+ }
106
+ return {
107
+ async authorize () {
108
+ return {};
109
+ },
110
+ async model (_authorization, request) {
111
+ return models.answer(request);
112
+ },
113
+ async discover () {
114
+ const answer = await transport.door(SITE_DOOR_DISCOVER, {});
115
+ const classified = classifyDoor(answer.status, answer.body, PRIVATE_AUTHORITY);
116
+ if (classified !== null) return discoveryFailure(classified);
117
+ const document = parseSiteDiscovery(answer.body);
118
+ if (document === null) return UNCERTAIN;
119
+ const entries = siteTracked(document);
120
+ tracked.clear();
121
+ for (const entry of entries)tracked.set(entry.locator, entry);
122
+ notifications.track(entries);
123
+ const published = new Set(entries.map((entry)=>entry.authority));
124
+ for (const authority of [
125
+ ...acquired.keys()
126
+ ]){
127
+ if (!published.has(authority)) acquired.delete(authority);
128
+ }
129
+ const fresh = new Map();
130
+ const current = new Map();
131
+ for (const entry of entries){
132
+ const kept = acquired.get(entry.authority);
133
+ if (kept !== undefined && kept.roomVersion === roomVersion(entry)) {
134
+ current.set(entry.authority, kept.model);
135
+ continue;
136
+ }
137
+ const held = await caughtUp(entry);
138
+ fresh.set(entry.authority, held);
139
+ current.set(entry.authority, await acquire(entry, held));
140
+ }
141
+ caught = fresh;
142
+ const rooms = entries.map((entry)=>{
143
+ const shelved = models.retain(modelKey(entry.locator, 'collection'), current.get(entry.authority));
144
+ return siteRoom(entry, shelved?.identity ?? null);
145
+ });
146
+ models.keep(entries.map((entry)=>entry.locator));
147
+ return {
148
+ ...mapDiscovery(document, rooms, siteCapabilities()),
149
+ slots: siteSlots(document)
150
+ };
151
+ },
152
+ async bootstrap (_authorization, request) {
153
+ const entry = tracked.get(request.locator);
154
+ if (entry === undefined) return {
155
+ kind: 'room-not-readable',
156
+ locator: request.locator
157
+ };
158
+ if (request.pageToken !== undefined) return UNCERTAIN;
159
+ const held = caught.get(entry.authority) ?? await caughtUp(entry);
160
+ if ('failure' in held) return held.failure;
161
+ return bootstrapOf(held.scope, entry);
162
+ },
163
+ async refresh (_authorization, request) {
164
+ const entry = tracked.get(request.locator);
165
+ if (entry === undefined) return {
166
+ kind: 'room-not-readable',
167
+ locator: request.locator
168
+ };
169
+ if (request.pageToken !== undefined) return UNCERTAIN;
170
+ const result = await refreshed(entry, request.fromRoomVersion);
171
+ if (result.kind === 'beyond-horizon') caught.delete(entry.authority);
172
+ return result;
173
+ },
174
+ async mutate () {
175
+ return {
176
+ kind: 'rejected',
177
+ affected: {},
178
+ code: 'write-grant',
179
+ fields: {}
180
+ };
181
+ },
182
+ async history () {
183
+ return {
184
+ kind: 'no-history'
185
+ };
186
+ },
187
+ async action (_authorization, request) {
188
+ return {
189
+ kind: 'rejected',
190
+ code: 'action-unimplemented',
191
+ fields: {
192
+ name: request.name
193
+ }
194
+ };
195
+ },
196
+ roomVersions: notifications
197
+ };
198
+ }
199
+
200
+ //# sourceMappingURL=site.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/workspace/packages/mdruntime-adapter/src/site.ts"],"sourcesContent":["import type {\n Adapter,\n AdapterFailure,\n BootstrapResult,\n DiscoverResult,\n DiscoveredRoom,\n ModelResult,\n RefreshResult,\n} from '@agentshouse/mdruntime';\nimport {\n mapDiscovery,\n parseSiteDiscovery,\n siteCapabilities,\n siteSlots,\n siteTracked,\n type SiteTracked,\n} from './discovery.js';\nimport {\n MODEL_ABSENT,\n failedModel,\n heldModel,\n modelKey,\n modelShelf,\n type HeldModel,\n} from './model.js';\nimport {\n advancedScope,\n authorityRoot,\n bootstrapOf,\n definitionsOf,\n parseEnumeration,\n parseSiteBootstrap,\n refreshFrom,\n selectionRoots,\n type HouseEnumeration,\n type HouseScope,\n} from './read.js';\nimport { classifyDoor, discoveryFailure } from './refusal.js';\nimport { houseNotifications } from './stream.js';\nimport {\n PRIVATE_AUTHORITY,\n SITE_DOOR_BOOTSTRAP,\n SITE_DOOR_DISCOVER,\n SITE_DOOR_ENUMERATE,\n type HouseSiteTransport,\n} from './transport.js';\nimport { logPosition, presented, roomVersion, type LogPosition } from './version.js';\n\ntype Refused = AdapterFailure | { kind: 'beyond-horizon' };\n\ntype CaughtUp = { scope: HouseScope } | { failure: AdapterFailure };\n\ntype Acquired = { roomVersion: string; model: HeldModel };\n\nconst UNCERTAIN = { kind: 'transport-uncertainty' } as const;\n\nfunction siteRoom(\n tracked: SiteTracked,\n attachedModel: DiscoveredRoom['attachedModel'],\n): DiscoveredRoom {\n const read = selectionRoots(tracked);\n return {\n name: tracked.handle,\n locator: tracked.locator,\n collectionRoot: tracked.collectionRoot,\n roomVersion: roomVersion(tracked),\n operations: { read: [...read], sync: [...read], write: [], delete: [] },\n replica: { selection: tracked.locator, admission: 'admitted' },\n attachedModel,\n providerOwnedPaths: [],\n };\n}\n\nfunction settled(refused: Refused): AdapterFailure {\n return refused.kind === 'beyond-horizon' ? UNCERTAIN : refused;\n}\n\nexport function createSiteAdapter(transport: HouseSiteTransport): Adapter {\n const notifications = houseNotifications(transport, 'site');\n const tracked = new Map<string, SiteTracked>();\n const models = modelShelf();\n const acquired = new Map<string, Acquired>();\n let caught = new Map<string, CaughtUp>();\n\n async function enumeration(\n entry: SiteTracked,\n from: LogPosition,\n ): Promise<HouseEnumeration | Refused> {\n const answer = await transport.door(SITE_DOOR_ENUMERATE, {\n positions: [presented(entry.authority, from)],\n });\n const classified = classifyDoor(answer.status, answer.body, entry.locator);\n if (classified !== null) return classified;\n return parseEnumeration(answer.body, 'site') ?? UNCERTAIN;\n }\n\n async function caughtUp(entry: SiteTracked): Promise<CaughtUp> {\n const answer = await transport.read(`${SITE_DOOR_BOOTSTRAP}${entry.authority}`);\n const classified = classifyDoor(answer.status, answer.body, entry.locator);\n if (classified !== null) return { failure: settled(classified) };\n const scope = parseSiteBootstrap(answer.body);\n if (scope === null) return { failure: UNCERTAIN };\n if (roomVersion(scope) === roomVersion(entry)) return { scope };\n const found = await enumeration(entry, scope);\n if ('kind' in found) return { failure: settled(found) };\n const view = found.authorities.find((held) => held.authority === entry.authority);\n if (view === undefined)\n return { failure: { kind: 'room-not-readable', locator: entry.locator } };\n return { scope: advancedScope(scope, view) };\n }\n\n async function refreshed(entry: SiteTracked, fromRoomVersion: string): Promise<RefreshResult> {\n const from = logPosition(fromRoomVersion);\n if (from === null) return { kind: 'beyond-horizon' };\n const streamed = notifications.advance(entry, from);\n if (streamed !== null) return streamed;\n const found = await enumeration(entry, from);\n if ('kind' in found) return found;\n return refreshFrom(found, entry, fromRoomVersion);\n }\n\n async function acquire(entry: SiteTracked, held: CaughtUp): Promise<HeldModel> {\n if ('failure' in held) return { snapshot: failedModel(held.failure), identity: null };\n const model = await heldModel(\n definitionsOf(held.scope, entry.modelRoot),\n `${authorityRoot(entry.handle)}/${entry.modelRoot}`,\n MODEL_ABSENT,\n );\n acquired.set(entry.authority, { roomVersion: roomVersion(held.scope), model });\n return model;\n }\n\n return {\n async authorize() {\n return {};\n },\n\n async model(_authorization, request): Promise<ModelResult> {\n return models.answer(request);\n },\n\n async discover(): Promise<DiscoverResult> {\n const answer = await transport.door(SITE_DOOR_DISCOVER, {});\n const classified = classifyDoor(answer.status, answer.body, PRIVATE_AUTHORITY);\n if (classified !== null) return discoveryFailure(classified);\n const document = parseSiteDiscovery(answer.body);\n if (document === null) return UNCERTAIN;\n const entries = siteTracked(document);\n tracked.clear();\n for (const entry of entries) tracked.set(entry.locator, entry);\n notifications.track(entries);\n const published = new Set(entries.map((entry) => entry.authority));\n for (const authority of [...acquired.keys()]) {\n if (!published.has(authority)) acquired.delete(authority);\n }\n const fresh = new Map<string, CaughtUp>();\n const current = new Map<string, HeldModel>();\n for (const entry of entries) {\n const kept = acquired.get(entry.authority);\n if (kept !== undefined && kept.roomVersion === roomVersion(entry)) {\n current.set(entry.authority, kept.model);\n continue;\n }\n const held = await caughtUp(entry);\n fresh.set(entry.authority, held);\n current.set(entry.authority, await acquire(entry, held));\n }\n caught = fresh;\n const rooms = entries.map((entry) => {\n const shelved = models.retain(\n modelKey(entry.locator, 'collection'),\n current.get(entry.authority),\n );\n return siteRoom(entry, shelved?.identity ?? null);\n });\n models.keep(entries.map((entry) => entry.locator));\n return { ...mapDiscovery(document, rooms, siteCapabilities()), slots: siteSlots(document) };\n },\n\n async bootstrap(_authorization, request): Promise<BootstrapResult> {\n const entry = tracked.get(request.locator);\n if (entry === undefined) return { kind: 'room-not-readable', locator: request.locator };\n if (request.pageToken !== undefined) return UNCERTAIN;\n const held = caught.get(entry.authority) ?? (await caughtUp(entry));\n if ('failure' in held) return held.failure;\n return bootstrapOf(held.scope, entry);\n },\n\n async refresh(_authorization, request): Promise<RefreshResult> {\n const entry = tracked.get(request.locator);\n if (entry === undefined) return { kind: 'room-not-readable', locator: request.locator };\n if (request.pageToken !== undefined) return UNCERTAIN;\n const result = await refreshed(entry, request.fromRoomVersion);\n if (result.kind === 'beyond-horizon') caught.delete(entry.authority);\n return result;\n },\n\n async mutate() {\n return { kind: 'rejected', affected: {}, code: 'write-grant', fields: {} };\n },\n\n async history() {\n return { kind: 'no-history' };\n },\n\n async action(_authorization, request) {\n return { kind: 'rejected', code: 'action-unimplemented', fields: { name: request.name } };\n },\n\n roomVersions: notifications,\n };\n}\n"],"names":["mapDiscovery","parseSiteDiscovery","siteCapabilities","siteSlots","siteTracked","MODEL_ABSENT","failedModel","heldModel","modelKey","modelShelf","advancedScope","authorityRoot","bootstrapOf","definitionsOf","parseEnumeration","parseSiteBootstrap","refreshFrom","selectionRoots","classifyDoor","discoveryFailure","houseNotifications","PRIVATE_AUTHORITY","SITE_DOOR_BOOTSTRAP","SITE_DOOR_DISCOVER","SITE_DOOR_ENUMERATE","logPosition","presented","roomVersion","UNCERTAIN","kind","siteRoom","tracked","attachedModel","read","name","handle","locator","collectionRoot","operations","sync","write","delete","replica","selection","admission","providerOwnedPaths","settled","refused","createSiteAdapter","transport","notifications","Map","models","acquired","caught","enumeration","entry","from","answer","door","positions","authority","classified","status","body","caughtUp","failure","scope","found","view","authorities","find","held","undefined","refreshed","fromRoomVersion","streamed","advance","acquire","snapshot","identity","model","modelRoot","set","authorize","_authorization","request","discover","document","entries","clear","track","published","Set","map","keys","has","fresh","current","kept","get","rooms","shelved","retain","keep","slots","bootstrap","pageToken","refresh","result","mutate","affected","code","fields","history","action","roomVersions"],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { RefreshPage, SelectedRooms, ViewedConversations } from '@agentshouse/mdruntime';
2
+ import type { TrackedAuthority } from './discovery.js';
3
+ import { type HouseDoor } from './transport.js';
4
+ import type { HouseMode } from './transport.js';
5
+ import { type LogPosition } from './version.js';
6
+ export type HouseNotifications = SelectedRooms & {
7
+ track(authorities: readonly TrackedAuthority[]): void;
8
+ advance(tracked: TrackedAuthority, from: LogPosition): RefreshPage | null;
9
+ conversations: ViewedConversations;
10
+ };
11
+ export declare function houseNotifications(transport: HouseDoor, mode: HouseMode): HouseNotifications;
12
+ //# sourceMappingURL=stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,WAAW,EAEX,aAAa,EACb,mBAAmB,EACpB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,EAAqB,KAAK,SAAS,EAA6B,MAAM,gBAAgB,CAAC;AAC9F,OAAO,KAAK,EAAE,SAAS,EAAsC,MAAM,gBAAgB,CAAC;AACpF,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAc7D,MAAM,MAAM,kBAAkB,GAAG,aAAa,GAAG;IAC/C,KAAK,CAAC,WAAW,EAAE,SAAS,gBAAgB,EAAE,GAAG,IAAI,CAAC;IACtD,OAAO,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,WAAW,GAAG,IAAI,CAAC;IAC1E,aAAa,EAAE,mBAAmB,CAAC;CACpC,CAAC;AAaF,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,GAAG,kBAAkB,CA+O5F"}
package/dist/stream.js ADDED
@@ -0,0 +1,298 @@
1
+ import { actionOutcome, HISTORY_PAGE, readConversationHistory } from './actions.js';
2
+ import { selects } from './read.js';
3
+ import { PRIVATE_AUTHORITY } from './transport.js';
4
+ import { roomVersion } from './version.js';
5
+ const HELD_POSITIONS_MAX = 256;
6
+ function position(value) {
7
+ if (!/^(?:0|[1-9][0-9]*)$/.test(value)) return null;
8
+ return BigInt(value);
9
+ }
10
+ function messageTurn(message) {
11
+ if (typeof message !== 'object' || message === null) return null;
12
+ const turn = message.message_id;
13
+ return typeof turn === 'string' ? turn : null;
14
+ }
15
+ export function houseNotifications(transport, mode) {
16
+ const stream = transport.stream;
17
+ const lines = new Map();
18
+ const locators = new Map();
19
+ const authorities = new Map();
20
+ const observers = new Set();
21
+ const conversationObservers = new Set();
22
+ const subscribedConversations = new Set();
23
+ let selected = [];
24
+ let viewed = [];
25
+ let listening = false;
26
+ function subscribe() {
27
+ const named = [];
28
+ const rooms = new Set();
29
+ for (const locator of selected){
30
+ const authority = authorities.get(locator);
31
+ if (authority === undefined || authority === PRIVATE_AUTHORITY) continue;
32
+ rooms.add(authority);
33
+ }
34
+ for (const room of rooms)named.push({
35
+ kind: 'room',
36
+ room
37
+ });
38
+ if (authorities.has(PRIVATE_AUTHORITY)) named.push({
39
+ kind: 'private'
40
+ });
41
+ for (const conversation of viewed){
42
+ named.push({
43
+ kind: 'conversation',
44
+ conversation
45
+ });
46
+ }
47
+ stream.subscribe(named);
48
+ }
49
+ function emitConversation(event) {
50
+ if (!viewed.includes(event.conversation)) return;
51
+ for (const observer of conversationObservers)observer(event);
52
+ }
53
+ async function catchUp(conversation, history) {
54
+ const viewedAnswer = await transport.door('/door/conversations/view', {
55
+ conversation_id: conversation
56
+ });
57
+ const summary = actionOutcome(viewedAnswer, 'conversations/view');
58
+ if (summary.kind === 'action' && typeof summary.result === 'object' && summary.result !== null) {
59
+ emitConversation({
60
+ kind: 'session-summary',
61
+ conversation,
62
+ summary: structuredClone('session' in summary.result ? summary.result.session : null)
63
+ });
64
+ }
65
+ if (!history) return;
66
+ const heldHistory = await readConversationHistory(transport, conversation);
67
+ if ('outcome' in heldHistory) return;
68
+ const newest = heldHistory.messages.slice(-HISTORY_PAGE);
69
+ for (const entry of newest){
70
+ const turn = messageTurn(entry);
71
+ if (turn === null) return;
72
+ emitConversation({
73
+ kind: 'accepted-message',
74
+ conversation,
75
+ message: {
76
+ turn,
77
+ message: structuredClone(entry)
78
+ }
79
+ });
80
+ }
81
+ }
82
+ function announce(authority, at) {
83
+ const version = roomVersion(at);
84
+ for (const locator of locators.get(authority) ?? []){
85
+ for (const observer of observers)observer({
86
+ locator,
87
+ roomVersion: version
88
+ });
89
+ }
90
+ }
91
+ function interrupt(authority) {
92
+ const line = lines.get(authority);
93
+ if (line !== undefined) lines.set(authority, {
94
+ logEpoch: line.logEpoch,
95
+ frames: []
96
+ });
97
+ }
98
+ function resubscribed(authority, position, logEpoch) {
99
+ if (position === undefined || logEpoch === undefined) {
100
+ interrupt(authority);
101
+ return;
102
+ }
103
+ const held = lines.get(authority)?.logEpoch;
104
+ lines.set(authority, {
105
+ logEpoch,
106
+ frames: []
107
+ });
108
+ if (held !== logEpoch) announce(authority, {
109
+ position,
110
+ logEpoch
111
+ });
112
+ }
113
+ function receive(frame) {
114
+ if (frame.type === 'draft') {
115
+ emitConversation({
116
+ kind: 'growing-text',
117
+ conversation: frame.conversation_id,
118
+ turn: frame.turn_id,
119
+ text: frame.text
120
+ });
121
+ return;
122
+ }
123
+ if (frame.type === 'message') {
124
+ const turn = messageTurn(frame.message);
125
+ if (turn === null) return;
126
+ emitConversation({
127
+ kind: 'accepted-message',
128
+ conversation: frame.conversation_id,
129
+ message: {
130
+ turn,
131
+ message: structuredClone(frame.message)
132
+ }
133
+ });
134
+ return;
135
+ }
136
+ if (frame.type === 'session') {
137
+ emitConversation({
138
+ kind: 'session-summary',
139
+ conversation: frame.conversation_id,
140
+ summary: structuredClone(frame.summary)
141
+ });
142
+ return;
143
+ }
144
+ if (frame.type === 'subscribed' && viewed.includes(frame.authority)) {
145
+ const reconnect = subscribedConversations.has(frame.authority);
146
+ subscribedConversations.add(frame.authority);
147
+ void catchUp(frame.authority, reconnect);
148
+ return;
149
+ }
150
+ if (frame.type === 'subscribed') {
151
+ resubscribed(frame.authority, frame.position, frame.log_epoch);
152
+ return;
153
+ }
154
+ if (frame.type !== 'entries') {
155
+ interrupt(frame.authority);
156
+ return;
157
+ }
158
+ const at = position(frame.position);
159
+ if (at === null) {
160
+ interrupt(frame.authority);
161
+ return;
162
+ }
163
+ const line = lines.get(frame.authority);
164
+ if (line?.logEpoch === frame.log_epoch) {
165
+ const last = line.frames.at(-1);
166
+ const continued = last !== undefined && last.position + 1n === at;
167
+ const next = continued ? [
168
+ ...line.frames,
169
+ {
170
+ position: at,
171
+ entries: frame.entries
172
+ }
173
+ ] : [
174
+ {
175
+ position: at,
176
+ entries: frame.entries
177
+ }
178
+ ];
179
+ lines.set(frame.authority, {
180
+ logEpoch: line.logEpoch,
181
+ frames: next.length > HELD_POSITIONS_MAX ? [] : next
182
+ });
183
+ } else {
184
+ interrupt(frame.authority);
185
+ }
186
+ announce(frame.authority, {
187
+ position: frame.position,
188
+ logEpoch: frame.log_epoch
189
+ });
190
+ }
191
+ return {
192
+ conversations: {
193
+ view (next) {
194
+ const open = new Set(next);
195
+ for (const conversation of subscribedConversations){
196
+ if (!open.has(conversation)) subscribedConversations.delete(conversation);
197
+ }
198
+ viewed = [
199
+ ...next
200
+ ];
201
+ subscribe();
202
+ },
203
+ observe (notify) {
204
+ conversationObservers.add(notify);
205
+ if (!listening) {
206
+ listening = true;
207
+ stream.observe(receive);
208
+ }
209
+ return ()=>{
210
+ conversationObservers.delete(notify);
211
+ };
212
+ }
213
+ },
214
+ track (entries) {
215
+ locators.clear();
216
+ authorities.clear();
217
+ for (const entry of entries){
218
+ locators.set(entry.authority, [
219
+ ...locators.get(entry.authority) ?? [],
220
+ entry.locator
221
+ ]);
222
+ authorities.set(entry.locator, entry.authority);
223
+ if (lines.get(entry.authority)?.logEpoch !== entry.logEpoch) {
224
+ lines.set(entry.authority, {
225
+ logEpoch: entry.logEpoch,
226
+ frames: []
227
+ });
228
+ }
229
+ }
230
+ for (const authority of lines.keys()){
231
+ if (!locators.has(authority)) lines.delete(authority);
232
+ }
233
+ },
234
+ select (named) {
235
+ selected = [
236
+ ...named
237
+ ];
238
+ subscribe();
239
+ },
240
+ observe (notify) {
241
+ observers.add(notify);
242
+ if (!listening) {
243
+ listening = true;
244
+ stream.observe(receive);
245
+ }
246
+ return ()=>{
247
+ observers.delete(notify);
248
+ };
249
+ },
250
+ advance (tracked, from) {
251
+ const line = lines.get(tracked.authority);
252
+ const start = position(from.position);
253
+ if (line === undefined || start === null || line.logEpoch !== from.logEpoch) return null;
254
+ const at = line.frames.findIndex((frame)=>frame.position === start + 1n);
255
+ if (at === -1) return null;
256
+ const pending = line.frames.slice(at);
257
+ const documents = {};
258
+ const revisions = {};
259
+ const removals = [];
260
+ for (const frame of pending){
261
+ for (const entry of frame.entries){
262
+ if (!selects(tracked, entry.path)) continue;
263
+ if (entry.kind === 'removed') {
264
+ delete documents[entry.path];
265
+ delete revisions[entry.path];
266
+ if (!removals.includes(entry.path)) removals.push(entry.path);
267
+ continue;
268
+ }
269
+ if (entry.text === undefined) return null;
270
+ if (mode === 'credential' && entry.revision === undefined) return null;
271
+ documents[entry.path] = entry.text;
272
+ if (entry.revision !== undefined) revisions[entry.path] = entry.revision;
273
+ const removed = removals.indexOf(entry.path);
274
+ if (removed !== -1) removals.splice(removed, 1);
275
+ }
276
+ }
277
+ const last = pending.at(-1);
278
+ if (last === undefined) return null;
279
+ lines.set(tracked.authority, {
280
+ logEpoch: line.logEpoch,
281
+ frames: pending
282
+ });
283
+ return {
284
+ kind: 'net-advancement',
285
+ roomVersion: roomVersion({
286
+ position: last.position.toString(),
287
+ logEpoch: line.logEpoch
288
+ }),
289
+ documents,
290
+ revisions,
291
+ binaryTargets: [],
292
+ removals: removals.sort()
293
+ };
294
+ }
295
+ };
296
+ }
297
+
298
+ //# sourceMappingURL=stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/workspace/packages/mdruntime-adapter/src/stream.ts"],"sourcesContent":["import type {\n ConversationEvent,\n RefreshPage,\n RoomVersionNotification,\n SelectedRooms,\n ViewedConversations,\n} from '@agentshouse/mdruntime';\nimport { actionOutcome, HISTORY_PAGE, readConversationHistory } from './actions.js';\nimport type { TrackedAuthority } from './discovery.js';\nimport { selects } from './read.js';\nimport { PRIVATE_AUTHORITY, type HouseDoor, type HouseStreamAuthority } from './transport.js';\nimport type { HouseMode, HouseStreamEntry, HouseStreamFrame } from './transport.js';\nimport { roomVersion, type LogPosition } from './version.js';\n\nconst HELD_POSITIONS_MAX = 256;\n\ntype HeldFrame = {\n position: bigint;\n entries: readonly HouseStreamEntry[];\n};\n\ntype HeldLine = {\n logEpoch: string;\n frames: readonly HeldFrame[];\n};\n\nexport type HouseNotifications = SelectedRooms & {\n track(authorities: readonly TrackedAuthority[]): void;\n advance(tracked: TrackedAuthority, from: LogPosition): RefreshPage | null;\n conversations: ViewedConversations;\n};\n\nfunction position(value: string): bigint | null {\n if (!/^(?:0|[1-9][0-9]*)$/.test(value)) return null;\n return BigInt(value);\n}\n\nfunction messageTurn(message: unknown): string | null {\n if (typeof message !== 'object' || message === null) return null;\n const turn = (message as { message_id?: unknown }).message_id;\n return typeof turn === 'string' ? turn : null;\n}\n\nexport function houseNotifications(transport: HouseDoor, mode: HouseMode): HouseNotifications {\n const stream = transport.stream;\n const lines = new Map<string, HeldLine>();\n const locators = new Map<string, string[]>();\n const authorities = new Map<string, string>();\n const observers = new Set<(notification: RoomVersionNotification) => void>();\n const conversationObservers = new Set<(event: ConversationEvent) => void>();\n const subscribedConversations = new Set<string>();\n let selected: readonly string[] = [];\n let viewed: readonly string[] = [];\n let listening = false;\n\n function subscribe() {\n const named: HouseStreamAuthority[] = [];\n const rooms = new Set<string>();\n for (const locator of selected) {\n const authority = authorities.get(locator);\n if (authority === undefined || authority === PRIVATE_AUTHORITY) continue;\n rooms.add(authority);\n }\n for (const room of rooms) named.push({ kind: 'room', room });\n if (authorities.has(PRIVATE_AUTHORITY)) named.push({ kind: 'private' });\n for (const conversation of viewed) {\n named.push({ kind: 'conversation', conversation });\n }\n stream.subscribe(named);\n }\n\n function emitConversation(event: ConversationEvent) {\n if (!viewed.includes(event.conversation)) return;\n for (const observer of conversationObservers) observer(event);\n }\n\n async function catchUp(conversation: string, history: boolean) {\n const viewedAnswer = await transport.door('/door/conversations/view', {\n conversation_id: conversation,\n });\n const summary = actionOutcome(viewedAnswer, 'conversations/view');\n if (\n summary.kind === 'action' &&\n typeof summary.result === 'object' &&\n summary.result !== null\n ) {\n emitConversation({\n kind: 'session-summary',\n conversation,\n summary: structuredClone('session' in summary.result ? summary.result.session : null),\n });\n }\n if (!history) return;\n const heldHistory = await readConversationHistory(transport, conversation);\n if ('outcome' in heldHistory) return;\n const newest = heldHistory.messages.slice(-HISTORY_PAGE);\n for (const entry of newest) {\n const turn = messageTurn(entry);\n if (turn === null) return;\n emitConversation({\n kind: 'accepted-message',\n conversation,\n message: { turn, message: structuredClone(entry) },\n });\n }\n }\n\n function announce(authority: string, at: LogPosition) {\n const version = roomVersion(at);\n for (const locator of locators.get(authority) ?? []) {\n for (const observer of observers) observer({ locator, roomVersion: version });\n }\n }\n\n function interrupt(authority: string) {\n const line = lines.get(authority);\n if (line !== undefined) lines.set(authority, { logEpoch: line.logEpoch, frames: [] });\n }\n\n function resubscribed(authority: string, position?: string, logEpoch?: string) {\n if (position === undefined || logEpoch === undefined) {\n interrupt(authority);\n return;\n }\n const held = lines.get(authority)?.logEpoch;\n lines.set(authority, { logEpoch, frames: [] });\n if (held !== logEpoch) announce(authority, { position, logEpoch });\n }\n\n function receive(frame: HouseStreamFrame) {\n if (frame.type === 'draft') {\n emitConversation({\n kind: 'growing-text',\n conversation: frame.conversation_id,\n turn: frame.turn_id,\n text: frame.text,\n });\n return;\n }\n if (frame.type === 'message') {\n const turn = messageTurn(frame.message);\n if (turn === null) return;\n emitConversation({\n kind: 'accepted-message',\n conversation: frame.conversation_id,\n message: { turn, message: structuredClone(frame.message) },\n });\n return;\n }\n if (frame.type === 'session') {\n emitConversation({\n kind: 'session-summary',\n conversation: frame.conversation_id,\n summary: structuredClone(frame.summary),\n });\n return;\n }\n if (frame.type === 'subscribed' && viewed.includes(frame.authority)) {\n const reconnect = subscribedConversations.has(frame.authority);\n subscribedConversations.add(frame.authority);\n void catchUp(frame.authority, reconnect);\n return;\n }\n if (frame.type === 'subscribed') {\n resubscribed(frame.authority, frame.position, frame.log_epoch);\n return;\n }\n if (frame.type !== 'entries') {\n interrupt(frame.authority);\n return;\n }\n const at = position(frame.position);\n if (at === null) {\n interrupt(frame.authority);\n return;\n }\n const line = lines.get(frame.authority);\n if (line?.logEpoch === frame.log_epoch) {\n const last = line.frames.at(-1);\n const continued = last !== undefined && last.position + 1n === at;\n const next = continued\n ? [...line.frames, { position: at, entries: frame.entries }]\n : [{ position: at, entries: frame.entries }];\n lines.set(frame.authority, {\n logEpoch: line.logEpoch,\n frames: next.length > HELD_POSITIONS_MAX ? [] : next,\n });\n } else {\n interrupt(frame.authority);\n }\n announce(frame.authority, { position: frame.position, logEpoch: frame.log_epoch });\n }\n\n return {\n conversations: {\n view(next) {\n const open = new Set(next);\n for (const conversation of subscribedConversations) {\n if (!open.has(conversation)) subscribedConversations.delete(conversation);\n }\n viewed = [...next];\n subscribe();\n },\n observe(notify) {\n conversationObservers.add(notify);\n if (!listening) {\n listening = true;\n stream.observe(receive);\n }\n return () => {\n conversationObservers.delete(notify);\n };\n },\n },\n track(entries) {\n locators.clear();\n authorities.clear();\n for (const entry of entries) {\n locators.set(entry.authority, [...(locators.get(entry.authority) ?? []), entry.locator]);\n authorities.set(entry.locator, entry.authority);\n if (lines.get(entry.authority)?.logEpoch !== entry.logEpoch) {\n lines.set(entry.authority, { logEpoch: entry.logEpoch, frames: [] });\n }\n }\n for (const authority of lines.keys()) {\n if (!locators.has(authority)) lines.delete(authority);\n }\n },\n select(named) {\n selected = [...named];\n subscribe();\n },\n observe(notify) {\n observers.add(notify);\n if (!listening) {\n listening = true;\n stream.observe(receive);\n }\n return () => {\n observers.delete(notify);\n };\n },\n advance(tracked, from) {\n const line = lines.get(tracked.authority);\n const start = position(from.position);\n if (line === undefined || start === null || line.logEpoch !== from.logEpoch) return null;\n const at = line.frames.findIndex((frame) => frame.position === start + 1n);\n if (at === -1) return null;\n const pending = line.frames.slice(at);\n const documents: Record<string, string> = {};\n const revisions: Record<string, string> = {};\n const removals: string[] = [];\n for (const frame of pending) {\n for (const entry of frame.entries) {\n if (!selects(tracked, entry.path)) continue;\n if (entry.kind === 'removed') {\n delete documents[entry.path];\n delete revisions[entry.path];\n if (!removals.includes(entry.path)) removals.push(entry.path);\n continue;\n }\n if (entry.text === undefined) return null;\n if (mode === 'credential' && entry.revision === undefined) return null;\n documents[entry.path] = entry.text;\n if (entry.revision !== undefined) revisions[entry.path] = entry.revision;\n const removed = removals.indexOf(entry.path);\n if (removed !== -1) removals.splice(removed, 1);\n }\n }\n const last = pending.at(-1);\n if (last === undefined) return null;\n lines.set(tracked.authority, { logEpoch: line.logEpoch, frames: pending });\n return {\n kind: 'net-advancement',\n roomVersion: roomVersion({ position: last.position.toString(), logEpoch: line.logEpoch }),\n documents,\n revisions,\n binaryTargets: [],\n removals: removals.sort(),\n };\n },\n };\n}\n"],"names":["actionOutcome","HISTORY_PAGE","readConversationHistory","selects","PRIVATE_AUTHORITY","roomVersion","HELD_POSITIONS_MAX","position","value","test","BigInt","messageTurn","message","turn","message_id","houseNotifications","transport","mode","stream","lines","Map","locators","authorities","observers","Set","conversationObservers","subscribedConversations","selected","viewed","listening","subscribe","named","rooms","locator","authority","get","undefined","add","room","push","kind","has","conversation","emitConversation","event","includes","observer","catchUp","history","viewedAnswer","door","conversation_id","summary","result","structuredClone","session","heldHistory","newest","messages","slice","entry","announce","at","version","interrupt","line","set","logEpoch","frames","resubscribed","held","receive","frame","type","turn_id","text","reconnect","log_epoch","last","continued","next","entries","length","conversations","view","open","delete","observe","notify","track","clear","keys","select","advance","tracked","from","start","findIndex","pending","documents","revisions","removals","path","revision","removed","indexOf","splice","toString","binaryTargets","sort"],"mappings":"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"}