@agentshouse/app-bridge 0.1.0-c4999e714a13d → 0.1.0-c4e2f96a8f06c

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/README.md CHANGED
@@ -3,16 +3,16 @@
3
3
  The types of the agents.house App bridge, an accessor and an in-page test host.
4
4
  House builds the bridge object in every App it serves and hands it to the page
5
5
  before the App's own scripts run; `houseBridge()` returns that object, so an App
6
- carries no bridge code of its own. It carries eleven families: navigation,
6
+ carries no bridge code of its own. It carries twelve families: navigation,
7
7
  ceremonies, installation, notifications, status, Site image reads, App release
8
- code, external calls, App messages and App and Site screenshot reads.
8
+ code, external calls, App messages, App and Site screenshot reads and the Chat.
9
9
  [docs/families.md](docs/families.md) describes each and the test host.
10
10
 
11
11
  The bridge carries no credential handling and no Runtime family. House builds
12
- the MD Runtime client into the page beside the bridge, and `bridge.runtime`
13
- resolves to that client, so the App imports and constructs none.
12
+ the MD Runtime client into the page beside the bridge and serves it the Chat, so
13
+ the App imports, constructs and bundles neither: `bridge.runtime` resolves to the client.
14
14
 
15
- House's `find_command` "App" is the guide to building an App or a Site.
15
+ House's guide to building an App is its Guide's `apps/` pages, which `open_guide` opens.
16
16
 
17
17
  ## Use
18
18
 
