@agentshouse/app-bridge 0.1.0-c357a960443ec → 0.1.0-c415579fa0c3a

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Anton (trof3039)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -7,18 +7,17 @@ installation, notifications, status, Site image reads, App release code,
7
7
  external calls, App messages and App and Site screenshot reads.
8
8
  [docs/families.md](docs/families.md) describes each and the test host.
9
9
 
10
- The package carries no credential handling and no Runtime family. It surfaces
11
- the dedicated Runtime port the worker transfers over the bridge as a plain
12
- message port, which the App hands to the MD Runtime client entry.
10
+ The package carries no credential handling and no Runtime family. House builds
11
+ the MD Runtime client into the page beside the bridge, and `bridge.runtime`
12
+ resolves to that client, so the App imports and constructs none.
13
13
 
14
14
  ## Use
15
15
 
16
16
  ```js
17
17
  import { connectHouseBridge } from '@agentshouse/app-bridge';
18
- import { connectMdRuntime } from '@agentshouse/mdruntime/client';
19
18
 
20
19
  const bridge = connectHouseBridge();
21
- const md = connectMdRuntime(await bridge.runtime);
20
+ const md = await bridge.runtime;
22
21
 
23
22
  bridge.onAddress((address) => render(address));
24
23
  bridge.onStatus((status) => showSync(status.sync));
@@ -38,9 +37,8 @@ async function manageSecurity(securityPath) {
38
37
  }
39
38
  ```
40
39
 
41
- `bridge.runtime` resolves with a structural `HouseMessagePort`. A consumer whose
42
- Runtime client entry asks for the DOM `MessagePort` type passes it through
43
- directly at run time and casts at the type level.
40
+ `bridge.runtime` resolves to the `MdRuntimeClient` of
41
+ `@agentshouse/mdruntime/client`, whose README describes its members.
44
42
 
45
43
  ## Test without a House
46
44
 
@@ -49,7 +47,7 @@ import { connectHouseBridge } from '@agentshouse/app-bridge';
49
47
  import { createHouseBridgeTestHost } from '@agentshouse/app-bridge/test-host';
50
48
 
51
49
  const host = createHouseBridgeTestHost({ address: '/rooms/atlas' });
52
- const bridge = connectHouseBridge(host.port);
50
+ const bridge = connectHouseBridge(host);
53
51
 
54
52
  bridge.push('/rooms/atlas/members');
55
53
  host.open('/rooms/atlas');
