@xenosystem/agent-interface-panel 0.1.153 → 0.1.155

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.
@@ -0,0 +1,60 @@
1
+ import { type ReactElement } from 'react';
2
+ import type { AgentHostClientIdentity, AgentHostTransport } from '@xenosystem/agent-interface-contract';
3
+ import { type SurfaceDocumentSource } from './index.js';
4
+ /**
5
+ * Mount the XENO Agent in an Electron app: the renderer half (decision 0003).
6
+ *
7
+ * <XenoAgentPanel appName="XENO Corpus" document={documentSource} />
8
+ *
9
+ * Connects to what the preload exposed (`exposeXenoAgentHost`) and renders the real conversation. There is no
10
+ * app-authored agent UI here on purpose, and nothing to keep in sync.
11
+ *
12
+ * ⚠️ No agent host is an ORDINARY state, not an error: the panel says so and the app keeps working.
13
+ *
14
+ * It hands the panel the bridge rather than the client, because a raw client exposes every host method to the
15
+ * renderer. It declares it can present prompts, because a person is sitting at this panel: without that the host has
16
+ * nobody to ask and refuses anything that needs asking.
17
+ *
18
+ * @unwired-by-design A public entry for products to mount: no module in this repository renders it, because this
19
+ * repository's own surfaces render the full interface. Proven by `scripts/smoke-mount-agent-panel.mjs`.
20
+ */
21
+ /** What `exposeXenoAgentHost` puts on `window.xenoAgentHost`. */
22
+ export interface XenoAgentHostBridge {
23
+ getIdentity(): Promise<AgentHostClientIdentity>;
24
+ request(method: string, input: unknown): Promise<unknown>;
25
+ subscribe(callback: (event: unknown) => void): string;
26
+ unsubscribe(id: string): boolean;
27
+ }
28
+ declare global {
29
+ interface Window {
30
+ xenoAgentHost?: XenoAgentHostBridge;
31
+ }
32
+ }
33
+ export type XenoAgentPanelState = 'connecting' | 'ready' | 'no-host';
34
+ export interface XenoAgentPanelProps {
35
+ /** Named in the no-host message, e.g. `XENO Corpus`. */
36
+ appName: string;
37
+ /** The app's open document, as it changes. With it, every document keeps its own conversations. */
38
+ document?: SurfaceDocumentSource;
39
+ /** Defaults to `window.xenoAgentHost`. */
40
+ host?: XenoAgentHostBridge;
41
+ appVersion?: string;
42
+ onStateChange?: (state: XenoAgentPanelState, detail: string) => void;
43
+ }
44
+ export declare function transportFromPreload(preload: XenoAgentHostBridge): AgentHostTransport;
45
+ /** The line under the panel, in each state that needs one. */
46
+ export declare function panelNotice(state: XenoAgentPanelState, appName: string, detail: string): string | null;
47
+ /**
48
+ * Connect to the host the preload exposed. Never throws: "there is no agent host" and "the app is broken" are different
49
+ * facts, and only the first is true here, so it comes back as a value.
50
+ */
51
+ export declare function connectPanelHost(preload: XenoAgentHostBridge | undefined, appVersion: string | undefined): Promise<{
52
+ ok: true;
53
+ bridge: object;
54
+ dispose(): void;
55
+ } | {
56
+ ok: false;
57
+ detail: string;
58
+ }>;
59
+ export declare function XenoAgentPanel(props: XenoAgentPanelProps): ReactElement;
60
+ //# sourceMappingURL=XenoAgentPanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"XenoAgentPanel.d.ts","sourceRoot":"","sources":["../src/XenoAgentPanel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkE,KAAK,YAAY,EAAE,MAAM,OAAO,CAAA;AAIzG,OAAO,KAAK,EACV,uBAAuB,EAIvB,kBAAkB,EACnB,MAAM,sCAAsC,CAAA;AAC7C,OAAO,EAAiC,KAAK,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAEtF;;;;;;;;;;;;;;;;GAgBG;AAEH,iEAAiE;AACjE,MAAM,WAAW,mBAAmB;IAClC,WAAW,IAAI,OAAO,CAAC,uBAAuB,CAAC,CAAA;IAC/C,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACzD,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,CAAA;IACrD,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAA;CACjC;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,aAAa,CAAC,EAAE,mBAAmB,CAAA;KACpC;CACF;AAED,MAAM,MAAM,mBAAmB,GAAG,YAAY,GAAG,OAAO,GAAG,SAAS,CAAA;AAEpE,MAAM,WAAW,mBAAmB;IAClC,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAA;IACf,mGAAmG;IACnG,QAAQ,CAAC,EAAE,qBAAqB,CAAA;IAChC,0CAA0C;IAC1C,IAAI,CAAC,EAAE,mBAAmB,CAAA;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;CACrE;AAMD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,mBAAmB,GAAG,kBAAkB,CAUrF;AAED,8DAA8D;AAC9D,wBAAgB,WAAW,CAAC,KAAK,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAItG;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,mBAAmB,GAAG,SAAS,EACxC,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,IAAI,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAWxF;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,YAAY,CA6DvE"}
@@ -0,0 +1,104 @@
1
+ import { createElement, useEffect, useRef, useState } from 'react';
2
+ import { createAppHost } from '@xenosystem/panel-sdk';
3
+ import { AgentHostClient } from '@xenosystem/agent-interface-client';
4
+ import { createAgentHostPlatformBridge } from '@xenosystem/agent-interface-ui';
5
+ import { createXenoAgentInterfacePanel } from './index.js';
6
+ const FILL = { display: 'flex', flexDirection: 'column', height: '100%' };
7
+ const MOUNT = { flex: 1, minHeight: 0 };
8
+ const NOTICE = { padding: '8px 10px', fontSize: 11, opacity: 0.7 };
9
+ export function transportFromPreload(preload) {
10
+ return {
11
+ async request(method, input) {
12
+ return await preload.request(method, input);
13
+ },
14
+ subscribe(listener) {
15
+ const id = preload.subscribe(listener);
16
+ return () => { preload.unsubscribe(id); };
17
+ },
18
+ };
19
+ }
20
+ /** The line under the panel, in each state that needs one. */
21
+ export function panelNotice(state, appName, detail) {
22
+ if (state === 'ready')
23
+ return null;
24
+ if (state === 'connecting')
25
+ return 'Connecting to the XENO Agent host…';
26
+ return `The XENO Agent is unavailable. ${appName} is unaffected.${detail ? ` ${detail}` : ''}`;
27
+ }
28
+ /**
29
+ * Connect to the host the preload exposed. Never throws: "there is no agent host" and "the app is broken" are different
30
+ * facts, and only the first is true here, so it comes back as a value.
31
+ */
32
+ export async function connectPanelHost(preload, appVersion) {
33
+ if (!preload)
34
+ return { ok: false, detail: 'This build has no agent bridge in its preload.' };
35
+ try {
36
+ const identity = await preload.getIdentity();
37
+ const client = new AgentHostClient({ transport: transportFromPreload(preload), identity, capabilities: { canPresentElicitations: true } });
38
+ await client.connect();
39
+ const platform = createAgentHostPlatformBridge(client, { appVersion: appVersion ?? '0.0.0' });
40
+ return { ok: true, bridge: platform.bridge, dispose: () => { platform.dispose(); client.disconnect(); } };
41
+ }
42
+ catch (error) {
43
+ return { ok: false, detail: error instanceof Error ? error.message : String(error) };
44
+ }
45
+ }
46
+ export function XenoAgentPanel(props) {
47
+ const { appName, document, host, appVersion, onStateChange } = props;
48
+ const container = useRef(null);
49
+ const [state, setState] = useState('connecting');
50
+ const [detail, setDetail] = useState('');
51
+ const report = useRef(onStateChange);
52
+ report.current = onStateChange;
53
+ useEffect(() => {
54
+ const root = container.current;
55
+ if (!root)
56
+ return;
57
+ let disposed = false;
58
+ let cleanup;
59
+ const update = (next, message = '') => {
60
+ if (disposed)
61
+ return;
62
+ setState(next);
63
+ setDetail(message);
64
+ report.current?.(next, message);
65
+ };
66
+ void (async () => {
67
+ const connection = await connectPanelHost(host ?? window.xenoAgentHost, appVersion);
68
+ if (!connection.ok) {
69
+ update('no-host', connection.detail);
70
+ return;
71
+ }
72
+ cleanup = connection.dispose;
73
+ if (disposed) {
74
+ cleanup();
75
+ return;
76
+ }
77
+ const module = createXenoAgentInterfacePanel({
78
+ createBridge: () => connection.bridge,
79
+ ...(document ? { document } : {}),
80
+ onError: (error) => { update('no-host', error instanceof Error ? error.message : String(error)); },
81
+ });
82
+ // This panel declares no ports an app wires, so the app host needs no real store.
83
+ const store = { getState: () => ({}), setState: () => { }, subscribe: () => () => { } };
84
+ const appHost = createAppHost({ manifest: module.manifest, store });
85
+ const instance = module.activate(appHost.host);
86
+ const unmount = instance.render(root);
87
+ const disposeConnection = cleanup;
88
+ cleanup = () => {
89
+ if (typeof unmount === 'function')
90
+ unmount();
91
+ instance.dispose();
92
+ disposeConnection?.();
93
+ };
94
+ update('ready');
95
+ })();
96
+ return () => {
97
+ disposed = true;
98
+ cleanup?.();
99
+ };
100
+ // The connection belongs to the mount. A new document moves the panel through `document`, not by reconnecting.
101
+ }, []);
102
+ return createElement('div', { className: 'xeno-panel-content', style: FILL }, createElement('div', { ref: container, style: MOUNT, 'data-xeno-agent-panel': state }), state === 'ready' ? null : createElement('div', { style: NOTICE, 'data-xeno-agent-panel-notice': state }, panelNotice(state, appName, detail)));
103
+ }
104
+ //# sourceMappingURL=XenoAgentPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"XenoAgentPanel.js","sourceRoot":"","sources":["../src/XenoAgentPanel.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xenosystem/agent-interface-panel",
3
- "version": "0.1.153",
3
+ "version": "0.1.155",
4
4
  "license": "UNLICENSED",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -9,6 +9,10 @@
