@artooi/ag-ui-web-component 0.12.0 → 0.14.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/CHANGELOG.md +88 -1
- package/README.md +75 -5
- package/dist/ag-ui-web-component.bundle.js +49 -23
- package/dist/ag-ui-web-component.bundle.js.map +4 -4
- package/dist/constants.d.ts +25 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/core/ag_ui_chat.d.ts +29 -4
- package/dist/core/ag_ui_chat.d.ts.map +1 -1
- package/dist/core/agui_client.d.ts +17 -0
- package/dist/core/agui_client.d.ts.map +1 -1
- package/dist/core/create_http_agent.d.ts +6 -0
- package/dist/core/create_http_agent.d.ts.map +1 -1
- package/dist/index.d.ts +7 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +220 -39
- package/dist/index.js.map +4 -4
- package/dist/tools/page_state.d.ts +40 -0
- package/dist/tools/page_state.d.ts.map +1 -0
- package/dist/ui/run_notice.d.ts +12 -0
- package/dist/ui/run_notice.d.ts.map +1 -0
- package/dist/ui/styles.d.ts +1 -1
- package/dist/ui/styles.d.ts.map +1 -1
- package/dist/ui/ui_strings.d.ts +4 -0
- package/dist/ui/ui_strings.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/constants.ts +28 -0
- package/src/core/ag_ui_chat.ts +154 -7
- package/src/core/agui_client.ts +37 -0
- package/src/core/create_http_agent.ts +7 -0
- package/src/index.ts +14 -1
- package/src/tools/page_state.ts +72 -0
- package/src/ui/run_notice.ts +35 -0
- package/src/ui/styles.ts +26 -0
- package/src/ui/ui_strings.ts +6 -0
- package/src/version.ts +1 -1
- package/dist/tools/state_hook.d.ts +0 -23
- package/dist/tools/state_hook.d.ts.map +0 -1
- package/src/tools/state_hook.ts +0 -53
package/src/core/agui_client.ts
CHANGED
|
@@ -79,6 +79,12 @@ export interface AgUiClientHandlers {
|
|
|
79
79
|
* their result itself — so this is the channel for server-executed output.
|
|
80
80
|
*/
|
|
81
81
|
onToolResult(toolCallId: string, content: string): void;
|
|
82
|
+
/**
|
|
83
|
+
* Fired for AG-UI activity events — ambient notices about what the *run* did,
|
|
84
|
+
* as opposed to work the agent asked for. `django-ag-ui` emits one with
|
|
85
|
+
* `activityType: "compaction"` when it condensed the history.
|
|
86
|
+
*/
|
|
87
|
+
onActivity(activityType: string, content: unknown): void;
|
|
82
88
|
/** Fired when a reasoning model starts emitting its chain-of-thought. */
|
|
83
89
|
onReasoningStart(): void;
|
|
84
90
|
/** Fired on every reasoning token; ``buffer`` is the full reasoning text so far. */
|
|
@@ -131,6 +137,13 @@ export interface AgUiClientConfig extends AgUiRunInputs {
|
|
|
131
137
|
* conversation in-memory only.
|
|
132
138
|
*/
|
|
133
139
|
onPersist?: (messages: readonly Message[]) => void;
|
|
140
|
+
/**
|
|
141
|
+
* Called whenever AG-UI shared state changes — the server streamed a
|
|
142
|
+
* `STATE_SNAPSHOT` / `STATE_DELTA`, or {@link AgUiClient.setState} was
|
|
143
|
+
* called. `@ag-ui/client` owns applying those events; this only forwards
|
|
144
|
+
* the result so a host can react.
|
|
145
|
+
*/
|
|
146
|
+
onStateChanged?: (state: Readonly<Record<string, unknown>>) => void;
|
|
134
147
|
/**
|
|
135
148
|
* Error text surfaced to {@link AgUiClientHandlers.onError} when a run's
|
|
136
149
|
* stream closes without a terminal AG-UI event (`RUN_FINISHED`/`RUN_ERROR`) —
|
|
@@ -182,6 +195,27 @@ export class AgUiClient {
|
|
|
182
195
|
this.#resolveInterrupts = config.resolveInterrupts ?? null;
|
|
183
196
|
this.#onPersist = config.onPersist ?? (() => {});
|
|
184
197
|
this.#connectionLostMessage = config.connectionLostMessage ?? "Connection lost";
|
|
198
|
+
const onStateChanged = config.onStateChanged;
|
|
199
|
+
if (onStateChanged !== undefined) {
|
|
200
|
+
// The agent applies STATE_SNAPSHOT / STATE_DELTA itself; subscribing is
|
|
201
|
+
// how we learn the result rather than re-deriving it from the event
|
|
202
|
+
// stream. Lives for the agent's lifetime, which is this client's.
|
|
203
|
+
this.#agent.subscribe({
|
|
204
|
+
onStateChanged: ({ state }) => {
|
|
205
|
+
onStateChanged(state as Record<string, unknown>);
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** The current AG-UI shared state, as the agent last applied it. */
|
|
212
|
+
get state(): Readonly<Record<string, unknown>> {
|
|
213
|
+
return this.#agent.state as Record<string, unknown>;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/** Replace the shared state; the next run sends it as `RunAgentInput.state`. */
|
|
217
|
+
setState(state: Readonly<Record<string, unknown>>): void {
|
|
218
|
+
this.#agent.setState({ ...state });
|
|
185
219
|
}
|
|
186
220
|
|
|
187
221
|
/** Whether a run is currently in flight. */
|
|
@@ -385,6 +419,9 @@ export class AgUiClient {
|
|
|
385
419
|
onToolCallResultEvent({ event }) {
|
|
386
420
|
h.onToolResult(event.toolCallId, event.content);
|
|
387
421
|
},
|
|
422
|
+
onActivitySnapshotEvent({ event }) {
|
|
423
|
+
h.onActivity(event.activityType, event.content);
|
|
424
|
+
},
|
|
388
425
|
// Reasoning. `@ag-ui/client` already maps the deprecated
|
|
389
426
|
// THINKING_* events onto these REASONING_* callbacks, so handling the
|
|
390
427
|
// reasoning family alone covers both protocol versions.
|
|
@@ -18,6 +18,12 @@ export interface HttpAgentOptions {
|
|
|
18
18
|
threadId?: string;
|
|
19
19
|
/** Rehydrated history to seed the agent with (durable conversation). */
|
|
20
20
|
initialMessages?: readonly Message[];
|
|
21
|
+
/**
|
|
22
|
+
* AG-UI shared state to seed the agent with. `@ag-ui/client` sends it as
|
|
23
|
+
* `RunAgentInput.state` on every run and replaces it in place when the
|
|
24
|
+
* server streams `STATE_SNAPSHOT` / `STATE_DELTA`.
|
|
25
|
+
*/
|
|
26
|
+
initialState?: Readonly<Record<string, unknown>>;
|
|
21
27
|
}
|
|
22
28
|
|
|
23
29
|
/**
|
|
@@ -31,6 +37,7 @@ export function createHttpAgent(options: HttpAgentOptions): AbstractAgent {
|
|
|
31
37
|
return new HttpAgent({
|
|
32
38
|
url: options.endpoint,
|
|
33
39
|
headers: options.headers ?? {},
|
|
40
|
+
initialState: { ...(options.initialState ?? {}) },
|
|
34
41
|
// HttpAgent invokes its configured fetch as a method (`this.fetch(...)`),
|
|
35
42
|
// which would rebind the global `fetch` to the agent instance and trigger
|
|
36
43
|
// "Illegal invocation" in browsers. Wrap it so `fetch` is always called as
|
package/src/index.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
// Public surface re-exports. Per CLAUDE.md, this is the only re-export point.
|
|
2
2
|
|
|
3
3
|
export {
|
|
4
|
+
COMPACTION_ACTIVITY_TYPE,
|
|
4
5
|
ELEMENT_TAG,
|
|
6
|
+
LOAD_CAPABILITY_TOOL,
|
|
5
7
|
MAX_TOOL_ROUNDS,
|
|
6
8
|
MESSAGE_ROLE,
|
|
9
|
+
STATE_EVENT,
|
|
7
10
|
SUBMIT_EVENT,
|
|
8
11
|
TOGGLE_EVENT,
|
|
9
12
|
TOOL_CALL_STATUS,
|
|
@@ -16,6 +19,7 @@ export {
|
|
|
16
19
|
export {
|
|
17
20
|
AgUiChat,
|
|
18
21
|
type MessageRole,
|
|
22
|
+
type StateDetail,
|
|
19
23
|
type SubmitDetail,
|
|
20
24
|
type ToggleDetail,
|
|
21
25
|
} from "./core/ag_ui_chat.js";
|
|
@@ -93,6 +97,16 @@ export {
|
|
|
93
97
|
type ResolvePageTarget,
|
|
94
98
|
} from "./tools/page_action_tools.js";
|
|
95
99
|
export { createPageMapContext, type PageMap } from "./tools/page_map.js";
|
|
100
|
+
/**
|
|
101
|
+
* @deprecated Renamed to `createPageStateTools` / `PageState`. The old names
|
|
102
|
+
* read as AG-UI shared-state sync, which this component does not implement.
|
|
103
|
+
*/
|
|
104
|
+
export {
|
|
105
|
+
createPageStateTools,
|
|
106
|
+
createStateHookTools,
|
|
107
|
+
type PageState,
|
|
108
|
+
type StateHook,
|
|
109
|
+
} from "./tools/page_state.js";
|
|
96
110
|
export { parseToolCatalog, type ToolCatalogEntry } from "./tools/parse_tool_catalog.js";
|
|
97
111
|
export {
|
|
98
112
|
createRouteTools,
|
|
@@ -100,7 +114,6 @@ export {
|
|
|
100
114
|
type RouteMap,
|
|
101
115
|
type RouteWithParams,
|
|
102
116
|
} from "./tools/route_map.js";
|
|
103
|
-
export { createStateHookTools, type StateHook } from "./tools/state_hook.js";
|
|
104
117
|
export {
|
|
105
118
|
type ApprovalOptions,
|
|
106
119
|
type ApprovalRenderer,
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { X_DESTRUCTIVE_KEY, X_SUMMARY_KEY } from "../constants.js";
|
|
2
|
+
import type { ClientTool } from "./client_tool_registry.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A binding from a named piece of host page state to agent tools.
|
|
6
|
+
*
|
|
7
|
+
* Ergonomic sugar over `registerTool` for SPA state (Redux/Zustand/signals):
|
|
8
|
+
* generates a read tool and, when `write` is given, a destructive set tool.
|
|
9
|
+
*
|
|
10
|
+
* This is **not** AG-UI shared state. `STATE_SNAPSHOT` / `STATE_DELTA` are
|
|
11
|
+
* protocol events carrying state between agent and client; this is a pair of
|
|
12
|
+
* ordinary client tools the agent calls like any other. The two are unrelated,
|
|
13
|
+
* which is why this no longer carries the word "hook" — the old name read as
|
|
14
|
+
* protocol state sync, which this component does not implement.
|
|
15
|
+
*/
|
|
16
|
+
export interface PageState {
|
|
17
|
+
/** Base name; tools become `read_<name>` and `set_<name>`. */
|
|
18
|
+
readonly name: string;
|
|
19
|
+
/** Returns the current state value. */
|
|
20
|
+
readonly read: () => unknown;
|
|
21
|
+
/** Mutates the state from the agent-supplied args. Omit for read-only. */
|
|
22
|
+
readonly write?: (args: Record<string, unknown>) => unknown;
|
|
23
|
+
/** JSON-Schema for the set tool's args. Defaults to an open object. */
|
|
24
|
+
readonly schema?: Record<string, unknown>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Build the tools for a {@link PageState}: always a `read_<name>` (read-only)
|
|
29
|
+
* tool, plus a `set_<name>` (`x-destructive`) tool when `write` is supplied.
|
|
30
|
+
*/
|
|
31
|
+
export function createPageStateTools(binding: PageState): ClientTool[] {
|
|
32
|
+
const tools: ClientTool[] = [
|
|
33
|
+
{
|
|
34
|
+
name: `read_${binding.name}`,
|
|
35
|
+
description: `Read the "${binding.name}" state.`,
|
|
36
|
+
parameters: {
|
|
37
|
+
type: "object",
|
|
38
|
+
properties: {},
|
|
39
|
+
required: [],
|
|
40
|
+
[X_SUMMARY_KEY]: `Read ${binding.name}`,
|
|
41
|
+
},
|
|
42
|
+
handler: () => binding.read(),
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
const write = binding.write;
|
|
46
|
+
if (write !== undefined) {
|
|
47
|
+
tools.push({
|
|
48
|
+
name: `set_${binding.name}`,
|
|
49
|
+
description: `Update the "${binding.name}" state.`,
|
|
50
|
+
parameters: {
|
|
51
|
+
...(binding.schema ?? { type: "object" }),
|
|
52
|
+
[X_DESTRUCTIVE_KEY]: true,
|
|
53
|
+
[X_SUMMARY_KEY]: `Update ${binding.name}`,
|
|
54
|
+
},
|
|
55
|
+
handler: (args) => write(args),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return tools;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @deprecated Renamed to {@link PageState}. The old name read as AG-UI
|
|
63
|
+
* shared-state sync (`STATE_SNAPSHOT` / `STATE_DELTA`), which this component
|
|
64
|
+
* does not implement. Will be removed in a future major.
|
|
65
|
+
*/
|
|
66
|
+
export type StateHook = PageState;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @deprecated Renamed to {@link createPageStateTools}. Will be removed in a
|
|
70
|
+
* future major.
|
|
71
|
+
*/
|
|
72
|
+
export const createStateHookTools = createPageStateTools;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A muted one-line notice about something the *run* did, rendered inline in the
|
|
3
|
+
* transcript between turns.
|
|
4
|
+
*
|
|
5
|
+
* Distinct from a tool card (which reports work the agent asked for and is
|
|
6
|
+
* settleable) and from an error (which is a failure). A notice is ambient: the
|
|
7
|
+
* agent condensed earlier turns, or loaded a skill. It never settles, never
|
|
8
|
+
* takes an action, and carries no controls — so it stays visually quiet and out
|
|
9
|
+
* of the way of the conversation it annotates.
|
|
10
|
+
*/
|
|
11
|
+
export function renderRunNotice(icon: string, text: string, kind: string): HTMLDivElement {
|
|
12
|
+
const notice = document.createElement("div");
|
|
13
|
+
notice.className = `run-notice run-notice--${kind}`;
|
|
14
|
+
notice.setAttribute("part", `run-notice run-notice-${kind}`);
|
|
15
|
+
// A status role, not an alert: this is informational and must not interrupt a
|
|
16
|
+
// screen reader mid-sentence. Polite announcements land after the current
|
|
17
|
+
// utterance, which is right for an annotation about turns already spoken.
|
|
18
|
+
notice.setAttribute("role", "status");
|
|
19
|
+
|
|
20
|
+
const glyph = document.createElement("span");
|
|
21
|
+
glyph.className = "run-notice-icon";
|
|
22
|
+
glyph.setAttribute("part", "run-notice-icon");
|
|
23
|
+
glyph.textContent = icon;
|
|
24
|
+
// Decorative: the adjacent text already says what happened, and a screen
|
|
25
|
+
// reader announcing the emoji's name would just add noise.
|
|
26
|
+
glyph.setAttribute("aria-hidden", "true");
|
|
27
|
+
|
|
28
|
+
const label = document.createElement("span");
|
|
29
|
+
label.className = "run-notice-text";
|
|
30
|
+
label.setAttribute("part", "run-notice-text");
|
|
31
|
+
label.textContent = text;
|
|
32
|
+
|
|
33
|
+
notice.append(glyph, label);
|
|
34
|
+
return notice;
|
|
35
|
+
}
|
package/src/ui/styles.ts
CHANGED
|
@@ -886,6 +886,32 @@ export const STYLES = `
|
|
|
886
886
|
margin-top: 6px;
|
|
887
887
|
}
|
|
888
888
|
|
|
889
|
+
.run-notice {
|
|
890
|
+
display: inline-flex;
|
|
891
|
+
align-items: center;
|
|
892
|
+
gap: 6px;
|
|
893
|
+
align-self: flex-start;
|
|
894
|
+
max-width: 100%;
|
|
895
|
+
margin: 2px 0;
|
|
896
|
+
padding: 3px 10px;
|
|
897
|
+
border: 1px dashed var(--ag-ui-border);
|
|
898
|
+
border-radius: 999px;
|
|
899
|
+
background: transparent;
|
|
900
|
+
color: var(--ag-ui-muted);
|
|
901
|
+
font-size: 0.8em;
|
|
902
|
+
line-height: 1.4;
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
.run-notice-icon {
|
|
906
|
+
flex: none;
|
|
907
|
+
opacity: 0.75;
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
.run-notice-text {
|
|
911
|
+
min-width: 0;
|
|
912
|
+
overflow-wrap: anywhere;
|
|
913
|
+
}
|
|
914
|
+
|
|
889
915
|
.attachment-chip {
|
|
890
916
|
display: inline-flex;
|
|
891
917
|
align-items: center;
|
package/src/ui/ui_strings.ts
CHANGED
|
@@ -49,6 +49,10 @@ export interface UiStrings {
|
|
|
49
49
|
navigating: string;
|
|
50
50
|
/** Missing-placeholder skill hint. Tokens: `{title}`, `{fields}`. */
|
|
51
51
|
skillNeeds: string;
|
|
52
|
+
/** Notice shown when the agent condensed earlier turns. Token: `{count}`. */
|
|
53
|
+
historyCompacted: string;
|
|
54
|
+
/** Notice shown when the agent loads an agent skill. Token: `{name}`. */
|
|
55
|
+
usingSkill: string;
|
|
52
56
|
|
|
53
57
|
// ── Composer ────────────────────────────────────────────────────────────────
|
|
54
58
|
/** `aria-label` of the message textarea. */
|
|
@@ -195,6 +199,8 @@ export const DEFAULT_UI_STRINGS: UiStrings = {
|
|
|
195
199
|
noResult: "No result returned.",
|
|
196
200
|
declinedAction: "User declined the action.",
|
|
197
201
|
navigating: "Navigating…",
|
|
202
|
+
historyCompacted: "Earlier turns condensed to fit the context window ({count} removed)",
|
|
203
|
+
usingSkill: "Using skill {name}",
|
|
198
204
|
skillNeeds: "“{title}” needs: {fields}",
|
|
199
205
|
|
|
200
206
|
message: "Message",
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION: string = "0.
|
|
1
|
+
export const VERSION: string = "0.14.0";
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { ClientTool } from "./client_tool_registry.js";
|
|
2
|
-
/**
|
|
3
|
-
* A binding from a named piece of host application state to agent tools.
|
|
4
|
-
*
|
|
5
|
-
* Ergonomic sugar over `registerTool` for SPA state (Redux/Zustand/signals):
|
|
6
|
-
* generates a read tool and, when `write` is given, a destructive set tool.
|
|
7
|
-
*/
|
|
8
|
-
export interface StateHook {
|
|
9
|
-
/** Base name; tools become `read_<name>` and `set_<name>`. */
|
|
10
|
-
readonly name: string;
|
|
11
|
-
/** Returns the current state value. */
|
|
12
|
-
readonly read: () => unknown;
|
|
13
|
-
/** Mutates the state from the agent-supplied args. Omit for read-only. */
|
|
14
|
-
readonly write?: (args: Record<string, unknown>) => unknown;
|
|
15
|
-
/** JSON-Schema for the set tool's args. Defaults to an open object. */
|
|
16
|
-
readonly schema?: Record<string, unknown>;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Build the tools for a {@link StateHook}: always a `read_<name>` (read-only)
|
|
20
|
-
* tool, plus a `set_<name>` (`x-destructive`) tool when `write` is supplied.
|
|
21
|
-
*/
|
|
22
|
-
export declare function createStateHookTools(hook: StateHook): ClientTool[];
|
|
23
|
-
//# sourceMappingURL=state_hook.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"state_hook.d.ts","sourceRoot":"","sources":["../../src/tools/state_hook.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5D;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACxB,8DAA8D;IAC9D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,OAAO,CAAC;IAC7B,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC;IAC5D,uEAAuE;IACvE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC3C;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,SAAS,GAAG,UAAU,EAAE,CA4BlE"}
|
package/src/tools/state_hook.ts
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { X_DESTRUCTIVE_KEY, X_SUMMARY_KEY } from "../constants.js";
|
|
2
|
-
import type { ClientTool } from "./client_tool_registry.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* A binding from a named piece of host application state to agent tools.
|
|
6
|
-
*
|
|
7
|
-
* Ergonomic sugar over `registerTool` for SPA state (Redux/Zustand/signals):
|
|
8
|
-
* generates a read tool and, when `write` is given, a destructive set tool.
|
|
9
|
-
*/
|
|
10
|
-
export interface StateHook {
|
|
11
|
-
/** Base name; tools become `read_<name>` and `set_<name>`. */
|
|
12
|
-
readonly name: string;
|
|
13
|
-
/** Returns the current state value. */
|
|
14
|
-
readonly read: () => unknown;
|
|
15
|
-
/** Mutates the state from the agent-supplied args. Omit for read-only. */
|
|
16
|
-
readonly write?: (args: Record<string, unknown>) => unknown;
|
|
17
|
-
/** JSON-Schema for the set tool's args. Defaults to an open object. */
|
|
18
|
-
readonly schema?: Record<string, unknown>;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Build the tools for a {@link StateHook}: always a `read_<name>` (read-only)
|
|
23
|
-
* tool, plus a `set_<name>` (`x-destructive`) tool when `write` is supplied.
|
|
24
|
-
*/
|
|
25
|
-
export function createStateHookTools(hook: StateHook): ClientTool[] {
|
|
26
|
-
const tools: ClientTool[] = [
|
|
27
|
-
{
|
|
28
|
-
name: `read_${hook.name}`,
|
|
29
|
-
description: `Read the "${hook.name}" state.`,
|
|
30
|
-
parameters: {
|
|
31
|
-
type: "object",
|
|
32
|
-
properties: {},
|
|
33
|
-
required: [],
|
|
34
|
-
[X_SUMMARY_KEY]: `Read ${hook.name}`,
|
|
35
|
-
},
|
|
36
|
-
handler: () => hook.read(),
|
|
37
|
-
},
|
|
38
|
-
];
|
|
39
|
-
const write = hook.write;
|
|
40
|
-
if (write !== undefined) {
|
|
41
|
-
tools.push({
|
|
42
|
-
name: `set_${hook.name}`,
|
|
43
|
-
description: `Update the "${hook.name}" state.`,
|
|
44
|
-
parameters: {
|
|
45
|
-
...(hook.schema ?? { type: "object" }),
|
|
46
|
-
[X_DESTRUCTIVE_KEY]: true,
|
|
47
|
-
[X_SUMMARY_KEY]: `Update ${hook.name}`,
|
|
48
|
-
},
|
|
49
|
-
handler: (args) => write(args),
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
return tools;
|
|
53
|
-
}
|