@parlor/client 0.2.0 → 0.3.1
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/dist/action-client.d.ts +7 -1
- package/dist/action-client.d.ts.map +1 -1
- package/dist/action-client.js +10 -2
- package/dist/action-client.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/react/chat/chat-ask.d.ts +3 -2
- package/dist/react/chat/chat-ask.d.ts.map +1 -1
- package/dist/react/chat/chat-ask.js +3 -2
- package/dist/react/chat/chat-ask.js.map +1 -1
- package/dist/react/chat/runtime.d.ts +17 -3
- package/dist/react/chat/runtime.d.ts.map +1 -1
- package/dist/react/chat/runtime.js +117 -16
- package/dist/react/chat/runtime.js.map +1 -1
- package/dist/react/chat/use-chat.d.ts.map +1 -1
- package/dist/react/chat/use-chat.js +2 -0
- package/dist/react/chat/use-chat.js.map +1 -1
- package/dist/react/chat/use-streaming-text.d.ts +7 -0
- package/dist/react/chat/use-streaming-text.d.ts.map +1 -0
- package/dist/react/chat/use-streaming-text.js +59 -0
- package/dist/react/chat/use-streaming-text.js.map +1 -0
- package/dist/react/hooks.d.ts.map +1 -1
- package/dist/react/hooks.js +3 -6
- package/dist/react/hooks.js.map +1 -1
- package/dist/react/index.d.ts +3 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +2 -0
- package/dist/react/index.js.map +1 -1
- package/dist/react/write-refresh.d.ts +27 -0
- package/dist/react/write-refresh.d.ts.map +1 -0
- package/dist/react/write-refresh.js +80 -0
- package/dist/react/write-refresh.js.map +1 -0
- package/dist/session.d.ts +7 -1
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js.map +1 -1
- package/package.json +6 -6
package/dist/action-client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ActionError, type ActionInput, type ActionMap, type ActionOutput, type Tag } from "@parlor/core";
|
|
1
|
+
import { ActionError, type ActionInput, type ActionMap, type ActionOutput, type ReadRequest, type RefreshedRead, type Tag } from "@parlor/core";
|
|
2
2
|
export declare function generateClientId(): string;
|
|
3
3
|
export type HeadersProvider = HeadersInit | (() => HeadersInit | Promise<HeadersInit>);
|
|
4
4
|
export interface ActionClientOptions {
|
|
@@ -10,12 +10,18 @@ export interface ActionClientOptions {
|
|
|
10
10
|
}
|
|
11
11
|
export interface CallOptions {
|
|
12
12
|
readonly signal?: AbortSignal | undefined;
|
|
13
|
+
/** For a write: the reads the page shows, to answer with fresh the ones it changed. */
|
|
14
|
+
readonly refresh?: readonly ReadRequest[] | undefined;
|
|
13
15
|
}
|
|
14
16
|
export interface ActionEnvelope<T> {
|
|
15
17
|
readonly data: T;
|
|
16
18
|
readonly tags: readonly Tag[];
|
|
17
19
|
/** The sync cursor a read's data reflects, when the server tracks it. */
|
|
18
20
|
readonly cursor?: string | undefined;
|
|
21
|
+
/** For a call with `refresh`, when the server knows it: what the write changed. */
|
|
22
|
+
readonly writes?: readonly Tag[] | undefined;
|
|
23
|
+
/** For a call with `refresh`, when the server knows it: each read named, in order. */
|
|
24
|
+
readonly refreshed?: readonly RefreshedRead[] | undefined;
|
|
19
25
|
}
|
|
20
26
|
export interface ActionClient<T extends ActionMap> {
|
|
21
27
|
readonly clientId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-client.d.ts","sourceRoot":"","sources":["../src/action-client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,YAAY,EAEjB,KAAK,GAAG,EACT,MAAM,cAAc,CAAC;AAWtB,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;AAEvF,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC;IAC/C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACxC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"action-client.d.ts","sourceRoot":"","sources":["../src/action-client.ts"],"names":[],"mappings":"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"}
|
package/dist/action-client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ActionError, SHELL_ORIGINS, } from "@parlor/core";
|
|
1
|
+
import { ActionError, encodeReadRequests, REFRESH_HEADER, SHELL_ORIGINS, } from "@parlor/core";
|
|
2
2
|
const DEFAULT_BASE_PATH = "/_parlor";
|
|
3
3
|
const SOURCE_HEADER = "x-parlor-source";
|
|
4
4
|
const CLIENT_HEADER = "x-parlor-client";
|
|
@@ -26,7 +26,12 @@ export async function toActionError(response, options = {}) {
|
|
|
26
26
|
export async function invokeAt(request, path, input, options = {}) {
|
|
27
27
|
const response = await request(path, {
|
|
28
28
|
method: "POST",
|
|
29
|
-
headers: {
|
|
29
|
+
headers: {
|
|
30
|
+
"content-type": "application/json",
|
|
31
|
+
...(options.refresh?.length
|
|
32
|
+
? { [REFRESH_HEADER]: encodeReadRequests(options.refresh) }
|
|
33
|
+
: {}),
|
|
34
|
+
},
|
|
30
35
|
body: JSON.stringify(input ?? {}),
|
|
31
36
|
signal: options.signal ?? null,
|
|
32
37
|
});
|
|
@@ -38,6 +43,9 @@ export async function invokeAt(request, path, input, options = {}) {
|
|
|
38
43
|
data: body.data,
|
|
39
44
|
tags: body.tags ?? [],
|
|
40
45
|
...(typeof body.cursor === "string" ? { cursor: body.cursor } : {}),
|
|
46
|
+
...(Array.isArray(body.writes) && Array.isArray(body.refreshed)
|
|
47
|
+
? { writes: body.writes, refreshed: body.refreshed }
|
|
48
|
+
: {}),
|
|
41
49
|
};
|
|
42
50
|
}
|
|
43
51
|
export function resolveServerOrigin() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-client.js","sourceRoot":"","sources":["../src/action-client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EAIX,aAAa,GAEd,MAAM,cAAc,CAAC;AAEtB,MAAM,iBAAiB,GAAG,UAAU,CAAC;AACrC,MAAM,aAAa,GAAG,iBAAiB,CAAC;AACxC,MAAM,aAAa,GAAG,iBAAiB,CAAC;AAExC,SAAS,iBAAiB;IACxB,MAAM,GAAG,GAAI,OAAO,IAAiD,CAAC,GAAG,CAAC;IAC1E,OAAO,GAAG,EAAE,iBAAiB,IAAI,EAAE,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAClF,CAAC;AAuCD,KAAK,UAAU,cAAc,CAC3B,QAAqC,EACrC,QAAgB,EAChB,KAAmB;IAEnB,MAAM,OAAO,GAAG,IAAI,OAAO,CACzB,OAAO,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,QAAQ,EAAE,CAAC,CAAC,CAAC,QAAQ,CAC7D,CAAC;IACF,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IACpE,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;IACjC,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;IACrC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,QAAkB,EAClB,OAAO,GAA6C,EAAE;IAEtD,MAAM,IAAI,GAAY,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACnE,IAAI,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC;QAAE,OAAO,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAChE,MAAM,IAAI,GACR,OAAO,CAAC,iBAAiB,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC;IAClF,OAAO,IAAI,WAAW,CAAC,IAAI,EAAE,mCAAmC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;AACrF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,OAA2C,EAC3C,IAAY,EACZ,KAAwB,EACxB,OAAO,GAA2D,EAAE;IAEpE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE;QACnC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE,CAAC;QACjC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,IAAI;KAC/B,CAAC,CAAC;IACH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,MAAM,aAAa,CACvB,QAAQ,EACR,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAC7D,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAIlC,CAAC;IACF,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;QACrB,GAAG,CAAC,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACpE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,OAAO,iBAAiB,EAAE,IAAI,UAAU,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,CAAC;AAClE,CAAC;AAED,SAAS,iBAAiB;IACxB,MAAM,GAAG,GAAI,OAAO,IAAiD,CAAC,GAAG,CAAC;IAC1E,OAAO,GAAG,EAAE,iBAAiB,IAAI,EAAE,CAAC;AACtC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CACvB,SAAS,GAAW,mBAAmB,EAAE,EACzC,QAAQ,GAAW,iBAAiB,EAAE;IAEtC,IAAI,QAAQ;QAAE,OAAO,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC;IAC9C,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,CAAC;IAC/C,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5E,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,OAAO,GAAwB,EAAE;IAEjC,MAAM,EACJ,OAAO,GAAG,iBAAiB,EAAE,EAC7B,QAAQ,GAAG,iBAAiB,EAC5B,OAAO,GACR,GAAG,OAAO,CAAC;IACZ,4EAA4E;IAC5E,IAAI,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAChC,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,CAAC,QAAQ,KAAK,gBAAgB,EAAE,CAAC,CAAC;IACtD,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC;IAEpD,MAAM,OAAO,GAAG,KAAK,EAAE,IAAY,EAAE,IAAI,GAAgB,EAAE,EAAE,EAAE,CAC7D,SAAS,CAAC,GAAG,OAAO,GAAG,IAAI,EAAE,EAAE;QAC7B,GAAG,IAAI;QACP,OAAO,EAAE,MAAM,cAAc,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC;KAC9D,CAAC,CAAC;IAEL,MAAM,MAAM,GAAG,KAAK,EAClB,IAAO,EACP,KAAwB,EACxB,WAAW,GAAgB,EAAE,EACgB,EAAE;QAC/C,OAAO,QAAQ,CAAO,OAAO,EAAE,GAAG,QAAQ,YAAY,IAAI,EAAE,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC;IACpF,CAAC,CAAC;IAEF,OAAO;QACL,IAAI,QAAQ;YACV,OAAO,KAAK,EAAE,CAAC;QACjB,CAAC;QACD,QAAQ;QACR,OAAO;QACP,MAAM;QACN,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,CACvC,CAAC,MAAM,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI;KAChD,CAAC;AACJ,CAAC","sourcesContent":["import {\n ActionError,\n type ActionInput,\n type ActionMap,\n type ActionOutput,\n SHELL_ORIGINS,\n type Tag,\n} from \"@parlor/core\";\n\nconst DEFAULT_BASE_PATH = \"/_parlor\";\nconst SOURCE_HEADER = \"x-parlor-source\";\nconst CLIENT_HEADER = \"x-parlor-client\";\n\nfunction injectedServerUrl(): string {\n const env = (import.meta as { env?: { PARLOR_SERVER_URL?: string } }).env;\n return env?.PARLOR_SERVER_URL ?? \"\";\n}\n\nexport function generateClientId(): string {\n return globalThis.crypto?.randomUUID?.() ?? Math.random().toString(36).slice(2);\n}\n\nexport type HeadersProvider = HeadersInit | (() => HeadersInit | Promise<HeadersInit>);\n\nexport interface ActionClientOptions {\n readonly baseUrl?: string | undefined;\n readonly basePath?: string | undefined;\n readonly fetch?: typeof fetch | undefined;\n readonly headers?: HeadersProvider | undefined;\n readonly clientId?: string | undefined;\n}\n\nexport interface CallOptions {\n readonly signal?: AbortSignal | undefined;\n}\n\nexport interface ActionEnvelope<T> {\n readonly data: T;\n readonly tags: readonly Tag[];\n /** The sync cursor a read's data reflects, when the server tracks it. */\n readonly cursor?: string | undefined;\n}\n\nexport interface ActionClient<T extends ActionMap> {\n readonly clientId: string;\n readonly basePath: string;\n call<K extends keyof T & string>(\n name: K,\n input: ActionInput<T[K]>,\n options?: CallOptions,\n ): Promise<ActionOutput<T[K]>>;\n invoke<K extends keyof T & string>(\n name: K,\n input: ActionInput<T[K]>,\n options?: CallOptions,\n ): Promise<ActionEnvelope<ActionOutput<T[K]>>>;\n request(path: string, init?: RequestInit): Promise<Response>;\n}\n\nasync function resolveHeaders(\n provider: HeadersProvider | undefined,\n clientId: string,\n extra?: HeadersInit,\n): Promise<Headers> {\n const headers = new Headers(\n typeof provider === \"function\" ? await provider() : provider,\n );\n new Headers(extra).forEach((value, key) => headers.set(key, value));\n headers.set(SOURCE_HEADER, \"ui\");\n headers.set(CLIENT_HEADER, clientId);\n return headers;\n}\n\nexport async function toActionError(\n response: Response,\n options: { readonly missingIsNotFound?: boolean } = {},\n): Promise<ActionError> {\n const body: unknown = await response.json().catch(() => undefined);\n if (ActionError.isBody(body)) return ActionError.fromBody(body);\n const code =\n options.missingIsNotFound && response.status === 404 ? \"not_found\" : \"internal\";\n return new ActionError(code, `Action request failed with HTTP ${response.status}`);\n}\n\nexport async function invokeAt<T extends ActionMap, K extends keyof T & string>(\n request: ActionClient<ActionMap>[\"request\"],\n path: string,\n input: ActionInput<T[K]>,\n options: CallOptions & { readonly missingIsNotFound?: boolean } = {},\n): Promise<ActionEnvelope<ActionOutput<T[K]>>> {\n const response = await request(path, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(input ?? {}),\n signal: options.signal ?? null,\n });\n if (!response.ok) {\n throw await toActionError(\n response,\n options.missingIsNotFound ? { missingIsNotFound: true } : {},\n );\n }\n const body = (await response.json()) as {\n data: ActionOutput<T[K]>;\n tags?: Tag[];\n cursor?: string;\n };\n return {\n data: body.data,\n tags: body.tags ?? [],\n ...(typeof body.cursor === \"string\" ? { cursor: body.cursor } : {}),\n };\n}\n\nexport function resolveServerOrigin(): string {\n return injectedServerUrl() || globalThis.location?.origin || \"\";\n}\n\nfunction injectedAppOrigin(): string {\n const env = (import.meta as { env?: { PARLOR_APP_ORIGIN?: string } }).env;\n return env?.PARLOR_APP_ORIGIN ?? \"\";\n}\n\n/**\n * The one name of this app's backend on every surface: the page's own origin when it is\n * served over http(s) and is not a shell's webview origin, else the shell's `server.url`.\n * `parlor dev` running several targets names the web target's origin for all of them.\n * Statements are signed for it and the host is paired with it.\n */\nexport function appOrigin(\n serverUrl: string = resolveServerOrigin(),\n injected: string = injectedAppOrigin(),\n): string {\n if (injected) return new URL(injected).origin;\n const page = globalThis.location?.origin ?? \"\";\n if (/^https?:\\/\\//.test(page) && !SHELL_ORIGINS.includes(page)) return page;\n try {\n return new URL(serverUrl).origin;\n } catch {\n return serverUrl;\n }\n}\n\nexport function createActionClient<T extends ActionMap>(\n options: ActionClientOptions = {},\n): ActionClient<T> {\n const {\n baseUrl = injectedServerUrl(),\n basePath = DEFAULT_BASE_PATH,\n headers,\n } = options;\n // Drawn on first use: workerd allows no random values while a module loads.\n let clientId = options.clientId;\n const ownId = () => (clientId ??= generateClientId());\n const fetchImpl = options.fetch ?? globalThis.fetch;\n\n const request = async (path: string, init: RequestInit = {}) =>\n fetchImpl(`${baseUrl}${path}`, {\n ...init,\n headers: await resolveHeaders(headers, ownId(), init.headers),\n });\n\n const invoke = async <K extends keyof T & string>(\n name: K,\n input: ActionInput<T[K]>,\n callOptions: CallOptions = {},\n ): Promise<ActionEnvelope<ActionOutput<T[K]>>> => {\n return invokeAt<T, K>(request, `${basePath}/actions/${name}`, input, callOptions);\n };\n\n return {\n get clientId() {\n return ownId();\n },\n basePath,\n request,\n invoke,\n call: async (name, input, callOptions) =>\n (await invoke(name, input, callOptions)).data,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"action-client.js","sourceRoot":"","sources":["../src/action-client.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ActionError,\n type ActionInput,\n type ActionMap,\n type ActionOutput,\n encodeReadRequests,\n type ReadRequest,\n REFRESH_HEADER,\n type RefreshedRead,\n SHELL_ORIGINS,\n type Tag,\n} from \"@parlor/core\";\n\nconst DEFAULT_BASE_PATH = \"/_parlor\";\nconst SOURCE_HEADER = \"x-parlor-source\";\nconst CLIENT_HEADER = \"x-parlor-client\";\n\nfunction injectedServerUrl(): string {\n const env = (import.meta as { env?: { PARLOR_SERVER_URL?: string } }).env;\n return env?.PARLOR_SERVER_URL ?? \"\";\n}\n\nexport function generateClientId(): string {\n return globalThis.crypto?.randomUUID?.() ?? Math.random().toString(36).slice(2);\n}\n\nexport type HeadersProvider = HeadersInit | (() => HeadersInit | Promise<HeadersInit>);\n\nexport interface ActionClientOptions {\n readonly baseUrl?: string | undefined;\n readonly basePath?: string | undefined;\n readonly fetch?: typeof fetch | undefined;\n readonly headers?: HeadersProvider | undefined;\n readonly clientId?: string | undefined;\n}\n\nexport interface CallOptions {\n readonly signal?: AbortSignal | undefined;\n /** For a write: the reads the page shows, to answer with fresh the ones it changed. */\n readonly refresh?: readonly ReadRequest[] | undefined;\n}\n\nexport interface ActionEnvelope<T> {\n readonly data: T;\n readonly tags: readonly Tag[];\n /** The sync cursor a read's data reflects, when the server tracks it. */\n readonly cursor?: string | undefined;\n /** For a call with `refresh`, when the server knows it: what the write changed. */\n readonly writes?: readonly Tag[] | undefined;\n /** For a call with `refresh`, when the server knows it: each read named, in order. */\n readonly refreshed?: readonly RefreshedRead[] | undefined;\n}\n\nexport interface ActionClient<T extends ActionMap> {\n readonly clientId: string;\n readonly basePath: string;\n call<K extends keyof T & string>(\n name: K,\n input: ActionInput<T[K]>,\n options?: CallOptions,\n ): Promise<ActionOutput<T[K]>>;\n invoke<K extends keyof T & string>(\n name: K,\n input: ActionInput<T[K]>,\n options?: CallOptions,\n ): Promise<ActionEnvelope<ActionOutput<T[K]>>>;\n request(path: string, init?: RequestInit): Promise<Response>;\n}\n\nasync function resolveHeaders(\n provider: HeadersProvider | undefined,\n clientId: string,\n extra?: HeadersInit,\n): Promise<Headers> {\n const headers = new Headers(\n typeof provider === \"function\" ? await provider() : provider,\n );\n new Headers(extra).forEach((value, key) => headers.set(key, value));\n headers.set(SOURCE_HEADER, \"ui\");\n headers.set(CLIENT_HEADER, clientId);\n return headers;\n}\n\nexport async function toActionError(\n response: Response,\n options: { readonly missingIsNotFound?: boolean } = {},\n): Promise<ActionError> {\n const body: unknown = await response.json().catch(() => undefined);\n if (ActionError.isBody(body)) return ActionError.fromBody(body);\n const code =\n options.missingIsNotFound && response.status === 404 ? \"not_found\" : \"internal\";\n return new ActionError(code, `Action request failed with HTTP ${response.status}`);\n}\n\nexport async function invokeAt<T extends ActionMap, K extends keyof T & string>(\n request: ActionClient<ActionMap>[\"request\"],\n path: string,\n input: ActionInput<T[K]>,\n options: CallOptions & { readonly missingIsNotFound?: boolean } = {},\n): Promise<ActionEnvelope<ActionOutput<T[K]>>> {\n const response = await request(path, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n ...(options.refresh?.length\n ? { [REFRESH_HEADER]: encodeReadRequests(options.refresh) }\n : {}),\n },\n body: JSON.stringify(input ?? {}),\n signal: options.signal ?? null,\n });\n if (!response.ok) {\n throw await toActionError(\n response,\n options.missingIsNotFound ? { missingIsNotFound: true } : {},\n );\n }\n const body = (await response.json()) as {\n data: ActionOutput<T[K]>;\n tags?: Tag[];\n cursor?: string;\n writes?: Tag[];\n refreshed?: RefreshedRead[];\n };\n return {\n data: body.data,\n tags: body.tags ?? [],\n ...(typeof body.cursor === \"string\" ? { cursor: body.cursor } : {}),\n ...(Array.isArray(body.writes) && Array.isArray(body.refreshed)\n ? { writes: body.writes, refreshed: body.refreshed }\n : {}),\n };\n}\n\nexport function resolveServerOrigin(): string {\n return injectedServerUrl() || globalThis.location?.origin || \"\";\n}\n\nfunction injectedAppOrigin(): string {\n const env = (import.meta as { env?: { PARLOR_APP_ORIGIN?: string } }).env;\n return env?.PARLOR_APP_ORIGIN ?? \"\";\n}\n\n/**\n * The one name of this app's backend on every surface: the page's own origin when it is\n * served over http(s) and is not a shell's webview origin, else the shell's `server.url`.\n * `parlor dev` running several targets names the web target's origin for all of them.\n * Statements are signed for it and the host is paired with it.\n */\nexport function appOrigin(\n serverUrl: string = resolveServerOrigin(),\n injected: string = injectedAppOrigin(),\n): string {\n if (injected) return new URL(injected).origin;\n const page = globalThis.location?.origin ?? \"\";\n if (/^https?:\\/\\//.test(page) && !SHELL_ORIGINS.includes(page)) return page;\n try {\n return new URL(serverUrl).origin;\n } catch {\n return serverUrl;\n }\n}\n\nexport function createActionClient<T extends ActionMap>(\n options: ActionClientOptions = {},\n): ActionClient<T> {\n const {\n baseUrl = injectedServerUrl(),\n basePath = DEFAULT_BASE_PATH,\n headers,\n } = options;\n // Drawn on first use: workerd allows no random values while a module loads.\n let clientId = options.clientId;\n const ownId = () => (clientId ??= generateClientId());\n const fetchImpl = options.fetch ?? globalThis.fetch;\n\n const request = async (path: string, init: RequestInit = {}) =>\n fetchImpl(`${baseUrl}${path}`, {\n ...init,\n headers: await resolveHeaders(headers, ownId(), init.headers),\n });\n\n const invoke = async <K extends keyof T & string>(\n name: K,\n input: ActionInput<T[K]>,\n callOptions: CallOptions = {},\n ): Promise<ActionEnvelope<ActionOutput<T[K]>>> => {\n return invokeAt<T, K>(request, `${basePath}/actions/${name}`, input, callOptions);\n };\n\n return {\n get clientId() {\n return ownId();\n },\n basePath,\n request,\n invoke,\n call: async (name, input, callOptions) =>\n (await invoke(name, input, callOptions)).data,\n };\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export { type ActionClient, appOrigin, type ActionClientOptions, type ActionEnve
|
|
|
2
2
|
export { type AgentViewBinding, type AgentViewDefinition, type AnyAgentView, defineAgentView, type WritableField, } from "@parlor/agent-ui";
|
|
3
3
|
export { ACTION_QUERY_PREFIX, actionQueryKey } from "./query-keys.js";
|
|
4
4
|
export { createPluginClient, type PluginClient } from "./plugin-client.js";
|
|
5
|
-
export type { AccountDevice, DeviceLinker, DeviceSource, FrameworkAuth, HostAuthorizer, PendingLink, SessionDevice, SessionSnapshot, SessionSource, SessionUser, } from "./session.js";
|
|
5
|
+
export type { AccountDevice, ComputerDisconnector, DeviceLinker, DeviceSource, FrameworkAuth, HostAuthorizer, PendingLink, SessionDevice, SessionSnapshot, SessionSource, SessionUser, } from "./session.js";
|
|
6
6
|
export { LinkOnComputer } from "./session.js";
|
|
7
7
|
export type { Register, RegisteredActions } from "./register.js";
|
|
8
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,YAAY,EACjB,SAAS,EACT,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,KAAK,eAAe,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,eAAe,EACf,KAAK,aAAa,GACnB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC3E,YAAY,EACV,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,cAAc,EACd,WAAW,EACX,aAAa,EACb,eAAe,EACf,aAAa,EACb,WAAW,GACZ,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,YAAY,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,YAAY,EACjB,SAAS,EACT,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,KAAK,eAAe,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,eAAe,EACf,KAAK,aAAa,GACnB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC3E,YAAY,EACV,aAAa,EACb,oBAAoB,EACpB,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,cAAc,EACd,WAAW,EACX,aAAa,EACb,eAAe,EACf,aAAa,EACb,WAAW,GACZ,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,YAAY,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,SAAS,EAIT,kBAAkB,EAClB,gBAAgB,GAEjB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAIL,eAAe,GAEhB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAqB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,SAAS,EAIT,kBAAkB,EAClB,gBAAgB,GAEjB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAIL,eAAe,GAEhB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAqB,MAAM,oBAAoB,CAAC;AAc3E,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC","sourcesContent":["export {\n type ActionClient,\n appOrigin,\n type ActionClientOptions,\n type ActionEnvelope,\n type CallOptions,\n createActionClient,\n generateClientId,\n type HeadersProvider,\n} from \"./action-client.js\";\nexport {\n type AgentViewBinding,\n type AgentViewDefinition,\n type AnyAgentView,\n defineAgentView,\n type WritableField,\n} from \"@parlor/agent-ui\";\nexport { ACTION_QUERY_PREFIX, actionQueryKey } from \"./query-keys.js\";\nexport { createPluginClient, type PluginClient } from \"./plugin-client.js\";\nexport type {\n AccountDevice,\n ComputerDisconnector,\n DeviceLinker,\n DeviceSource,\n FrameworkAuth,\n HostAuthorizer,\n PendingLink,\n SessionDevice,\n SessionSnapshot,\n SessionSource,\n SessionUser,\n} from \"./session.js\";\nexport { LinkOnComputer } from \"./session.js\";\nexport type { Register, RegisteredActions } from \"./register.js\";\n"]}
|
|
@@ -9,8 +9,9 @@ export interface ChatAskProps extends ComponentProps<"div"> {
|
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
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)
|
|
13
|
-
*
|
|
12
|
+
* `data-approval` is `presence` (answering triggers the OS prompt), `device` (answered by
|
|
13
|
+
* the device that sent the prompt) or `computer` (answered on the computer; choices
|
|
14
|
+
* disabled). `data-state` is `open`, `answered` or `closed`.
|
|
14
15
|
* Escape declines.
|
|
15
16
|
*/
|
|
16
17
|
export declare function Ask({ item, onKeyDown, ...props }: ChatAskProps): ReactNode;
|
|
@@ -1 +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
|
|
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;;;;;;GAMG;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"}
|
|
@@ -6,8 +6,9 @@ const AskScope = createContext(undefined);
|
|
|
6
6
|
const report = (error) => console.error("[parlor] The chat could not answer:", error);
|
|
7
7
|
/**
|
|
8
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)
|
|
10
|
-
*
|
|
9
|
+
* `data-approval` is `presence` (answering triggers the OS prompt), `device` (answered by
|
|
10
|
+
* the device that sent the prompt) or `computer` (answered on the computer; choices
|
|
11
|
+
* disabled). `data-state` is `open`, `answered` or `closed`.
|
|
11
12
|
* Escape declines.
|
|
12
13
|
*/
|
|
13
14
|
export function Ask({ item, onKeyDown, ...props }) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-ask.js","sourceRoot":"","sources":["../../../src/react/chat/chat-ask.tsx"],"names":[],"mappings":";AAEA,OAAO,EAEL,aAAa,EAGb,GAAG,EACH,OAAO,GACR,MAAM,OAAO,CAAC;AAEf,OAAO,EAAiB,SAAS,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAI9C,MAAM,QAAQ,GAAG,aAAa,CAAsB,SAAS,CAAC,CAAC;AAE/D,MAAM,MAAM,GAAG,CAAC,KAAc,EAAE,EAAE,CAChC,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;AAM9D
|
|
1
|
+
{"version":3,"file":"chat-ask.js","sourceRoot":"","sources":["../../../src/react/chat/chat-ask.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { AgentConfirmation } from \"@parlor/agent-ui/client\";\nimport type { ChatItem } from \"@parlor/chat\";\nimport {\n type ComponentProps,\n createContext,\n type KeyboardEvent,\n type ReactNode,\n use,\n useMemo,\n} from \"react\";\n\nimport { type AskField, askFields, askValues } from \"./ask-fields.js\";\nimport { useChatRuntime } from \"./context.js\";\n\ntype AskItem = Extract<ChatItem<AgentConfirmation>, { kind: \"ask\" }>;\n\nconst AskScope = createContext<AskItem | undefined>(undefined);\n\nconst report = (error: unknown) =>\n console.error(\"[parlor] The chat could not answer:\", error);\n\nexport interface ChatAskProps extends ComponentProps<\"div\"> {\n readonly item: AskItem;\n}\n\n/**\n * The agent's own permission prompt or question: `role=\"group\"` named by its question.\n * `data-approval` is `presence` (answering triggers the OS prompt), `device` (answered by\n * the device that sent the prompt) or `computer` (answered on the computer; choices\n * disabled). `data-state` is `open`, `answered` or `closed`.\n * Escape declines.\n */\nexport function Ask({ item, onKeyDown, ...props }: ChatAskProps): ReactNode {\n const runtime = useChatRuntime(\"Chat.Ask\");\n const decline = (event: KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n if (event.defaultPrevented || event.key !== \"Escape\") return;\n const rejection = item.choices.find((choice) => choice.effect.startsWith(\"reject\"));\n if (!rejection || item.answer.state !== \"open\" || item.approval === \"computer\")\n return;\n event.preventDefault();\n event.stopPropagation();\n runtime.answer(item.id, rejection.id).catch(report);\n };\n return (\n <AskScope value={item}>\n <div\n role=\"group\"\n aria-label={item.question}\n tabIndex={-1}\n {...props}\n data-approval={item.approval}\n data-state={item.answer.state}\n onKeyDown={decline}\n />\n </AskScope>\n );\n}\n\nexport interface ChatAskChoiceProps extends ComponentProps<\"button\"> {\n readonly choice: AskItem[\"choices\"][number];\n}\n\n/** `type=\"button\"`; answers the enclosing ask with this choice. */\nexport function AskChoice({ choice, onClick, ...props }: ChatAskChoiceProps): ReactNode {\n const runtime = useChatRuntime(\"Chat.AskChoice\");\n const ask = use(AskScope);\n if (!ask) throw new Error(\"Chat.AskChoice must be rendered inside Chat.Ask.\");\n return (\n <button\n type=\"button\"\n disabled={ask.approval === \"computer\" || ask.answer.state !== \"open\"}\n data-effect={choice.effect}\n aria-pressed={\n ask.answer.state === \"answered\" ? ask.answer.choice === choice.id : undefined\n }\n {...props}\n onClick={(event) => {\n onClick?.(event);\n if (!event.defaultPrevented) runtime.answer(ask.id, choice.id).catch(report);\n }}\n />\n );\n}\n\nconst isAllow = (choice: AskItem[\"choices\"][number]) => choice.effect.startsWith(\"allow\");\n\nexport type ChatAskFormProps = ComponentProps<\"form\">;\n\n/**\n * A form ask's `<form>`: one `<input name=\"{property}\">` per property of its schema (`number`\n * for numbers and integers, `checkbox` for booleans, text otherwise). Submitting answers the\n * ask with its allow choice and the values typed per the schema. Its children, a submit\n * button for one, go after the inputs. Everything is disabled once the ask is not open or\n * is answered on the computer. Renders nothing for an ask without a form.\n */\nexport function AskForm({ onSubmit, children, ...props }: ChatAskFormProps): ReactNode {\n const runtime = useChatRuntime(\"Chat.AskForm\");\n const ask = use(AskScope);\n if (!ask) throw new Error(\"Chat.AskForm must be rendered inside Chat.Ask.\");\n const { form } = ask;\n const fields = useMemo(() => (form ? askFields(form) : []), [form]);\n const accept = ask.choices.find(isAllow);\n if (!form || !accept) return null;\n return (\n <form\n {...props}\n onSubmit={(event) => {\n onSubmit?.(event);\n event.preventDefault();\n runtime\n .answer(ask.id, accept.id, askValues(fields, event.currentTarget))\n .catch(report);\n }}\n >\n <fieldset disabled={ask.approval === \"computer\" || ask.answer.state !== \"open\"}>\n {fields.map((field) => (\n <AskInput key={field.name} field={field} />\n ))}\n {children}\n </fieldset>\n </form>\n );\n}\n\nfunction AskInput({ field }: { readonly field: AskField }): ReactNode {\n return (\n <label data-type={field.type}>\n <span>{field.label}</span>\n <input\n name={field.name}\n type={field.type}\n required={field.required && field.type !== \"checkbox\"}\n step={field.type === \"number\" ? (field.integer ? 1 : \"any\") : undefined}\n />\n </label>\n );\n}\n"]}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { AgentConfirmation, AgentUiClient } from "@parlor/agent-ui/client";
|
|
2
2
|
import type { CapabilityHandle, LocalAgentHost } from "@parlor/capabilities";
|
|
3
|
-
import { type ChatItem, type HostSummary, type ThreadSummary } from "@parlor/chat";
|
|
3
|
+
import { type AgentOption, type AgentUsage, type ChatItem, type HostSummary, type ThreadSummary } from "@parlor/chat";
|
|
4
4
|
import type { ChatUserActionMap } from "@parlor/chat/server";
|
|
5
5
|
import { type Tag } from "@parlor/core";
|
|
6
6
|
import type { ClientChannel } from "@parlor/sync";
|
|
7
7
|
import type { PluginClient } from "../../plugin-client.js";
|
|
8
|
-
import type { DeviceLinker, DeviceSource, HostAuthorizer } from "../../session.js";
|
|
8
|
+
import type { ComputerDisconnector, DeviceLinker, DeviceSource, HostAuthorizer } from "../../session.js";
|
|
9
9
|
/** One agent the user can talk to; `key` is `<hostId>/<agentId>`. */
|
|
10
10
|
export interface AgentChoice {
|
|
11
11
|
readonly key: string;
|
|
@@ -14,6 +14,16 @@ export interface AgentChoice {
|
|
|
14
14
|
readonly online: boolean;
|
|
15
15
|
readonly ready: boolean;
|
|
16
16
|
readonly problem: string | undefined;
|
|
17
|
+
/** What a prompt to this agent may choose, such as its model; empty until it has said. */
|
|
18
|
+
readonly options: readonly AgentChoiceOption[];
|
|
19
|
+
/** The account's allowance, as the agent last reported it. */
|
|
20
|
+
readonly usage: AgentUsage | undefined;
|
|
21
|
+
/** The name this agent knows the app by outside the sidebar, when the user let it use the app there. */
|
|
22
|
+
readonly outsideName: string | undefined;
|
|
23
|
+
}
|
|
24
|
+
export interface AgentChoiceOption extends AgentOption {
|
|
25
|
+
/** The value the next prompt runs with: this device's choice, or the agent's own. */
|
|
26
|
+
readonly selected: string;
|
|
17
27
|
}
|
|
18
28
|
/** How this client adds a computer, decided by the `localAgentHost` capability. */
|
|
19
29
|
export type ConnectOption = {
|
|
@@ -118,6 +128,10 @@ export interface ChatCommands {
|
|
|
118
128
|
/** A `presence` ask triggers the OS prompt first; a `computer` ask refuses. */
|
|
119
129
|
answer(askId: string, choice: string, values?: Readonly<Record<string, string | number | boolean>>): Promise<void>;
|
|
120
130
|
choose(agentKey: string): void;
|
|
131
|
+
/** Chooses a value of the chosen agent's option for this device's next prompts to it. */
|
|
132
|
+
setOption(optionId: string, value: string): void;
|
|
133
|
+
/** Disconnects a computer: its agents leave the sidebar and stop using the app outside it. */
|
|
134
|
+
disconnect(hostId: string): Promise<void>;
|
|
121
135
|
/** `undefined` opens the most recent thread, if there is one. */
|
|
122
136
|
openThread(threadId: string | undefined): void;
|
|
123
137
|
/** Starts a blank thread; it exists on the server once the first prompt is sent. */
|
|
@@ -157,7 +171,7 @@ export interface ChatRuntimeDeps {
|
|
|
157
171
|
readonly transport: () => "sse" | "poll" | undefined;
|
|
158
172
|
readonly onNegotiated: (listener: (transport: "sse" | "poll") => void) => () => void;
|
|
159
173
|
readonly isHidden?: (() => boolean) | undefined;
|
|
160
|
-
readonly auth: Partial<DeviceSource & HostAuthorizer & DeviceLinker> | undefined;
|
|
174
|
+
readonly auth: Partial<DeviceSource & HostAuthorizer & DeviceLinker & ComputerDisconnector> | undefined;
|
|
161
175
|
readonly localHost: Promise<CapabilityHandle<LocalAgentHost>>;
|
|
162
176
|
readonly threadId: string | undefined;
|
|
163
177
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/react/chat/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAChF,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC7E,OAAO,
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/react/chat/runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -64,8 +64,11 @@ export function createChatRuntime(deps) {
|
|
|
64
64
|
let draft = "";
|
|
65
65
|
let failure;
|
|
66
66
|
let chosen;
|
|
67
|
+
let optionChoices = readOptionChoices();
|
|
67
68
|
let sending = false;
|
|
68
69
|
let pendingSend;
|
|
70
|
+
/** The prompt in flight, shown in its thread until the server's copy arrives. */
|
|
71
|
+
let shownSend;
|
|
69
72
|
let startedNew = false;
|
|
70
73
|
let connect = {
|
|
71
74
|
kind: "command",
|
|
@@ -121,14 +124,27 @@ export function createChatRuntime(deps) {
|
|
|
121
124
|
return undefined;
|
|
122
125
|
return refusedLast(hostId, deviceId) ? 0 : due - PRESENCE_MARGIN_MS;
|
|
123
126
|
};
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
127
|
+
/** This device's choices for `agentKey` that its agent still offers. */
|
|
128
|
+
const chosenOptions = (agentKey, options) => Object.fromEntries(Object.entries(optionChoices[agentKey] ?? {}).filter(([id, value]) => options.some((option) => option.id === id && option.values.some((candidate) => candidate.id === value))));
|
|
129
|
+
const choices = () => hosts.flatMap((host) => host.agents.map((agent) => {
|
|
130
|
+
const key = `${host.id}/${agent.id}`;
|
|
131
|
+
const offered = agent.options ?? [];
|
|
132
|
+
const picked = chosenOptions(key, offered);
|
|
133
|
+
return {
|
|
134
|
+
key,
|
|
135
|
+
name: agent.name,
|
|
136
|
+
hostName: host.name,
|
|
137
|
+
online: host.online,
|
|
138
|
+
ready: agent.ready,
|
|
139
|
+
problem: agent.problem,
|
|
140
|
+
options: offered.map((option) => ({
|
|
141
|
+
...option,
|
|
142
|
+
selected: picked[option.id] ?? option.current,
|
|
143
|
+
})),
|
|
144
|
+
usage: agent.usage,
|
|
145
|
+
outsideName: agent.outsideName,
|
|
146
|
+
};
|
|
147
|
+
}));
|
|
132
148
|
const waitOn = (reason, hostId) => ({
|
|
133
149
|
reason,
|
|
134
150
|
hostId,
|
|
@@ -171,6 +187,27 @@ export function createChatRuntime(deps) {
|
|
|
171
187
|
hosts.some((host) => host.id === turn.agent.hostId && !host.online));
|
|
172
188
|
return offline && waitOn("offline", offline.agent.hostId);
|
|
173
189
|
};
|
|
190
|
+
const withShownSend = (folded) => {
|
|
191
|
+
if (shownSend && items.has(shownSend.itemId))
|
|
192
|
+
shownSend = undefined;
|
|
193
|
+
const shown = shownSend;
|
|
194
|
+
if (!shown || (threadId !== shown.openedIn && threadId !== shown.threadId)) {
|
|
195
|
+
return folded;
|
|
196
|
+
}
|
|
197
|
+
const [hostId, agentId] = shown.agent.split("/");
|
|
198
|
+
const row = {
|
|
199
|
+
kind: "prompt",
|
|
200
|
+
id: shown.itemId,
|
|
201
|
+
turnId: shown.turnId,
|
|
202
|
+
text: shown.text,
|
|
203
|
+
agent: { hostId: asId("host", hostId), agentId },
|
|
204
|
+
state: "queued",
|
|
205
|
+
failure: undefined,
|
|
206
|
+
mine: true,
|
|
207
|
+
sending: true,
|
|
208
|
+
};
|
|
209
|
+
return [...folded, row];
|
|
210
|
+
};
|
|
174
211
|
const compute = () => {
|
|
175
212
|
const agents = choices();
|
|
176
213
|
const wanted = chosen ??
|
|
@@ -203,13 +240,15 @@ export function createChatRuntime(deps) {
|
|
|
203
240
|
moreThreads,
|
|
204
241
|
hasOlder,
|
|
205
242
|
loadingOlder,
|
|
206
|
-
items: foldThread({
|
|
243
|
+
items: withShownSend(foldThread({
|
|
207
244
|
items: [...items.values()].sort(bySeq),
|
|
208
245
|
open: [...open.turns.values()],
|
|
209
246
|
turns,
|
|
210
|
-
confirmations: agentUi.confirmations
|
|
247
|
+
confirmations: agentUi.confirmations
|
|
248
|
+
.get()
|
|
249
|
+
.filter((c) => c.threadId === threadId),
|
|
211
250
|
deviceId: device?.id,
|
|
212
|
-
}),
|
|
251
|
+
})),
|
|
213
252
|
hosts,
|
|
214
253
|
agents,
|
|
215
254
|
agent,
|
|
@@ -477,6 +516,10 @@ export function createChatRuntime(deps) {
|
|
|
477
516
|
try {
|
|
478
517
|
await reporting(async () => {
|
|
479
518
|
const agent = { hostId: asId("host", hostId), agentId };
|
|
519
|
+
const offered = hosts
|
|
520
|
+
.find((host) => host.id === hostId)
|
|
521
|
+
?.agents.find((candidate) => candidate.id === agentId)?.options;
|
|
522
|
+
const options = chosenOptions(agentKey, offered ?? []);
|
|
480
523
|
const signed = deps.auth?.device
|
|
481
524
|
? await signPrompt({
|
|
482
525
|
threadId: attempt.threadId,
|
|
@@ -490,7 +533,12 @@ export function createChatRuntime(deps) {
|
|
|
490
533
|
turnId: attempt.turnId,
|
|
491
534
|
itemId: attempt.itemId,
|
|
492
535
|
clientId: deps.clientId,
|
|
493
|
-
prompt: {
|
|
536
|
+
prompt: {
|
|
537
|
+
text: attempt.text,
|
|
538
|
+
agent,
|
|
539
|
+
...(signed ? { signed } : {}),
|
|
540
|
+
...(Object.keys(options).length > 0 ? { options } : {}),
|
|
541
|
+
},
|
|
494
542
|
});
|
|
495
543
|
settle();
|
|
496
544
|
if (epoch !== generation)
|
|
@@ -518,6 +566,7 @@ export function createChatRuntime(deps) {
|
|
|
518
566
|
open = NO_OPEN_TURNS;
|
|
519
567
|
beforeLoad = [];
|
|
520
568
|
pendingSend = undefined;
|
|
569
|
+
shownSend = undefined;
|
|
521
570
|
stopIds.clear();
|
|
522
571
|
answerIds.clear();
|
|
523
572
|
dirty = false;
|
|
@@ -563,11 +612,26 @@ export function createChatRuntime(deps) {
|
|
|
563
612
|
turnId: mint("turn"),
|
|
564
613
|
itemId: mint("item"),
|
|
565
614
|
});
|
|
566
|
-
await whenSetUp(
|
|
567
|
-
|
|
615
|
+
await whenSetUp(async () => {
|
|
616
|
+
let delivered = false;
|
|
617
|
+
shownSend = attempt;
|
|
568
618
|
if (draft.trim() === prompt)
|
|
569
619
|
draft = "";
|
|
570
|
-
|
|
620
|
+
emit();
|
|
621
|
+
try {
|
|
622
|
+
await submit(attempt, target.key, () => {
|
|
623
|
+
delivered = true;
|
|
624
|
+
pendingSend = undefined;
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
finally {
|
|
628
|
+
if (!delivered && shownSend === attempt) {
|
|
629
|
+
shownSend = undefined;
|
|
630
|
+
draft = draft.trim() === "" ? attempt.text : `${attempt.text}\n\n${draft}`;
|
|
631
|
+
emit();
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
});
|
|
571
635
|
},
|
|
572
636
|
async loadOlder() {
|
|
573
637
|
const target = threadId;
|
|
@@ -663,7 +727,7 @@ export function createChatRuntime(deps) {
|
|
|
663
727
|
};
|
|
664
728
|
await whenSetUp(() => reporting(async () => {
|
|
665
729
|
const found = deps.auth?.device ? await deviceOf() : undefined;
|
|
666
|
-
if (ask.approval === "presence" && !found) {
|
|
730
|
+
if ((ask.approval === "presence" || ask.approval === "device") && !found) {
|
|
667
731
|
throw new NeedsDevice("This question needs a device that can confirm it is you.");
|
|
668
732
|
}
|
|
669
733
|
const signed = await found?.signAnswer(toSign, {
|
|
@@ -766,6 +830,25 @@ export function createChatRuntime(deps) {
|
|
|
766
830
|
chosen = agentKey;
|
|
767
831
|
emit();
|
|
768
832
|
},
|
|
833
|
+
async disconnect(hostId) {
|
|
834
|
+
if (!deps.auth?.disconnectComputer) {
|
|
835
|
+
throw new Error("This app cannot disconnect computers.");
|
|
836
|
+
}
|
|
837
|
+
await deps.auth.disconnectComputer(hostId);
|
|
838
|
+
await refreshHosts();
|
|
839
|
+
emit();
|
|
840
|
+
},
|
|
841
|
+
setOption(optionId, value) {
|
|
842
|
+
const agentKey = state.agent?.key;
|
|
843
|
+
if (agentKey === undefined)
|
|
844
|
+
return;
|
|
845
|
+
optionChoices = {
|
|
846
|
+
...optionChoices,
|
|
847
|
+
[agentKey]: { ...optionChoices[agentKey], [optionId]: value },
|
|
848
|
+
};
|
|
849
|
+
writeOptionChoices(optionChoices);
|
|
850
|
+
emit();
|
|
851
|
+
},
|
|
769
852
|
openThread(target) {
|
|
770
853
|
switchTo(target === undefined ? undefined : asId("thread", target), false);
|
|
771
854
|
},
|
|
@@ -837,6 +920,7 @@ export function createChatRuntime(deps) {
|
|
|
837
920
|
announceActivity();
|
|
838
921
|
});
|
|
839
922
|
const offConfirmations = agentUi.confirmations.subscribe(emit);
|
|
923
|
+
const offLink = deps.auth?.subscribeLink?.(() => void refreshLink());
|
|
840
924
|
emit();
|
|
841
925
|
announceActivity();
|
|
842
926
|
void initial();
|
|
@@ -854,6 +938,7 @@ export function createChatRuntime(deps) {
|
|
|
854
938
|
offResume();
|
|
855
939
|
offNegotiated();
|
|
856
940
|
offConfirmations();
|
|
941
|
+
offLink?.();
|
|
857
942
|
stopWatching?.();
|
|
858
943
|
stopWatching = undefined;
|
|
859
944
|
watched = undefined;
|
|
@@ -936,4 +1021,20 @@ export function createChatRuntime(deps) {
|
|
|
936
1021
|
}
|
|
937
1022
|
return runtime;
|
|
938
1023
|
}
|
|
1024
|
+
const OPTION_CHOICES_KEY = "parlor:agent-options";
|
|
1025
|
+
function readOptionChoices() {
|
|
1026
|
+
try {
|
|
1027
|
+
const stored = JSON.parse(globalThis.localStorage?.getItem(OPTION_CHOICES_KEY) ?? "{}");
|
|
1028
|
+
return stored && typeof stored === "object" ? stored : {};
|
|
1029
|
+
}
|
|
1030
|
+
catch {
|
|
1031
|
+
return {};
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
function writeOptionChoices(choices) {
|
|
1035
|
+
try {
|
|
1036
|
+
globalThis.localStorage?.setItem(OPTION_CHOICES_KEY, JSON.stringify(choices));
|
|
1037
|
+
}
|
|
1038
|
+
catch { }
|
|
1039
|
+
}
|
|
939
1040
|
//# sourceMappingURL=runtime.js.map
|