9
9
  ".": {
10
10
  "types": "./dist/index.d.ts",
11
11
  "import": "./dist/index.js"
12
+ },
13
+ "./react": {
14
+ "types": "./dist/XenoAgentPanel.d.ts",
15
+ "import": "./dist/XenoAgentPanel.js"
12
16
  }
13
17
  },
14
18
  "//sideEffects": "Only stylesheets are un-droppable; unused JS may be tree-shaken.",
@@ -24,10 +28,11 @@
24
28
  },
25
29
  "dependencies": {
26
30
  "@xenosystem/panel-agent": "^0.1.0",
27
- "@xenosystem/agent-interface-embed": "0.1.153",
28
- "@xenosystem/agent-conversation": "0.1.153",
29
- "@xenosystem/agent-interface-client": "0.1.153",
30
- "@xenosystem/agent-interface-contract": "0.1.153"
31
+ "@xenosystem/agent-conversation": "0.1.155",
32
+ "@xenosystem/agent-interface-contract": "0.1.155",
33
+ "@xenosystem/agent-interface-client": "0.1.155",
34
+ "@xenosystem/agent-interface-ui": "0.1.155",
35
+ "@xenosystem/agent-interface-embed": "0.1.155"
31
36
  },
32
37
  "peerDependencies": {
33
38
  "@xenosystem/panel-sdk": "^1.1.0",