@parlor/client 0.0.0-stage → 0.1.0
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 +21 -0
- package/README.md +20 -2
- package/dist/action-client.d.ts +40 -0
- package/dist/action-client.d.ts.map +1 -0
- package/dist/action-client.js +83 -0
- package/dist/action-client.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin-client.d.ts +11 -0
- package/dist/plugin-client.d.ts.map +1 -0
- package/dist/plugin-client.js +14 -0
- package/dist/plugin-client.js.map +1 -0
- package/dist/query-keys.d.ts +3 -0
- package/dist/query-keys.d.ts.map +1 -0
- package/dist/query-keys.js +5 -0
- package/dist/query-keys.js.map +1 -0
- package/dist/react/agent-ui/activity-state.d.ts +20 -0
- package/dist/react/agent-ui/activity-state.d.ts.map +1 -0
- package/dist/react/agent-ui/activity-state.js +14 -0
- package/dist/react/agent-ui/activity-state.js.map +1 -0
- package/dist/react/agent-ui/chat-activity.d.ts +13 -0
- package/dist/react/agent-ui/chat-activity.d.ts.map +1 -0
- package/dist/react/agent-ui/chat-activity.js +26 -0
- package/dist/react/agent-ui/chat-activity.js.map +1 -0
- package/dist/react/agent-ui/chat-confirm.d.ts +28 -0
- package/dist/react/agent-ui/chat-confirm.d.ts.map +1 -0
- package/dist/react/agent-ui/chat-confirm.js +140 -0
- package/dist/react/agent-ui/chat-confirm.js.map +1 -0
- package/dist/react/agent-ui/chat.d.ts +7 -0
- package/dist/react/agent-ui/chat.d.ts.map +1 -0
- package/dist/react/agent-ui/chat.js +7 -0
- package/dist/react/agent-ui/chat.js.map +1 -0
- package/dist/react/agent-ui/dev.d.ts +12 -0
- package/dist/react/agent-ui/dev.d.ts.map +1 -0
- package/dist/react/agent-ui/dev.js +80 -0
- package/dist/react/agent-ui/dev.js.map +1 -0
- package/dist/react/agent-ui/runtime.d.ts +12 -0
- package/dist/react/agent-ui/runtime.d.ts.map +1 -0
- package/dist/react/agent-ui/runtime.js +50 -0
- package/dist/react/agent-ui/runtime.js.map +1 -0
- package/dist/react/agent-ui/use-agent-activity.d.ts +3 -0
- package/dist/react/agent-ui/use-agent-activity.d.ts.map +1 -0
- package/dist/react/agent-ui/use-agent-activity.js +7 -0
- package/dist/react/agent-ui/use-agent-activity.js.map +1 -0
- package/dist/react/agent-ui/use-agent-confirmations.d.ts +8 -0
- package/dist/react/agent-ui/use-agent-confirmations.d.ts.map +1 -0
- package/dist/react/agent-ui/use-agent-confirmations.js +12 -0
- package/dist/react/agent-ui/use-agent-confirmations.js.map +1 -0
- package/dist/react/agent-ui/use-agent-view.d.ts +11 -0
- package/dist/react/agent-ui/use-agent-view.d.ts.map +1 -0
- package/dist/react/agent-ui/use-agent-view.js +25 -0
- package/dist/react/agent-ui/use-agent-view.js.map +1 -0
- package/dist/react/chat/ask-fields.d.ts +13 -0
- package/dist/react/chat/ask-fields.d.ts.map +1 -0
- package/dist/react/chat/ask-fields.js +46 -0
- package/dist/react/chat/ask-fields.js.map +1 -0
- package/dist/react/chat/chat-ask.d.ts +32 -0
- package/dist/react/chat/chat-ask.d.ts.map +1 -0
- package/dist/react/chat/chat-ask.js +69 -0
- package/dist/react/chat/chat-ask.js.map +1 -0
- package/dist/react/chat/chat-composer.d.ts +18 -0
- package/dist/react/chat/chat-composer.d.ts.map +1 -0
- package/dist/react/chat/chat-composer.js +81 -0
- package/dist/react/chat/chat-composer.js.map +1 -0
- package/dist/react/chat/chat-root.d.ts +14 -0
- package/dist/react/chat/chat-root.d.ts.map +1 -0
- package/dist/react/chat/chat-root.js +21 -0
- package/dist/react/chat/chat-root.js.map +1 -0
- package/dist/react/chat/chat-thread.d.ts +18 -0
- package/dist/react/chat/chat-thread.d.ts.map +1 -0
- package/dist/react/chat/chat-thread.js +69 -0
- package/dist/react/chat/chat-thread.js.map +1 -0
- package/dist/react/chat/context.d.ts +6 -0
- package/dist/react/chat/context.d.ts.map +1 -0
- package/dist/react/chat/context.js +24 -0
- package/dist/react/chat/context.js.map +1 -0
- package/dist/react/chat/create.d.ts +15 -0
- package/dist/react/chat/create.d.ts.map +1 -0
- package/dist/react/chat/create.js +23 -0
- package/dist/react/chat/create.js.map +1 -0
- package/dist/react/chat/open-turns.d.ts +10 -0
- package/dist/react/chat/open-turns.d.ts.map +1 -0
- package/dist/react/chat/open-turns.js +60 -0
- package/dist/react/chat/open-turns.js.map +1 -0
- package/dist/react/chat/runtime.d.ts +156 -0
- package/dist/react/chat/runtime.d.ts.map +1 -0
- package/dist/react/chat/runtime.js +928 -0
- package/dist/react/chat/runtime.js.map +1 -0
- package/dist/react/chat/use-chat.d.ts +4 -0
- package/dist/react/chat/use-chat.d.ts.map +1 -0
- package/dist/react/chat/use-chat.js +22 -0
- package/dist/react/chat/use-chat.js.map +1 -0
- package/dist/react/chat/use-device-setup.d.ts +9 -0
- package/dist/react/chat/use-device-setup.d.ts.map +1 -0
- package/dist/react/chat/use-device-setup.js +17 -0
- package/dist/react/chat/use-device-setup.js.map +1 -0
- package/dist/react/hooks.d.ts +11 -0
- package/dist/react/hooks.d.ts.map +1 -0
- package/dist/react/hooks.js +32 -0
- package/dist/react/hooks.js.map +1 -0
- package/dist/react/index.d.ts +20 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +13 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/provider.d.ts +38 -0
- package/dist/react/provider.d.ts.map +1 -0
- package/dist/react/provider.js +126 -0
- package/dist/react/provider.js.map +1 -0
- package/dist/react/retry.d.ts +5 -0
- package/dist/react/retry.d.ts.map +1 -0
- package/dist/react/retry.js +22 -0
- package/dist/react/retry.js.map +1 -0
- package/dist/react/sync-bridge.d.ts +25 -0
- package/dist/react/sync-bridge.d.ts.map +1 -0
- package/dist/react/sync-bridge.js +65 -0
- package/dist/react/sync-bridge.js.map +1 -0
- package/dist/react/sync.d.ts +12 -0
- package/dist/react/sync.d.ts.map +1 -0
- package/dist/react/sync.js +36 -0
- package/dist/react/sync.js.map +1 -0
- package/dist/react/use-capability.d.ts +6 -0
- package/dist/react/use-capability.d.ts.map +1 -0
- package/dist/react/use-capability.js +21 -0
- package/dist/react/use-capability.js.map +1 -0
- package/dist/react/use-devices.d.ts +34 -0
- package/dist/react/use-devices.d.ts.map +1 -0
- package/dist/react/use-devices.js +93 -0
- package/dist/react/use-devices.js.map +1 -0
- package/dist/react/use-link-device.d.ts +42 -0
- package/dist/react/use-link-device.d.ts.map +1 -0
- package/dist/react/use-link-device.js +58 -0
- package/dist/react/use-link-device.js.map +1 -0
- package/dist/register.d.ts +7 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +2 -0
- package/dist/register.js.map +1 -0
- package/dist/session.d.ts +121 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +5 -0
- package/dist/session.js.map +1 -0
- package/package.json +62 -3
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
const TOGGLE_HINT = "Alt+Shift+A";
|
|
2
|
+
const MAX_LOG = 10;
|
|
3
|
+
function overlay(agentUi, clientId) {
|
|
4
|
+
const panel = document.createElement("aside");
|
|
5
|
+
panel.setAttribute("aria-label", "Parlor agent UI");
|
|
6
|
+
panel.hidden = true;
|
|
7
|
+
Object.assign(panel.style, {
|
|
8
|
+
position: "fixed",
|
|
9
|
+
right: "12px",
|
|
10
|
+
bottom: "12px",
|
|
11
|
+
width: "min(420px, calc(100vw - 24px))",
|
|
12
|
+
maxHeight: "60vh",
|
|
13
|
+
overflow: "auto",
|
|
14
|
+
zIndex: "2147483647",
|
|
15
|
+
background: "#111",
|
|
16
|
+
color: "#eee",
|
|
17
|
+
font: "12px/1.4 ui-monospace, monospace",
|
|
18
|
+
padding: "12px",
|
|
19
|
+
borderRadius: "8px",
|
|
20
|
+
boxShadow: "0 4px 24px rgba(0, 0, 0, 0.3)",
|
|
21
|
+
});
|
|
22
|
+
const header = document.createElement("div");
|
|
23
|
+
const log = document.createElement("ol");
|
|
24
|
+
log.style.margin = "8px 0";
|
|
25
|
+
log.style.paddingLeft = "28px";
|
|
26
|
+
const snapshot = document.createElement("pre");
|
|
27
|
+
snapshot.style.margin = "0";
|
|
28
|
+
snapshot.style.whiteSpace = "pre-wrap";
|
|
29
|
+
panel.append(header, log, snapshot);
|
|
30
|
+
document.body.append(panel);
|
|
31
|
+
const entries = [];
|
|
32
|
+
let lastStarted;
|
|
33
|
+
const render = () => {
|
|
34
|
+
header.textContent = `client ${clientId} (${TOGGLE_HINT} to close)`;
|
|
35
|
+
log.replaceChildren(...entries.map((text) => Object.assign(document.createElement("li"), { textContent: text })));
|
|
36
|
+
void agentUi.screen().then((screen) => {
|
|
37
|
+
snapshot.textContent = JSON.stringify(screen, null, 2);
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
const unsubscribe = agentUi.activity.subscribe(() => {
|
|
41
|
+
const { busy, last } = agentUi.activity.get();
|
|
42
|
+
if (!busy || !last || last.at === lastStarted)
|
|
43
|
+
return;
|
|
44
|
+
lastStarted = last.at;
|
|
45
|
+
const via = last.origin.name
|
|
46
|
+
? `${last.origin.via} ${last.origin.name}`
|
|
47
|
+
: last.origin.via;
|
|
48
|
+
entries.unshift(`${new Date(last.at).toLocaleTimeString()} ${last.op} from ${via}`);
|
|
49
|
+
entries.length = Math.min(entries.length, MAX_LOG);
|
|
50
|
+
if (!panel.hidden)
|
|
51
|
+
render();
|
|
52
|
+
});
|
|
53
|
+
let refresh;
|
|
54
|
+
const onKey = (event) => {
|
|
55
|
+
if (!(event.altKey && event.shiftKey && event.code === "KeyA"))
|
|
56
|
+
return;
|
|
57
|
+
panel.hidden = !panel.hidden;
|
|
58
|
+
clearInterval(refresh);
|
|
59
|
+
if (panel.hidden)
|
|
60
|
+
return;
|
|
61
|
+
render();
|
|
62
|
+
refresh = setInterval(render, 1000);
|
|
63
|
+
};
|
|
64
|
+
window.addEventListener("keydown", onKey);
|
|
65
|
+
return () => {
|
|
66
|
+
window.removeEventListener("keydown", onKey);
|
|
67
|
+
clearInterval(refresh);
|
|
68
|
+
unsubscribe();
|
|
69
|
+
panel.remove();
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
export function installAgentUiDevtools(agentUi, clientId) {
|
|
73
|
+
window.__parlor = { clientId, screen: () => agentUi.screen() };
|
|
74
|
+
const removeOverlay = overlay(agentUi, clientId);
|
|
75
|
+
return () => {
|
|
76
|
+
removeOverlay();
|
|
77
|
+
delete window.__parlor;
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=dev.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../../src/react/agent-ui/dev.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type AgentUiClient } from "@parlor/agent-ui/client";
|
|
2
|
+
import type { QueryClient } from "@tanstack/react-query";
|
|
3
|
+
import type { AnyRouter } from "@tanstack/react-router";
|
|
4
|
+
import type { ActionClient } from "../../action-client.js";
|
|
5
|
+
import type { RegisteredActions } from "../../register.js";
|
|
6
|
+
export interface AgentUiRuntimeInput {
|
|
7
|
+
readonly client: ActionClient<RegisteredActions>;
|
|
8
|
+
readonly queryClient: QueryClient;
|
|
9
|
+
readonly router: AnyRouter | undefined;
|
|
10
|
+
}
|
|
11
|
+
export declare function createAgentUiRuntime({ client, queryClient, router, }: AgentUiRuntimeInput): AgentUiClient;
|
|
12
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/react/agent-ui/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAuB,MAAM,yBAAyB,CAAC;AAElF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC,iBAAiB,CAAC,CAAC;IACjD,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC;CACxC;AAqBD,wBAAgB,oBAAoB,CAAC,EACnC,MAAM,EACN,WAAW,EACX,MAAM,GACP,EAAE,mBAAmB,GAAG,aAAa,CA2BrC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { createAgentUiClient } from "@parlor/agent-ui/client";
|
|
2
|
+
import { detectPlatform } from "@parlor/capabilities";
|
|
3
|
+
import { ACTION_QUERY_PREFIX } from "../../query-keys.js";
|
|
4
|
+
function fetchingActions(queryClient) {
|
|
5
|
+
return queryClient.isFetching({ queryKey: ACTION_QUERY_PREFIX });
|
|
6
|
+
}
|
|
7
|
+
function actionsSettled(queryClient, timeoutMs) {
|
|
8
|
+
if (fetchingActions(queryClient) === 0)
|
|
9
|
+
return Promise.resolve();
|
|
10
|
+
return new Promise((resolve) => {
|
|
11
|
+
const done = () => {
|
|
12
|
+
unsubscribe();
|
|
13
|
+
clearTimeout(timer);
|
|
14
|
+
resolve();
|
|
15
|
+
};
|
|
16
|
+
const unsubscribe = queryClient.getQueryCache().subscribe(() => {
|
|
17
|
+
if (fetchingActions(queryClient) === 0)
|
|
18
|
+
done();
|
|
19
|
+
});
|
|
20
|
+
const timer = setTimeout(done, timeoutMs);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
export function createAgentUiRuntime({ client, queryClient, router, }) {
|
|
24
|
+
return createAgentUiClient({
|
|
25
|
+
router,
|
|
26
|
+
queries: {
|
|
27
|
+
active: () => queryClient
|
|
28
|
+
.getQueryCache()
|
|
29
|
+
.findAll({ queryKey: ACTION_QUERY_PREFIX, type: "active" })
|
|
30
|
+
.map((query) => ({
|
|
31
|
+
action: String(query.queryKey[ACTION_QUERY_PREFIX.length]),
|
|
32
|
+
input: query.queryKey[ACTION_QUERY_PREFIX.length + 1] ?? {},
|
|
33
|
+
status: query.state.status,
|
|
34
|
+
})),
|
|
35
|
+
settled: (timeoutMs) => actionsSettled(queryClient, timeoutMs),
|
|
36
|
+
},
|
|
37
|
+
send: async (message) => {
|
|
38
|
+
const response = await client.request(`${client.basePath}/ui`, {
|
|
39
|
+
method: "POST",
|
|
40
|
+
headers: { "content-type": "application/json" },
|
|
41
|
+
body: JSON.stringify(message),
|
|
42
|
+
keepalive: message.type !== "reply",
|
|
43
|
+
});
|
|
44
|
+
return response.status === 200 ? response.text() : undefined;
|
|
45
|
+
},
|
|
46
|
+
platform: detectPlatform(),
|
|
47
|
+
dev: import.meta.env.DEV,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/react/agent-ui/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAClF,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAKtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAS1D,SAAS,eAAe,CAAC,WAAwB;IAC/C,OAAO,WAAW,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,mBAAmB,EAAE,CAAC,CAAC;AACnE,CAAC;AAED,SAAS,cAAc,CAAC,WAAwB,EAAE,SAAiB;IACjE,IAAI,eAAe,CAAC,WAAW,CAAC,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IACjE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,WAAW,EAAE,CAAC;YACd,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QACF,MAAM,WAAW,GAAG,WAAW,CAAC,aAAa,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE;YAC7D,IAAI,eAAe,CAAC,WAAW,CAAC,KAAK,CAAC;gBAAE,IAAI,EAAE,CAAC;QACjD,CAAC,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,EACnC,MAAM,EACN,WAAW,EACX,MAAM,GACc;IACpB,OAAO,mBAAmB,CAAC;QACzB,MAAM;QACN,OAAO,EAAE;YACP,MAAM,EAAE,GAAG,EAAE,CACX,WAAW;iBACR,aAAa,EAAE;iBACf,OAAO,CAAC,EAAE,QAAQ,EAAE,mBAAmB,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;iBAC1D,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACf,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;gBAC1D,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,mBAAmB,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE;gBAC3D,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM;aAC3B,CAAC,CAAC;YACP,OAAO,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,cAAc,CAAC,WAAW,EAAE,SAAS,CAAC;SAC/D;QACD,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YACtB,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC,QAAQ,KAAK,EAAE;gBAC7D,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;gBAC7B,SAAS,EAAE,OAAO,CAAC,IAAI,KAAK,OAAO;aACpC,CAAC,CAAC;YACH,OAAO,QAAQ,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QAC/D,CAAC;QACD,QAAQ,EAAE,cAAc,EAAE;QAC1B,GAAG,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG;KACzB,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-agent-activity.d.ts","sourceRoot":"","sources":["../../../src/react/agent-ui/use-agent-activity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAK7D,wBAAgB,gBAAgB,IAAI,aAAa,CAGhD"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { useSyncExternalStore } from "react";
|
|
2
|
+
import { useFramework } from "../provider.js";
|
|
3
|
+
export function useAgentActivity() {
|
|
4
|
+
const { activity } = useFramework().agentUi;
|
|
5
|
+
return useSyncExternalStore(activity.subscribe, activity.get, activity.get);
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=use-agent-activity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-agent-activity.js","sourceRoot":"","sources":["../../../src/react/agent-ui/use-agent-activity.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAE7C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,MAAM,UAAU,gBAAgB;IAC9B,MAAM,EAAE,QAAQ,EAAE,GAAG,YAAY,EAAE,CAAC,OAAO,CAAC;IAC5C,OAAO,oBAAoB,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC;AAC9E,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AgentConfirmation } from "@parlor/agent-ui/client";
|
|
2
|
+
/**
|
|
3
|
+
* The agent requests waiting for this user's approval on this client, newest last. Headless:
|
|
4
|
+
* the app draws the card and calls `approve` or `decline`. Rendering this hook is what tells
|
|
5
|
+
* the server this client can show a confirmation; render it where it is always mounted.
|
|
6
|
+
*/
|
|
7
|
+
export declare function useAgentConfirmations(): readonly AgentConfirmation[];
|
|
8
|
+
//# sourceMappingURL=use-agent-confirmations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-agent-confirmations.d.ts","sourceRoot":"","sources":["../../../src/react/agent-ui/use-agent-confirmations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAKjE;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,SAAS,iBAAiB,EAAE,CAOpE"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { useSyncExternalStore } from "react";
|
|
2
|
+
import { useFramework } from "../provider.js";
|
|
3
|
+
/**
|
|
4
|
+
* The agent requests waiting for this user's approval on this client, newest last. Headless:
|
|
5
|
+
* the app draws the card and calls `approve` or `decline`. Rendering this hook is what tells
|
|
6
|
+
* the server this client can show a confirmation; render it where it is always mounted.
|
|
7
|
+
*/
|
|
8
|
+
export function useAgentConfirmations() {
|
|
9
|
+
const { confirmations } = useFramework().agentUi;
|
|
10
|
+
return useSyncExternalStore(confirmations.subscribe, confirmations.get, confirmations.get);
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=use-agent-confirmations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-agent-confirmations.js","sourceRoot":"","sources":["../../../src/react/agent-ui/use-agent-confirmations.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAE7C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C;;;;GAIG;AACH,MAAM,UAAU,qBAAqB;IACnC,MAAM,EAAE,aAAa,EAAE,GAAG,YAAY,EAAE,CAAC,OAAO,CAAC;IACjD,OAAO,oBAAoB,CACzB,aAAa,CAAC,SAAS,EACvB,aAAa,CAAC,GAAG,EACjB,aAAa,CAAC,GAAG,CAClB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { AgentViewBinding, AnyAgentView, WritableField } from "@parlor/agent-ui";
|
|
2
|
+
export interface AgentViewHandle<D extends AnyAgentView = AnyAgentView> {
|
|
3
|
+
readonly ref: (element: Element | null) => void;
|
|
4
|
+
/**
|
|
5
|
+
* Fields the agent wrote that still hold what it wrote, for the app to style; the user
|
|
6
|
+
* changing a field removes it. Always empty for a read-only view.
|
|
7
|
+
*/
|
|
8
|
+
readonly agentFields: ReadonlySet<WritableField<D>>;
|
|
9
|
+
}
|
|
10
|
+
export declare function useAgentView<D extends AnyAgentView>(view: D, binding: AgentViewBinding<D>): AgentViewHandle<D>;
|
|
11
|
+
//# sourceMappingURL=use-agent-view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-agent-view.d.ts","sourceRoot":"","sources":["../../../src/react/agent-ui/use-agent-view.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAOtF,MAAM,WAAW,eAAe,CAAC,CAAC,SAAS,YAAY,GAAG,YAAY;IACpE,QAAQ,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,CAAC;IAChD;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;CACrD;AAYD,wBAAgB,YAAY,CAAC,CAAC,SAAS,YAAY,EACjD,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAC3B,eAAe,CAAC,CAAC,CAAC,CASpB"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { agentFieldsOf } from "@parlor/agent-ui/client";
|
|
2
|
+
import { useEffect, useInsertionEffect, useState, useSyncExternalStore } from "react";
|
|
3
|
+
import { flushSync } from "react-dom";
|
|
4
|
+
import { useFramework } from "../provider.js";
|
|
5
|
+
function committing(binding) {
|
|
6
|
+
const { set } = binding;
|
|
7
|
+
if (!set)
|
|
8
|
+
return binding;
|
|
9
|
+
return {
|
|
10
|
+
key: binding.key,
|
|
11
|
+
get: binding.get,
|
|
12
|
+
set: (next, changed) => flushSync(() => set(next, changed)),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function useAgentView(view, binding) {
|
|
16
|
+
const { agentUi } = useFramework();
|
|
17
|
+
const erased = committing(binding);
|
|
18
|
+
const [slot] = useState(() => agentUi.views.track(view, erased));
|
|
19
|
+
useInsertionEffect(() => slot.bind(erased));
|
|
20
|
+
useEffect(() => slot.mount(binding.key), [slot, binding.key]);
|
|
21
|
+
const writes = useSyncExternalStore(slot.subscribeWrites, slot.writes, slot.writes);
|
|
22
|
+
const agentFields = agentFieldsOf(writes, writes.size === 0 ? {} : binding.get());
|
|
23
|
+
return { ref: slot.ref, agentFields };
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=use-agent-view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-agent-view.js","sourceRoot":"","sources":["../../../src/react/agent-ui/use-agent-view.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAuB,MAAM,yBAAyB,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AACtF,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAW9C,SAAS,UAAU,CAAC,OAAuC;IACzD,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;IACxB,IAAI,CAAC,GAAG;QAAE,OAAO,OAAO,CAAC;IACzB,OAAO;QACL,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,GAAG,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;KAC5D,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,IAAO,EACP,OAA4B;IAE5B,MAAM,EAAE,OAAO,EAAE,GAAG,YAAY,EAAE,CAAC;IACnC,MAAM,MAAM,GAAG,UAAU,CAAC,OAAoD,CAAC,CAAC;IAChF,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IACjE,kBAAkB,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5C,SAAS,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9D,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACpF,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAClF,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,WAAW,EAAwB,CAAC;AAC9D,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface AskField {
|
|
2
|
+
readonly name: string;
|
|
3
|
+
readonly label: string;
|
|
4
|
+
readonly type: "number" | "checkbox" | "text";
|
|
5
|
+
readonly integer: boolean;
|
|
6
|
+
readonly required: boolean;
|
|
7
|
+
}
|
|
8
|
+
export type AskValues = Record<string, string | number | boolean>;
|
|
9
|
+
/** One field per property of a form ask's JSON Schema object, in schema order. */
|
|
10
|
+
export declare function askFields(form: Readonly<Record<string, unknown>>): AskField[];
|
|
11
|
+
/** What a filled form answers: numbers as numbers, checkboxes as booleans, blanks left out. */
|
|
12
|
+
export declare function askValues(fields: readonly AskField[], form: HTMLFormElement): AskValues;
|
|
13
|
+
//# sourceMappingURL=ask-fields.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ask-fields.d.ts","sourceRoot":"","sources":["../../../src/react/chat/ask-fields.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;IAC9C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;AAkBlE,kFAAkF;AAClF,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,QAAQ,EAAE,CAY7E;AAED,+FAA+F;AAC/F,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS,QAAQ,EAAE,EAAE,IAAI,EAAE,eAAe,GAAG,SAAS,CAWvF"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2
|
+
function typeOf(schema) {
|
|
3
|
+
switch (schema.type) {
|
|
4
|
+
case "integer":
|
|
5
|
+
return { type: "number", integer: true };
|
|
6
|
+
case "number":
|
|
7
|
+
return { type: "number", integer: false };
|
|
8
|
+
case "boolean":
|
|
9
|
+
return { type: "checkbox", integer: false };
|
|
10
|
+
default:
|
|
11
|
+
return { type: "text", integer: false };
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/** One field per property of a form ask's JSON Schema object, in schema order. */
|
|
15
|
+
export function askFields(form) {
|
|
16
|
+
const properties = isRecord(form.properties) ? form.properties : {};
|
|
17
|
+
const required = Array.isArray(form.required) ? form.required : [];
|
|
18
|
+
return Object.entries(properties).map(([name, property]) => {
|
|
19
|
+
const schema = isRecord(property) ? property : {};
|
|
20
|
+
return {
|
|
21
|
+
name,
|
|
22
|
+
label: typeof schema.title === "string" ? schema.title : name,
|
|
23
|
+
required: required.includes(name),
|
|
24
|
+
...typeOf(schema),
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
/** What a filled form answers: numbers as numbers, checkboxes as booleans, blanks left out. */
|
|
29
|
+
export function askValues(fields, form) {
|
|
30
|
+
const values = {};
|
|
31
|
+
for (const field of fields) {
|
|
32
|
+
const input = form.elements.namedItem(field.name);
|
|
33
|
+
if (!(input instanceof HTMLInputElement))
|
|
34
|
+
continue;
|
|
35
|
+
if (field.type === "checkbox")
|
|
36
|
+
values[field.name] = input.checked;
|
|
37
|
+
else if (input.value === "")
|
|
38
|
+
continue;
|
|
39
|
+
else if (field.type === "number")
|
|
40
|
+
values[field.name] = Number(input.value);
|
|
41
|
+
else
|
|
42
|
+
values[field.name] = input.value;
|
|
43
|
+
}
|
|
44
|
+
return values;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=ask-fields.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ask-fields.js","sourceRoot":"","sources":["../../../src/react/chat/ask-fields.ts"],"names":[],"mappings":"AAUA,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAoC,EAAE,CACpE,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAEvE,SAAS,MAAM,CAAC,MAA+B;IAC7C,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,SAAS;YACZ,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3C,KAAK,QAAQ;YACX,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC5C,KAAK,SAAS;YACZ,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC9C;YACE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC5C,CAAC;AACH,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,SAAS,CAAC,IAAuC;IAC/D,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;IACpE,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IACnE,OAAO,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE;QACzD,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAClD,OAAO;YACL,IAAI;YACJ,KAAK,EAAE,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;YAC7D,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;YACjC,GAAG,MAAM,CAAC,MAAM,CAAC;SAClB,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,SAAS,CAAC,MAA2B,EAAE,IAAqB;IAC1E,MAAM,MAAM,GAAc,EAAE,CAAC;IAC7B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClD,IAAI,CAAC,CAAC,KAAK,YAAY,gBAAgB,CAAC;YAAE,SAAS;QACnD,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;YAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC;aAC7D,IAAI,KAAK,CAAC,KAAK,KAAK,EAAE;YAAE,SAAS;aACjC,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;;YACtE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;IACxC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { AgentConfirmation } from "@parlor/agent-ui/client";
|
|
2
|
+
import type { ChatItem } from "@parlor/chat";
|
|
3
|
+
import { type ComponentProps, type ReactNode } from "react";
|
|
4
|
+
type AskItem = Extract<ChatItem<AgentConfirmation>, {
|
|
5
|
+
kind: "ask";
|
|
6
|
+
}>;
|
|
7
|
+
export interface ChatAskProps extends ComponentProps<"div"> {
|
|
8
|
+
readonly item: AskItem;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The agent's own permission prompt or question: `role="group"` named by its question.
|
|
12
|
+
* `data-approval` is `presence` (answering triggers the OS prompt) or `computer` (answered
|
|
13
|
+
* on the computer; choices disabled). `data-state` is `open`, `answered` or `closed`.
|
|
14
|
+
* Escape declines.
|
|
15
|
+
*/
|
|
16
|
+
export declare function Ask({ item, onKeyDown, ...props }: ChatAskProps): ReactNode;
|
|
17
|
+
export interface ChatAskChoiceProps extends ComponentProps<"button"> {
|
|
18
|
+
readonly choice: AskItem["choices"][number];
|
|
19
|
+
}
|
|
20
|
+
/** `type="button"`; answers the enclosing ask with this choice. */
|
|
21
|
+
export declare function AskChoice({ choice, onClick, ...props }: ChatAskChoiceProps): ReactNode;
|
|
22
|
+
export type ChatAskFormProps = ComponentProps<"form">;
|
|
23
|
+
/**
|
|
24
|
+
* A form ask's `<form>`: one `<input name="{property}">` per property of its schema (`number`
|
|
25
|
+
* for numbers and integers, `checkbox` for booleans, text otherwise). Submitting answers the
|
|
26
|
+
* ask with its allow choice and the values typed per the schema. Its children, a submit
|
|
27
|
+
* button for one, go after the inputs. Everything is disabled once the ask is not open or
|
|
28
|
+
* is answered on the computer. Renders nothing for an ask without a form.
|
|
29
|
+
*/
|
|
30
|
+
export declare function AskForm({ onSubmit, children, ...props }: ChatAskFormProps): ReactNode;
|
|
31
|
+
export {};
|
|
32
|
+
//# sourceMappingURL=chat-ask.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-ask.d.ts","sourceRoot":"","sources":["../../../src/react/chat/chat-ask.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EACL,KAAK,cAAc,EAGnB,KAAK,SAAS,EAGf,MAAM,OAAO,CAAC;AAKf,KAAK,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC;AAOrE,MAAM,WAAW,YAAa,SAAQ,cAAc,CAAC,KAAK,CAAC;IACzD,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;CACxB;AAED;;;;;GAKG;AACH,wBAAgB,GAAG,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,YAAY,GAAG,SAAS,CAyB1E;AAED,MAAM,WAAW,kBAAmB,SAAQ,cAAc,CAAC,QAAQ,CAAC;IAClE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;CAC7C;AAED,mEAAmE;AACnE,wBAAgB,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,kBAAkB,GAAG,SAAS,CAmBtF;AAID,MAAM,MAAM,gBAAgB,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;AAEtD;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,gBAAgB,GAAG,SAAS,CA2BrF"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, use, useMemo, } from "react";
|
|
3
|
+
import { askFields, askValues } from "./ask-fields.js";
|
|
4
|
+
import { useChatRuntime } from "./context.js";
|
|
5
|
+
const AskScope = createContext(undefined);
|
|
6
|
+
const report = (error) => console.error("[parlor] The chat could not answer:", error);
|
|
7
|
+
/**
|
|
8
|
+
* The agent's own permission prompt or question: `role="group"` named by its question.
|
|
9
|
+
* `data-approval` is `presence` (answering triggers the OS prompt) or `computer` (answered
|
|
10
|
+
* on the computer; choices disabled). `data-state` is `open`, `answered` or `closed`.
|
|
11
|
+
* Escape declines.
|
|
12
|
+
*/
|
|
13
|
+
export function Ask({ item, onKeyDown, ...props }) {
|
|
14
|
+
const runtime = useChatRuntime("Chat.Ask");
|
|
15
|
+
const decline = (event) => {
|
|
16
|
+
onKeyDown?.(event);
|
|
17
|
+
if (event.defaultPrevented || event.key !== "Escape")
|
|
18
|
+
return;
|
|
19
|
+
const rejection = item.choices.find((choice) => choice.effect.startsWith("reject"));
|
|
20
|
+
if (!rejection || item.answer.state !== "open" || item.approval === "computer")
|
|
21
|
+
return;
|
|
22
|
+
event.preventDefault();
|
|
23
|
+
event.stopPropagation();
|
|
24
|
+
runtime.answer(item.id, rejection.id).catch(report);
|
|
25
|
+
};
|
|
26
|
+
return (_jsx(AskScope, { value: item, children: _jsx("div", { role: "group", "aria-label": item.question, tabIndex: -1, ...props, "data-approval": item.approval, "data-state": item.answer.state, onKeyDown: decline }) }));
|
|
27
|
+
}
|
|
28
|
+
/** `type="button"`; answers the enclosing ask with this choice. */
|
|
29
|
+
export function AskChoice({ choice, onClick, ...props }) {
|
|
30
|
+
const runtime = useChatRuntime("Chat.AskChoice");
|
|
31
|
+
const ask = use(AskScope);
|
|
32
|
+
if (!ask)
|
|
33
|
+
throw new Error("Chat.AskChoice must be rendered inside Chat.Ask.");
|
|
34
|
+
return (_jsx("button", { type: "button", disabled: ask.approval === "computer" || ask.answer.state !== "open", "data-effect": choice.effect, "aria-pressed": ask.answer.state === "answered" ? ask.answer.choice === choice.id : undefined, ...props, onClick: (event) => {
|
|
35
|
+
onClick?.(event);
|
|
36
|
+
if (!event.defaultPrevented)
|
|
37
|
+
runtime.answer(ask.id, choice.id).catch(report);
|
|
38
|
+
} }));
|
|
39
|
+
}
|
|
40
|
+
const isAllow = (choice) => choice.effect.startsWith("allow");
|
|
41
|
+
/**
|
|
42
|
+
* A form ask's `<form>`: one `<input name="{property}">` per property of its schema (`number`
|
|
43
|
+
* for numbers and integers, `checkbox` for booleans, text otherwise). Submitting answers the
|
|
44
|
+
* ask with its allow choice and the values typed per the schema. Its children, a submit
|
|
45
|
+
* button for one, go after the inputs. Everything is disabled once the ask is not open or
|
|
46
|
+
* is answered on the computer. Renders nothing for an ask without a form.
|
|
47
|
+
*/
|
|
48
|
+
export function AskForm({ onSubmit, children, ...props }) {
|
|
49
|
+
const runtime = useChatRuntime("Chat.AskForm");
|
|
50
|
+
const ask = use(AskScope);
|
|
51
|
+
if (!ask)
|
|
52
|
+
throw new Error("Chat.AskForm must be rendered inside Chat.Ask.");
|
|
53
|
+
const { form } = ask;
|
|
54
|
+
const fields = useMemo(() => (form ? askFields(form) : []), [form]);
|
|
55
|
+
const accept = ask.choices.find(isAllow);
|
|
56
|
+
if (!form || !accept)
|
|
57
|
+
return null;
|
|
58
|
+
return (_jsx("form", { ...props, onSubmit: (event) => {
|
|
59
|
+
onSubmit?.(event);
|
|
60
|
+
event.preventDefault();
|
|
61
|
+
runtime
|
|
62
|
+
.answer(ask.id, accept.id, askValues(fields, event.currentTarget))
|
|
63
|
+
.catch(report);
|
|
64
|
+
}, children: _jsxs("fieldset", { disabled: ask.approval === "computer" || ask.answer.state !== "open", children: [fields.map((field) => (_jsx(AskInput, { field: field }, field.name))), children] }) }));
|
|
65
|
+
}
|
|
66
|
+
function AskInput({ field }) {
|
|
67
|
+
return (_jsxs("label", { "data-type": field.type, children: [_jsx("span", { children: field.label }), _jsx("input", { name: field.name, type: field.type, required: field.required && field.type !== "checkbox", step: field.type === "number" ? (field.integer ? 1 : "any") : undefined })] }));
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=chat-ask.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-ask.js","sourceRoot":"","sources":["../../../src/react/chat/chat-ask.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ComponentProps, ReactNode } from "react";
|
|
2
|
+
/** A `<form>` whose submit sends the draft; `data-running` while a turn runs. */
|
|
3
|
+
export declare function Composer({ onSubmit, ...props }: ComponentProps<"form">): ReactNode;
|
|
4
|
+
/**
|
|
5
|
+
* A `<textarea>` bound to the draft: Enter sends, Shift+Enter breaks the line, IME
|
|
6
|
+
* composition never sends. Disabled while no agent can be chosen.
|
|
7
|
+
*/
|
|
8
|
+
export declare function Input({ onChange, onKeyDown, ...props }: Omit<ComponentProps<"textarea">, "value" | "defaultValue">): ReactNode;
|
|
9
|
+
/** `type="submit"`; disabled while the draft is empty or no agent is chosen. */
|
|
10
|
+
export declare function Send({ children, ...props }: ComponentProps<"button">): ReactNode;
|
|
11
|
+
/** `type="button"`; rendered only while a turn runs. Stops it, keeping the partial text. */
|
|
12
|
+
export declare function Stop({ children, onClick, ...props }: ComponentProps<"button">): ReactNode;
|
|
13
|
+
/**
|
|
14
|
+
* The chat's state in words, for a live region: a `p[role=status]` that is empty when
|
|
15
|
+
* there is nothing to say, so a wait never shows without text. `children` replaces the text.
|
|
16
|
+
*/
|
|
17
|
+
export declare function Status({ children, ...props }: ComponentProps<"p">): ReactNode;
|
|
18
|
+
//# sourceMappingURL=chat-composer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-composer.d.ts","sourceRoot":"","sources":["../../../src/react/chat/chat-composer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAC;AAQtE,iFAAiF;AACjF,wBAAgB,QAAQ,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,cAAc,CAAC,MAAM,CAAC,GAAG,SAAS,CAiBlF;AAED;;;GAGG;AACH,wBAAgB,KAAK,CAAC,EACpB,QAAQ,EACR,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,EAAE,OAAO,GAAG,cAAc,CAAC,GAAG,SAAS,CAuBxE;AAED,gFAAgF;AAChF,wBAAgB,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,cAAc,CAAC,QAAQ,CAAC,GAAG,SAAS,CAOhF;AAED,4FAA4F;AAC5F,wBAAgB,IAAI,CAAC,EACnB,QAAQ,EACR,OAAO,EACP,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,QAAQ,CAAC,GAAG,SAAS,CAgBtC;AAgBD;;;GAGG;AACH,wBAAgB,MAAM,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,cAAc,CAAC,GAAG,CAAC,GAAG,SAAS,CAO7E"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { canSend, useChatRuntime, useChatState } from "./context.js";
|
|
3
|
+
const report = (error) => console.error("[parlor] The chat could not do that:", error);
|
|
4
|
+
/** A `<form>` whose submit sends the draft; `data-running` while a turn runs. */
|
|
5
|
+
export function Composer({ onSubmit, ...props }) {
|
|
6
|
+
const runtime = useChatRuntime("Chat.Composer");
|
|
7
|
+
const state = useChatState("Chat.Composer");
|
|
8
|
+
const submit = (event) => {
|
|
9
|
+
onSubmit?.(event);
|
|
10
|
+
event.preventDefault();
|
|
11
|
+
if (canSend(state))
|
|
12
|
+
runtime.send().catch(report);
|
|
13
|
+
};
|
|
14
|
+
return (_jsx("form", { ...props, onSubmit: submit, "data-running": state.status === "running" ? "" : undefined }));
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A `<textarea>` bound to the draft: Enter sends, Shift+Enter breaks the line, IME
|
|
18
|
+
* composition never sends. Disabled while no agent can be chosen.
|
|
19
|
+
*/
|
|
20
|
+
export function Input({ onChange, onKeyDown, ...props }) {
|
|
21
|
+
const runtime = useChatRuntime("Chat.Input");
|
|
22
|
+
const state = useChatState("Chat.Input");
|
|
23
|
+
const keyDown = (event) => {
|
|
24
|
+
onKeyDown?.(event);
|
|
25
|
+
if (event.defaultPrevented || event.key !== "Enter" || event.shiftKey)
|
|
26
|
+
return;
|
|
27
|
+
if (event.nativeEvent.isComposing)
|
|
28
|
+
return;
|
|
29
|
+
event.preventDefault();
|
|
30
|
+
if (canSend(state))
|
|
31
|
+
runtime.send().catch(report);
|
|
32
|
+
};
|
|
33
|
+
return (_jsx("textarea", { "aria-label": "Message", disabled: state.agent === undefined || state.status === "unavailable", ...props, value: state.draft, onChange: (event) => {
|
|
34
|
+
onChange?.(event);
|
|
35
|
+
runtime.setDraft(event.target.value);
|
|
36
|
+
}, onKeyDown: keyDown }));
|
|
37
|
+
}
|
|
38
|
+
/** `type="submit"`; disabled while the draft is empty or no agent is chosen. */
|
|
39
|
+
export function Send({ children, ...props }) {
|
|
40
|
+
const state = useChatState("Chat.Send");
|
|
41
|
+
return (_jsx("button", { type: "submit", disabled: !canSend(state), ...props, children: children ?? "Send" }));
|
|
42
|
+
}
|
|
43
|
+
/** `type="button"`; rendered only while a turn runs. Stops it, keeping the partial text. */
|
|
44
|
+
export function Stop({ children, onClick, ...props }) {
|
|
45
|
+
const runtime = useChatRuntime("Chat.Stop");
|
|
46
|
+
const state = useChatState("Chat.Stop");
|
|
47
|
+
if (state.status !== "running" && state.status !== "waiting")
|
|
48
|
+
return null;
|
|
49
|
+
return (_jsx("button", { type: "button", ...props, onClick: (event) => {
|
|
50
|
+
onClick?.(event);
|
|
51
|
+
if (!event.defaultPrevented)
|
|
52
|
+
runtime.stop().catch(report);
|
|
53
|
+
}, children: children ?? "Stop" }));
|
|
54
|
+
}
|
|
55
|
+
function statusText({ status, wait, setup, link, presenceDue }) {
|
|
56
|
+
if (setup?.step === "passkey")
|
|
57
|
+
return "Waiting for the passkey";
|
|
58
|
+
if (link.status === "unlinked")
|
|
59
|
+
return "Link this device to send messages";
|
|
60
|
+
if (wait) {
|
|
61
|
+
return wait.reason === "offline"
|
|
62
|
+
? `Waiting for ${wait.hostName} to come online`
|
|
63
|
+
: `Waiting for ${wait.hostName} to approve this device`;
|
|
64
|
+
}
|
|
65
|
+
if (status === "sending")
|
|
66
|
+
return "Sending...";
|
|
67
|
+
if (status === "running")
|
|
68
|
+
return "Working...";
|
|
69
|
+
if (presenceDue)
|
|
70
|
+
return "Sending will ask for Face ID or Touch ID";
|
|
71
|
+
return "";
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The chat's state in words, for a live region: a `p[role=status]` that is empty when
|
|
75
|
+
* there is nothing to say, so a wait never shows without text. `children` replaces the text.
|
|
76
|
+
*/
|
|
77
|
+
export function Status({ children, ...props }) {
|
|
78
|
+
const state = useChatState("Chat.Status");
|
|
79
|
+
return (_jsx("p", { role: "status", ...props, "data-status": state.status, "data-wait": state.wait?.reason, children: children ?? statusText(state) }));
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=chat-composer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-composer.js","sourceRoot":"","sources":["../../../src/react/chat/chat-composer.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAGrE,MAAM,MAAM,GAAG,CAAC,KAAc,EAAE,EAAE,CAChC,OAAO,CAAC,KAAK,CAAC,sCAAsC,EAAE,KAAK,CAAC,CAAC;AAE/D,iFAAiF;AACjF,MAAM,UAAU,QAAQ,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAA0B;IACrE,MAAM,OAAO,GAAG,cAAc,CAAC,eAAe,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,YAAY,CAAC,eAAe,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,CACb,KAAqE,EACrE,EAAE;QACF,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC;QAClB,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,IAAI,OAAO,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACnD,CAAC,CAAC;IACF,OAAO,CACL,kBACM,KAAK,EACT,QAAQ,EAAE,MAAM,kBACF,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,GACzD,CACH,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,KAAK,CAAC,EACpB,QAAQ,EACR,SAAS,EACT,GAAG,KAAK,EACmD;IAC3D,MAAM,OAAO,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,CAAC,KAAyC,EAAE,EAAE;QAC5D,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC;QACnB,IAAI,KAAK,CAAC,gBAAgB,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,IAAI,KAAK,CAAC,QAAQ;YAAE,OAAO;QAC9E,IAAI,KAAK,CAAC,WAAW,CAAC,WAAW;YAAE,OAAO;QAC1C,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,IAAI,OAAO,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACnD,CAAC,CAAC;IACF,OAAO,CACL,iCACa,SAAS,EACpB,QAAQ,EAAE,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,KAAK,aAAa,KACjE,KAAK,EACT,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;YAClB,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC;YAClB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvC,CAAC,EACD,SAAS,EAAE,OAAO,GAClB,CACH,CAAC;AACJ,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAA4B;IACnE,MAAM,KAAK,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;IACxC,OAAO,CACL,iBAAQ,IAAI,EAAC,QAAQ,EAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,KAAM,KAAK,YACvD,QAAQ,IAAI,MAAM,GACZ,CACV,CAAC;AACJ,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,IAAI,CAAC,EACnB,QAAQ,EACR,OAAO,EACP,GAAG,KAAK,EACiB;IACzB,MAAM,OAAO,GAAG,cAAc,CAAC,WAAW,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;IACxC,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC1E,OAAO,CACL,iBACE,IAAI,EAAC,QAAQ,KACT,KAAK,EACT,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACjB,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;YACjB,IAAI,CAAC,KAAK,CAAC,gBAAgB;gBAAE,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC5D,CAAC,YAEA,QAAQ,IAAI,MAAM,GACZ,CACV,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAa;IACvE,IAAI,KAAK,EAAE,IAAI,KAAK,SAAS;QAAE,OAAO,yBAAyB,CAAC;IAChE,IAAI,IAAI,CAAC,MAAM,KAAK,UAAU;QAAE,OAAO,mCAAmC,CAAC;IAC3E,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,IAAI,CAAC,MAAM,KAAK,SAAS;YAC9B,CAAC,CAAC,eAAe,IAAI,CAAC,QAAQ,iBAAiB;YAC/C,CAAC,CAAC,eAAe,IAAI,CAAC,QAAQ,yBAAyB,CAAC;IAC5D,CAAC;IACD,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,YAAY,CAAC;IAC9C,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,YAAY,CAAC;IAC9C,IAAI,WAAW;QAAE,OAAO,0CAA0C,CAAC;IACnE,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,MAAM,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAuB;IAChE,MAAM,KAAK,GAAG,YAAY,CAAC,aAAa,CAAC,CAAC;IAC1C,OAAO,CACL,YAAG,IAAI,EAAC,QAAQ,KAAK,KAAK,iBAAe,KAAK,CAAC,MAAM,eAAa,KAAK,CAAC,IAAI,EAAE,MAAM,YACjF,QAAQ,IAAI,UAAU,CAAC,KAAK,CAAC,GAC5B,CACL,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
export interface ChatRootProps {
|
|
3
|
+
/** The thread to show. When omitted, the most recent one, or a blank one for a user with none. */
|
|
4
|
+
readonly threadId?: string | undefined;
|
|
5
|
+
readonly children: ReactNode;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Owns one chat runtime for its subtree: the `chat` channel on the existing sync stream,
|
|
9
|
+
* its thread in presence `watching` so inline confirmations reach this client, and the
|
|
10
|
+
* confirmation subscription. Renders no DOM of its own. When the signed-in user changes,
|
|
11
|
+
* the subtree remounts with a fresh runtime, so nothing of the previous user remains.
|
|
12
|
+
*/
|
|
13
|
+
export declare function Root({ threadId, children }: ChatRootProps): ReactNode;
|
|
14
|
+
//# sourceMappingURL=chat-root.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-root.d.ts","sourceRoot":"","sources":["../../../src/react/chat/chat-root.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAsB,MAAM,OAAO,CAAC;AAM3D,MAAM,WAAW,aAAa;IAC5B,kGAAkG;IAClG,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;CAC9B;AAED;;;;;GAKG;AACH,wBAAgB,IAAI,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,aAAa,GAAG,SAAS,CAMrE"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useMemo } from "react";
|
|
3
|
+
import { useFramework, useIdentityEpoch } from "../provider.js";
|
|
4
|
+
import { ChatScope } from "./context.js";
|
|
5
|
+
import { createRootRuntime } from "./create.js";
|
|
6
|
+
/**
|
|
7
|
+
* Owns one chat runtime for its subtree: the `chat` channel on the existing sync stream,
|
|
8
|
+
* its thread in presence `watching` so inline confirmations reach this client, and the
|
|
9
|
+
* confirmation subscription. Renders no DOM of its own. When the signed-in user changes,
|
|
10
|
+
* the subtree remounts with a fresh runtime, so nothing of the previous user remains.
|
|
11
|
+
*/
|
|
12
|
+
export function Root({ threadId, children }) {
|
|
13
|
+
return (_jsx(UserChat, { threadId: threadId, children: children }, useIdentityEpoch()));
|
|
14
|
+
}
|
|
15
|
+
function UserChat({ threadId, children }) {
|
|
16
|
+
const { client, agentUi, auth, sync } = useFramework();
|
|
17
|
+
const runtime = useMemo(() => createRootRuntime({ client, agentUi, auth, sync, threadId }), [client, agentUi, auth, sync, threadId]);
|
|
18
|
+
useEffect(() => runtime.start(), [runtime]);
|
|
19
|
+
return _jsx(ChatScope, { value: runtime, children: children });
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=chat-root.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-root.js","sourceRoot":"","sources":["../../../src/react/chat/chat-root.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAkB,SAAS,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAE3D,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAQhD;;;;;GAKG;AACH,MAAM,UAAU,IAAI,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAiB;IACxD,OAAO,CACL,KAAC,QAAQ,IAA0B,QAAQ,EAAE,QAAQ,YAClD,QAAQ,IADI,gBAAgB,EAAE,CAEtB,CACZ,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAiB;IACrD,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,YAAY,EAAE,CAAC;IACvD,MAAM,OAAO,GAAG,OAAO,CACrB,GAAG,EAAE,CAAC,iBAAiB,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAClE,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,CACxC,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAE5C,OAAO,KAAC,SAAS,IAAC,KAAK,EAAE,OAAO,YAAG,QAAQ,GAAa,CAAC;AAC3D,CAAC"}
|