@ulearning/ai-generative-frame 0.0.0-stage → 1.0.0-next.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 +233 -2
- package/dist/assistant-ui/entry.d.ts +34 -0
- package/dist/assistant-ui/entry.d.ts.map +1 -0
- package/dist/assistant-ui/entry.js +50 -0
- package/dist/assistant-ui/entry.js.map +1 -0
- package/dist/assistant-ui/extension.d.ts +18 -0
- package/dist/assistant-ui/extension.d.ts.map +1 -0
- package/dist/assistant-ui/extension.js +0 -0
- package/dist/assistant-ui/history.d.ts +15 -0
- package/dist/assistant-ui/history.d.ts.map +1 -0
- package/dist/assistant-ui/history.js +39 -0
- package/dist/assistant-ui/history.js.map +1 -0
- package/dist/assistant-ui/modelContext.d.ts +45 -0
- package/dist/assistant-ui/modelContext.d.ts.map +1 -0
- package/dist/assistant-ui/modelContext.js +88 -0
- package/dist/assistant-ui/modelContext.js.map +1 -0
- package/dist/assistant-ui/snapshotSaver.d.ts +11 -0
- package/dist/assistant-ui/snapshotSaver.d.ts.map +1 -0
- package/dist/assistant-ui/snapshotSaver.js +83 -0
- package/dist/assistant-ui/snapshotSaver.js.map +1 -0
- package/dist/assistant-ui/tool-calls.d.ts +21 -0
- package/dist/assistant-ui/tool-calls.d.ts.map +1 -0
- package/dist/assistant-ui/tool-calls.js +65 -0
- package/dist/assistant-ui/tool-calls.js.map +1 -0
- package/dist/assistant-ui/toolkit.d.ts +96 -0
- package/dist/assistant-ui/toolkit.d.ts.map +1 -0
- package/dist/assistant-ui/toolkit.js +456 -0
- package/dist/assistant-ui/toolkit.js.map +1 -0
- package/dist/assistant-ui/useSharedContext.d.ts +14 -0
- package/dist/assistant-ui/useSharedContext.d.ts.map +1 -0
- package/dist/assistant-ui/useSharedContext.js +27 -0
- package/dist/assistant-ui/useSharedContext.js.map +1 -0
- package/dist/assistant-ui.d.ts +3 -0
- package/dist/assistant-ui.d.ts.map +1 -0
- package/dist/assistant-ui.js +1 -0
- package/dist/bootstrap.d.ts +23 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +78 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/csp.d.ts +25 -0
- package/dist/csp.d.ts.map +1 -0
- package/dist/csp.js +78 -0
- package/dist/csp.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/json-schema.d.ts +70 -0
- package/dist/json-schema.d.ts.map +1 -0
- package/dist/json-schema.js +163 -0
- package/dist/json-schema.js.map +1 -0
- package/dist/preview.d.ts +30 -0
- package/dist/preview.d.ts.map +1 -0
- package/dist/preview.js +60 -0
- package/dist/preview.js.map +1 -0
- package/dist/prompts/guidance.d.ts +41 -0
- package/dist/prompts/guidance.d.ts.map +1 -0
- package/dist/prompts/guidance.js +268 -0
- package/dist/prompts/guidance.js.map +1 -0
- package/dist/prompts.d.ts +2 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +1 -0
- package/dist/protocol.d.ts +114 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +49 -0
- package/dist/protocol.js.map +1 -0
- package/dist/repair/repair.d.ts +72 -0
- package/dist/repair/repair.d.ts.map +1 -0
- package/dist/repair/repair.js +103 -0
- package/dist/repair/repair.js.map +1 -0
- package/dist/repair.d.ts +2 -0
- package/dist/repair.d.ts.map +1 -0
- package/dist/repair.js +1 -0
- package/dist/rpc.d.ts +60 -0
- package/dist/rpc.d.ts.map +1 -0
- package/dist/rpc.js +127 -0
- package/dist/rpc.js.map +1 -0
- package/dist/runtime/diagnostics.d.ts +17 -0
- package/dist/runtime/diagnostics.d.ts.map +1 -0
- package/dist/runtime/diagnostics.js +128 -0
- package/dist/runtime/diagnostics.js.map +1 -0
- package/dist/runtime/generated.d.ts +2 -0
- package/dist/runtime/generated.d.ts.map +1 -0
- package/dist/runtime/generated.js +5 -0
- package/dist/runtime/generated.js.map +1 -0
- package/dist/runtime/index.d.ts +7 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +264 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/morph.d.ts +51 -0
- package/dist/runtime/morph.d.ts.map +1 -0
- package/dist/runtime/morph.js +251 -0
- package/dist/runtime/morph.js.map +1 -0
- package/dist/runtime/screenshot.d.ts +23 -0
- package/dist/runtime/screenshot.d.ts.map +1 -0
- package/dist/runtime/screenshot.js +188 -0
- package/dist/runtime/screenshot.js.map +1 -0
- package/dist/runtime/size.d.ts +10 -0
- package/dist/runtime/size.d.ts.map +1 -0
- package/dist/runtime/size.js +21 -0
- package/dist/runtime/size.js.map +1 -0
- package/dist/runtime/storage.d.ts +4 -0
- package/dist/runtime/storage.d.ts.map +1 -0
- package/dist/runtime/storage.js +38 -0
- package/dist/runtime/storage.js.map +1 -0
- package/dist/spec/actions.d.ts +40 -0
- package/dist/spec/actions.d.ts.map +1 -0
- package/dist/spec/actions.js +53 -0
- package/dist/spec/actions.js.map +1 -0
- package/dist/spec/assistant-ui/thread.d.ts +66 -0
- package/dist/spec/assistant-ui/thread.d.ts.map +1 -0
- package/dist/spec/assistant-ui/thread.js +252 -0
- package/dist/spec/assistant-ui/thread.js.map +1 -0
- package/dist/spec/assistant-ui/toolkit.d.ts +33 -0
- package/dist/spec/assistant-ui/toolkit.d.ts.map +1 -0
- package/dist/spec/assistant-ui/toolkit.js +142 -0
- package/dist/spec/assistant-ui/toolkit.js.map +1 -0
- package/dist/spec/assistant-ui/web.d.ts +6 -0
- package/dist/spec/assistant-ui/web.d.ts.map +1 -0
- package/dist/spec/assistant-ui/web.js +48 -0
- package/dist/spec/assistant-ui/web.js.map +1 -0
- package/dist/spec/assistant-ui.d.ts +3 -0
- package/dist/spec/assistant-ui.d.ts.map +1 -0
- package/dist/spec/assistant-ui.js +1 -0
- package/dist/spec/calc.d.ts +8 -0
- package/dist/spec/calc.d.ts.map +1 -0
- package/dist/spec/calc.js +498 -0
- package/dist/spec/calc.js.map +1 -0
- package/dist/spec/catalog.d.ts +52 -0
- package/dist/spec/catalog.d.ts.map +1 -0
- package/dist/spec/catalog.js +104 -0
- package/dist/spec/catalog.js.map +1 -0
- package/dist/spec/expressions.d.ts +45 -0
- package/dist/spec/expressions.d.ts.map +1 -0
- package/dist/spec/expressions.js +199 -0
- package/dist/spec/expressions.js.map +1 -0
- package/dist/spec/patch.d.ts +20 -0
- package/dist/spec/patch.d.ts.map +1 -0
- package/dist/spec/patch.js +77 -0
- package/dist/spec/patch.js.map +1 -0
- package/dist/spec/pending.d.ts +15 -0
- package/dist/spec/pending.d.ts.map +1 -0
- package/dist/spec/pending.js +33 -0
- package/dist/spec/pending.js.map +1 -0
- package/dist/spec/pointer.d.ts +17 -0
- package/dist/spec/pointer.d.ts.map +1 -0
- package/dist/spec/pointer.js +88 -0
- package/dist/spec/pointer.js.map +1 -0
- package/dist/spec/prompt.d.ts +29 -0
- package/dist/spec/prompt.d.ts.map +1 -0
- package/dist/spec/prompt.js +145 -0
- package/dist/spec/prompt.js.map +1 -0
- package/dist/spec/render-spec.d.ts +50 -0
- package/dist/spec/render-spec.d.ts.map +1 -0
- package/dist/spec/render-spec.js +104 -0
- package/dist/spec/render-spec.js.map +1 -0
- package/dist/spec/resolve.d.ts +39 -0
- package/dist/spec/resolve.d.ts.map +1 -0
- package/dist/spec/resolve.js +51 -0
- package/dist/spec/resolve.js.map +1 -0
- package/dist/spec/resolved.d.ts +3 -0
- package/dist/spec/resolved.d.ts.map +1 -0
- package/dist/spec/resolved.js +36 -0
- package/dist/spec/resolved.js.map +1 -0
- package/dist/spec/state.d.ts +34 -0
- package/dist/spec/state.d.ts.map +1 -0
- package/dist/spec/state.js +111 -0
- package/dist/spec/state.js.map +1 -0
- package/dist/spec/stream.d.ts +50 -0
- package/dist/spec/stream.d.ts.map +1 -0
- package/dist/spec/stream.js +168 -0
- package/dist/spec/stream.js.map +1 -0
- package/dist/spec/tools.d.ts +3 -0
- package/dist/spec/tools.d.ts.map +1 -0
- package/dist/spec/tools.js +3 -0
- package/dist/spec/tree.d.ts +21 -0
- package/dist/spec/tree.d.ts.map +1 -0
- package/dist/spec/tree.js +27 -0
- package/dist/spec/tree.js.map +1 -0
- package/dist/spec/types.d.ts +66 -0
- package/dist/spec/types.d.ts.map +1 -0
- package/dist/spec/types.js +9 -0
- package/dist/spec/types.js.map +1 -0
- package/dist/spec/validate.d.ts +32 -0
- package/dist/spec/validate.d.ts.map +1 -0
- package/dist/spec/validate.js +264 -0
- package/dist/spec/validate.js.map +1 -0
- package/dist/spec/vue/SpecRenderer.d.ts +43 -0
- package/dist/spec/vue/SpecRenderer.d.ts.map +1 -0
- package/dist/spec/vue/SpecRenderer.js +357 -0
- package/dist/spec/vue/SpecRenderer.js.map +1 -0
- package/dist/spec/vue/useSpecStream.d.ts +19 -0
- package/dist/spec/vue/useSpecStream.d.ts.map +1 -0
- package/dist/spec/vue/useSpecStream.js +115 -0
- package/dist/spec/vue/useSpecStream.js.map +1 -0
- package/dist/spec/vue.d.ts +3 -0
- package/dist/spec/vue.d.ts.map +1 -0
- package/dist/spec/vue.js +3 -0
- package/dist/spec.d.ts +12 -0
- package/dist/spec.d.ts.map +1 -0
- package/dist/spec.js +8 -0
- package/dist/theme.d.ts +38 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +370 -0
- package/dist/theme.js.map +1 -0
- package/dist/tools/define.d.ts +43 -0
- package/dist/tools/define.d.ts.map +1 -0
- package/dist/tools/define.js +31 -0
- package/dist/tools/define.js.map +1 -0
- package/dist/tools/edits.d.ts +19 -0
- package/dist/tools/edits.d.ts.map +1 -0
- package/dist/tools/edits.js +55 -0
- package/dist/tools/edits.js.map +1 -0
- package/dist/tools/registry.d.ts +19 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +33 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/tools.d.ts +88 -0
- package/dist/tools/tools.d.ts.map +1 -0
- package/dist/tools/tools.js +235 -0
- package/dist/tools/tools.js.map +1 -0
- package/dist/tools.d.ts +5 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +5 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +5 -0
- package/dist/version.js.map +1 -0
- package/dist/vue/Widget.d.ts +16 -0
- package/dist/vue/Widget.d.ts.map +1 -0
- package/dist/vue/Widget.js +58 -0
- package/dist/vue/Widget.js.map +1 -0
- package/dist/vue/sync.d.ts +19 -0
- package/dist/vue/sync.d.ts.map +1 -0
- package/dist/vue/sync.js +31 -0
- package/dist/vue/sync.js.map +1 -0
- package/dist/vue/themeStore.d.ts +23 -0
- package/dist/vue/themeStore.d.ts.map +1 -0
- package/dist/vue/themeStore.js +115 -0
- package/dist/vue/themeStore.js.map +1 -0
- package/dist/vue/useThemeTokens.d.ts +6 -0
- package/dist/vue/useThemeTokens.d.ts.map +1 -0
- package/dist/vue/useThemeTokens.js +49 -0
- package/dist/vue/useThemeTokens.js.map +1 -0
- package/dist/vue/useWidget.d.ts +10 -0
- package/dist/vue/useWidget.d.ts.map +1 -0
- package/dist/vue/useWidget.js +81 -0
- package/dist/vue/useWidget.js.map +1 -0
- package/dist/vue.d.ts +5 -0
- package/dist/vue.d.ts.map +1 -0
- package/dist/vue.js +4 -0
- package/dist/widget.d.ts +129 -0
- package/dist/widget.d.ts.map +1 -0
- package/dist/widget.js +655 -0
- package/dist/widget.js.map +1 -0
- package/package.json +125 -3
- package/src/assistant-ui/entry.ts +124 -0
- package/src/assistant-ui/extension.ts +19 -0
- package/src/assistant-ui/history.ts +63 -0
- package/src/assistant-ui/modelContext.ts +162 -0
- package/src/assistant-ui/snapshotSaver.ts +116 -0
- package/src/assistant-ui/tool-calls.ts +115 -0
- package/src/assistant-ui/toolkit.tsx +747 -0
- package/src/assistant-ui/useSharedContext.ts +40 -0
- package/src/assistant-ui.ts +14 -0
- package/src/bootstrap.ts +112 -0
- package/src/csp.ts +96 -0
- package/src/index.ts +44 -0
- package/src/json-schema.ts +353 -0
- package/src/preview.ts +120 -0
- package/src/prompts/guidance.ts +369 -0
- package/src/prompts.ts +8 -0
- package/src/protocol.ts +141 -0
- package/src/repair/repair.ts +202 -0
- package/src/repair.ts +11 -0
- package/src/rpc.ts +228 -0
- package/src/runtime/diagnostics.ts +165 -0
- package/src/runtime/generated.ts +2 -0
- package/src/runtime/index.ts +343 -0
- package/src/runtime/morph.ts +352 -0
- package/src/runtime/screenshot.ts +288 -0
- package/src/runtime/size.ts +17 -0
- package/src/runtime/storage.ts +49 -0
- package/src/spec/actions.ts +111 -0
- package/src/spec/assistant-ui/thread.ts +381 -0
- package/src/spec/assistant-ui/toolkit.tsx +295 -0
- package/src/spec/assistant-ui/web.tsx +63 -0
- package/src/spec/assistant-ui.ts +2 -0
- package/src/spec/calc.ts +598 -0
- package/src/spec/catalog.ts +196 -0
- package/src/spec/expressions.ts +301 -0
- package/src/spec/patch.ts +112 -0
- package/src/spec/pending.ts +36 -0
- package/src/spec/pointer.ts +170 -0
- package/src/spec/prompt.ts +243 -0
- package/src/spec/render-spec.ts +144 -0
- package/src/spec/resolve.ts +123 -0
- package/src/spec/resolved.ts +53 -0
- package/src/spec/state.ts +193 -0
- package/src/spec/stream.ts +230 -0
- package/src/spec/tools.ts +17 -0
- package/src/spec/tree.ts +37 -0
- package/src/spec/types.ts +51 -0
- package/src/spec/validate.ts +429 -0
- package/src/spec/vue/SpecRenderer.tsx +544 -0
- package/src/spec/vue/__tests__/harness.ts +50 -0
- package/src/spec/vue/useSpecStream.ts +162 -0
- package/src/spec/vue.ts +13 -0
- package/src/spec.ts +55 -0
- package/src/theme.ts +423 -0
- package/src/tools/define.ts +65 -0
- package/src/tools/edits.ts +73 -0
- package/src/tools/registry.ts +44 -0
- package/src/tools/tools.ts +361 -0
- package/src/tools.ts +32 -0
- package/src/version.ts +4 -0
- package/src/vue/Widget.tsx +74 -0
- package/src/vue/sync.ts +36 -0
- package/src/vue/themeStore.ts +157 -0
- package/src/vue/useThemeTokens.ts +71 -0
- package/src/vue/useWidget.ts +117 -0
- package/src/vue.ts +8 -0
- package/src/widget.ts +1080 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Catalog } from "./catalog.js";
|
|
2
|
+
import { type ExpressionContext } from "./expressions.js";
|
|
3
|
+
import type { SpecStateStore } from "./state.js";
|
|
4
|
+
import type { ActionBinding } from "./types.js";
|
|
5
|
+
/** Where an action was dispatched from. */
|
|
6
|
+
export type ActionSource = {
|
|
7
|
+
elementId?: string;
|
|
8
|
+
/** The event name, or the watched path for `watch`. */
|
|
9
|
+
trigger?: string;
|
|
10
|
+
/** Whether a component's event or a `watch` binding dispatched the action. */
|
|
11
|
+
kind?: "event" | "watch";
|
|
12
|
+
};
|
|
13
|
+
export type ActionHandler = (params: Record<string, unknown>, context: ActionSource & {
|
|
14
|
+
state: SpecStateStore;
|
|
15
|
+
}) => unknown;
|
|
16
|
+
export type ActionDispatcherOptions = {
|
|
17
|
+
store: SpecStateStore;
|
|
18
|
+
catalog?: Catalog;
|
|
19
|
+
/** Handlers by action name; they take precedence over `onAction`. */
|
|
20
|
+
handlers?: Record<string, ActionHandler>;
|
|
21
|
+
/** Called for catalog actions without a handler. */
|
|
22
|
+
onAction?: (name: string, params: Record<string, unknown>, context: ActionSource & {
|
|
23
|
+
state: SpecStateStore;
|
|
24
|
+
}) => unknown;
|
|
25
|
+
/** Reports actions that fail or are unknown instead of throwing. */
|
|
26
|
+
onError?: (error: Error, binding: ActionBinding) => void;
|
|
27
|
+
};
|
|
28
|
+
export type ActionDispatcher = (bindings: ActionBinding | readonly ActionBinding[] | undefined, context: Omit<ExpressionContext, "state" | "event"> & ActionSource & {
|
|
29
|
+
/** The payload the event carried, read by `{ $event }`. */
|
|
30
|
+
payload?: unknown;
|
|
31
|
+
}) => Promise<unknown[]>;
|
|
32
|
+
/**
|
|
33
|
+
* Creates the function elements use to run their bound actions: params are
|
|
34
|
+
* resolved against current state (and the event payload), `setState` writes
|
|
35
|
+
* the store, and every other action goes to a host handler. Actions in a list
|
|
36
|
+
* run in order, see state written by the ones before them, and stop at the
|
|
37
|
+
* first one that fails.
|
|
38
|
+
*/
|
|
39
|
+
export declare function createActionDispatcher(options: ActionDispatcherOptions): ActionDispatcher;
|
|
40
|
+
//# sourceMappingURL=actions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.d.ts","mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAW;AACxC,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,kBAAe;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAS;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAS;AAE5C;AACA,MAAM,MAAM,YAAY,GAAG;IACzB,SAAS,CAAC,EAAE,MAAM;IAClB;IACA,OAAO,CAAC,EAAE,MAAM;IAChB;IACA,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO;CACzB;AAED,MAAM,MAAM,aAAa,GAAG,CAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE,YAAY,GAAG;IAAE,KAAK,EAAE,cAAc;CAAE,KAC9C,OAAO;AAEZ,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,cAAc;IACrB,OAAO,CAAC,EAAE,OAAO;IACjB;IACA,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC;IACxC;IACA,QAAQ,CAAC,EAAE,CACT,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE,YAAY,GAAG;QAAE,KAAK,EAAE,cAAc;KAAE,KAC9C,OAAO;IACZ;IACA,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,KAAK,IAAI;CACzD;AAED,MAAM,MAAM,gBAAgB,GAAG,CAC7B,QAAQ,EAAE,aAAa,GAAG,SAAS,aAAa,EAAE,GAAG,SAAS,EAC9D,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,OAAO,GAAG,OAAO,CAAC,GACjD,YAAY,GAAG;IACb;IACA,OAAO,CAAC,EAAE,OAAO;CAClB,KACA,OAAO,CAAC,OAAO,EAAE,CAAC;AAEvB;;;;;;;AAOA,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,uBAAuB,GAC/B,gBAAgB","names":[],"ignoreList":[],"sources":["../../src/spec/actions.ts"],"sourcesContent":[null]}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { resolveValue } from "./expressions.js";
|
|
2
|
+
// src/spec/actions.ts
|
|
3
|
+
/**
|
|
4
|
+
* Creates the function elements use to run their bound actions: params are
|
|
5
|
+
* resolved against current state (and the event payload), `setState` writes
|
|
6
|
+
* the store, and every other action goes to a host handler. Actions in a list
|
|
7
|
+
* run in order, see state written by the ones before them, and stop at the
|
|
8
|
+
* first one that fails.
|
|
9
|
+
*/
|
|
10
|
+
function createActionDispatcher(options) {
|
|
11
|
+
const report = (error, binding) => {
|
|
12
|
+
const normalized = error instanceof Error ? error : new Error(String(error));
|
|
13
|
+
if (options.onError) options.onError(normalized, binding);
|
|
14
|
+
else console.warn(`[generative-frame] action "${binding.action}" failed:`, normalized);
|
|
15
|
+
};
|
|
16
|
+
return async (bindings, context) => {
|
|
17
|
+
const list = bindings === void 0 ? [] : Array.isArray(bindings) ? bindings : [bindings];
|
|
18
|
+
const results = [];
|
|
19
|
+
for (const binding of list) {
|
|
20
|
+
const { payload, elementId, trigger, kind, ...scope } = context;
|
|
21
|
+
const params = resolveValue(binding.params ?? {}, {
|
|
22
|
+
...scope,
|
|
23
|
+
state: options.store.getState(),
|
|
24
|
+
event: payload
|
|
25
|
+
}) ?? {};
|
|
26
|
+
const source = {
|
|
27
|
+
...elementId !== void 0 ? { elementId } : {},
|
|
28
|
+
...trigger !== void 0 ? { trigger } : {},
|
|
29
|
+
...kind !== void 0 ? { kind } : {},
|
|
30
|
+
state: options.store
|
|
31
|
+
};
|
|
32
|
+
try {
|
|
33
|
+
const handler = options.handlers?.[binding.action];
|
|
34
|
+
if (handler) results.push(await handler(params, source));
|
|
35
|
+
else if (binding.action === "setState") {
|
|
36
|
+
if (typeof params["path"] !== "string") throw new Error("setState needs a string `path`");
|
|
37
|
+
options.store.set(params["path"], params["value"]);
|
|
38
|
+
results.push(void 0);
|
|
39
|
+
} else if (options.catalog && !options.catalog.action(binding.action)) throw new Error(`Unknown action "${binding.action}"`);
|
|
40
|
+
else if (options.onAction) results.push(await options.onAction(binding.action, params, source));
|
|
41
|
+
else throw new Error(`No handler for action "${binding.action}"`);
|
|
42
|
+
} catch (error) {
|
|
43
|
+
report(error, binding);
|
|
44
|
+
results.push(void 0);
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return results;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export { createActionDispatcher };
|
|
52
|
+
|
|
53
|
+
//# sourceMappingURL=actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.js","names":[],"sources":["../../src/spec/actions.ts"],"sourcesContent":["import type { Catalog } from \"./catalog\";\nimport { resolveValue, type ExpressionContext } from \"./expressions\";\nimport type { SpecStateStore } from \"./state\";\nimport type { ActionBinding } from \"./types\";\n\n/** Where an action was dispatched from. */\nexport type ActionSource = {\n elementId?: string;\n /** The event name, or the watched path for `watch`. */\n trigger?: string;\n /** Whether a component's event or a `watch` binding dispatched the action. */\n kind?: \"event\" | \"watch\";\n};\n\nexport type ActionHandler = (\n params: Record<string, unknown>,\n context: ActionSource & { state: SpecStateStore },\n) => unknown;\n\nexport type ActionDispatcherOptions = {\n store: SpecStateStore;\n catalog?: Catalog;\n /** Handlers by action name; they take precedence over `onAction`. */\n handlers?: Record<string, ActionHandler>;\n /** Called for catalog actions without a handler. */\n onAction?: (\n name: string,\n params: Record<string, unknown>,\n context: ActionSource & { state: SpecStateStore },\n ) => unknown;\n /** Reports actions that fail or are unknown instead of throwing. */\n onError?: (error: Error, binding: ActionBinding) => void;\n};\n\nexport type ActionDispatcher = (\n bindings: ActionBinding | readonly ActionBinding[] | undefined,\n context: Omit<ExpressionContext, \"state\" | \"event\"> &\n ActionSource & {\n /** The payload the event carried, read by `{ $event }`. */\n payload?: unknown;\n },\n) => Promise<unknown[]>;\n\n/**\n * Creates the function elements use to run their bound actions: params are\n * resolved against current state (and the event payload), `setState` writes\n * the store, and every other action goes to a host handler. Actions in a list\n * run in order, see state written by the ones before them, and stop at the\n * first one that fails.\n */\nexport function createActionDispatcher(\n options: ActionDispatcherOptions,\n): ActionDispatcher {\n const report = (error: unknown, binding: ActionBinding) => {\n const normalized =\n error instanceof Error ? error : new Error(String(error));\n if (options.onError) options.onError(normalized, binding);\n else\n console.warn(\n `[generative-frame] action \"${binding.action}\" failed:`,\n normalized,\n );\n };\n\n return async (bindings, context) => {\n const list =\n bindings === undefined\n ? []\n : Array.isArray(bindings)\n ? bindings\n : [bindings];\n const results: unknown[] = [];\n for (const binding of list as ActionBinding[]) {\n const { payload, elementId, trigger, kind, ...scope } = context;\n const params = (resolveValue(binding.params ?? {}, {\n ...scope,\n state: options.store.getState(),\n event: payload,\n }) ?? {}) as Record<string, unknown>;\n const source = {\n ...(elementId !== undefined ? { elementId } : {}),\n ...(trigger !== undefined ? { trigger } : {}),\n ...(kind !== undefined ? { kind } : {}),\n state: options.store,\n };\n try {\n const handler = options.handlers?.[binding.action];\n if (handler) {\n results.push(await handler(params, source));\n } else if (binding.action === \"setState\") {\n if (typeof params[\"path\"] !== \"string\") {\n throw new Error(\"setState needs a string `path`\");\n }\n options.store.set(params[\"path\"], params[\"value\"]);\n results.push(undefined);\n } else if (options.catalog && !options.catalog.action(binding.action)) {\n throw new Error(`Unknown action \"${binding.action}\"`);\n } else if (options.onAction) {\n results.push(await options.onAction(binding.action, params, source));\n } else {\n throw new Error(`No handler for action \"${binding.action}\"`);\n }\n } catch (error) {\n report(error, binding);\n results.push(undefined);\n break;\n }\n }\n return results;\n };\n}\n"],"mappings":";;;;;;;;;AAkDA,SAAgB,uBACd,SACkB;CAClB,MAAM,UAAU,OAAgB,YAA2B;EACzD,MAAM,aACJ,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;EAC1D,IAAI,QAAQ,SAAS,QAAQ,QAAQ,YAAY,OAAO;OAEtD,QAAQ,KACN,8BAA8B,QAAQ,OAAO,YAC7C,UACF;CACJ;CAEA,OAAO,OAAO,UAAU,YAAY;EAClC,MAAM,OACJ,aAAa,KAAA,IACT,CAAC,IACD,MAAM,QAAQ,QAAQ,IACpB,WACA,CAAC,QAAQ;EACjB,MAAM,UAAqB,CAAC;EAC5B,KAAK,MAAM,WAAW,MAAyB;GAC7C,MAAM,EAAE,SAAS,WAAW,SAAS,MAAM,GAAG,UAAU;GACxD,MAAM,SAAU,aAAa,QAAQ,UAAU,CAAC,GAAG;IACjD,GAAG;IACH,OAAO,QAAQ,MAAM,SAAS;IAC9B,OAAO;GACT,CAAC,KAAK,CAAC;GACP,MAAM,SAAS;IACb,GAAI,cAAc,KAAA,IAAY,EAAE,UAAU,IAAI,CAAC;IAC/C,GAAI,YAAY,KAAA,IAAY,EAAE,QAAQ,IAAI,CAAC;IAC3C,GAAI,SAAS,KAAA,IAAY,EAAE,KAAK,IAAI,CAAC;IACrC,OAAO,QAAQ;GACjB;GACA,IAAI;IACF,MAAM,UAAU,QAAQ,WAAW,QAAQ;IAC3C,IAAI,SACF,QAAQ,KAAK,MAAM,QAAQ,QAAQ,MAAM,CAAC;SACrC,IAAI,QAAQ,WAAW,YAAY;KACxC,IAAI,OAAO,OAAO,YAAY,UAC5B,MAAM,IAAI,MAAM,gCAAgC;KAElD,QAAQ,MAAM,IAAI,OAAO,SAAS,OAAO,QAAQ;KACjD,QAAQ,KAAK,KAAA,CAAS;IACxB,OAAO,IAAI,QAAQ,WAAW,CAAC,QAAQ,QAAQ,OAAO,QAAQ,MAAM,GAClE,MAAM,IAAI,MAAM,mBAAmB,QAAQ,OAAO,EAAE;SAC/C,IAAI,QAAQ,UACjB,QAAQ,KAAK,MAAM,QAAQ,SAAS,QAAQ,QAAQ,QAAQ,MAAM,CAAC;SAEnE,MAAM,IAAI,MAAM,0BAA0B,QAAQ,OAAO,EAAE;GAE/D,SAAS,OAAO;IACd,OAAO,OAAO,OAAO;IACrB,QAAQ,KAAK,KAAA,CAAS;IACtB;GACF;EACF;EACA,OAAO;CACT;AACF"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { type MessageLike } from "../../assistant-ui/tool-calls.js";
|
|
2
|
+
import type { ActionHandler } from "../actions.js";
|
|
3
|
+
import type { Catalog } from "../catalog.js";
|
|
4
|
+
import type { SpecPromptOptions } from "../prompt.js";
|
|
5
|
+
import { type RenderSpecInput } from "../render-spec.js";
|
|
6
|
+
import type { SpecStateWrite } from "../state.js";
|
|
7
|
+
import type { Spec } from "../types.js";
|
|
8
|
+
/** The arguments of a `render_spec` call, which stream in. */
|
|
9
|
+
export type SpecArgs = Partial<RenderSpecInput>;
|
|
10
|
+
/** The interactions a host records on a tool call, as its `unstable_interactions` prop holds them. */
|
|
11
|
+
export type InteractionLog = {
|
|
12
|
+
readonly entries: readonly ({
|
|
13
|
+
readonly type: "action";
|
|
14
|
+
readonly payload: Readonly<Record<string, unknown>>;
|
|
15
|
+
} | {
|
|
16
|
+
readonly type: "human-response";
|
|
17
|
+
readonly payload: unknown;
|
|
18
|
+
})[];
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* The state writes saved on a `render_spec` call: the newest `setState` interaction recorded for that call. An entry whose `writes` is not a list marks a save that failed, so the call starts from the model's state rather than from an older snapshot.
|
|
22
|
+
*/
|
|
23
|
+
export declare function savedWrites(log: InteractionLog | undefined, toolCallId: string): SpecStateWrite[];
|
|
24
|
+
/** Results of the tool calls before this one, by tool name and newest first, leaving out the widget toolkit's own tools. Tool names are keys every model can see, unlike call ids, which some formats never show, and counting back from this call keeps an index stable when a host prunes older history. */
|
|
25
|
+
export declare function resolveToolResults(messages: readonly MessageLike[], toolCallId: string): Record<string, unknown[]>;
|
|
26
|
+
/** A `spec` argument as the renderers read it, with `elements` an object even while the argument is still streaming in. */
|
|
27
|
+
export declare const specFromArgs: (spec: object) => Spec;
|
|
28
|
+
/**
|
|
29
|
+
* The spec a `render_spec` call's patches apply onto: the result of the
|
|
30
|
+
* earlier `render_spec` calls with the same title in the thread.
|
|
31
|
+
*/
|
|
32
|
+
export declare function resolveSpecBase(messages: readonly MessageLike[], toolCallId: string, title: string): Spec | undefined;
|
|
33
|
+
/** Whether a later `render_spec` call in the same message has this call's title. That call shows the spec this one's patches lead to, so this one shows nothing rather than a second copy. */
|
|
34
|
+
export declare function supersededInMessage(messages: readonly MessageLike[], toolCallId: string, title: string): boolean;
|
|
35
|
+
type SpecHistory = {
|
|
36
|
+
base(title: string): {
|
|
37
|
+
spec: Spec | undefined;
|
|
38
|
+
version: number;
|
|
39
|
+
};
|
|
40
|
+
toolResults: Record<string, unknown[]> | undefined;
|
|
41
|
+
};
|
|
42
|
+
/** What a mounted call registers for `execute`: the spec each title held before it in its own thread, how many calls built it, and the earlier results it mounts under `/tools`. */
|
|
43
|
+
export declare const callHistory: (messages: readonly MessageLike[], toolCallId: string, toolResults: Record<string, unknown[]> | undefined) => SpecHistory;
|
|
44
|
+
/**
|
|
45
|
+
* The `render_spec` tool a toolkit shares across its calls. Each mounted call
|
|
46
|
+
* registers its {@link callHistory} in `histories` under its tool call id, so
|
|
47
|
+
* `execute` patches the base that call's own thread held, even after a reload
|
|
48
|
+
* or in another thread.
|
|
49
|
+
*/
|
|
50
|
+
export declare function createSpecCalls(catalog: Catalog, specPrompt: Omit<SpecPromptOptions, "mode"> | undefined): {
|
|
51
|
+
tools: import("../render-spec.js").SpecTools;
|
|
52
|
+
histories: Map<string, SpecHistory>;
|
|
53
|
+
execute: (input: RenderSpecInput, call: {
|
|
54
|
+
toolCallId: string;
|
|
55
|
+
}) => Promise<import("../render-spec.js").RenderSpecResult>;
|
|
56
|
+
};
|
|
57
|
+
/** The `spec` module of `read_me`: the catalog guidance with the built-in actions every assistant-ui toolkit handles, the app's rules, and where earlier tool results are. */
|
|
58
|
+
export declare const specModules: (catalog: Catalog, specPrompt: Omit<SpecPromptOptions, "mode"> | undefined, host: {
|
|
59
|
+
clipboard: boolean;
|
|
60
|
+
}) => import("../tools.js").GuidanceModule[];
|
|
61
|
+
/** Writes to the browser's clipboard, rejecting where the Clipboard API is missing. */
|
|
62
|
+
export declare const writeClipboard: (text: string) => Promise<void>;
|
|
63
|
+
/** The built-in `copyText` handler. A copy that does not happen fails, so the rest of the list, such as a confirmation, does not run. */
|
|
64
|
+
export declare const copyTextHandler: (write: (text: string) => Promise<void>) => ActionHandler;
|
|
65
|
+
export {};
|
|
66
|
+
//# sourceMappingURL=thread.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thread.d.ts","mappings":"AAAA,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,kCAA+B;AACtC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAY;AAC/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAY;AAIzC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAW;AAClD,OAAO,EAIL,KAAK,eAAe,EACrB,MAAM,mBAAgB;AACvB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAU;AAG9C,OAAO,KAAK,EAAE,IAAI,EAAe,MAAM,aAAU;AAGjD;AACA,MAAM,MAAM,QAAQ,GAAG,OAAO,CAAC,eAAe,CAAC;AAE/C;AACA,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,OAAO,EAAE,SAAS,CACvB;QACE,QAAQ,CAAC,IAAI,EAAE,QAAQ;QACvB,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACpD,GACD;QAAE,QAAQ,CAAC,IAAI,EAAE,gBAAgB;QAAE,QAAQ,CAAC,OAAO,EAAE,OAAO;KAAE,CACjE,EAAE;CACJ;AAED;;;AAGA,wBAAgB,WAAW,CACzB,GAAG,EAAE,cAAc,GAAG,SAAS,EAC/B,UAAU,EAAE,MAAM,GACjB,cAAc,EAAE;AAmCnB;AACA,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,SAAS,WAAW,EAAE,EAChC,UAAU,EAAE,MAAM,GACjB,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;AAqB5B;AACA,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,KAAG,IAK3C;AAED;;;;AAIA,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,SAAS,WAAW,EAAE,EAChC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,GACZ,IAAI,GAAG,SAAS;AAiBnB;AACA,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,SAAS,WAAW,EAAE,EAChC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,GACZ,OAAO;AAsBV,KAAK,WAAW,GAAG;IACjB,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,IAAI,GAAG,SAAS;QAAE,OAAO,EAAE,MAAM;KAAE;IAChE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,SAAS;CACnD;AAED;AACA,eAAO,MAAM,WAAW,GACtB,UAAU,SAAS,WAAW,EAAE,EAChC,YAAY,MAAM,EAClB,aAAa,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,SAAS,KACjD,WAMD;AA0HF;;;;;;AAMA,wBAAgB,eAAe,CAC7B,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,GAAG,SAAS;;;qBAS9C,eAAe,QAChB;QAAE,UAAU,EAAE,MAAM;KAAE;;AAuBhC;AACA,eAAO,MAAM,WAAW,GACtB,SAAS,OAAO,EAChB,YAAY,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,GAAG,SAAS,EACvD,MAAM;IAAE,SAAS,EAAE,OAAO;CAAE,2CAY7B;AAED;AACA,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,KAAG,OAAO,CAAC,IAAI,CAGK;AAE/D;AACA,eAAO,MAAM,eAAe,GACzB,OAAO,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,KAAG,aAYzC","names":[],"ignoreList":[],"sources":["../../../src/spec/assistant-ui/thread.ts"],"sourcesContent":[null]}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { hasLaterToolCallInMessage, toolCalls } from "../../assistant-ui/tool-calls.js";
|
|
2
|
+
import { escapePointerToken, getAtPointer } from "../pointer.js";
|
|
3
|
+
import { formulaValueReads } from "../calc.js";
|
|
4
|
+
import { conditionGuards, templateStatePaths } from "../expressions.js";
|
|
5
|
+
import { parseSpecStream } from "../stream.js";
|
|
6
|
+
import { formatSpecIssues } from "../validate.js";
|
|
7
|
+
import { childIdsOf, safePointer } from "../tree.js";
|
|
8
|
+
import { SPEC_TOOL_RESULTS_RULE, createSpecTools, specGuidanceModule } from "../render-spec.js";
|
|
9
|
+
// src/spec/assistant-ui/thread.ts
|
|
10
|
+
/**
|
|
11
|
+
* The state writes saved on a `render_spec` call: the newest `setState` interaction recorded for that call. An entry whose `writes` is not a list marks a save that failed, so the call starts from the model's state rather than from an older snapshot.
|
|
12
|
+
*/
|
|
13
|
+
function savedWrites(log, toolCallId) {
|
|
14
|
+
const entries = log?.entries ?? [];
|
|
15
|
+
for (let index = entries.length - 1; index >= 0; index--) {
|
|
16
|
+
const entry = entries[index];
|
|
17
|
+
if (entry.type !== "action" || entry.payload["type"] !== "setState" || entry.payload["toolCallId"] !== toolCallId) continue;
|
|
18
|
+
const writes = entry.payload["writes"];
|
|
19
|
+
if (!Array.isArray(writes)) return [];
|
|
20
|
+
return writes.filter((write) => Array.isArray(write) && typeof write[0] === "string" && (write.length === 2 || write.length === 3 && write[2] === "replace" || write.length === 4 && (write[2] === "add" || write[2] === "replace") && Array.isArray(write[3]) && write[3].every((path) => typeof path === "string")));
|
|
21
|
+
}
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
const WIDGET_TOOLS = /* @__PURE__ */ new Set([
|
|
25
|
+
"read_me",
|
|
26
|
+
"show_widget",
|
|
27
|
+
"edit_widget",
|
|
28
|
+
"preview_widget",
|
|
29
|
+
"render_spec"
|
|
30
|
+
]);
|
|
31
|
+
/** Results of the tool calls before this one, by tool name and newest first, leaving out the widget toolkit's own tools. Tool names are keys every model can see, unlike call ids, which some formats never show, and counting back from this call keeps an index stable when a host prunes older history. */
|
|
32
|
+
function resolveToolResults(messages, toolCallId) {
|
|
33
|
+
const results = Object.create(null);
|
|
34
|
+
for (const call of toolCalls(messages)) {
|
|
35
|
+
if (call.id === toolCallId) break;
|
|
36
|
+
if (WIDGET_TOOLS.has(call.name)) continue;
|
|
37
|
+
(results[call.name] ??= []).unshift(decodeResult(call.result));
|
|
38
|
+
}
|
|
39
|
+
return results;
|
|
40
|
+
}
|
|
41
|
+
/** A string result that holds a JSON object or array is decoded, since the model read that string as the structure. */
|
|
42
|
+
function decodeResult(result) {
|
|
43
|
+
if (typeof result !== "string") return result;
|
|
44
|
+
try {
|
|
45
|
+
const value = JSON.parse(result);
|
|
46
|
+
return typeof value === "object" && value !== null ? value : result;
|
|
47
|
+
} catch {
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** A `spec` argument as the renderers read it, with `elements` an object even while the argument is still streaming in. */
|
|
52
|
+
const specFromArgs = (spec) => {
|
|
53
|
+
const value = {
|
|
54
|
+
state: {},
|
|
55
|
+
...spec
|
|
56
|
+
};
|
|
57
|
+
return typeof value.elements === "object" && value.elements !== null ? value : {
|
|
58
|
+
...value,
|
|
59
|
+
elements: {}
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* The spec a `render_spec` call's patches apply onto: the result of the
|
|
64
|
+
* earlier `render_spec` calls with the same title in the thread.
|
|
65
|
+
*/
|
|
66
|
+
function resolveSpecBase(messages, toolCallId, title) {
|
|
67
|
+
let spec;
|
|
68
|
+
for (const call of toolCalls(messages)) {
|
|
69
|
+
if (call.id === toolCallId) return spec;
|
|
70
|
+
if (call.name !== "render_spec" || call.args["title"] !== title) continue;
|
|
71
|
+
if (call.args["spec"] && typeof call.args["spec"] === "object") spec = specFromArgs(call.args["spec"]);
|
|
72
|
+
else if (typeof call.args["patches"] === "string") spec = parseSpecStream(call.args["patches"], spec ? { initial: spec } : {}).spec;
|
|
73
|
+
}
|
|
74
|
+
return spec;
|
|
75
|
+
}
|
|
76
|
+
/** Whether a later `render_spec` call in the same message has this call's title. That call shows the spec this one's patches lead to, so this one shows nothing rather than a second copy. */
|
|
77
|
+
function supersededInMessage(messages, toolCallId, title) {
|
|
78
|
+
return hasLaterToolCallInMessage(messages, toolCallId, title, (call) => call.name === "render_spec");
|
|
79
|
+
}
|
|
80
|
+
function priorSpecCalls(messages, toolCallId, title) {
|
|
81
|
+
let count = 0;
|
|
82
|
+
for (const call of toolCalls(messages)) {
|
|
83
|
+
if (call.id === toolCallId) break;
|
|
84
|
+
if (call.name === "render_spec" && call.args["title"] === title) count++;
|
|
85
|
+
}
|
|
86
|
+
return count;
|
|
87
|
+
}
|
|
88
|
+
/** What a mounted call registers for `execute`: the spec each title held before it in its own thread, how many calls built it, and the earlier results it mounts under `/tools`. */
|
|
89
|
+
const callHistory = (messages, toolCallId, toolResults) => ({
|
|
90
|
+
base: (title) => ({
|
|
91
|
+
spec: resolveSpecBase(messages, toolCallId, title),
|
|
92
|
+
version: priorSpecCalls(messages, toolCallId, title)
|
|
93
|
+
}),
|
|
94
|
+
toolResults
|
|
95
|
+
});
|
|
96
|
+
const readsTools = (pointer) => pointer === "/tools" || pointer.startsWith("/tools/");
|
|
97
|
+
/** Collects the state paths a value shows, leaving out reads in a branch that only renders while that path has a value: the `$then` of a `$cond` that tests it, and the `?` branch of a `$calc` condition on it. */
|
|
98
|
+
function collectShown(value, guarded, shown) {
|
|
99
|
+
if (Array.isArray(value)) {
|
|
100
|
+
for (const item of value) collectShown(item, guarded, shown);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (typeof value !== "object" || value === null) return;
|
|
104
|
+
const record = value;
|
|
105
|
+
if ("$cond" in record) {
|
|
106
|
+
const tested = conditionGuards(record["$cond"]).map(safePointer);
|
|
107
|
+
collectShown(record["$then"], /* @__PURE__ */ new Set([...guarded, ...tested]), shown);
|
|
108
|
+
collectShown(record["$else"], guarded, shown);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
for (const [key, child] of Object.entries(record)) {
|
|
112
|
+
if (typeof child !== "string") {
|
|
113
|
+
collectShown(child, guarded, shown);
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
const paths = key === "$state" || key === "$bindState" ? [child] : key === "$template" ? templateStatePaths(child) : key === "$calc" ? formulaValueReads(child) : [];
|
|
117
|
+
for (const path of paths) {
|
|
118
|
+
const pointer = safePointer(path);
|
|
119
|
+
if (!guarded.has(pointer)) shown.push(pointer);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/** Each place a spec can render an element, with the paths a `visible` condition on it or an ancestor guards there: reachable from the root through children and slots, leaving out one hidden with `visible: false` along with what it holds, and the repeated children of a `/tools` path the results hold no array at. An element under parents that guard different paths appears once per set of guards. */
|
|
124
|
+
function renderedElements(spec, state) {
|
|
125
|
+
const elements = spec.elements ?? {};
|
|
126
|
+
const rendered = [];
|
|
127
|
+
const seen = /* @__PURE__ */ new Set();
|
|
128
|
+
const pending = typeof spec.root === "string" ? [[spec.root, /* @__PURE__ */ new Set()]] : [];
|
|
129
|
+
while (pending.length > 0) {
|
|
130
|
+
const [id, inherited] = pending.pop();
|
|
131
|
+
if (!Object.hasOwn(elements, id)) continue;
|
|
132
|
+
const element = elements[id];
|
|
133
|
+
if (typeof element !== "object" || element === null) continue;
|
|
134
|
+
if (element.visible === false) continue;
|
|
135
|
+
const guarded = /* @__PURE__ */ new Set([...inherited, ...conditionGuards(element.visible).map(safePointer)]);
|
|
136
|
+
const visit = JSON.stringify([id, ...[...guarded].sort()]);
|
|
137
|
+
if (seen.has(visit)) continue;
|
|
138
|
+
seen.add(visit);
|
|
139
|
+
rendered.push([
|
|
140
|
+
id,
|
|
141
|
+
element,
|
|
142
|
+
guarded
|
|
143
|
+
]);
|
|
144
|
+
const repeat = typeof element.repeat?.path === "string" ? safePointer(element.repeat.path) : void 0;
|
|
145
|
+
const repeatsNothing = repeat !== void 0 && readsTools(repeat) && !Array.isArray(getAtPointer(state, repeat));
|
|
146
|
+
for (const slot of ["default", ...Object.keys(element.slots ?? {})]) {
|
|
147
|
+
if (slot === "default" && repeatsNothing) continue;
|
|
148
|
+
for (const child of childIdsOf(element, slot)) if (typeof child === "string") pending.push([child, guarded]);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return rendered;
|
|
152
|
+
}
|
|
153
|
+
/** Each place a spec shows state under `/tools` that the mounted results do not have, as a warning, since the model may have read the value from output the thread does not store or may mean a field that is absent. A read that only renders while its path has a value, under a `visible` condition or `$cond` test on it, is left out. */
|
|
154
|
+
function missingToolResults(spec, toolResults) {
|
|
155
|
+
const issues = [];
|
|
156
|
+
const state = { tools: toolResults };
|
|
157
|
+
const reported = /* @__PURE__ */ new Set();
|
|
158
|
+
for (const [id, element, guarded] of renderedElements(spec, state)) {
|
|
159
|
+
const shown = [];
|
|
160
|
+
collectShown([
|
|
161
|
+
element.props,
|
|
162
|
+
element.on,
|
|
163
|
+
element.watch
|
|
164
|
+
], guarded, shown);
|
|
165
|
+
if (typeof element.repeat?.path === "string") {
|
|
166
|
+
const pointer = safePointer(element.repeat.path);
|
|
167
|
+
if (!guarded.has(pointer)) shown.push(pointer);
|
|
168
|
+
}
|
|
169
|
+
for (const pointer of new Set(shown)) {
|
|
170
|
+
if (!readsTools(pointer)) continue;
|
|
171
|
+
if (getAtPointer(state, pointer) !== void 0) continue;
|
|
172
|
+
const report = JSON.stringify([id, pointer]);
|
|
173
|
+
if (reported.has(report)) continue;
|
|
174
|
+
reported.add(report);
|
|
175
|
+
issues.push({
|
|
176
|
+
code: "missing-tool-result",
|
|
177
|
+
severity: "warning",
|
|
178
|
+
elementId: id,
|
|
179
|
+
path: `/elements/${escapePointerToken(id)}`,
|
|
180
|
+
message: `"${id}" shows \`${pointer}\`, which the earlier tool results do not have, so it shows nothing there. If you read that value from the tool's output, write it into the spec instead.`
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return issues;
|
|
185
|
+
}
|
|
186
|
+
/** The app's rules and where earlier tool results are, which `render_spec`'s description and the `spec` module both carry. */
|
|
187
|
+
const toolkitRules = (specPrompt) => [...specPrompt?.customRules ?? [], SPEC_TOOL_RESULTS_RULE];
|
|
188
|
+
/**
|
|
189
|
+
* The `render_spec` tool a toolkit shares across its calls. Each mounted call
|
|
190
|
+
* registers its {@link callHistory} in `histories` under its tool call id, so
|
|
191
|
+
* `execute` patches the base that call's own thread held, even after a reload
|
|
192
|
+
* or in another thread.
|
|
193
|
+
*/
|
|
194
|
+
function createSpecCalls(catalog, specPrompt) {
|
|
195
|
+
const specs = /* @__PURE__ */ new Map();
|
|
196
|
+
const tools = createSpecTools(catalog, {
|
|
197
|
+
specs,
|
|
198
|
+
customRules: toolkitRules(specPrompt)
|
|
199
|
+
});
|
|
200
|
+
const histories = /* @__PURE__ */ new Map();
|
|
201
|
+
const execute = async (input, call) => {
|
|
202
|
+
const history = histories.get(call.toolCallId);
|
|
203
|
+
if (history) {
|
|
204
|
+
const { spec, version } = history.base(input.title);
|
|
205
|
+
if (spec) specs.set(input.title, {
|
|
206
|
+
spec,
|
|
207
|
+
version
|
|
208
|
+
});
|
|
209
|
+
else specs.delete(input.title);
|
|
210
|
+
}
|
|
211
|
+
const running = tools.render_spec.execute(input);
|
|
212
|
+
const spec = specs.get(input.title)?.spec;
|
|
213
|
+
const result = await running;
|
|
214
|
+
if (!history?.toolResults || !spec || spec.state?.["tools"] !== void 0) return result;
|
|
215
|
+
const missing = missingToolResults(spec, history.toolResults);
|
|
216
|
+
if (missing.length === 0) return result;
|
|
217
|
+
const issues = [...result.issues, ...missing];
|
|
218
|
+
return {
|
|
219
|
+
...result,
|
|
220
|
+
issues,
|
|
221
|
+
feedback: formatSpecIssues(issues)
|
|
222
|
+
};
|
|
223
|
+
};
|
|
224
|
+
return {
|
|
225
|
+
tools,
|
|
226
|
+
histories,
|
|
227
|
+
execute
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
/** The `spec` module of `read_me`: the catalog guidance with the built-in actions every assistant-ui toolkit handles, the app's rules, and where earlier tool results are. */
|
|
231
|
+
const specModules = (catalog, specPrompt, host) => [specGuidanceModule(catalog, {
|
|
232
|
+
...specPrompt,
|
|
233
|
+
hostApi: {
|
|
234
|
+
prompt: true,
|
|
235
|
+
modelContext: true,
|
|
236
|
+
clipboard: host.clipboard,
|
|
237
|
+
...specPrompt?.hostApi
|
|
238
|
+
},
|
|
239
|
+
customRules: toolkitRules(specPrompt)
|
|
240
|
+
})];
|
|
241
|
+
/** Writes to the browser's clipboard, rejecting where the Clipboard API is missing. */
|
|
242
|
+
const writeClipboard = (text) => typeof navigator !== "undefined" && navigator.clipboard ? navigator.clipboard.writeText(text) : Promise.reject(/* @__PURE__ */ new Error("Clipboard API is unavailable"));
|
|
243
|
+
/** The built-in `copyText` handler. A copy that does not happen fails, so the rest of the list, such as a confirmation, does not run. */
|
|
244
|
+
const copyTextHandler = (write) => (params, source) => {
|
|
245
|
+
if (source.kind === "watch") throw new Error("copyText runs only from an event a component emits, never from `watch`");
|
|
246
|
+
const text = params["text"];
|
|
247
|
+
if (typeof text !== "string") throw new Error("copyText needs a string `text`");
|
|
248
|
+
return write(text);
|
|
249
|
+
};
|
|
250
|
+
export { callHistory, copyTextHandler, createSpecCalls, resolveSpecBase, resolveToolResults, savedWrites, specFromArgs, specModules, supersededInMessage, writeClipboard };
|
|
251
|
+
|
|
252
|
+
//# sourceMappingURL=thread.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thread.js","names":[],"sources":["../../../src/spec/assistant-ui/thread.ts"],"sourcesContent":["import {\n hasLaterToolCallInMessage,\n toolCalls,\n type MessageLike,\n} from \"../../assistant-ui/tool-calls\";\nimport type { ActionHandler } from \"../actions\";\nimport type { Catalog } from \"../catalog\";\nimport { formulaValueReads } from \"../calc\";\nimport { conditionGuards, templateStatePaths } from \"../expressions\";\nimport { escapePointerToken, getAtPointer } from \"../pointer\";\nimport type { SpecPromptOptions } from \"../prompt\";\nimport {\n createSpecTools,\n SPEC_TOOL_RESULTS_RULE,\n specGuidanceModule,\n type RenderSpecInput,\n} from \"../render-spec\";\nimport type { SpecStateWrite } from \"../state\";\nimport { parseSpecStream } from \"../stream\";\nimport { childIdsOf, safePointer } from \"../tree\";\nimport type { Spec, SpecElement } from \"../types\";\nimport { formatSpecIssues, type SpecIssue } from \"../validate\";\n\n/** The arguments of a `render_spec` call, which stream in. */\nexport type SpecArgs = Partial<RenderSpecInput>;\n\n/** The interactions a host records on a tool call, as its `unstable_interactions` prop holds them. */\nexport type InteractionLog = {\n readonly entries: readonly (\n | {\n readonly type: \"action\";\n readonly payload: Readonly<Record<string, unknown>>;\n }\n | { readonly type: \"human-response\"; readonly payload: unknown }\n )[];\n};\n\n/**\n * The state writes saved on a `render_spec` call: the newest `setState` interaction recorded for that call. An entry whose `writes` is not a list marks a save that failed, so the call starts from the model's state rather than from an older snapshot.\n */\nexport function savedWrites(\n log: InteractionLog | undefined,\n toolCallId: string,\n): SpecStateWrite[] {\n const entries = log?.entries ?? [];\n for (let index = entries.length - 1; index >= 0; index--) {\n const entry = entries[index]!;\n if (\n entry.type !== \"action\" ||\n entry.payload[\"type\"] !== \"setState\" ||\n entry.payload[\"toolCallId\"] !== toolCallId\n )\n continue;\n const writes = entry.payload[\"writes\"];\n if (!Array.isArray(writes)) return [];\n return writes.filter(\n (write): write is SpecStateWrite =>\n Array.isArray(write) &&\n typeof write[0] === \"string\" &&\n (write.length === 2 ||\n (write.length === 3 && write[2] === \"replace\") ||\n (write.length === 4 &&\n (write[2] === \"add\" || write[2] === \"replace\") &&\n Array.isArray(write[3]) &&\n write[3].every((path: unknown) => typeof path === \"string\"))),\n );\n }\n return [];\n}\n\nconst WIDGET_TOOLS = new Set([\n \"read_me\",\n \"show_widget\",\n \"edit_widget\",\n \"preview_widget\",\n \"render_spec\",\n]);\n\n/** Results of the tool calls before this one, by tool name and newest first, leaving out the widget toolkit's own tools. Tool names are keys every model can see, unlike call ids, which some formats never show, and counting back from this call keeps an index stable when a host prunes older history. */\nexport function resolveToolResults(\n messages: readonly MessageLike[],\n toolCallId: string,\n): Record<string, unknown[]> {\n const results: Record<string, unknown[]> = Object.create(null);\n for (const call of toolCalls(messages)) {\n if (call.id === toolCallId) break;\n if (WIDGET_TOOLS.has(call.name)) continue;\n (results[call.name] ??= []).unshift(decodeResult(call.result));\n }\n return results;\n}\n\n/** A string result that holds a JSON object or array is decoded, since the model read that string as the structure. */\nfunction decodeResult(result: unknown): unknown {\n if (typeof result !== \"string\") return result;\n try {\n const value: unknown = JSON.parse(result);\n return typeof value === \"object\" && value !== null ? value : result;\n } catch {\n return result;\n }\n}\n\n/** A `spec` argument as the renderers read it, with `elements` an object even while the argument is still streaming in. */\nexport const specFromArgs = (spec: object): Spec => {\n const value = { state: {}, ...spec } as Spec;\n return typeof value.elements === \"object\" && value.elements !== null\n ? value\n : { ...value, elements: {} };\n};\n\n/**\n * The spec a `render_spec` call's patches apply onto: the result of the\n * earlier `render_spec` calls with the same title in the thread.\n */\nexport function resolveSpecBase(\n messages: readonly MessageLike[],\n toolCallId: string,\n title: string,\n): Spec | undefined {\n let spec: Spec | undefined;\n for (const call of toolCalls(messages)) {\n if (call.id === toolCallId) return spec;\n if (call.name !== \"render_spec\" || call.args[\"title\"] !== title) continue;\n if (call.args[\"spec\"] && typeof call.args[\"spec\"] === \"object\") {\n spec = specFromArgs(call.args[\"spec\"]);\n } else if (typeof call.args[\"patches\"] === \"string\") {\n spec = parseSpecStream(\n call.args[\"patches\"],\n spec ? { initial: spec } : {},\n ).spec;\n }\n }\n return spec;\n}\n\n/** Whether a later `render_spec` call in the same message has this call's title. That call shows the spec this one's patches lead to, so this one shows nothing rather than a second copy. */\nexport function supersededInMessage(\n messages: readonly MessageLike[],\n toolCallId: string,\n title: string,\n): boolean {\n return hasLaterToolCallInMessage(\n messages,\n toolCallId,\n title,\n (call) => call.name === \"render_spec\",\n );\n}\n\nfunction priorSpecCalls(\n messages: readonly MessageLike[],\n toolCallId: string,\n title: string,\n): number {\n let count = 0;\n for (const call of toolCalls(messages)) {\n if (call.id === toolCallId) break;\n if (call.name === \"render_spec\" && call.args[\"title\"] === title) count++;\n }\n return count;\n}\n\ntype SpecHistory = {\n base(title: string): { spec: Spec | undefined; version: number };\n toolResults: Record<string, unknown[]> | undefined;\n};\n\n/** What a mounted call registers for `execute`: the spec each title held before it in its own thread, how many calls built it, and the earlier results it mounts under `/tools`. */\nexport const callHistory = (\n messages: readonly MessageLike[],\n toolCallId: string,\n toolResults: Record<string, unknown[]> | undefined,\n): SpecHistory => ({\n base: (title) => ({\n spec: resolveSpecBase(messages, toolCallId, title),\n version: priorSpecCalls(messages, toolCallId, title),\n }),\n toolResults,\n});\n\nconst readsTools = (pointer: string) =>\n pointer === \"/tools\" || pointer.startsWith(\"/tools/\");\n\n/** Collects the state paths a value shows, leaving out reads in a branch that only renders while that path has a value: the `$then` of a `$cond` that tests it, and the `?` branch of a `$calc` condition on it. */\nfunction collectShown(\n value: unknown,\n guarded: ReadonlySet<string>,\n shown: string[],\n): void {\n if (Array.isArray(value)) {\n for (const item of value) collectShown(item, guarded, shown);\n return;\n }\n if (typeof value !== \"object\" || value === null) return;\n const record = value as Record<string, unknown>;\n if (\"$cond\" in record) {\n const tested = conditionGuards(record[\"$cond\"]).map(safePointer);\n collectShown(record[\"$then\"], new Set([...guarded, ...tested]), shown);\n collectShown(record[\"$else\"], guarded, shown);\n return;\n }\n for (const [key, child] of Object.entries(record)) {\n if (typeof child !== \"string\") {\n collectShown(child, guarded, shown);\n continue;\n }\n const paths =\n key === \"$state\" || key === \"$bindState\"\n ? [child]\n : key === \"$template\"\n ? templateStatePaths(child)\n : key === \"$calc\"\n ? formulaValueReads(child)\n : [];\n for (const path of paths) {\n const pointer = safePointer(path);\n if (!guarded.has(pointer)) shown.push(pointer);\n }\n }\n}\n\n/** Each place a spec can render an element, with the paths a `visible` condition on it or an ancestor guards there: reachable from the root through children and slots, leaving out one hidden with `visible: false` along with what it holds, and the repeated children of a `/tools` path the results hold no array at. An element under parents that guard different paths appears once per set of guards. */\nfunction renderedElements(\n spec: Spec,\n state: unknown,\n): [string, SpecElement, ReadonlySet<string>][] {\n const elements = spec.elements ?? {};\n const rendered: [string, SpecElement, ReadonlySet<string>][] = [];\n const seen = new Set<string>();\n const pending: [string, ReadonlySet<string>][] =\n typeof spec.root === \"string\" ? [[spec.root, new Set()]] : [];\n while (pending.length > 0) {\n const [id, inherited] = pending.pop()!;\n if (!Object.hasOwn(elements, id)) continue;\n const element = elements[id];\n if (typeof element !== \"object\" || element === null) continue;\n if (element.visible === false) continue;\n const guarded = new Set([\n ...inherited,\n ...conditionGuards(element.visible).map(safePointer),\n ]);\n const visit = JSON.stringify([id, ...[...guarded].sort()]);\n if (seen.has(visit)) continue;\n seen.add(visit);\n rendered.push([id, element, guarded]);\n const repeat =\n typeof element.repeat?.path === \"string\"\n ? safePointer(element.repeat.path)\n : undefined;\n const repeatsNothing =\n repeat !== undefined &&\n readsTools(repeat) &&\n !Array.isArray(getAtPointer(state, repeat));\n for (const slot of [\"default\", ...Object.keys(element.slots ?? {})]) {\n if (slot === \"default\" && repeatsNothing) continue;\n for (const child of childIdsOf(element, slot))\n if (typeof child === \"string\") pending.push([child, guarded]);\n }\n }\n return rendered;\n}\n\n/** Each place a spec shows state under `/tools` that the mounted results do not have, as a warning, since the model may have read the value from output the thread does not store or may mean a field that is absent. A read that only renders while its path has a value, under a `visible` condition or `$cond` test on it, is left out. */\nfunction missingToolResults(\n spec: Spec,\n toolResults: Record<string, unknown[]>,\n): SpecIssue[] {\n const issues: SpecIssue[] = [];\n const state = { tools: toolResults };\n const reported = new Set<string>();\n for (const [id, element, guarded] of renderedElements(spec, state)) {\n const shown: string[] = [];\n collectShown([element.props, element.on, element.watch], guarded, shown);\n if (typeof element.repeat?.path === \"string\") {\n const pointer = safePointer(element.repeat.path);\n if (!guarded.has(pointer)) shown.push(pointer);\n }\n for (const pointer of new Set(shown)) {\n if (!readsTools(pointer)) continue;\n if (getAtPointer(state, pointer) !== undefined) continue;\n const report = JSON.stringify([id, pointer]);\n if (reported.has(report)) continue;\n reported.add(report);\n issues.push({\n code: \"missing-tool-result\",\n severity: \"warning\",\n elementId: id,\n path: `/elements/${escapePointerToken(id)}`,\n message: `\"${id}\" shows \\`${pointer}\\`, which the earlier tool results do not have, so it shows nothing there. If you read that value from the tool's output, write it into the spec instead.`,\n });\n }\n }\n return issues;\n}\n\n/** The app's rules and where earlier tool results are, which `render_spec`'s description and the `spec` module both carry. */\nconst toolkitRules = (\n specPrompt: Omit<SpecPromptOptions, \"mode\"> | undefined,\n) => [...(specPrompt?.customRules ?? []), SPEC_TOOL_RESULTS_RULE];\n\n/**\n * The `render_spec` tool a toolkit shares across its calls. Each mounted call\n * registers its {@link callHistory} in `histories` under its tool call id, so\n * `execute` patches the base that call's own thread held, even after a reload\n * or in another thread.\n */\nexport function createSpecCalls(\n catalog: Catalog,\n specPrompt: Omit<SpecPromptOptions, \"mode\"> | undefined,\n) {\n const specs = new Map<string, { spec: Spec; version: number }>();\n const tools = createSpecTools(catalog, {\n specs,\n customRules: toolkitRules(specPrompt),\n });\n const histories = new Map<string, SpecHistory>();\n const execute = async (\n input: RenderSpecInput,\n call: { toolCallId: string },\n ) => {\n const history = histories.get(call.toolCallId);\n if (history) {\n const { spec, version } = history.base(input.title);\n if (spec) specs.set(input.title, { spec, version });\n else specs.delete(input.title);\n }\n const running = tools.render_spec.execute(input);\n // `execute` stores this call's spec before it returns, so the spec is read before an overlapping call with the same title stores its own.\n const spec = specs.get(input.title)?.spec;\n const result = await running;\n // The results are mounted only while the spec writes no `tools` of its own.\n if (!history?.toolResults || !spec || spec.state?.[\"tools\"] !== undefined)\n return result;\n const missing = missingToolResults(spec, history.toolResults);\n if (missing.length === 0) return result;\n const issues = [...result.issues, ...missing];\n return { ...result, issues, feedback: formatSpecIssues(issues) };\n };\n return { tools, histories, execute };\n}\n\n/** The `spec` module of `read_me`: the catalog guidance with the built-in actions every assistant-ui toolkit handles, the app's rules, and where earlier tool results are. */\nexport const specModules = (\n catalog: Catalog,\n specPrompt: Omit<SpecPromptOptions, \"mode\"> | undefined,\n host: { clipboard: boolean },\n) => [\n specGuidanceModule(catalog, {\n ...specPrompt,\n hostApi: {\n prompt: true,\n modelContext: true,\n clipboard: host.clipboard,\n ...specPrompt?.hostApi,\n },\n customRules: toolkitRules(specPrompt),\n }),\n];\n\n/** Writes to the browser's clipboard, rejecting where the Clipboard API is missing. */\nexport const writeClipboard = (text: string): Promise<void> =>\n typeof navigator !== \"undefined\" && navigator.clipboard\n ? navigator.clipboard.writeText(text)\n : Promise.reject(new Error(\"Clipboard API is unavailable\"));\n\n/** The built-in `copyText` handler. A copy that does not happen fails, so the rest of the list, such as a confirmation, does not run. */\nexport const copyTextHandler =\n (write: (text: string) => Promise<void>): ActionHandler =>\n (params, source) => {\n if (source.kind === \"watch\") {\n throw new Error(\n \"copyText runs only from an event a component emits, never from `watch`\",\n );\n }\n const text = params[\"text\"];\n if (typeof text !== \"string\") {\n throw new Error(\"copyText needs a string `text`\");\n }\n return write(text);\n };\n"],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type Component, type MaybeRefOrGetter } from "vue";
|
|
2
|
+
import type { WidgetToolkitExtension } from "../../assistant-ui/extension.js";
|
|
3
|
+
import { type ModelContextSource } from "../../assistant-ui/modelContext.js";
|
|
4
|
+
import type { MessageLike } from "../../assistant-ui/tool-calls.js";
|
|
5
|
+
import type { ActionHandler } from "../actions.js";
|
|
6
|
+
import type { Catalog } from "../catalog.js";
|
|
7
|
+
import type { SpecPromptOptions } from "../prompt.js";
|
|
8
|
+
import type { SpecComponents } from "../vue/SpecRenderer.js";
|
|
9
|
+
import { type SpecStateStore } from "../state.js";
|
|
10
|
+
export type SpecToolkitOptions = {
|
|
11
|
+
components: SpecComponents;
|
|
12
|
+
handlers?: Record<string, ActionHandler>;
|
|
13
|
+
onAction?: (name: string, params: Record<string, unknown>, context: {
|
|
14
|
+
elementId?: string;
|
|
15
|
+
trigger?: string;
|
|
16
|
+
state: SpecStateStore;
|
|
17
|
+
}) => unknown;
|
|
18
|
+
placeholder?: Component;
|
|
19
|
+
specPrompt?: Omit<SpecPromptOptions, "mode">;
|
|
20
|
+
toolResults?: boolean;
|
|
21
|
+
};
|
|
22
|
+
export type SpecToolkitPlatform = {
|
|
23
|
+
useMessages(): MaybeRefOrGetter<readonly MessageLike[]>;
|
|
24
|
+
useArgsComplete(): MaybeRefOrGetter<boolean>;
|
|
25
|
+
SpecRenderer: Component;
|
|
26
|
+
/** The frame renders its content through its default Vue slot. */
|
|
27
|
+
Frame: Component;
|
|
28
|
+
useSendMessage(): (text: string) => void;
|
|
29
|
+
useModelContext(source: ModelContextSource): void;
|
|
30
|
+
copyText?: (text: string) => Promise<void>;
|
|
31
|
+
};
|
|
32
|
+
export declare const specToolkitFor: ({ useMessages, useArgsComplete, SpecRenderer, Frame, useSendMessage, useModelContext, copyText, }: SpecToolkitPlatform) => (catalog: Catalog, options: SpecToolkitOptions) => WidgetToolkitExtension;
|
|
33
|
+
//# sourceMappingURL=toolkit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolkit.d.ts","mappings":"AAAA,OAAO,EAUL,KAAK,SAAS,EACd,KAAK,gBAAgB,EACtB,MAAM,KAAK;AAEZ,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,iCAA8B;AAC1E,OAAO,EAGL,KAAK,kBAAkB,EAExB,MAAM,oCAAiC;AAExC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAA+B;AAEhE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAY;AAC/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAY;AACzC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAW;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAqB;AAEzD,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,aAAU;AAcjB,MAAM,MAAM,kBAAkB,GAAG;IAC/B,UAAU,EAAE,cAAc;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC;IACxC,QAAQ,CAAC,EAAE,CACT,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM;QAAE,OAAO,CAAC,EAAE,MAAM;QAAE,KAAK,EAAE,cAAc;KAAE,KACrE,OAAO;IACZ,WAAW,CAAC,EAAE,SAAS;IACvB,UAAU,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC;IAC5C,WAAW,CAAC,EAAE,OAAO;CACtB;AACD,MAAM,MAAM,mBAAmB,GAAG;IAChC,WAAW,IAAI,gBAAgB,CAAC,SAAS,WAAW,EAAE,CAAC;IACvD,eAAe,IAAI,gBAAgB,CAAC,OAAO,CAAC;IAC5C,YAAY,EAAE,SAAS;IACvB;IACA,KAAK,EAAE,SAAS;IAChB,cAAc,IAAI,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI;IACxC,eAAe,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI;IACjD,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;CAC3C;AAWD,eAAO,MAAM,cAAc,GACxB,mGAQE,mBAAmB,MACrB,SAAS,OAAO,EAAE,SAAS,kBAAkB,KAAG,sBA6MhD","names":[],"ignoreList":[],"sources":["../../../src/spec/assistant-ui/toolkit.tsx"],"sourcesContent":[null]}
|