package/dist/calls.d.ts CHANGED
@@ -414,48 +414,19 @@ export interface HouseMethods {
414
414
  readonly 'record.list': {
415
415
  readonly params: {
416
416
  readonly room_ref: string;
417
- readonly record?: string;
418
417
  readonly cursor?: string;
419
418
  readonly limit?: number;
420
419
  readonly order?: 'asc' | 'desc';
421
420
  };
422
421
  readonly result: {
423
- readonly attachments: readonly {
424
- readonly bytes: number;
425
- readonly file: string;
426
- readonly media_type: string | null;
427
- readonly name: string | null;
428
- readonly referrer: {
429
- readonly record: string;
430
- readonly room_ref: string;
431
- };
432
- readonly sha256: string;
433
- }[];
434
- readonly body: string | null;
435
- readonly claimed: unknown;
436
- readonly created_at: string;
437
- readonly record: string;
438
- readonly ref: string;
439
- } | {
440
- readonly next_cursor?: string;
441
422
  readonly records: readonly {
442
- readonly attachments: readonly {
443
- readonly bytes: number;
444
- readonly file: string;
445
- readonly media_type: string | null;
446
- readonly name: string | null;
447
- readonly referrer: {
448
- readonly record: string;
449
- readonly room_ref: string;
450
- };
451
- readonly sha256: string;
452
- }[];
453
- readonly body: string | null;
454
- readonly claimed: unknown;
455
- readonly created_at: string;
456
423
  readonly record: string;
457
424
  readonly ref: string;
425
+ readonly created_at: string;
426
+ readonly body: string | null;
427
+ readonly claimed: unknown;
458
428
  }[];
429
+ readonly next_cursor?: string;
459
430
  };
460
431
  };
461
432
  readonly 'relay.read': {
@@ -957,6 +928,7 @@ export interface HouseMethods {
957
928
  } | {
958
929
  readonly position: number;
959
930
  readonly outcome: 'no_target';
931
+ readonly code: 'no_recipient' | 'routine_access_not_found' | 'routine_retired' | 'target_agent_unavailable';
960
932
  } | {
961
933
  readonly position: number;
962
934
  readonly outcome: 'requested';
@@ -1006,19 +978,21 @@ export interface HouseMethods {
1006
978
  readonly position: number;
1007
979
  readonly outcome: 'refused';
1008
980
  readonly code: 'cap_reached';
1009
- readonly cap: 'address_submissions' | 'writes' | 'push_addresses' | 'push_deliveries' | 'external_accounts' | 'shared_schemas' | 'export_starts' | 'share_creations' | 'share_room_creations' | 'live_shares' | 'ownership_offers' | 'site_rooms' | 'slot_rooms' | 'room_triggers' | 'app_sockets' | 'kit_connections' | 'open_uploads' | 'waiting_web_wizards';
981
+ readonly cap: 'address_submissions' | 'writes' | 'push_addresses' | 'push_deliveries' | 'external_accounts' | 'shared_schemas' | 'export_starts' | 'share_creations' | 'share_room_creations' | 'live_shares' | 'ownership_offers' | 'site_rooms' | 'slot_rooms' | 'room_triggers' | 'app_sockets' | 'kit_connections' | 'open_uploads' | 'waiting_web_wizards' | 'folder_subscriptions';
1010
982
  } | {
1011
983
  readonly position: number;
1012
984
  readonly outcome: 'refused';
1013
985
  readonly code: 'cap_reached';
1014
- readonly cap: 'address_submissions' | 'writes' | 'push_addresses' | 'push_deliveries' | 'external_accounts' | 'shared_schemas' | 'export_starts' | 'share_creations' | 'share_room_creations' | 'live_shares' | 'ownership_offers' | 'site_rooms' | 'slot_rooms' | 'room_triggers' | 'app_sockets' | 'kit_connections' | 'open_uploads' | 'waiting_web_wizards';
986
+ readonly cap: 'address_submissions' | 'writes' | 'push_addresses' | 'push_deliveries' | 'external_accounts' | 'shared_schemas' | 'export_starts' | 'share_creations' | 'share_room_creations' | 'live_shares' | 'ownership_offers' | 'site_rooms' | 'slot_rooms' | 'room_triggers' | 'app_sockets' | 'kit_connections' | 'open_uploads' | 'waiting_web_wizards' | 'folder_subscriptions';
1015
987
  readonly retry_at: string;
1016
988
  } | {
1017
989
  readonly position: number;
1018
990
  readonly outcome: 'withdrawn';
991
+ readonly code: 'agent_unavailable';
1019
992
  } | {
1020
993
  readonly position: number;
1021
994
  readonly outcome: 'failed';
995
+ readonly code: 'internal_error' | 'routine_request_not_started';
1022
996
  } | {
1023
997
  readonly position: number;
1024
998
  readonly outcome: 'waiting';
package/dist/index.d.ts CHANGED
@@ -134,8 +134,29 @@ export interface HouseCooperation {
134
134
  ready(): Promise<boolean> | boolean;
135
135
  settle(activation: HouseActivation): void;
136
136
  }
137
+ export type HouseChatWidth = 'full' | '3/4' | '1/2' | '1/3';
138
+ export interface HouseChatOpened {
139
+ readonly conversation: string | null;
140
+ readonly agent: string | null;
141
+ }
142
+ export interface HouseChatOptions {
143
+ readonly conversation?: string | null;
144
+ readonly agent?: string | null;
145
+ readonly showChats?: boolean;
146
+ readonly width?: HouseChatWidth;
147
+ readonly onOpen?: (opened: HouseChatOpened) => void;
148
+ readonly onLink?: (href: string) => void;
149
+ }
150
+ export interface HouseMountedChat {
151
+ update(options: HouseChatOptions): void;
152
+ unmount(): void;
153
+ }
154
+ export interface HouseChat {
155
+ mount(element: object, options?: HouseChatOptions): Promise<HouseMountedChat>;
156
+ }
137
157
  export interface HouseBridge {
138
158
  readonly runtime: Promise<HouseRuntime>;
159
+ readonly chat: HouseChat;
139
160
  address(): string | null;
140
161
  onAddress(listener: (address: string) => void): () => void;
141
162
  push(address: string): Promise<string>;
@@ -121,7 +121,6 @@ export type ItemFacts = {
121
121
  readonly delivery: string;
122
122
  readonly source: string | null;
123
123
  readonly address: string | null;
124
- readonly has_attachment: boolean;
125
124
  readonly container: string | null;
126
125
  readonly author: string | null;
127
126
  readonly headers: Readonly<Record<string, string>>;
@@ -60,6 +60,7 @@ export declare const JSON_TYPES: readonly JsonType[];
60
60
  export declare const BUILT_IN_TYPE = "any";
61
61
  export declare const ATTACHMENT = "attachment";
62
62
  export declare const ARRAY_INDEX: RegExp;
63
+ export declare const JSON_POINTER: RegExp;
63
64
  export declare function escapePointer(key: string): string;
64
65
  export declare function pointerSegments(pointer: string): string[];
65
66
  export declare function refTarget(reference: string, defs: Readonly<Record<string, unknown>>): {
@@ -10,7 +10,7 @@ export type { RoomTarget } from './paths.js';
10
10
  export { MARKDOWN_SYNTAX_PROFILE } from './profile.js';
11
11
  export { project } from './project.js';
12
12
  export { references } from './references.js';
13
- export { ARRAY_INDEX, ATTACHMENT, crossedFacts, escapePointer, itemFacts, memberFacts, pointerFacts, pointerSegments, } from './definition.js';
13
+ export { ARRAY_INDEX, ATTACHMENT, crossedFacts, escapePointer, itemFacts, JSON_POINTER, memberFacts, pointerFacts, pointerSegments, } from './definition.js';
14
14
  export type { Definition, FieldRules, JsonType, PatternFacts, PointerFacts, RuleValue, SectionSpec, Shape, Transition, ValueFacts, } from './definition.js';
15
15
  export type { ApplyResult, BodyResult, Change, Division, DivisionContext, Document, DocumentCheck, Frontmatter, FrontmatterResult, Library, ModelVerification, Link, ParseResult, Projection, ProjectionContext, Reached, Reference, Refusal, RoomReference, Span, Validation, ValidationContext, ValidationStep, VerifiedModel, } from './types.js';
16
16
  export { assess, bodyRoomLinks, checkDocument, resolves, roomReferences, sectionReferences, validate, validating, verdicts, verify, } from './validate.js';
@@ -2,6 +2,7 @@ import type { Definition } from './definition.js';
2
2
  export type Library = Readonly<Record<string, string>>;
3
3
  export type VerifiedModel = {
4
4
  readonly types: Readonly<Record<string, Definition>>;
5
+ readonly nameable?: readonly string[];
5
6
  };
6
7
  export type ModelVerification = {
7
8
  readonly verdict: 'accept';
@@ -269,7 +269,6 @@ export type HeadChange = {
269
269
  time: string;
270
270
  };
271
271
  export type BinaryFile = {
272
- fileRef: string;
273
272
  byteLength: number;
274
273
  mediaType: string;
275
274
  sha256: string;
@@ -290,10 +289,15 @@ export type BootstrapRequest = {
290
289
  selection: string;
291
290
  pageToken?: PageToken;
292
291
  held?: HeldContent;
292
+ received?: Uint8Array;
293
+ arriving?: (bytes: number) => void;
294
+ };
295
+ export type BootstrapInventory = {
296
+ readonly parts: number;
297
+ readonly bytes: number;
293
298
  };
294
299
  export type RoomModels = {
295
300
  collection?: ModelResult;
296
- selection?: ModelResult;
297
301
  };
298
302
  export type BootstrapPage = {
299
303
  kind: 'bootstrap';
@@ -306,6 +310,8 @@ export type BootstrapPage = {
306
310
  binaryFiles: Readonly<Record<string, BinaryFile>>;
307
311
  folders?: readonly string[];
308
312
  pageToken?: PageToken;
313
+ inventory?: BootstrapInventory;
314
+ received?: Uint8Array;
309
315
  };
310
316
  export type BootstrapResult = BootstrapPage | {
311
317
  kind: 'beyond-horizon';
@@ -412,15 +418,6 @@ export type BinaryRequest = {
412
418
  locator: string;
413
419
  path: string;
414
420
  revision: string;
415
- fileRef?: string;
416
- } | {
417
- kind: 'reference';
418
- fileRef: string;
419
- referrer: unknown;
420
- };
421
- export type ReferrerScope = {
422
- locator: string;
423
- path?: string;
424
421
  };
425
422
  export type BinaryResult = {
426
423
  kind: 'binary';
@@ -497,6 +494,7 @@ export type Adapter = {
497
494
  readonly localSaves?: true;
498
495
  readonly exhaustiveDiscovery?: true;
499
496
  readonly roomTypes?: string;
497
+ readonly nameableRoomTypes?: readonly string[];
500
498
  authorize(): Promise<Authorization>;
501
499
  discover(authorization: Authorization, scope?: DiscoveryScope): Promise<DiscoverResult>;
502
500
  bootstrap(authorization: Authorization, request: BootstrapRequest): Promise<BootstrapResult>;
@@ -504,10 +502,7 @@ export type Adapter = {
504
502
  mutate(authorization: Authorization, request: MutationRequest, keep: (upload: unknown) => Promise<void>): Promise<MutationResult>;
505
503
  history(authorization: Authorization, request: HistoryRequest): Promise<HistoryResult>;
506
504
  binary(authorization: Authorization, request: BinaryRequest): Promise<BinaryResult>;
507
- link(authorization: Authorization, request: Extract<BinaryRequest, {
508
- kind: 'path';
509
- }>): Promise<BinaryLinkResult>;
510
- referrerScope(referrer: unknown): ReferrerScope | null;
505
+ link(authorization: Authorization, request: BinaryRequest): Promise<BinaryLinkResult>;
511
506
  action(authorization: Authorization, request: ActionRequest): Promise<ActionResult>;
512
507
  reached(locator: string, roomVersion: string, target: string): boolean;
513
508
  follows(locator: string, roomVersion: string, next: string): boolean;
@@ -3,7 +3,6 @@ export type BinaryFileRecord = {
3
3
  readonly state: 'accepted';
4
4
  readonly revision: string;
5
5
  readonly path: string;
6
- readonly fileRef: string;
7
6
  readonly byteLength: number;
8
7
  readonly mediaType: string;
9
8
  readonly sha256: string;
@@ -15,8 +14,4 @@ export type BinaryFileRecord = {
15
14
  readonly mediaType: string;
16
15
  readonly sha256: string;
17
16
  };
18
- export type BinaryReference = {
19
- readonly fileRef: string;
20
- readonly referrer: unknown;
21
- };
22
17
  export declare function binaryRecord(path: string, held: HeldBinary, revision: string | undefined): BinaryFileRecord;
@@ -2,11 +2,6 @@ export type DocumentChange = {
2
2
  readonly locator: string;
3
3
  readonly path: string | null;
4
4
  };
5
- export type MessageChange = {
6
- conversation: string;
7
- identity: string;
8
- text: string | null;
9
- };
10
5
  export type ChangeSet = {
11
6
  documents: readonly DocumentChange[];
12
7
  drafts: readonly {
@@ -16,7 +11,6 @@ export type ChangeSet = {
16
11
  rooms: readonly string[];
17
12
  queues: readonly string[];
18
13
  presentations: readonly string[];
19
- messages: readonly MessageChange[];
20
14
  conversations: readonly string[];
21
15
  };
22
16
  type Changed = {
@@ -27,7 +21,7 @@ type Changed = {
27
21
  presentation?: string;
28
22
  };
29
23
  export declare function changeSet(locator: string, changed?: Changed): ChangeSet;
30
- export declare function conversationChangeSet(messages: readonly MessageChange[], conversations: readonly string[]): ChangeSet;
24
+ export declare function conversationChangeSet(conversations: readonly string[]): ChangeSet;
31
25
  export declare function mergeChangeSets(sets: readonly ChangeSet[]): ChangeSet;
32
26
  export declare function touches(set: ChangeSet, locator: string, path: string): boolean;
33
27
  export {};
@@ -2,7 +2,6 @@ import type { AppRoom, ConnectionRefusal, HistoryQuery, RoomSchemas, SavedParts,
2
2
  import type { Member, ServiceMode } from './adapter.js';
3
3
  import type { ChatDraft, ConversationAgent, ConversationEntry, ConversationOptions, ConversationView } from './conversation.js';
4
4
  import { type Observation } from './observation.js';
5
- import type { BinaryReference } from './binary.js';
6
5
  import type { ChosenFile } from './file.js';
7
6
  import type { BinaryAnswer, BinaryLinkAnswer, CallResult, HistoryAnswer, Offline, QueueEntry, Resolution } from './outcome.js';
8
7
  import type { DocumentQuery, DocumentResult, GroupQuery, GroupResult, PendingResult } from './query.js';
@@ -22,7 +21,7 @@ export type MdRuntimeClient = {
22
21
  roomDraft: {
23
22
  list(): Promise<readonly RoomDraft[]>;
24
23
  read(room: string, path: string): Promise<RoomDraft | null>;
25
- write(room: string, path: string, revision: string | null, parts: RoomDraftParts): Promise<RoomDraftWrite>;
24
+ write(room: string, path: string, revision: string | null, parts: RoomDraftParts, next?: string): Promise<RoomDraftWrite>;
26
25
  discard(room: string, path: string, revision: string): Promise<RoomDraftWrite>;
27
26
  };
28
27
  save(room: string, roomDrafts: readonly SavedRoomDraft[]): Promise<SaveResult>;
@@ -54,7 +53,6 @@ export type MdRuntimeClient = {
54
53
  binaryFile: {
55
54
  read(room: string, path: string, revision?: string): Promise<BinaryAnswer>;
56
55
  link(room: string, path: string, revision?: string): Promise<BinaryLinkAnswer>;
57
- readReference(reference: BinaryReference): Promise<BinaryAnswer>;
58
56
  };
59
57
  call(name: string, input: unknown): Promise<CallResult>;
60
58
  reached(locator: string, roomVersion: string, path?: string): Promise<boolean>;
@@ -86,6 +84,7 @@ export type MdRuntimeClient = {
86
84
  export declare function connectMdRuntime(port: RuntimePort): MdRuntimeClient;
87
85
  export declare function inTurn(client: MdRuntimeClient, work: () => Promise<void>): Promise<void>;
88
86
  export { chainedWindows, type WindowAnswer, type WindowChain } from './chain.js';
87
+ export { roomDraftRevision } from './identity.js';
89
88
  export type { Observation } from './observation.js';
90
89
  export type { Open } from './open.js';
91
90
  export { unanswered, type RuntimePort, type WireMember } from './wire.js';
@@ -1,10 +1,15 @@
1
1
  import type { Plan, QueryRows } from './query.js';
2
- import type { Connection } from './tables.js';
2
+ import type { Connection, Value } from './tables.js';
3
3
  export type QueryRoom = {
4
4
  readonly locator: string;
5
5
  readonly key: number;
6
6
  };
7
+ export type Fragment = {
8
+ readonly sql: string;
9
+ readonly bind: readonly Value[];
10
+ };
7
11
  export type QueryAnswer = QueryRows & {
8
12
  readonly more?: string;
9
13
  };
14
+ export declare function selected(connection: Connection, plan: Plan, rooms: readonly QueryRoom[]): Fragment;
10
15
  export declare function answerQuery(connection: Connection, plan: Plan, rooms: readonly QueryRoom[], budget?: number | null): QueryAnswer;
@@ -7,14 +7,13 @@ import { type Adapter, type Authorization, type Member, type ProviderRefusal, ty
7
7
  import { type ChatDraftSurface, type ConversationAgent, type ConversationEntry, type ConversationOptions, type ConversationSurface, type ConversationView } from './conversation.js';
8
8
  import { type WrittenBy } from './change.js';
9
9
  import type { Open } from './open.js';
10
- import { type BinaryReference } from './binary.js';
11
10
  import { type BinaryLinkAnswer, type CallResult, type HeldBinaryAnswer, type HistoryAnswer, type QueueEntry, type Resolution } from './outcome.js';
12
11
  import { type Recovery } from './recovery.js';
13
12
  import { type SaveRefusal } from './save.js';
14
13
  import { type RoomDraft, type RoomDraftParts, type RoomDraftWrite } from './room-draft.js';
15
14
  import { type SyncStatus } from './status.js';
16
15
  import { type RuntimeShell } from './durability.js';
17
- import { type CapacityCause, type CodeAvailability, type Persistence, type Readiness, type SearchObligation } from './readiness.js';
16
+ import { type CodeAvailability, type Persistence, type Readiness, type SearchObligation, type Space } from './readiness.js';
18
17
  import type { RuntimeDatabase } from './tables.js';
19
18
  import { type NarrowedView, type PortReach, type RuntimeView } from './reach.js';
20
19
  export type AppTypedSelection = {
@@ -73,7 +72,7 @@ export type SavedParts = {
73
72
  export type RoomDraftSurface = {
74
73
  list(): Promise<readonly RoomDraft[]>;
75
74
  read(room: string, path: string): Promise<RoomDraft | null>;
76
- write(room: string, path: string, revision: string | null, parts: unknown): Promise<RoomDraftWrite>;
75
+ write(room: string, path: string, revision: string | null, parts: unknown, next?: string): Promise<RoomDraftWrite>;
77
76
  discard(room: string, path: string, revision: string): Promise<RoomDraftWrite>;
78
77
  };
79
78
  export type PresentationSurface = {
@@ -84,7 +83,6 @@ export type PresentationSurface = {
84
83
  export type BinaryFileSurface = {
85
84
  read(room: string, path: string, revision?: string): Promise<HeldBinaryAnswer>;
86
85
  link(room: string, path: string, revision?: string): Promise<BinaryLinkAnswer>;
87
- readReference(reference: BinaryReference): Promise<HeldBinaryAnswer>;
88
86
  part(file: string, part: number): Promise<Uint8Array | null>;
89
87
  };
90
88
  export type HistoryQuery = {
@@ -138,7 +136,7 @@ export type RuntimeTopic = 'rooms' | 'readiness' | 'connection-refusal' | 'stora
138
136
  export type ReadinessPort = {
139
137
  readonly target: string;
140
138
  readonly code: CodeAvailability;
141
- readonly capacity: CapacityCause | null;
139
+ readonly space: Space | null;
142
140
  readonly search: SearchObligation;
143
141
  };
144
142
  export type ComposedRuntime = RuntimeView & {
@@ -146,6 +144,7 @@ export type ComposedRuntime = RuntimeView & {
146
144
  stop(): Promise<void>;
147
145
  lose(locators: readonly string[]): Promise<void>;
148
146
  persisted(answer: Persistence): void;
147
+ shown(onScreen: boolean): void;
149
148
  within(reach: PortReach | null, port: ReadinessPort): NarrowedView;
150
149
  };
151
150
  export declare function composeRuntime(options: MdRuntimeOptions): ComposedRuntime;
@@ -85,6 +85,7 @@ export type ConversationDependencies = {
85
85
  stream(): ConversationStream | undefined;
86
86
  publish(set: ChangeSet): void;
87
87
  online(): boolean;
88
+ full(): boolean;
88
89
  closed(): boolean;
89
90
  unanswered(): void;
90
91
  expired(operation: string): boolean;
@@ -112,5 +113,6 @@ export type ConversationStore = {
112
113
  };
113
114
  export declare function unheldView(conversation: string): ConversationView;
114
115
  export declare const SESSION_STARTED = "Session started";
116
+ export declare const HISTORY_CONVERSATIONS = 64;
115
117
  export declare function newChat(agent: string): string;
116
118
  export declare function createConversationStore(deps: ConversationDependencies): ConversationStore;
@@ -1,15 +1,12 @@
1
1
  import type { Persistence } from './readiness.js';
2
- export type StorageEstimate = {
3
- readonly usage: number;
4
- readonly total: number;
5
- };
6
2
  export type RuntimeShell = {
7
3
  persistence: Persistence;
8
4
  generation: string | null;
5
+ onScreen: boolean;
9
6
  keepGeneration(value: string): void | Promise<void>;
10
7
  dropGeneration(): void | Promise<void>;
11
- estimate?(): Promise<StorageEstimate | null>;
12
8
  cleanUp?(): Promise<number>;
13
9
  };
10
+ export declare function refusedForSpace(error: unknown): boolean;
14
11
  export declare function detectStorageLoss(stored: string | null, reported: string | null): string | null;
15
12
  export declare function nextGeneration(stored: string | null, reported: string | null): string;
@@ -0,0 +1,26 @@
1
+ import { type QueryRoom } from './compile.js';
2
+ import type { Plan } from './query.js';
3
+ import type { HitCursor, SearchWindow } from './search.js';
4
+ import type { Connection } from './tables.js';
5
+ export declare const SEARCH_TABLES: readonly string[];
6
+ export type SearchAsk = {
7
+ readonly text: string;
8
+ readonly limit: number;
9
+ readonly after: readonly [HitCursor, HitCursor] | null;
10
+ readonly total: boolean;
11
+ readonly documents: {
12
+ readonly plan: Plan;
13
+ readonly rooms: readonly QueryRoom[];
14
+ readonly beneath: readonly {
15
+ readonly key: number;
16
+ readonly roots: readonly string[];
17
+ }[];
18
+ } | null;
19
+ readonly conversations: readonly string[];
20
+ };
21
+ export declare function indexDocument(connection: Connection, id: number, path: string, content: string): void;
22
+ export declare function indexMessage(connection: Connection, id: number, text: string): void;
23
+ export declare function unindexDocuments(connection: Connection, ids: Iterable<number>): void;
24
+ export declare function unindexMessages(connection: Connection, ids: Iterable<number>): void;
25
+ export declare function unindexAll(connection: Connection): void;
26
+ export declare function searched(connection: Connection, ask: SearchAsk): SearchWindow;
@@ -0,0 +1,6 @@
1
+ export declare function changeBatchIdentity(at?: number): string;
2
+ export declare function identityTime(identity: string): number;
3
+ export declare function roomDraftRevision(): string;
4
+ export declare function chatDraftRevision(): string;
5
+ export declare function transferIdentity(): string;
6
+ export declare function binaryLocalId(): string;
@@ -0,0 +1,27 @@
1
+ import type { AcceptedMessage } from './adapter.js';
2
+ import type { Connection } from './tables.js';
3
+ export declare const MESSAGE_TABLES: readonly string[];
4
+ export type HeldConversation = {
5
+ readonly conversation: string;
6
+ readonly read: string | null | undefined;
7
+ readonly partial: boolean;
8
+ };
9
+ export type MessageWindow = {
10
+ readonly messages: AcceptedMessage[];
11
+ readonly more: boolean;
12
+ };
13
+ export type ConversationWrite = {
14
+ readonly conversation: string;
15
+ readonly messages: readonly AcceptedMessage[];
16
+ readonly read?: {
17
+ readonly at: string | null;
18
+ readonly partial: boolean;
19
+ };
20
+ };
21
+ export declare function heldConversations(connection: Connection): HeldConversation[];
22
+ export declare function keptMessages(connection: Connection, { conversation, messages, read }: ConversationWrite): null;
23
+ export declare function messageWindow(connection: Connection, conversation: string, limit: number, before: readonly [string, string] | null): MessageWindow;
24
+ export declare function messageCount(connection: Connection, conversation: string): number;
25
+ export declare function turnArrived(connection: Connection, conversation: string, turn: string): boolean;
26
+ export declare function droppedMessages(connection: Connection, conversations: readonly string[]): void;
27
+ export declare function forgottenMessages(connection: Connection): void;
@@ -44,7 +44,6 @@ export declare const UNREADABLE: Refused<'unreadable'>;
44
44
  export declare const LOCKED_UNREADABLE: Refused<'unreadable'>;
45
45
  export declare const ABSENT_TARGET: Refused<'absent'>;
46
46
  export declare function absentBinary(path: string): Refused<'absent'>;
47
- export declare function absentReference(fileRef: string): Refused<'absent'>;
48
47
  export declare function binaryAnswer(result: KeptResult): HeldBinaryAnswer;
49
48
  export declare function binaryLinkAnswer(result: BinaryLinkResult): BinaryLinkAnswer;
50
49
  export declare const ROOM_LOCKED = "room-locked";
@@ -58,6 +58,7 @@ export type Select = 'all' | {
58
58
  backlinks?: true;
59
59
  change?: true;
60
60
  fileId?: true;
61
+ revision?: true;
61
62
  };
62
63
  export type OrderOptions = {
63
64
  nulls?: 'first' | 'last';
@@ -103,6 +104,7 @@ export type QueryDocument = {
103
104
  backlinks?: readonly Backlink[];
104
105
  change?: HeadChange | null;
105
106
  fileId?: string | null;
107
+ revision?: string | null;
106
108
  binaryFile?: BinaryFileRecord;
107
109
  };
108
110
  export type QueryGroup = {
@@ -119,7 +121,7 @@ export type QueryCoverage = {
119
121
  indexes: readonly string[];
120
122
  overlay: readonly string[];
121
123
  };
122
- export type Awaits = Open<'acquisition' | 'preparation' | 'index' | 'unlock'>;
124
+ export type Awaits = Open<'acquisition' | 'preparation' | 'unlock'>;
123
125
  export type PendingRoom = {
124
126
  room: string;
125
127
  awaits: Awaits;
@@ -214,6 +216,7 @@ export type DocumentShape = {
214
216
  backlinks: boolean;
215
217
  change: boolean;
216
218
  fileId: boolean;
219
+ revision: boolean;
217
220
  orderBy: readonly {
218
221
  key: KeyPlan;
219
222
  options: OrderOptions & {
@@ -1,4 +1,3 @@
1
- import type { ReferrerScope } from './adapter.js';
2
1
  import type { MdRuntime, ReadinessPort, RuntimeTopic } from './connection.js';
3
2
  import type { Plan, PlanReach, QueryResult } from './query.js';
4
3
  import type { Readiness } from './readiness.js';
@@ -28,7 +27,6 @@ export type Reachable = RuntimeView & {
28
27
  watchPlan(plan: Plan, deliver: (message: unknown) => void): () => void;
29
28
  search(input: unknown, reach: PortReach | null, locked: readonly string[]): Promise<SearchResult>;
30
29
  watchReadiness(port: ReadinessPort, reach: PortReach | null, deliver: (readiness: Readiness) => void): () => void;
31
- referrerScope(referrer: unknown): ReferrerScope | null;
32
30
  locked(room: string): boolean;
33
31
  lockedRooms(): readonly string[];
34
32
  watchLocks(notify: () => void): () => void;
@@ -1,11 +1,11 @@
1
1
  import type { Open } from './open.js';
2
2
  export type CodeAvailability = Open<'stored' | 'absent'>;
3
- export type RoomPreparation = Open<'complete' | 'acquiring' | 'preparing' | 'indexing' | 'refused' | 'unadmitted'>;
3
+ export type RoomPreparation = Open<'complete' | 'acquiring' | 'preparing' | 'refused' | 'unadmitted'>;
4
4
  export type RoomCoverage = {
5
5
  readonly room: string;
6
6
  readonly state: RoomPreparation;
7
7
  };
8
- export type ConversationCoverage = Open<'complete' | 'acquiring' | 'indexing' | 'undeclared'>;
8
+ export type ConversationCoverage = Open<'complete' | 'acquiring' | 'undeclared'>;
9
9
  export type SearchObligation = Open<'required' | 'unused'>;
10
10
  export type TargetCoverage = {
11
11
  readonly complete: boolean;
@@ -18,17 +18,28 @@ export type Persistence = Open<'granted' | 'denied' | 'unavailable'>;
18
18
  export type Durability = Open<'persistent' | 'best-effort'>;
19
19
  export type ConnectionAvailability = Open<'connected' | 'connecting' | 'unreachable'>;
20
20
  export type HouseOutcome = Open<'open' | 'write-halted' | 'refused'>;
21
- export type CapacityCause = {
22
- readonly cause: Open<'insufficient-space' | 'storage-exceeded'>;
23
- readonly needed: number | null;
24
- readonly available: number | null;
25
- };
21
+ export type Space = Open<'full'>;
26
22
  export type RefusedRoom = {
27
23
  readonly room: string;
24
+ readonly name: string;
28
25
  readonly file: string;
29
26
  readonly rule: string;
30
27
  readonly location: string | null;
31
28
  };
29
+ export type InstallationStep = Open<'listing' | 'downloading' | 'writing' | 'replaying'>;
30
+ export type InstallationPause = Open<'hidden'>;
31
+ export type InstallationAmount = {
32
+ readonly done: number;
33
+ readonly total: number;
34
+ };
35
+ export type Installation = {
36
+ readonly step: InstallationStep | null;
37
+ readonly paused: InstallationPause | null;
38
+ readonly rooms: InstallationAmount;
39
+ readonly parts: InstallationAmount;
40
+ readonly bytes: InstallationAmount;
41
+ readonly received: InstallationAmount;
42
+ };
32
43
  export type ReadinessStatus = Open<'preparing' | 'paused' | 'refused' | 'ready' | 'lost'>;
33
44
  export type Readiness = {
34
45
  readonly status: ReadinessStatus;
@@ -40,7 +51,8 @@ export type Readiness = {
40
51
  readonly persistence: Persistence;
41
52
  readonly connection: ConnectionAvailability;
42
53
  readonly house: HouseOutcome;
43
- readonly capacity: CapacityCause | null;
54
+ readonly space: Space | null;
55
+ readonly installation: Installation;
44
56
  readonly refused: readonly RefusedRoom[];
45
57
  readonly lost: boolean;
46
58
  };
@@ -48,5 +60,4 @@ export type ReadinessFacts = Omit<Readiness, 'status' | 'ready' | 'usable' | 'du
48
60
  readonly coverage: Omit<TargetCoverage, 'complete'>;
49
61
  readonly established: boolean;
50
62
  };
51
- export declare const SETTLED_ROOMS: ReadonlySet<string>;
52
63
  export declare function readinessOf(facts: ReadinessFacts): Readiness;
@@ -1,4 +1,4 @@
1
- import type { MutationResult, OperationScopes, ReplicaAdmission, TypedSelection } from './adapter.js';
1
+ import type { BootstrapInventory, MutationResult, OperationScopes, ReplicaAdmission, TypedSelection } from './adapter.js';
2
2
  import { type ChangeBatch, type Precondition } from './change.js';
3
3
  import { type Collection, type Composition } from './collection.js';
4
4
  import type { ModelState } from './model.js';
@@ -12,10 +12,10 @@ export type ReplicaRecord = {
12
12
  readonly replica: ReplicaAdmission;
13
13
  readonly model: ModelState;
14
14
  readonly typedSelection: TypedSelection | null;
15
- readonly selectionModel: ModelState;
16
15
  readonly providerOwnedPaths: readonly string[];
17
16
  readonly roomVersion: string;
18
17
  readonly transfer: string;
18
+ readonly inventory: BootstrapInventory | null;
19
19
  readonly key: number;
20
20
  };
21
21
  export type HeldReplica = {
@@ -24,6 +24,7 @@ export type HeldReplica = {
24
24
  readonly overlaid: ReadonlySet<string>;
25
25
  readonly count: number;
26
26
  readonly confirmed: number;
27
+ readonly indexed: boolean;
27
28
  };
28
29
  export type VisibleLayer = Layer & {
29
30
  readonly collection: Collection;
@@ -32,7 +33,7 @@ export type Slice = Layer & {
32
33
  readonly written: Readonly<Record<string, string>>;
33
34
  readonly held: ReadonlySet<string>;
34
35
  };
35
- export declare function compositionOf(record: Pick<ReplicaRecord, 'model' | 'typedSelection' | 'selectionModel'>): Composition;
36
+ export declare function compositionOf(record: Pick<ReplicaRecord, 'model' | 'typedSelection'>, builtIn: ModelState): Composition;
36
37
  export declare function sameMembership(record: Pick<ReplicaRecord, 'typedSelection'>, other: Pick<ReplicaRecord, 'typedSelection'>): boolean;
37
38
  export declare function storedRecord(record: ReplicaRecord): string;
38
39
  export declare function slicing(entries: readonly HeldEntry[], paths: Iterable<string>): Generator<number, Slice, void>;
@@ -127,6 +127,7 @@ export type SavedDraft = {
127
127
  readonly parts: HeldParts;
128
128
  };
129
129
  export declare function readParts(value: unknown): RoomDraftParts;
130
+ export declare function gatheredParts(earlier: unknown, later: unknown): unknown;
130
131
  export declare function held(current: HeldParts | undefined, parts: RoomDraftParts, file?: HeldFile): HeldParts;
131
132
  export declare function underneath(parts: HeldParts, path: string, visible: VisibleLayer | undefined): ChangedUnderneath;
132
133
  export declare function heldFile(blob: Blob, base: string | null): Promise<HeldFile>;
@@ -1,5 +1,4 @@
1
1
  import type { ProviderRefusal } from './adapter.js';
2
- import type { ChangeSet } from './change-set.js';
3
2
  import { type CoveredRoom, type Filter, type PendingRoom } from './query.js';
4
3
  import type { Open } from './open.js';
5
4
  export type DocumentPart = Open<'fields' | 'sections' | 'preamble' | 'path'>;
@@ -12,29 +11,32 @@ export type SearchRequest = {
12
11
  after?: string;
13
12
  total?: true;
14
13
  };
14
+ export type MessagePart = Open<'text'>;
15
+ export type Snippet<Part extends string> = {
16
+ part: Part;
17
+ text: string;
18
+ at: readonly [number, number];
19
+ };
15
20
  export type DocumentHit = {
16
21
  room: string;
17
22
  path: string;
18
23
  type: string;
19
24
  score: number;
20
25
  matches: Readonly<Record<string, readonly DocumentPart[]>>;
26
+ snippet?: Snippet<DocumentPart>;
21
27
  };
22
28
  export type MessageHit = {
23
29
  conversation: string;
24
30
  identity: string;
25
31
  score: number;
26
- matches: Readonly<Record<string, readonly Open<'text'>[]>>;
32
+ matches: Readonly<Record<string, readonly MessagePart[]>>;
33
+ snippet?: Snippet<MessagePart>;
27
34
  };
28
35
  export type SearchCoverage = {
29
36
  rooms: readonly CoveredRoom[];
30
37
  conversations: readonly string[];
31
- index: string;
32
38
  overlay: readonly string[];
33
39
  };
34
- export type PendingConversation = {
35
- conversation: string;
36
- awaits: Open<'index'>;
37
- };
38
40
  export type SearchHits = {
39
41
  documents: readonly DocumentHit[];
40
42
  messages: readonly MessageHit[];
@@ -47,7 +49,7 @@ export type SearchWindow = SearchHits & {
47
49
  };
48
50
  };
49
51
  export type SearchPending = SearchHits & {
50
- pending: readonly (PendingRoom | PendingConversation)[];
52
+ pending: readonly PendingRoom[];
51
53
  coverage: SearchCoverage;
52
54
  };
53
55
  export type SearchUndeclared = ProviderRefusal & {
@@ -57,24 +59,7 @@ export type SearchResult = (SearchWindow & {
57
59
  coverage: SearchCoverage;
58
60
  }) | SearchPending | SearchUndeclared;
59
61
  export declare function undeclaredSearch(): SearchUndeclared;
60
- export type SearchedDocument = {
61
- room: string;
62
- path: string;
63
- type: string;
64
- fields: Readonly<Record<string, unknown>>;
65
- preamble: string;
66
- sections: Readonly<Record<string, string>>;
67
- };
68
- export type SearchedMessage = {
69
- conversation: string;
70
- identity: string;
71
- text: string;
72
- };
73
- export type SearchSource = {
74
- room(room: string): AsyncIterable<readonly SearchedDocument[]>;
75
- documents(room: string, paths: readonly string[]): Promise<readonly SearchedDocument[]>;
76
- };
77
- type HitCursor = readonly [number, string, string] | readonly [] | null;
62
+ export type HitCursor = readonly [number, string, string] | readonly [] | null;
78
63
  export type SearchPlan = {
79
64
  text: string;
80
65
  documents: unknown;
@@ -84,21 +69,4 @@ export type SearchPlan = {
84
69
  after: readonly [HitCursor, HitCursor] | null;
85
70
  total: boolean;
86
71
  };
87
- export type SearchIndex = {
88
- generation(): string;
89
- rooms(): ReadonlySet<string>;
90
- conversations(): ReadonlySet<string>;
91
- indexRoom(room: string): Promise<void>;
92
- indexMessages(conversation: string, messages: readonly SearchedMessage[], whole: boolean): void;
93
- forget(rooms: readonly string[]): void;
94
- changed(set: ChangeSet): void;
95
- changes(): number;
96
- caughtUp(): Promise<void>;
97
- search(plan: SearchPlan, documents: readonly {
98
- room: string;
99
- path: string;
100
- }[] | null, conversations: readonly string[], rooms: ReadonlySet<string> | null, selections: ReadonlyMap<string, readonly string[]> | null): SearchWindow;
101
- };
102
72
  export declare function searchPlanOf(input: unknown): SearchPlan;
103
- export declare function createSearchIndex(source: SearchSource): SearchIndex;
104
- export {};
@@ -1,16 +1,18 @@
1
- import type { Capability, Member, ProviderLimit } from './adapter.js';
2
- import type { AcceptedMessage, KeptReceipt } from './adapter.js';
1
+ import type { BootstrapInventory, Capability, KeptReceipt, Member, ProviderLimit } from './adapter.js';
3
2
  import type { ChangeBatch } from './change.js';
4
3
  import type { Composition } from './collection.js';
5
4
  import type { Plan } from './query.js';
6
5
  import type { ReplicaRecord } from './replica.js';
7
- import type { Later } from './turn.js';
8
6
  import type { Submission } from './outcome.js';
9
7
  import type { RoomDraftRecord, SavedDraft } from './room-draft.js';
10
8
  import type { ModelState } from './model.js';
11
- import type { SearchedDocument } from './search.js';
12
- import type { CommittedWrite, CountedRoom, HeldEntry, QueryAnswer, QueryRoom, Referrer, RoomCommit, RuntimeDatabase, StoredEntry, StoredFile, TypedEntry, View, Walked } from './tables.js';
13
- export declare const STORE_SCHEMA = 26;
9
+ import type { SearchWindow } from './search.js';
10
+ import type { CommittedWrite, ConversationWrite, CountedRoom, HeldConversation, HeldEntry, MessageWindow, QueryAnswer, QueryRoom, Referrer, RoomCommit, RuntimeDatabase, SearchAsk, StoredEntry, StoredFile, TypedEntry, View, Walked } from './tables.js';
11
+ export type { ConversationWrite, HeldConversation, MessageWindow } from './tables.js';
12
+ export type TransferWriting = {
13
+ readonly token: string | null;
14
+ readonly written: number;
15
+ };
14
16
  export type TransferRecord = {
15
17
  readonly locator: string;
16
18
  readonly transfer: string;
@@ -18,9 +20,11 @@ export type TransferRecord = {
18
20
  readonly from: string;
19
21
  readonly last: string;
20
22
  readonly pageToken: string | null;
23
+ readonly writing: TransferWriting | null;
24
+ readonly inventory: BootstrapInventory | null;
25
+ readonly done: BootstrapInventory;
21
26
  readonly models: {
22
27
  readonly collection: ModelState;
23
- readonly selection: ModelState;
24
28
  };
25
29
  readonly key: number | null;
26
30
  };
@@ -45,23 +49,6 @@ export type PresentationRecord = {
45
49
  app: string;
46
50
  value: unknown;
47
51
  };
48
- export type HeldConversation = {
49
- conversation: string;
50
- read: string | null | undefined;
51
- partial: boolean;
52
- };
53
- export type MessageWindow = {
54
- messages: AcceptedMessage[];
55
- more: boolean;
56
- };
57
- export type ConversationWrite = {
58
- conversation: string;
59
- messages: readonly AcceptedMessage[];
60
- read?: {
61
- at: string | null;
62
- partial: boolean;
63
- };
64
- };
65
52
  export type ChatSubmission = {
66
53
  readonly operation: string;
67
54
  readonly text: string;
@@ -102,7 +89,7 @@ export type RefreshedPage = StagedPage & {
102
89
  export type Opened = {
103
90
  readonly rooms: ReadonlyMap<string, ReplicaRecord>;
104
91
  readonly transfers: ReadonlyMap<string, TransferRecord>;
105
- readonly unprepared: ReadonlySet<number>;
92
+ readonly unindexed: ReadonlySet<number>;
106
93
  readonly overlaid: ReadonlyMap<number, ReadonlySet<string>>;
107
94
  readonly erasing: boolean;
108
95
  readonly orphans: readonly number[];
@@ -134,11 +121,10 @@ export type RuntimeStore = {
134
121
  readonly revision: string;
135
122
  }[]>;
136
123
  typedWithin(key: number, view: View, roots: readonly string[], within: boolean): Promise<boolean>;
137
- searched(key: number, locator: string, after: string | null, limit: number, paths: readonly string[] | null): Promise<{
138
- readonly documents: readonly SearchedDocument[];
139
- readonly next: string | null;
140
- }>;
141
- stage(record: TransferRecord, composition: Composition, page: StagedPage, key: number | null, last: boolean): Promise<number | null>;
124
+ search(ask: SearchAsk): Promise<SearchWindow>;
125
+ stage(record: TransferRecord, composition: Composition, page: StagedPage, written?: string): Promise<number | null>;
126
+ transferPart(locator: string, token: string): Promise<Uint8Array | null>;
127
+ keepPart(locator: string, token: string, part: Uint8Array): Promise<void>;
142
128
  refresh(key: number, page: RefreshedPage): Promise<void>;
143
129
  unrefresh(key: number): Promise<void>;
144
130
  commit(commit: Commit): Promise<CommittedWrite>;
@@ -157,8 +143,6 @@ export type RuntimeStore = {
157
143
  keepMessages(write: ConversationWrite): Promise<void>;
158
144
  messageWindow(conversation: string, limit: number, before: readonly [string, string] | null): Promise<MessageWindow>;
159
145
  messageCount(conversation: string): Promise<number>;
160
- messagesAfter(conversation: string, identity: string | null): Promise<AcceptedMessage[]>;
161
- messageIdentities(conversation: string): Promise<readonly string[]>;
162
146
  turnArrived(conversation: string, turn: string): Promise<boolean>;
163
147
  dropConversations(conversations: readonly string[]): Promise<void>;
164
148
  chatDrafts(): Promise<readonly ChatDraftRecord[]>;
@@ -180,9 +164,5 @@ export type RuntimeStore = {
180
164
  generation(): Promise<string | null>;
181
165
  rememberGeneration(value: string): Promise<void>;
182
166
  file(key: string, type: string): Promise<Blob>;
183
- close(): void;
184
167
  };
185
- export declare function transacted<T>(database: IDBDatabase, stores: string | readonly string[], mode: IDBTransactionMode, work: (transaction: IDBTransaction) => Later<T>): Promise<T>;
186
- export declare function endRuntimeStore(database: RuntimeDatabase, holder: string | undefined): Promise<boolean>;
187
- export declare function openDatabase(name: string, version: number, upgrade: (opening: IDBOpenDBRequest, oldVersion: number) => void): Promise<IDBDatabase>;
188
- export declare function openRuntimeStore(fenced: (locator: string) => boolean, authored: RuntimeDatabase): Promise<RuntimeStore>;
168
+ export declare function openRuntimeStore(fenced: (locator: string) => boolean, authored: RuntimeDatabase): RuntimeStore;
@@ -1,7 +1,6 @@
1
1
  import type { HeadChange } from './adapter.js';
2
2
  import type { Composition } from './collection.js';
3
3
  import type { HeldBinary } from './overlay.js';
4
- import type { SearchedDocument } from './search.js';
5
4
  import type { Connection } from './tables.js';
6
5
  export declare const REPLICA_TABLES: readonly string[];
7
6
  export type View = 'confirmed' | 'visible' | 'refreshed';
@@ -85,7 +84,7 @@ export type RoomCommit = {
85
84
  export type Committed = {
86
85
  readonly counts: Readonly<Record<string, number>>;
87
86
  readonly changed: Readonly<Record<string, readonly string[] | null>>;
88
- readonly prepared: Readonly<Record<string, boolean>>;
87
+ readonly indexed: Readonly<Record<string, boolean>>;
89
88
  };
90
89
  export type CountedRoom = {
91
90
  readonly key: number;
@@ -100,11 +99,12 @@ export declare function entered(connection: Connection, locator: string, composi
100
99
  export declare function stage(connection: Connection, request: {
101
100
  readonly locator: string;
102
101
  readonly transfer: string;
103
- readonly record: string | null;
102
+ readonly record: string;
104
103
  readonly key: number | null;
105
104
  readonly composition: Composition;
106
105
  readonly entries: readonly StoredEntry[];
107
106
  readonly folders: readonly string[];
107
+ readonly written?: string;
108
108
  }): number;
109
109
  export declare function refreshing(connection: Connection, request: {
110
110
  readonly key: number;
@@ -134,9 +134,11 @@ export declare function files(connection: Connection, key: number, view: View, a
134
134
  readonly revision: string;
135
135
  }[];
136
136
  export declare function typedWithin(connection: Connection, key: number, view: View, roots: readonly string[], within: boolean): boolean;
137
- export declare function searched(connection: Connection, key: number, locator: string, after: string | null, limit: number, only: readonly string[] | null): {
138
- readonly documents: readonly SearchedDocument[];
139
- readonly next: string | null;
140
- };
137
+ export declare function transferPart(connection: Connection, locator: string, token: string): Uint8Array | null;
138
+ export declare function keepPart(connection: Connection, request: {
139
+ readonly locator: string;
140
+ readonly token: string;
141
+ readonly part: Uint8Array;
142
+ }): null;
141
143
  export declare function opened(connection: Connection): ReplicaOpened;
142
144
  export declare function ended(connection: Connection): void;
@@ -1,11 +1,15 @@
1
1
  import { type QueryAnswer, type QueryRoom } from './compile.js';
2
2
  import type { KeptReceipt } from './adapter.js';
3
3
  import type { Composition } from './collection.js';
4
+ import { type SearchAsk } from './fulltext.js';
5
+ import { type ConversationWrite, type HeldConversation, type MessageWindow } from './messages.js';
4
6
  import type { Plan } from './query.js';
5
- import type { SearchedDocument } from './search.js';
7
+ import type { SearchWindow } from './search.js';
6
8
  import { type Committed, type CountedRoom, type HeldEntry, type ReplicaOpened, type Referrer, type RoomCommit, type StoredEntry, type TypedEntry, type View, type Walked } from './stored.js';
7
9
  export type { Committed, CountedRoom, HeldEntry, OverlayEntry, ReplicaOpened, Referrer, RoomCommit, StoredEntry, TypedEntry, View, Walked, } from './stored.js';
8
10
  export type { QueryAnswer, QueryRoom } from './compile.js';
11
+ export type { SearchAsk } from './fulltext.js';
12
+ export type { ConversationWrite, HeldConversation, MessageWindow } from './messages.js';
9
13
  export type Value = string | number | bigint | Uint8Array | null;
10
14
  export type Row = Readonly<Record<string, Value>>;
11
15
  export interface Connection {
@@ -22,6 +26,15 @@ export interface SqliteEngine {
22
26
  heap8u(): Uint8Array;
23
27
  };
24
28
  }
29
+ export interface SqliteStatement {
30
+ readonly parameterCount: number;
31
+ bind(values: readonly Value[]): unknown;
32
+ step(): boolean;
33
+ get(values: Value[]): Value[];
34
+ getColumnNames(names: string[]): string[];
35
+ resetNoThrow(clearBindings: boolean): number;
36
+ finalize(): unknown;
37
+ }
25
38
  export interface SqliteDatabase {
26
39
  readonly pointer: number;
27
40
  exec(options: {
@@ -30,6 +43,7 @@ export interface SqliteDatabase {
30
43
  readonly rowMode?: 'object';
31
44
  readonly returnValue?: 'resultRows';
32
45
  }): Row[];
46
+ prepare(sql: string): SqliteStatement;
33
47
  }
34
48
  export declare function sqliteConnection(engine: SqliteEngine, database: SqliteDatabase): Connection;
35
49
  export declare const FILE_PART_BYTES = 1048576;
@@ -43,6 +57,7 @@ export interface FileSpool {
43
57
  held(): Iterable<string>;
44
58
  spool(key: string, type: string, parts: Iterable<Uint8Array>): Promise<Blob>;
45
59
  drop(key: string): Promise<void>;
60
+ probe(bytes: number): Promise<void>;
46
61
  }
47
62
  export type KeptPending = {
48
63
  readonly id: string;
@@ -191,16 +206,7 @@ export interface RuntimeRequests {
191
206
  readonly 'replica.counts': Asked<{
192
207
  readonly rooms: readonly CountedRoom[];
193
208
  }, readonly number[]>;
194
- readonly 'replica.searched': Asked<{
195
- readonly key: number;
196
- readonly locator: string;
197
- readonly after: string | null;
198
- readonly limit: number;
199
- readonly paths: readonly string[] | null;
200
- }, {
201
- readonly documents: readonly SearchedDocument[];
202
- readonly next: string | null;
203
- }>;
209
+ readonly 'replica.search': Asked<SearchAsk, SearchWindow>;
204
210
  readonly 'replica.received': Asked<Nothing, readonly KeptReceipt[]>;
205
211
  readonly 'replica.receivedParts': Asked<{
206
212
  readonly key: string;
@@ -209,12 +215,22 @@ export interface RuntimeRequests {
209
215
  readonly 'replica.stage': Asked<{
210
216
  readonly locator: string;
211
217
  readonly transfer: string;
212
- readonly record: string | null;
218
+ readonly record: string;
213
219
  readonly key: number | null;
214
220
  readonly composition: Composition;
215
221
  readonly entries: readonly StoredEntry[];
216
222
  readonly folders: readonly string[];
223
+ readonly written?: string;
217
224
  }, number | null>;
225
+ readonly 'replica.transferPart': Asked<{
226
+ readonly locator: string;
227
+ readonly token: string;
228
+ }, Uint8Array | null>;
229
+ readonly 'replica.keepPart': Asked<{
230
+ readonly locator: string;
231
+ readonly token: string;
232
+ readonly part: Uint8Array;
233
+ }, null>;
218
234
  readonly 'replica.refresh': Asked<{
219
235
  readonly key: number;
220
236
  readonly entries: readonly StoredEntry[];
@@ -301,6 +317,24 @@ export interface RuntimeRequests {
301
317
  readonly key: string;
302
318
  readonly part: number;
303
319
  }, Uint8Array | null>;
320
+ readonly 'conversation.held': Asked<Nothing, readonly HeldConversation[]>;
321
+ readonly 'conversation.keep': Asked<ConversationWrite, null>;
322
+ readonly 'conversation.window': Asked<{
323
+ readonly conversation: string;
324
+ readonly limit: number;
325
+ readonly before: readonly [string, string] | null;
326
+ }, MessageWindow>;
327
+ readonly 'conversation.count': Asked<{
328
+ readonly conversation: string;
329
+ }, number>;
330
+ readonly 'conversation.turn': Asked<{
331
+ readonly conversation: string;
332
+ readonly turn: string;
333
+ }, boolean>;
334
+ readonly 'conversation.drop': Asked<{
335
+ readonly conversations: readonly string[];
336
+ }, null>;
337
+ readonly 'space.probe': Asked<Nothing, null>;
304
338
  }
305
339
  export type RuntimeKind = keyof RuntimeRequests;
306
340
  export type RuntimeRequest<K extends RuntimeKind = RuntimeKind> = {
@@ -54,10 +54,6 @@ declare const MEMBERS: {
54
54
  readonly reach: 'within';
55
55
  readonly effect: 'read';
56
56
  };
57
- readonly 'binaryFile.readReference': {
58
- readonly reach: 'within';
59
- readonly effect: 'read';
60
- };
61
57
  readonly 'binaryFile.part': {
62
58
  readonly reach: 'within';
63
59
  readonly effect: 'read';
@@ -1,11 +1,17 @@
1
1
  import type { MdRuntimeClient } from './mdruntime/client.js';
2
- import type { HouseActivation, HouseAnalyticsChoice, HouseAppMessage, HouseExternalAnswer, HouseExternalRequest, HouseNavigationMode, HouseRefusal, HouseSourceDownload, HouseSourceTop, HouseStatus, HouseTab, HouseTask } from './index.js';
2
+ import type { HouseActivation, HouseAnalyticsChoice, HouseAppMessage, HouseChatOptions, HouseExternalAnswer, HouseExternalRequest, HouseNavigationMode, HouseRefusal, HouseSourceDownload, HouseSourceTop, HouseStatus, HouseTab, HouseTask } from './index.js';
3
3
  export interface HouseBridgeNavigation {
4
4
  readonly mode: HouseNavigationMode;
5
5
  readonly address: string;
6
6
  }
7
+ export interface HouseBridgeChat {
8
+ readonly element: object;
9
+ readonly options: HouseChatOptions;
10
+ readonly mounted: boolean;
11
+ }
7
12
  export interface HouseBridgeTestHost {
8
13
  readonly navigations: readonly HouseBridgeNavigation[];
14
+ readonly chats: readonly HouseBridgeChat[];
9
15
  readonly ceremonies: readonly string[];
10
16
  readonly consents: readonly HouseAnalyticsChoice[];
11
17
  readonly tabs: readonly HouseTab[];
package/dist/test-host.js CHANGED
@@ -50,6 +50,7 @@ export function createHouseBridgeTestHost(options = {}) {
50
50
  const consents = [];
51
51
  const tabs = [];
52
52
  const externalCalls = [];
53
+ const chats = [];
53
54
  const addressListeners = new Set();
54
55
  const statusListeners = new Set();
55
56
  const messageListeners = new Set();
@@ -100,6 +101,20 @@ export function createHouseBridgeTestHost(options = {}) {
100
101
  }
101
102
  const bridge = {
102
103
  runtime: runtime,
104
+ chat: {
105
+ mount(element, options = {}) {
106
+ const chat = { element, options, mounted: true };
107
+ chats.push(chat);
108
+ return Promise.resolve({
109
+ update(next) {
110
+ chat.options = next;
111
+ },
112
+ unmount() {
113
+ chat.mounted = false;
114
+ },
115
+ });
116
+ },
117
+ },
103
118
  address: () => shown,
104
119
  onAddress(listener) {
105
120
  return followHeld(addressListeners, listener, () => shown);
@@ -164,6 +179,7 @@ export function createHouseBridgeTestHost(options = {}) {
164
179
  arrive(current);
165
180
  return {
166
181
  navigations,
182
+ chats,
167
183
  ceremonies,
168
184
  consents,
169
185
  tabs,
package/docs/families.md CHANGED
@@ -56,8 +56,8 @@
56
56
  applied any other call, an act on House is answered the outcome
57
57
  `transport-uncertainty`, and every other call, a Save or a draft write among
58
58
  them, fails with the retryable code `transport-uncertainty`.
59
- - **Site image read** - given a Published Room and an original attachment
60
- reference, it answers the web copy's path and metadata, or `null` when no
59
+ - **Site image read** - given a Published Room and the Path of one of its
60
+ binary entries, it answers the web copy's path and metadata, or `null` when no
61
61
  copy exists. The original bytes never cross this bridge at a Site.
62
62
  - **App release code** - `sourceTop(app, release)` answers the top level of
63
63
  the latest successful release of an App the User may use: its folders, its
@@ -84,7 +84,7 @@
84
84
  the sender's User id, and `body`, the JSON value they sent, until the
85
85
  function it returns is called. App code sends one through the Runtime's
86
86
  `call('message.send', { to, body })` with the recipient's User id and
87
- a body of at most 32 KiB of JSON; House fills in the App and relays it only
87
+ a body of at most 32 kB of JSON; House fills in the App and relays it only
88
88
  to copies running now, storing nothing. The panel sends none.
89
89
  - **App screenshot read** - given an App reference, `readScreenshot(app)`
90
90
  answers the image this browser captured of that App's screen the first time
@@ -96,8 +96,23 @@
96
96
  after its latest release, as a JPEG `Blob`, or `null` when House holds none
97
97
  or does not answer. A Site's own renderer reads none.
98
98
 
99
+ - **Chat** - `chat.mount(element, options)` places House's Chat, the one chat
100
+ in which the User's Agent conversations show, in `element` over the page's
101
+ `runtime` client, and resolves to a handle: `update(options)` replaces its
102
+ options and `unmount()` removes it. House serves the Chat with the page and
103
+ keeps it current, so the App installs and bundles nothing for it. The
104
+ options: `conversation` opens one, `null` for a new chat, `agent` is the
105
+ Agent a new chat goes to, `showChats` adds its conversation list, `width` is
106
+ `full`, the element, or `3/4`, `1/2` or `1/3` of the window docked at its
107
+ right edge, `onOpen` hears each conversation it opens as
108
+ `{ conversation, agent }`, and `onLink` takes a link without a scheme in
109
+ place of the browser. CSS custom properties named `--chat-*` on the element
110
+ or an ancestor set its look. It shows conversations only to a release that
111
+ declares them. A Site and the House panel have none: their call rejects with
112
+ an error named and coded `NotSupportedError`, with `retryable` false.
113
+
99
114
  - **Cooperation** - `cooperate({ checkpoint, persist, capture, restore,
100
- ready, settle })` lets House activate a newer release of the App while it
115
+ ready, settle })` lets House activate a newer release of the App while it
101
116
  runs, keeping the User's task; the function it returns withdraws it.
102
117
  Register it in the entry script, before the first draw, or House treats the
103
118
  page as not cooperating and the newer release waits for the App's next
@@ -141,7 +156,9 @@ records in `tabs` each `setTab`, answers a release code read from the
141
156
  by App reference and `readSiteScreenshot` from the `siteScreenshots` it was
142
157
  given by Site identifier, answers every `install()` `'manual'`, as a browser
143
158
  with no install prompt does, answers every `notifications()` `'unavailable'`,
144
- as a browser without push does, settles every `setBadge`, delivers each App
159
+ as a browser without push does, settles every `setBadge`, records in `chats`
160
+ each Chat `chat.mount` places, with its `element`, the `options` it was last
161
+ given and whether it is still `mounted`, drawing nothing, delivers each App
145
162
  message `message({ from, body })` plays, and hands `bridge.runtime` the MD
146
163
  Runtime client `attachRuntime(client)` gives it. `checkpoint()` runs the
147
164
  registered cooperation's checkpoint, persist and capture and answers the task,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@agentshouse/app-bridge",
3
- "version": "0.1.0-c4999e714a13d",
4
- "description": "Types of the agents.house App bridge House hands every App: navigation, the tab title and icon, ceremonies, installation, notifications and the icon badge, status, Site image reads, App release code, App and Site screenshot reads, and App messages, with an accessor and an in-page test host.",
3
+ "version": "0.1.0-c4e2f96a8f06c",
4
+ "description": "Types of the agents.house App bridge House hands every App: navigation, the tab title and icon, ceremonies, installation, notifications and the icon badge, status, Site image reads, App release code, App and Site screenshot reads, App messages and the Chat, with an accessor and an in-page test host.",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "sideEffects": false,
@@ -23,5 +23,10 @@
23
23
  "docs",
24
24
  "README.md",
25
25
  "LICENSE"
26
- ]
26
+ ],
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "git+https://github.com/agentshouse/core.git",
30
+ "directory": "client"
31
+ }
27
32
  }
@@ -1,8 +0,0 @@
1
- export declare function yielded(): Promise<void>;
2
- export declare const ROW_WEIGHT = 256;
3
- export type Later<T> = T | Promise<T>;
4
- export declare function after<T, R>(value: Later<T>, next: (value: T) => Later<R>): Later<R>;
5
- export declare function paced(): (weight: number) => Later<void>;
6
- export declare function inUnits<T>(items: Iterable<T>, each: (item: T) => number, ended?: () => void, paused?: () => Promise<void>): Later<void>;
7
- export declare function finished<R>(steps: Generator<number, R, void>): R;
8
- export declare function stepped<R>(steps: Generator<number, R, void>): Later<R>;