@@ -1,4 +1,6 @@
1
- import type { HouseAppMessage, HouseExternalAnswer, HouseExternalRequest, HouseBridgePort, HouseGaChoice, HouseMessagePort, HouseRefusal, HouseSourceDownload, HouseSourceTop, HouseStatus, HouseTab } from './wire.js';
1
+ import type { MdRuntimeClient } from '@agentshouse/mdruntime/client';
2
+ import type { HouseAppMessage, HouseExternalAnswer, HouseExternalRequest, HouseBridgePort, HouseGaChoice, HouseImageCopy, HouseInstallation, HouseNotifications, HouseRefusal, HouseSourceDownload, HouseSourceTop, HouseStatus, HouseTab } from './wire.js';
3
+ export type { HouseImageCopy } from './wire.js';
2
4
  export declare class HouseCeremonyRefused extends Error {
3
5
  readonly path: string | null;
4
6
  constructor(path: string | null);
@@ -7,16 +9,12 @@ export declare class HouseNavigationRefused extends Error {
7
9
  readonly address: string | null;
8
10
  constructor(address: string | null);
9
11
  }
10
- export interface HouseImageCopy {
11
- readonly attachment: string;
12
- readonly copy: string;
13
- readonly name: string;
14
- readonly media_type: string;
12
+ export interface HouseBridgeSource {
13
+ readonly port: Promise<HouseBridgePort>;
14
+ readonly runtime: Promise<MdRuntimeClient>;
15
15
  }
16
- type HouseInstallation = 'accepted' | 'dismissed' | 'manual';
17
- type HouseNotifications = 'on' | 'off' | 'blocked' | 'unavailable';
18
16
  export interface HouseBridge {
19
- readonly runtime: Promise<HouseMessagePort>;
17
+ readonly runtime: Promise<MdRuntimeClient>;
20
18
  address(): string | null;
21
19
  onAddress(listener: (address: string) => void): () => void;
22
20
  push(address: string): Promise<string>;
@@ -37,5 +35,4 @@ export interface HouseBridge {
37
35
  messages(listener: (message: HouseAppMessage) => void): () => void;
38
36
  gaConsent(choice: HouseGaChoice): void;
39
37
  }
40
- export declare function connectHouseBridge(source?: Promise<HouseBridgePort>): HouseBridge;
41
- export {};
38
+ export declare function connectHouseBridge(source?: HouseBridgeSource): HouseBridge;
@@ -14,19 +14,45 @@ export class HouseNavigationRefused extends Error {
14
14
  this.address = address;
15
15
  }
16
16
  }
17
- function answered(pending, answer, value) {
18
- if (typeof answer.id !== 'number')
19
- return;
17
+ function pendingAnswer(pending, answer) {
20
18
  const asked = pending.get(answer.id);
21
19
  if (asked === undefined)
22
- return;
20
+ return null;
23
21
  pending.delete(answer.id);
24
- if (answer.refused === true)
22
+ if (answer.refused === true) {
25
23
  asked.reject(new HouseCeremonyRefused(null));
26
- else if (answer.refusal !== undefined)
24
+ return null;
25
+ }
26
+ if (answer.refusal !== undefined) {
27
27
  asked.reject(new DOMException(answer.refusal.message, answer.refusal.name));
28
- else
29
- asked.resolve(value);
28
+ return null;
29
+ }
30
+ return asked;
31
+ }
32
+ const FRAME_HOUSES = [
33
+ 'runtime',
34
+ 'status',
35
+ 'screenshot',
36
+ 'address',
37
+ 'ceremony-refused',
38
+ 'navigate-refused',
39
+ 'attachment',
40
+ 'source',
41
+ 'external-call',
42
+ 'install',
43
+ 'notifications',
44
+ 'badge',
45
+ 'app-message',
46
+ ];
47
+ function frameMessage(value) {
48
+ if (value === null || typeof value !== 'object')
49
+ return null;
50
+ const message = value;
51
+ if (typeof message.house !== 'string')
52
+ return null;
53
+ if (!FRAME_HOUSES.includes(message.house))
54
+ return null;
55
+ return value;
30
56
  }
31
57
  function settled() {
32
58
  let settle = null;
@@ -36,13 +62,12 @@ function settled() {
36
62
  return { promise, settle: settle };
37
63
  }
38
64
  function heldBridge() {
39
- const held = globalThis.houseBridge;
40
- if (held === undefined)
65
+ const held = globalThis;
66
+ if (held.houseBridge === undefined || held.houseRuntime === undefined)
41
67
  throw new Error('house_bridge_absent');
42
- return held;
68
+ return { port: held.houseBridge, runtime: held.houseRuntime };
43
69
  }
44
70
  export function connectHouseBridge(source = heldBridge()) {
45
- const runtime = settled();
46
71
  const ceremonies = [];
47
72
  const navigations = [];
48
73
  const attachments = new Map();
@@ -73,15 +98,9 @@ export function connectHouseBridge(source = heldBridge()) {
73
98
  held.postMessage(message);
74
99
  }
75
100
  function receive(event) {
76
- const data = event.data;
77
- if (data === null || typeof data !== 'object')
101
+ const data = frameMessage(event.data);
102
+ if (data === null)
78
103
  return;
79
- if (data.house === 'runtime') {
80
- const [port] = event.ports;
81
- if (port !== undefined)
82
- runtime.settle.resolve(port);
83
- return;
84
- }
85
104
  if (data.house === 'status') {
86
105
  status = data.status;
87
106
  for (const listener of statusListeners)
@@ -111,61 +130,59 @@ export function connectHouseBridge(source = heldBridge()) {
111
130
  return;
112
131
  }
113
132
  if (data.house === 'attachment') {
114
- const answer = data;
115
- if (typeof answer.id !== 'number')
133
+ if (typeof data.id !== 'number')
116
134
  return;
117
- const pending = attachments.get(answer.id);
135
+ const pending = attachments.get(data.id);
118
136
  if (pending === undefined)
119
137
  return;
120
- attachments.delete(answer.id);
121
- pending.resolve(answer.image ?? null);
138
+ attachments.delete(data.id);
139
+ pending.resolve(data.image ?? null);
122
140
  return;
123
141
  }
124
142
  if (data.house === 'install') {
125
- const answer = data;
126
- answered(installations, answer, answer.outcome);
143
+ const pending = pendingAnswer(installations, data);
144
+ if (pending !== null && 'outcome' in data)
145
+ pending.resolve(data.outcome);
127
146
  return;
128
147
  }
129
148
  if (data.house === 'notifications') {
130
- const answer = data;
131
- answered(notifications, answer, answer.state);
149
+ const pending = pendingAnswer(notifications, data);
150
+ if (pending !== null && 'state' in data)
151
+ pending.resolve(data.state);
132
152
  return;
133
153
  }
134
154
  if (data.house === 'badge') {
135
- answered(badges, data, undefined);
155
+ pendingAnswer(badges, data)?.resolve();
136
156
  return;
137
157
  }
138
158
  if (data.house === 'source') {
139
- const answer = data;
140
- if (typeof answer.id !== 'number')
159
+ if (typeof data.id !== 'number')
141
160
  return;
142
- const pending = sources.get(answer.id);
161
+ const pending = sources.get(data.id);
143
162
  if (pending === undefined)
144
163
  return;
145
- sources.delete(answer.id);
146
- pending.resolve(answer.answer ?? null);
164
+ sources.delete(data.id);
165
+ pending.resolve(data.answer ?? null);
147
166
  return;
148
167
  }
149
168
  if (data.house === 'external-call') {
150
- const answer = data;
151
- if (typeof answer.id !== 'number')
169
+ if (typeof data.id !== 'number')
152
170
  return;
153
- const pending = externals.get(answer.id);
171
+ const pending = externals.get(data.id);
154
172
  if (pending === undefined)
155
173
  return;
156
- externals.delete(answer.id);
157
- pending.resolve(answer.answer ?? null);
174
+ externals.delete(data.id);
175
+ pending.resolve(data.answer ?? null);
158
176
  return;
159
177
  }
160
178
  if (data.house === 'screenshot') {
161
- const answer = data;
162
- if (typeof answer.id !== 'number')
179
+ if (typeof data.id !== 'number')
163
180
  return;
164
- const pending = screenshots.get(answer.id);
181
+ const pending = screenshots.get(data.id);
165
182
  if (pending === undefined)
166
183
  return;
167
- screenshots.delete(answer.id);
168
- pending.resolve(answer.image ?? null);
184
+ screenshots.delete(data.id);
185
+ pending.resolve(data.image ?? null);
169
186
  return;
170
187
  }
171
188
  if (data.house === 'ceremony-refused') {
@@ -176,7 +193,7 @@ export function connectHouseBridge(source = heldBridge()) {
176
193
  pending?.settle.reject(new HouseCeremonyRefused(named));
177
194
  }
178
195
  }
179
- void source.then((port) => {
196
+ void source.port.then((port) => {
180
197
  held = port;
181
198
  port.addEventListener('message', receive);
182
199
  port.start();
@@ -196,7 +213,10 @@ export function connectHouseBridge(source = heldBridge()) {
196
213
  const pending = settled();
197
214
  const id = ++nextScreenshot;
198
215
  screenshots.set(id, pending.settle);
199
- send({ house, id, ...asked });
216
+ if (house === 'screenshot-read' && 'app' in asked)
217
+ send({ house, id, app: asked.app });
218
+ if (house === 'site-screenshot-read' && 'site' in asked)
219
+ send({ house, id, site: asked.site });
200
220
  return pending.promise;
201
221
  }
202
222
  function navigate(mode, asked) {
@@ -206,7 +226,7 @@ export function connectHouseBridge(source = heldBridge()) {
206
226
  return pending.promise;
207
227
  }
208
228
  return {
209
- runtime: runtime.promise,
229
+ runtime: source.runtime,
210
230
  address() {
211
231
  return address;
212
232
  },
@@ -1,3 +1,3 @@
1
- export { connectHouseBridge, HouseCeremonyRefused, HouseNavigationRefused, type HouseBridge, type HouseImageCopy, } from './bridge.js';
1
+ export { connectHouseBridge, HouseCeremonyRefused, HouseNavigationRefused, type HouseBridge, type HouseBridgeSource, type HouseImageCopy, } from './bridge.js';
2
2
  export { HOUSE_ADDRESS_MAX_CHARS } from './wire.js';
3
- export type { HouseAppMessage, HouseBridgeEvent, HouseBridgePort, HouseCredentialState, HouseExternalAnswer, HouseExternalRequest, HouseGa, HouseGaChoice, HouseMessagePort, HouseNavigationMode, HouseRefusal, HouseSourceDownload, HouseSourceFile, HouseSourceTop, HouseStatus, HouseSyncState, } from './wire.js';
3
+ export type { HouseAppMessage, HouseBridgeEvent, HouseBridgePort, HouseCredentialState, HouseExternalAnswer, HouseExternalRequest, HouseGa, HouseGaChoice, HouseNavigationMode, HouseRefusal, HouseSourceDownload, HouseSourceFile, HouseSourceTop, HouseStatus, HouseSyncState, } from './wire.js';
@@ -1,11 +1,11 @@
1
- import type { HouseImageCopy } from './bridge.js';
2
- import type { HouseAppMessage, HouseBridgePort, HouseExternalAnswer, HouseExternalRequest, HouseGaChoice, HouseMessagePort, HouseNavigationMode, HouseRefusal, HouseSourceDownload, HouseSourceTop, HouseStatus, HouseTab } from './wire.js';
1
+ import type { MdRuntimeClient } from '@agentshouse/mdruntime/client';
2
+ import type { HouseBridgeSource, HouseImageCopy } from './bridge.js';
3
+ import type { HouseAppMessage, HouseExternalAnswer, HouseExternalRequest, HouseGaChoice, HouseNavigationMode, HouseRefusal, HouseSourceDownload, HouseSourceTop, HouseStatus, HouseTab } from './wire.js';
3
4
  export interface HouseBridgeNavigation {
4
5
  readonly mode: HouseNavigationMode;
5
6
  readonly address: string;
6
7
  }
7
- export interface HouseBridgeTestHost {
8
- readonly port: Promise<HouseBridgePort>;
8
+ export interface HouseBridgeTestHost extends HouseBridgeSource {
9
9
  readonly navigations: readonly HouseBridgeNavigation[];
10
10
  readonly ceremonies: readonly string[];
11
11
  readonly consents: readonly HouseGaChoice[];
@@ -15,7 +15,7 @@ export interface HouseBridgeTestHost {
15
15
  open(address: string): void;
16
16
  publish(status: HouseStatus): void;
17
17
  message(message: HouseAppMessage): void;
18
- attachRuntime(runtime: HouseMessagePort): void;
18
+ attachRuntime(runtime: MdRuntimeClient): void;
19
19
  }
20
20
  export interface HouseBridgeTestHostOptions {
21
21
  readonly address?: string;
@@ -23,8 +23,12 @@ export function createHouseBridgeTestHost(options = {}) {
23
23
  let started = false;
24
24
  let address = appAddressOf('/', options.address ?? '/');
25
25
  let status = options.status ?? null;
26
- function deliver(data, ports = []) {
27
- const event = { data, ports };
26
+ let attached = () => { };
27
+ const runtime = new Promise((resolve) => {
28
+ attached = resolve;
29
+ });
30
+ function deliver(data) {
31
+ const event = { data };
28
32
  if (!started) {
29
33
  queued.push(event);
30
34
  return;
@@ -158,6 +162,7 @@ export function createHouseBridgeTestHost(options = {}) {
158
162
  deliver({ house: 'address', address, navigated: false });
159
163
  return {
160
164
  port: Promise.resolve(port),
165
+ runtime,
161
166
  navigations,
162
167
  ceremonies,
163
168
  consents,
@@ -173,8 +178,8 @@ export function createHouseBridgeTestHost(options = {}) {
173
178
  message(message) {
174
179
  deliver({ house: 'app-message', from: message.from, body: message.body });
175
180
  },
176
- attachRuntime(runtime) {
177
- deliver({ house: 'runtime' }, [runtime]);
181
+ attachRuntime(client) {
182
+ attached(client);
178
183
  },
179
184
  };
180
185
  }
@@ -1,14 +1,12 @@
1
1
  import type { TabChange } from '../../src/apps/tab.js';
2
2
  export interface HouseBridgeEvent {
3
3
  readonly data: unknown;
4
- readonly ports: readonly HouseMessagePort[];
5
4
  }
6
- export interface HouseMessagePort {
7
- postMessage(message: unknown): void;
5
+ export interface HouseBridgePort {
6
+ postMessage(message: HouseFrameRequest): void;
8
7
  addEventListener(type: 'message', listener: (event: HouseBridgeEvent) => void): void;
9
8
  start(): void;
10
9
  }
11
- export type HouseBridgePort = HouseMessagePort;
12
10
  export interface HouseSyncState {
13
11
  readonly state: string;
14
12
  readonly providerUnreachable: boolean;
@@ -23,7 +21,11 @@ export interface HouseGa {
23
21
  readonly choice: HouseGaChoice | null;
24
22
  }
25
23
  export interface HouseStatus {
26
- readonly app: string;
24
+ readonly app: string | null;
25
+ readonly preferences: {
26
+ readonly room_ref: string;
27
+ readonly path: string;
28
+ } | null;
27
29
  readonly runtime: string;
28
30
  readonly credential: HouseCredentialState;
29
31
  readonly sync: HouseSyncState | null;
@@ -33,6 +35,7 @@ export interface HouseStatus {
33
35
  readonly loss: string | null;
34
36
  readonly ga: HouseGa;
35
37
  readonly service_mode: 'open' | 'write-halted' | null;
38
+ readonly offline: boolean;
36
39
  }
37
40
  export type HouseNavigationMode = 'push' | 'replace';
38
41
  interface HouseRelease {
@@ -85,5 +88,128 @@ export interface HouseAppMessage {
85
88
  readonly from: string;
86
89
  readonly body: unknown;
87
90
  }
91
+ export type HouseInstallation = 'accepted' | 'dismissed' | 'manual';
92
+ export type HouseNotifications = 'on' | 'off' | 'blocked' | 'unavailable';
93
+ export interface HouseImageCopy {
94
+ readonly attachment: string;
95
+ readonly copy: string;
96
+ readonly name: string;
97
+ readonly media_type: string;
98
+ }
99
+ export interface HouseFrameRefusal {
100
+ readonly name: string;
101
+ readonly message: string;
102
+ }
103
+ export type HouseFrameRequest = {
104
+ readonly house: 'navigate';
105
+ readonly mode: HouseNavigationMode;
106
+ readonly address: string;
107
+ } | ({
108
+ readonly house: 'tab';
109
+ } & HouseTab) | {
110
+ readonly house: 'ceremony';
111
+ readonly path: string;
112
+ } | {
113
+ readonly house: 'install';
114
+ readonly id: number;
115
+ } | {
116
+ readonly house: 'notifications';
117
+ readonly id: number;
118
+ readonly on?: boolean;
119
+ } | {
120
+ readonly house: 'badge';
121
+ readonly id: number;
122
+ readonly unread: readonly string[];
123
+ } | {
124
+ readonly house: 'attachment-read';
125
+ readonly id: number;
126
+ readonly room: string;
127
+ readonly attachment: string;
128
+ } | {
129
+ readonly house: 'source-top' | 'source-download';
130
+ readonly id: number;
131
+ readonly app: string;
132
+ readonly release?: string;
133
+ } | {
134
+ readonly house: 'external-call';
135
+ readonly id: number;
136
+ readonly request: HouseExternalRequest;
137
+ } | {
138
+ readonly house: 'screenshot-read';
139
+ readonly id: number;
140
+ readonly app: string;
141
+ } | {
142
+ readonly house: 'site-screenshot-read';
143
+ readonly id: number;
144
+ readonly site: string;
145
+ } | {
146
+ readonly house: 'ga/consent';
147
+ readonly choice: HouseGaChoice;
148
+ };
149
+ export type HouseInstallAnswer = {
150
+ readonly outcome: HouseInstallation;
151
+ } | {
152
+ readonly refusal: HouseFrameRefusal;
153
+ };
154
+ export type HouseNotificationAnswer = {
155
+ readonly refused: true;
156
+ } | {
157
+ readonly refusal: HouseFrameRefusal;
158
+ } | {
159
+ readonly state: HouseNotifications;
160
+ };
161
+ export type HouseBadgeAnswer = {
162
+ readonly refused: true;
163
+ } | {
164
+ readonly refusal: HouseFrameRefusal;
165
+ } | {
166
+ readonly refused?: never;
167
+ readonly refusal?: never;
168
+ };
169
+ export type HouseFrameMessage = {
170
+ readonly house: 'runtime';
171
+ } | {
172
+ readonly house: 'status';
173
+ readonly status: HouseStatus;
174
+ } | {
175
+ readonly house: 'screenshot';
176
+ readonly id: number;
177
+ readonly image: Blob | null;
178
+ } | {
179
+ readonly house: 'address';
180
+ readonly address: string;
181
+ readonly navigated: boolean;
182
+ } | {
183
+ readonly house: 'ceremony-refused';
184
+ readonly path: string | null;
185
+ } | {
186
+ readonly house: 'navigate-refused';
187
+ readonly address: string | null;
188
+ } | {
189
+ readonly house: 'attachment';
190
+ readonly id: number;
191
+ readonly image: HouseImageCopy | null;
192
+ } | {
193
+ readonly house: 'source';
194
+ readonly id: number;
195
+ readonly answer: HouseSourceTop | HouseSourceDownload | HouseRefusal | null;
196
+ } | {
197
+ readonly house: 'external-call';
198
+ readonly id: number;
199
+ readonly answer: HouseExternalAnswer | HouseRefusal | null;
200
+ } | ({
201
+ readonly house: 'install';
202
+ readonly id: number;
203
+ } & HouseInstallAnswer) | ({
204
+ readonly house: 'notifications';
205
+ readonly id: number;
206
+ } & HouseNotificationAnswer) | ({
207
+ readonly house: 'badge';
208
+ readonly id: number;
209
+ } & HouseBadgeAnswer) | {
210
+ readonly house: 'app-message';
211
+ readonly from: string;
212
+ readonly body: unknown;
213
+ };
88
214
  export declare const HOUSE_ADDRESS_MAX_CHARS = 1000;
89
215
  export {};
@@ -12,5 +12,5 @@ export function appAddressOf(root, address) {
12
12
  export function shellAddressOf(root, appAddress) {
13
13
  const { path, rest } = split(appAddress);
14
14
  const below = path === '/' ? '' : path;
15
- return `${root === '/' ? '' : root}${below}${rest}` || '/';
15
+ return `${`${root === '/' ? '' : root}${below}` || '/'}${rest}`;
16
16
  }
package/docs/families.md CHANGED
@@ -32,7 +32,9 @@
32
32
  click. `setBadge(unread)` takes the identifiers of the Human Notifications
33
33
  unread in this storage and sets the icon's badge to their number, or clears
34
34
  it at none, where the browser shows one.
35
- - **Status** - the App reference the Runtime port is attached under, sync
35
+ - **Status** - the App reference the runtime client is attached under,
36
+ `preferences`: the `room_ref` and Path of the App's own preferences document,
37
+ or `null` until the runtime holds that Room, sync
36
38
  state, credential state and observed failure, `ga`:
37
39
  whether the page measures and the visitor's stored analytics choice, and
38
40
  `service_mode`: `open`, `write-halted` while House refuses writes, so the
@@ -100,4 +102,5 @@ reference and `readSiteScreenshot` from the `siteScreenshots` it was given by
100
102
  Site identifier, answers every `install()` `'manual'`, as a browser with no install
101
103
  prompt does, answers every `notifications()` `'unavailable'`, as a browser
102
104
  without push does, settles every `setBadge`, delivers each App message
103
- `message({ from, body })` plays, and attaches a Runtime port.
105
+ `message({ from, body })` plays, and hands `bridge.runtime` the MD Runtime
106
+ client `attachRuntime(client)` gives it.
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@agentshouse/app-bridge",
3
- "version": "0.1.0-c357a960443ec",
3
+ "version": "0.1.0-c415579fa0c3a",
4
4
  "description": "Renderer-side client of the agents.house App bridge: 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 in-page test host.",
5
- "license": "UNLICENSED",
5
+ "license": "MIT",
6
6
  "type": "module",
7
7
  "sideEffects": false,
8
8
  "engines": {
@@ -18,9 +18,13 @@
18
18
  "default": "./dist/client/src/test-host.js"
19
19
  }
20
20
  },
21
+ "dependencies": {
22
+ "@agentshouse/mdruntime": "0.1.0-c6e4c19c13638"
23
+ },
21
24
  "files": [
22
25
  "dist",
23
26
  "docs",
24
- "README.md"
27
+ "README.md",
28
+ "LICENSE"
25
29
  ]
26
30
  }