@agentshouse/app-bridge 0.1.0-c2dfa65932edd → 0.1.0-c2e4124b00b94

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
@@ -41,7 +41,9 @@ async function manageSecurity(securityPath) {
41
41
  ```
42
42
 
43
43
  `bridge.runtime` resolves to the `MdRuntimeClient` of
44
- `@agentshouse/mdruntime/client`, whose README describes its members.
44
+ `@agentshouse/mdruntime/client`, whose README describes its members. Its
45
+ `call(name, input)` reaches House: `HouseCalls` names each Call an App makes
46
+ and the input it takes, such as `call('member.list', { room_ref })`.
45
47
 
46
48
  ## Test without a House
47
49
 
@@ -0,0 +1,117 @@
1
+ export interface HouseCalls {
2
+ readonly 'access.read': {
3
+ readonly room_ref: string;
4
+ };
5
+ readonly 'conversation.answer': {
6
+ readonly answer: {
7
+ readonly interaction_id: string;
8
+ readonly response: unknown;
9
+ };
10
+ readonly conversation: string;
11
+ readonly operation_id?: string;
12
+ };
13
+ readonly 'conversation.create': {
14
+ readonly agent_id: string;
15
+ readonly operation_id?: string;
16
+ };
17
+ readonly 'conversation.delete': {
18
+ readonly conversation: string;
19
+ readonly operation_id?: string;
20
+ };
21
+ readonly 'conversation.history': {
22
+ readonly conversations: readonly {
23
+ readonly after?: string;
24
+ readonly conversation: string;
25
+ }[];
26
+ };
27
+ readonly 'conversation.interrupt': {
28
+ readonly conversation: string;
29
+ readonly operation_id?: string;
30
+ };
31
+ readonly 'conversation.kill': {
32
+ readonly conversation: string;
33
+ readonly operation_id?: string;
34
+ };
35
+ readonly 'conversation.markDone': {
36
+ readonly conversation_id?: string;
37
+ readonly result?: string;
38
+ readonly operation_id: string;
39
+ };
40
+ readonly 'conversation.rename': {
41
+ readonly conversation_id: string;
42
+ readonly operation_id: string;
43
+ readonly name: string;
44
+ };
45
+ readonly 'conversation.send': {
46
+ readonly conversation: string;
47
+ readonly files?: readonly {
48
+ readonly blob: Blob;
49
+ readonly byteLength: number;
50
+ readonly contentHash: string;
51
+ readonly height?: number;
52
+ readonly mediaType: string;
53
+ readonly name: string;
54
+ readonly width?: number;
55
+ }[];
56
+ readonly operation_id?: string;
57
+ readonly text?: string;
58
+ };
59
+ readonly 'conversation.setOption': {
60
+ readonly conversation_id: string;
61
+ readonly operation_id: string;
62
+ readonly option: string;
63
+ readonly value: string | boolean;
64
+ };
65
+ readonly 'feature.list': Readonly<Record<string, never>>;
66
+ readonly 'holder.list': Readonly<Record<string, never>>;
67
+ readonly 'holder.ring': {
68
+ readonly to: string;
69
+ };
70
+ readonly 'member.list': {
71
+ readonly room_ref: string;
72
+ readonly history?: boolean;
73
+ readonly limit?: number;
74
+ readonly cursor?: string;
75
+ };
76
+ readonly 'message.send': {
77
+ readonly to: string;
78
+ readonly body: unknown;
79
+ };
80
+ readonly 'processing.read': {
81
+ readonly room_ref: string;
82
+ readonly path: string;
83
+ };
84
+ readonly 'record.list': {
85
+ readonly room_ref: string;
86
+ readonly record?: string;
87
+ readonly cursor?: string;
88
+ readonly limit?: number;
89
+ readonly order?: 'asc' | 'desc';
90
+ };
91
+ readonly 'relay.read': Readonly<Record<string, never>>;
92
+ readonly 'routine.list': {
93
+ readonly room_ref: string;
94
+ };
95
+ readonly 'routineAccess.list': {
96
+ readonly room_ref: string;
97
+ };
98
+ readonly 'routineAllowance.list': {
99
+ readonly room_ref: string;
100
+ readonly access: string;
101
+ };
102
+ readonly 'routineRequest.list': {
103
+ readonly room_ref: string;
104
+ };
105
+ readonly 'storage.read': {
106
+ readonly room_ref?: string;
107
+ };
108
+ readonly submit: {
109
+ readonly content: string;
110
+ };
111
+ readonly 'trigger.list': {
112
+ readonly room_ref: string;
113
+ };
114
+ readonly 'triggerOccurrence.list': {
115
+ readonly room_ref: string;
116
+ };
117
+ }
package/dist/calls.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.d.ts CHANGED
@@ -1,5 +1,11 @@
1
1
  import type { MdRuntimeClient } from '@agentshouse/mdruntime/client';
2
+ import type { HouseCalls } from './calls.js';
3
+ export type { HouseCalls } from './calls.js';
2
4
  type Open<Value extends string> = Value | (string & {});
5
+ export type HouseCallInput<Name extends string> = Name extends keyof HouseCalls ? HouseCalls[Name] : unknown;
6
+ export interface HouseRuntime extends Omit<MdRuntimeClient, 'call'> {
7
+ call<Name extends Open<keyof HouseCalls>>(name: Name, input: HouseCallInput<Name>): ReturnType<MdRuntimeClient['call']>;
8
+ }
3
9
  export interface HouseSyncState {
4
10
  readonly state: string;
5
11
  readonly providerUnreachable: boolean;
@@ -105,7 +111,7 @@ export interface HouseBrowserRefused extends Error {
105
111
  readonly retryable: boolean;
106
112
  }
107
113
  export interface HouseBridge {
108
- readonly runtime: Promise<MdRuntimeClient>;
114
+ readonly runtime: Promise<HouseRuntime>;
109
115
  address(): string | null;
110
116
  onAddress(listener: (address: string) => void): () => void;
111
117
  push(address: string): Promise<string>;
@@ -129,4 +135,3 @@ export interface HouseHeld {
129
135
  readonly houseBridge: HouseBridge;
130
136
  }
131
137
  export declare const houseBridge: () => HouseBridge;
132
- export {};
package/dist/test-host.js CHANGED
@@ -29,6 +29,21 @@ function navigationRefused(address) {
29
29
  address,
30
30
  });
31
31
  }
32
+ function followHeld(listeners, listener, held) {
33
+ let following = true;
34
+ queueMicrotask(() => {
35
+ if (!following)
36
+ return;
37
+ listeners.add(listener);
38
+ const value = held();
39
+ if (value !== null)
40
+ listener(value);
41
+ });
42
+ return () => {
43
+ following = false;
44
+ listeners.delete(listener);
45
+ };
46
+ }
32
47
  export function createHouseBridgeTestHost(options = {}) {
33
48
  const navigations = [];
34
49
  const ceremonies = [];
@@ -63,7 +78,17 @@ export function createHouseBridgeTestHost(options = {}) {
63
78
  });
64
79
  }
65
80
  function navigate(mode, asked) {
66
- const target = sameOriginPath(asked);
81
+ let path = asked;
82
+ if (/^https?:\/\//i.test(asked)) {
83
+ try {
84
+ const target = new URL(asked);
85
+ path = target.origin === HOST_ORIGIN ? target.pathname + target.search + target.hash : '';
86
+ }
87
+ catch {
88
+ path = '';
89
+ }
90
+ }
91
+ const target = sameOriginPath(path);
67
92
  if (target === null)
68
93
  return Promise.reject(navigationRefused(asked));
69
94
  navigations.push({ mode, address: target });
@@ -76,10 +101,7 @@ export function createHouseBridgeTestHost(options = {}) {
76
101
  runtime,
77
102
  address: () => shown,
78
103
  onAddress(listener) {
79
- addressListeners.add(listener);
80
- return () => {
81
- addressListeners.delete(listener);
82
- };
104
+ return followHeld(addressListeners, listener, () => shown);
83
105
  },
84
106
  push: (asked) => navigate('push', asked),
85
107
  replace: (asked) => navigate('replace', asked),
@@ -106,10 +128,7 @@ export function createHouseBridgeTestHost(options = {}) {
106
128
  readSiteScreenshot: (site) => Promise.resolve(options.siteScreenshots?.[site] ?? null),
107
129
  status: () => seen,
108
130
  onStatus(listener) {
109
- statusListeners.add(listener);
110
- return () => {
111
- statusListeners.delete(listener);
112
- };
131
+ return followHeld(statusListeners, listener, () => seen);
113
132
  },
114
133
  messages(listener) {
115
134
  messageListeners.add(listener);
package/docs/families.md CHANGED
@@ -39,7 +39,9 @@
39
39
  whether the page measures and the visitor's stored analytics choice, and
40
40
  `serviceMode`: `open`, `write-halted` while House refuses writes, so the
41
41
  App can stop retrying them, or `null` while the runtime holds no House
42
- connection. Every status field is camelCase.
42
+ connection. Every status field is camelCase. `onStatus(listener)` and
43
+ `onAddress(listener)` hand a listener the status and the address the bridge
44
+ already holds, then each change.
43
45
  The App reports the visitor's choice with `analyticsConsent('accept')` or
44
46
  `analyticsConsent('decline')`; the shell hands it to House's analytics loader, and
45
47
  the choice never reaches House.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentshouse/app-bridge",
3
- "version": "0.1.0-c2dfa65932edd",
3
+ "version": "0.1.0-c2e4124b00b94",
4
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.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -19,7 +19,7 @@
19
19
  }
20
20
  },
21
21
  "dependencies": {
22
- "@agentshouse/mdruntime": "0.1.0-cd3ee807e46ae"
22
+ "@agentshouse/mdruntime": "0.1.0-c16fc8caac7ff"
23
23
  },
24
24
  "files": [
25
25
  "dist",