@particle-academy/agent-integrations 0.48.0 → 0.49.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 +32 -0
- package/README.md +45 -0
- package/dist/bridges/screens.d.cts +36 -5
- package/dist/bridges/screens.d.ts +36 -5
- package/dist/bridges-screens.cjs +71 -17
- package/dist/bridges-screens.cjs.map +1 -1
- package/dist/bridges-screens.js +1 -1
- package/dist/{chunk-7NVATRLE.js → chunk-HOZCDDRA.js} +74 -19
- package/dist/chunk-HOZCDDRA.js.map +1 -0
- package/dist/index.cjs +79 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-7NVATRLE.js.map +0 -1
|
@@ -1,9 +1,33 @@
|
|
|
1
1
|
import { ensureUndoToolsRegistered } from './chunk-R4XXOGQH.js';
|
|
2
2
|
import { wrapToolWithActivity } from './chunk-2VENWGLZ.js';
|
|
3
|
+
import { emitActivity } from './chunk-C3TYI5TJ.js';
|
|
3
4
|
import { textResult, errorResult } from './chunk-CZV3WUW5.js';
|
|
4
5
|
|
|
5
6
|
// src/bridges/screens.ts
|
|
6
7
|
var DEFAULT_AGENT = { id: "agent", name: "Agent", color: "#a855f7" };
|
|
8
|
+
function hostErrorMessage(e, fallback) {
|
|
9
|
+
let msg;
|
|
10
|
+
if (e instanceof Error) msg = e.message;
|
|
11
|
+
else if (typeof e === "string") msg = e;
|
|
12
|
+
else if (e && typeof e === "object" && typeof e.message === "string") {
|
|
13
|
+
msg = e.message;
|
|
14
|
+
}
|
|
15
|
+
const firstFrame = msg ? msg.search(/\n\s+at\s/) : -1;
|
|
16
|
+
if (msg && firstFrame >= 0) msg = msg.slice(0, firstFrame);
|
|
17
|
+
msg = msg?.trim();
|
|
18
|
+
return msg ? msg : fallback;
|
|
19
|
+
}
|
|
20
|
+
async function commit(run, fallback) {
|
|
21
|
+
try {
|
|
22
|
+
const r = await run();
|
|
23
|
+
if (r && typeof r === "object" && r.ok === false) {
|
|
24
|
+
return { ok: false, error: hostErrorMessage(r.error, fallback) };
|
|
25
|
+
}
|
|
26
|
+
return { ok: true };
|
|
27
|
+
} catch (e) {
|
|
28
|
+
return { ok: false, error: hostErrorMessage(e, fallback) };
|
|
29
|
+
}
|
|
30
|
+
}
|
|
7
31
|
function registerScreensBridge(host, options) {
|
|
8
32
|
const { adapter } = options;
|
|
9
33
|
const agent = { ...DEFAULT_AGENT, ...options.agent ?? {} };
|
|
@@ -19,7 +43,7 @@ function registerScreensBridge(host, options) {
|
|
|
19
43
|
try {
|
|
20
44
|
return await handler(args);
|
|
21
45
|
} catch (e) {
|
|
22
|
-
return errorResult(e
|
|
46
|
+
return errorResult(hostErrorMessage(e, `${name} failed.`));
|
|
23
47
|
}
|
|
24
48
|
};
|
|
25
49
|
const final = isMutation ? wrapToolWithActivity(wrapped, {
|
|
@@ -81,20 +105,40 @@ function registerScreensBridge(host, options) {
|
|
|
81
105
|
config: { type: "object", description: "Template-specific config (e.g. { fields: [...] } for a form)." }
|
|
82
106
|
},
|
|
83
107
|
["id", "kind"],
|
|
84
|
-
(args) => {
|
|
85
|
-
|
|
108
|
+
async (args) => {
|
|
109
|
+
const createScreen = adapter.createScreen;
|
|
110
|
+
if (!createScreen) return errorResult("Host did not provide createScreen.");
|
|
86
111
|
const id = String(args.id);
|
|
87
112
|
const kind = String(args.kind);
|
|
88
113
|
if (adapter.listScreens().find((s) => s.id === id)) {
|
|
89
114
|
return errorResult(`Screen ${id} already exists. Use screens_destroy first or pick a fresh id.`);
|
|
90
115
|
}
|
|
91
|
-
|
|
116
|
+
const created = await commit(() => createScreen({
|
|
92
117
|
id,
|
|
93
118
|
title: typeof args.title === "string" ? args.title : void 0,
|
|
94
119
|
kind,
|
|
95
120
|
config: args.config && typeof args.config === "object" ? args.config : void 0
|
|
96
|
-
});
|
|
97
|
-
|
|
121
|
+
}), `Host failed to create screen "${id}".`);
|
|
122
|
+
if (!created.ok) return errorResult(created.error);
|
|
123
|
+
const activated = await commit(() => adapter.setActive(id), `Host failed to activate screen "${id}".`);
|
|
124
|
+
if (!activated.ok) {
|
|
125
|
+
const state = { id, kind, created: true, activated: false };
|
|
126
|
+
emitActivity({
|
|
127
|
+
agentId: agent.id,
|
|
128
|
+
agentName: agent.name,
|
|
129
|
+
agentColor: agent.color,
|
|
130
|
+
target: target(id),
|
|
131
|
+
action: "screens_create",
|
|
132
|
+
timestamp: Date.now(),
|
|
133
|
+
meta: state
|
|
134
|
+
});
|
|
135
|
+
return {
|
|
136
|
+
...errorResult(
|
|
137
|
+
`Screen "${id}" was created but not activated: ${activated.error} The screen exists; do not call screens_create again. Call screens_navigate to show it, or screens_destroy to remove it.`
|
|
138
|
+
),
|
|
139
|
+
structuredContent: state
|
|
140
|
+
};
|
|
141
|
+
}
|
|
98
142
|
return textResult(`Created ${kind} screen "${id}"`, { id, kind });
|
|
99
143
|
},
|
|
100
144
|
true,
|
|
@@ -105,13 +149,15 @@ function registerScreensBridge(host, options) {
|
|
|
105
149
|
"Remove a previously-created screen. Active screen falls back to the first remaining one (or null).",
|
|
106
150
|
{ id: { type: "string" } },
|
|
107
151
|
["id"],
|
|
108
|
-
(args) => {
|
|
109
|
-
|
|
152
|
+
async (args) => {
|
|
153
|
+
const destroyScreen = adapter.destroyScreen;
|
|
154
|
+
if (!destroyScreen) return errorResult("Host did not provide destroyScreen.");
|
|
110
155
|
const id = String(args.id);
|
|
111
156
|
if (!adapter.listScreens().find((s) => s.id === id)) {
|
|
112
157
|
return errorResult(`No screen with id ${id}`);
|
|
113
158
|
}
|
|
114
|
-
|
|
159
|
+
const done = await commit(() => destroyScreen(id), `Host failed to destroy screen "${id}".`);
|
|
160
|
+
if (!done.ok) return errorResult(done.error);
|
|
115
161
|
return textResult(`Destroyed screen ${id}`, { id });
|
|
116
162
|
},
|
|
117
163
|
true,
|
|
@@ -125,9 +171,15 @@ function registerScreensBridge(host, options) {
|
|
|
125
171
|
layout: { type: "string", enum: ["single", "split-h", "split-v", "grid-2x2", "stack"] }
|
|
126
172
|
},
|
|
127
173
|
["id", "layout"],
|
|
128
|
-
(args) => {
|
|
129
|
-
|
|
130
|
-
|
|
174
|
+
async (args) => {
|
|
175
|
+
const updateScreenContent = adapter.updateScreenContent;
|
|
176
|
+
if (!updateScreenContent) return errorResult("Host did not provide updateScreenContent.");
|
|
177
|
+
const id = String(args.id);
|
|
178
|
+
const done = await commit(
|
|
179
|
+
() => updateScreenContent(id, { layout: String(args.layout) }),
|
|
180
|
+
`Host failed to change the layout of screen "${id}".`
|
|
181
|
+
);
|
|
182
|
+
if (!done.ok) return errorResult(done.error);
|
|
131
183
|
return textResult(`Layout of ${args.id} \u2192 ${args.layout}`, { id: args.id, layout: args.layout });
|
|
132
184
|
},
|
|
133
185
|
true,
|
|
@@ -141,11 +193,13 @@ function registerScreensBridge(host, options) {
|
|
|
141
193
|
partial: { type: "object", description: "Shallow-merged into the screen's config." }
|
|
142
194
|
},
|
|
143
195
|
["id", "partial"],
|
|
144
|
-
(args) => {
|
|
145
|
-
|
|
196
|
+
async (args) => {
|
|
197
|
+
const updateScreenContent = adapter.updateScreenContent;
|
|
198
|
+
if (!updateScreenContent) return errorResult("Host did not provide updateScreenContent.");
|
|
146
199
|
const id = String(args.id);
|
|
147
200
|
const partial = args.partial && typeof args.partial === "object" ? args.partial : {};
|
|
148
|
-
|
|
201
|
+
const done = await commit(() => updateScreenContent(id, partial), `Host failed to update screen "${id}".`);
|
|
202
|
+
if (!done.ok) return errorResult(done.error);
|
|
149
203
|
return textResult(`Updated content of ${id}`, { id });
|
|
150
204
|
},
|
|
151
205
|
true,
|
|
@@ -156,13 +210,14 @@ function registerScreensBridge(host, options) {
|
|
|
156
210
|
"Switch the human's view to a different screen. The host updates its router / tab state and re-renders.",
|
|
157
211
|
{ screen: { type: "string", description: "Screen id to activate." } },
|
|
158
212
|
["screen"],
|
|
159
|
-
(args) => {
|
|
213
|
+
async (args) => {
|
|
160
214
|
const screenId = String(args.screen ?? "");
|
|
161
215
|
const screens = adapter.listScreens();
|
|
162
216
|
if (!screens.find((s) => s.id === screenId)) {
|
|
163
217
|
return errorResult(`No screen registered with id "${screenId}". Call screens_list first.`);
|
|
164
218
|
}
|
|
165
|
-
adapter.setActive(screenId);
|
|
219
|
+
const done = await commit(() => adapter.setActive(screenId), `Host failed to navigate to screen "${screenId}".`);
|
|
220
|
+
if (!done.ok) return errorResult(done.error);
|
|
166
221
|
return textResult(`Navigated to ${screenId}`, { screen: screenId });
|
|
167
222
|
},
|
|
168
223
|
true,
|
|
@@ -178,5 +233,5 @@ function registerScreensBridge(host, options) {
|
|
|
178
233
|
}
|
|
179
234
|
|
|
180
235
|
export { registerScreensBridge };
|
|
181
|
-
//# sourceMappingURL=chunk-
|
|
182
|
-
//# sourceMappingURL=chunk-
|
|
236
|
+
//# sourceMappingURL=chunk-HOZCDDRA.js.map
|
|
237
|
+
//# sourceMappingURL=chunk-HOZCDDRA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/bridges/screens.ts"],"names":[],"mappings":"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","file":"chunk-HOZCDDRA.js","sourcesContent":["import { textResult, errorResult } from \"../mcp/server\";\nimport type { ToolHost } from \"../mcp/tool-host\";\nimport type { JsonObject } from \"../mcp/types\";\nimport type { Bridge } from \"./types\";\nimport { wrapToolWithActivity } from \"../presence/wrap-tool-with-activity\";\nimport { ensureUndoToolsRegistered } from \"../undo/undo-tools\";\nimport { emitActivity } from \"../presence/registry\";\nimport type { AgentTarget } from \"../presence/types\";\n\n/**\n * Loose snapshot of a screen — what's in fancy-screens' ScreenMeta plus\n * the host's optional activity status. Kept here so this bridge has no\n * hard dep on fancy-screens.\n */\nexport type ScreenSnapshot = {\n id: string;\n title?: string;\n /** Whether this screen is the one the human / agent is looking at. */\n active: boolean;\n /** Optional category / kind (e.g. \"form\", \"whiteboard\"). */\n kind?: string;\n};\n\n/**\n * Spec for a dynamically-created screen. The host's `createScreen`\n * implementation looks up `kind` in its template registry and instantiates\n * the matching surface (form / whiteboard / sheet / chart / markdown / etc.).\n */\nexport type ScreenCreateSpec = {\n id: string;\n title?: string;\n /** Template kind. Hosts decide the catalog. */\n kind: string;\n /** Template-specific config. Form: { fields }. Sheet: { headers }. etc. */\n config?: Record<string, unknown>;\n};\n\n/**\n * What a mutating adapter method may resolve to, to acknowledge (or refuse)\n * a commit. `{ ok: false }` is a refusal the agent can act on: `error` is\n * shown to the agent verbatim, so keep it a human-readable sentence, never a\n * stack trace or an internal path. `code` is a machine-readable hint\n * (e.g. `\"conflict\"`) for the host's own use; it is not shown to the agent.\n */\nexport type ScreensAdapterResult = { ok: true } | { ok: false; error: string; code?: string };\n\n/**\n * Return type of every mutating adapter method. A sync `void` return keeps\n * the original behaviour. A Promise makes the bridge WAIT: the tool reports\n * success, and emits its AgentActivity event, only after the promise\n * resolves. A rejection or an `{ ok: false }` result becomes an error result\n * and emits no activity.\n */\nexport type ScreensAdapterCommit = void | Promise<void | ScreensAdapterResult>;\n\n/**\n * Adapter exposes the host's screen-navigation surface to the bridge.\n * Hosts wire this up against react-router, a custom tab state, or the\n * fancy-screens registry — wherever \"current screen\" lives.\n *\n * The optional create / destroy / update hooks let agents author screens\n * dynamically against a host-defined template catalog.\n *\n * Every mutating method may be sync (`void`) or async (`Promise`); see\n * {@link ScreensAdapterCommit}. Return a Promise when the host's commit is\n * authoritative — persisted, or able to refuse or conflict — so the agent is\n * told the truth instead of \"success\" before anything was committed.\n *\n * This bridge pushes NO undo entries: `agent_undo` cannot revert a screens\n * tool. A host that needs undo for navigation or screen authoring must keep\n * its own history.\n */\nexport type ScreensBridgeAdapter = {\n /** List every available screen. */\n listScreens: () => ScreenSnapshot[];\n /** Read which screen is currently active. */\n getActive: () => string | null;\n /** Navigate to a screen by id. Host updates router / tab state. */\n setActive: (screenId: string) => ScreensAdapterCommit;\n /** Optional: instantiate a new screen from a template + config. */\n createScreen?: (spec: ScreenCreateSpec) => ScreensAdapterCommit;\n /** Optional: remove a previously-created screen. */\n destroyScreen?: (screenId: string) => ScreensAdapterCommit;\n /** Optional: shallow-merge new config into an existing screen. */\n updateScreenContent?: (screenId: string, partial: Record<string, unknown>) => ScreensAdapterCommit;\n /** Optional: enumerate the kinds the host knows how to instantiate. */\n listKinds?: () => Array<{ kind: string; label?: string; description?: string; configSchema?: unknown }>;\n};\n\nexport type ScreensBridgeOptions = {\n adapter: ScreensBridgeAdapter;\n agent?: { id: string; name?: string; color?: string };\n};\n\nconst DEFAULT_AGENT = { id: \"agent\", name: \"Agent\", color: \"#a855f7\" };\n\n/**\n * The agent-facing text for a host failure. Only the message is used — never\n * `stack`, which carries file paths — matching the other bridges. A message\n * that itself embeds stack frames is cut at the first frame. A non-Error\n * rejection (a plain object, a response) has no reliable message, so it gets\n * the fallback rather than \"[object Object]\".\n */\nfunction hostErrorMessage(e: unknown, fallback: string): string {\n let msg: string | undefined;\n if (e instanceof Error) msg = e.message;\n else if (typeof e === \"string\") msg = e;\n else if (e && typeof e === \"object\" && typeof (e as { message?: unknown }).message === \"string\") {\n msg = (e as { message: string }).message;\n }\n const firstFrame = msg ? msg.search(/\\n\\s+at\\s/) : -1;\n if (msg && firstFrame >= 0) msg = msg.slice(0, firstFrame);\n msg = msg?.trim();\n return msg ? msg : fallback;\n}\n\ntype CommitOutcome = { ok: true } | { ok: false; error: string };\n\n/** Run one adapter commit, await it, and normalise every way it can fail. */\nasync function commit(run: () => ScreensAdapterCommit, fallback: string): Promise<CommitOutcome> {\n try {\n const r = await run();\n if (r && typeof r === \"object\" && r.ok === false) {\n return { ok: false, error: hostErrorMessage(r.error, fallback) };\n }\n return { ok: true };\n } catch (e) {\n return { ok: false, error: hostErrorMessage(e, fallback) };\n }\n}\n\n/**\n * registerScreensBridge — top-level navigation bridge so agents can\n * switch between screens (`screens_navigate`) and discover what surfaces\n * exist (`screens_list`, `screens_describe_active`).\n *\n * Pair with the per-surface bridges (whiteboard, form, sheet, etc.) so\n * the agent has both navigation and per-screen control.\n */\nexport function registerScreensBridge(\n host: ToolHost,\n options: ScreensBridgeOptions,\n): Bridge {\n const { adapter } = options;\n const agent = { ...DEFAULT_AGENT, ...(options.agent ?? {}) };\n const disposers: Array<() => void> = [];\n\n // agent_undo / agent_redo / agent_history are registered whenever any bridge\n // mounts, so undo availability doesn't hinge on which bridges are co-present.\n ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });\n\n const target = (screenId: string): AgentTarget => ({\n kind: \"screens\",\n screenId,\n label: `Screen ${screenId}`,\n });\n\n const reg = (\n name: string,\n description: string,\n properties: Record<string, unknown>,\n required: string[],\n handler: (args: JsonObject) => Promise<any> | any,\n isMutation: boolean,\n targetFromArgs?: (args: JsonObject) => AgentTarget,\n ) => {\n const wrapped = async (args: JsonObject) => {\n try { return await handler(args); }\n catch (e) { return errorResult(hostErrorMessage(e, `${name} failed.`)); }\n };\n const final = isMutation\n ? wrapToolWithActivity(wrapped, {\n toolName: name, agent, kind: \"screens\",\n resolveTarget: ({ args }) => targetFromArgs?.(args) ?? null,\n })\n : wrapped;\n disposers.push(\n host.registerTool(\n { name, description, inputSchema: { type: \"object\", properties: properties as any, required, additionalProperties: false } },\n final as any,\n ),\n );\n };\n\n reg(\n \"screens_list\",\n \"List every screen the host has registered. Returns id, title, active flag, and optional kind.\",\n {},\n [],\n () => {\n const screens = adapter.listScreens();\n const text = screens\n .map((s) => `${s.active ? \"▸\" : \" \"} ${s.id}${s.title ? ` — ${s.title}` : \"\"}${s.kind ? ` [${s.kind}]` : \"\"}`)\n .join(\"\\n\");\n return textResult(text || \"(no screens)\", { screens, active: adapter.getActive() });\n },\n false,\n );\n\n reg(\n \"screens_describe_active\",\n \"Get the currently-active screen id (or null).\",\n {},\n [],\n () => {\n const active = adapter.getActive();\n return textResult(active ?? \"(none)\", { active });\n },\n false,\n );\n\n reg(\n \"screens_list_kinds\",\n \"List the screen kinds (templates) the host knows how to instantiate. Use this before screens_create to know what's available.\",\n {},\n [],\n () => {\n if (!adapter.listKinds) return errorResult(\"Host did not register a kind catalog. Cannot create screens dynamically.\");\n const kinds = adapter.listKinds();\n const text = kinds.map((k) => `${k.kind}${k.label ? ` — ${k.label}` : \"\"}${k.description ? ` (${k.description})` : \"\"}`).join(\"\\n\");\n return textResult(text || \"(no kinds registered)\", kinds);\n },\n false,\n );\n\n reg(\n \"screens_create\",\n \"Instantiate a new screen from a template kind + config. Switches the active view to the new screen.\",\n {\n id: { type: \"string\", description: \"Stable screen id. Must be unique.\" },\n title: { type: \"string\" },\n kind: { type: \"string\", description: \"Template kind — call screens_list_kinds for the catalog.\" },\n config: { type: \"object\", description: \"Template-specific config (e.g. { fields: [...] } for a form).\" },\n },\n [\"id\", \"kind\"],\n async (args) => {\n const createScreen = adapter.createScreen;\n if (!createScreen) return errorResult(\"Host did not provide createScreen.\");\n const id = String(args.id);\n const kind = String(args.kind);\n if (adapter.listScreens().find((s) => s.id === id)) {\n return errorResult(`Screen ${id} already exists. Use screens_destroy first or pick a fresh id.`);\n }\n const created = await commit(() => createScreen({\n id,\n title: typeof args.title === \"string\" ? args.title : undefined,\n kind,\n config: (args.config && typeof args.config === \"object\") ? args.config as Record<string, unknown> : undefined,\n }), `Host failed to create screen \"${id}\".`);\n // Nothing was created, so there is nothing to activate.\n if (!created.ok) return errorResult(created.error);\n\n const activated = await commit(() => adapter.setActive(id), `Host failed to activate screen \"${id}\".`);\n if (!activated.ok) {\n // Partial commit: the screen EXISTS but is not showing. Reported as an\n // error so an agent branching on isError does not go on to tell the\n // human \"look at the new screen\". The create DID commit, though, and\n // every committed mutation must be observable, so its activity is\n // emitted here by hand (wrapToolWithActivity skips error results).\n const state = { id, kind, created: true, activated: false };\n emitActivity({\n agentId: agent.id,\n agentName: agent.name,\n agentColor: agent.color,\n target: target(id),\n action: \"screens_create\",\n timestamp: Date.now(),\n meta: state,\n });\n return {\n ...errorResult(\n `Screen \"${id}\" was created but not activated: ${activated.error} ` +\n \"The screen exists; do not call screens_create again. \" +\n \"Call screens_navigate to show it, or screens_destroy to remove it.\",\n ),\n structuredContent: state,\n };\n }\n return textResult(`Created ${kind} screen \"${id}\"`, { id, kind });\n },\n true,\n (args) => target(String(args.id ?? \"\")),\n );\n\n reg(\n \"screens_destroy\",\n \"Remove a previously-created screen. Active screen falls back to the first remaining one (or null).\",\n { id: { type: \"string\" } },\n [\"id\"],\n async (args) => {\n const destroyScreen = adapter.destroyScreen;\n if (!destroyScreen) return errorResult(\"Host did not provide destroyScreen.\");\n const id = String(args.id);\n if (!adapter.listScreens().find((s) => s.id === id)) {\n return errorResult(`No screen with id ${id}`);\n }\n const done = await commit(() => destroyScreen(id), `Host failed to destroy screen \"${id}\".`);\n if (!done.ok) return errorResult(done.error);\n return textResult(`Destroyed screen ${id}`, { id });\n },\n true,\n (args) => target(String(args.id ?? \"\")),\n );\n\n reg(\n \"screens_set_layout\",\n \"Change the layout of an existing composite screen. Layouts: 'single', 'split-h' (left/right), 'split-v' (top/bottom), 'grid-2x2', 'stack' (tabs).\",\n {\n id: { type: \"string\" },\n layout: { type: \"string\", enum: [\"single\", \"split-h\", \"split-v\", \"grid-2x2\", \"stack\"] },\n },\n [\"id\", \"layout\"],\n async (args) => {\n const updateScreenContent = adapter.updateScreenContent;\n if (!updateScreenContent) return errorResult(\"Host did not provide updateScreenContent.\");\n const id = String(args.id);\n const done = await commit(\n () => updateScreenContent(id, { layout: String(args.layout) }),\n `Host failed to change the layout of screen \"${id}\".`,\n );\n if (!done.ok) return errorResult(done.error);\n return textResult(`Layout of ${args.id} → ${args.layout}`, { id: args.id, layout: args.layout });\n },\n true,\n (args) => target(String(args.id ?? \"\")),\n );\n\n reg(\n \"screens_update_content\",\n \"Merge new config into an existing screen (e.g. add a field to a form, append a sheet column, change chart series).\",\n {\n id: { type: \"string\" },\n partial: { type: \"object\", description: \"Shallow-merged into the screen's config.\" },\n },\n [\"id\", \"partial\"],\n async (args) => {\n const updateScreenContent = adapter.updateScreenContent;\n if (!updateScreenContent) return errorResult(\"Host did not provide updateScreenContent.\");\n const id = String(args.id);\n const partial = (args.partial && typeof args.partial === \"object\") ? args.partial as Record<string, unknown> : {};\n const done = await commit(() => updateScreenContent(id, partial), `Host failed to update screen \"${id}\".`);\n if (!done.ok) return errorResult(done.error);\n return textResult(`Updated content of ${id}`, { id });\n },\n true,\n (args) => target(String(args.id ?? \"\")),\n );\n\n reg(\n \"screens_navigate\",\n \"Switch the human's view to a different screen. The host updates its router / tab state and re-renders.\",\n { screen: { type: \"string\", description: \"Screen id to activate.\" } },\n [\"screen\"],\n async (args) => {\n const screenId = String(args.screen ?? \"\");\n const screens = adapter.listScreens();\n if (!screens.find((s) => s.id === screenId)) {\n return errorResult(`No screen registered with id \"${screenId}\". Call screens_list first.`);\n }\n const done = await commit(() => adapter.setActive(screenId), `Host failed to navigate to screen \"${screenId}\".`);\n if (!done.ok) return errorResult(done.error);\n return textResult(`Navigated to ${screenId}`, { screen: screenId });\n },\n true,\n (args) => target(String(args.screen ?? \"\")),\n );\n\n return {\n id: \"screens\",\n title: \"Screens\",\n dispose: () => { for (const d of disposers) d(); },\n };\n}\n"]}
|
package/dist/index.cjs
CHANGED
|
@@ -1460,7 +1460,7 @@ function registerGridBridge(host, options) {
|
|
|
1460
1460
|
throw new Error(`Unknown column "${id}". Available: ${known.join(", ")}`);
|
|
1461
1461
|
}
|
|
1462
1462
|
};
|
|
1463
|
-
const
|
|
1463
|
+
const commit2 = (next, action, label, previous) => {
|
|
1464
1464
|
adapter.setState(next);
|
|
1465
1465
|
fancyAutoCommon.pushUndoEntry(agent.id, {
|
|
1466
1466
|
timestamp: Date.now(),
|
|
@@ -1521,7 +1521,7 @@ function registerGridBridge(host, options) {
|
|
|
1521
1521
|
return { id: String(s.id), desc: Boolean(s.desc) };
|
|
1522
1522
|
});
|
|
1523
1523
|
const previous = adapter.getState();
|
|
1524
|
-
|
|
1524
|
+
commit2({ ...previous, sorting }, "grid_sort", `Sorted by ${sorting.map((s) => s.id).join(", ") || "nothing"}`, previous);
|
|
1525
1525
|
return textResult(`Sorted by ${sorting.map((s) => `${s.id}${s.desc ? " desc" : ""}`).join(", ") || "nothing"}.`);
|
|
1526
1526
|
},
|
|
1527
1527
|
true,
|
|
@@ -1550,7 +1550,7 @@ function registerGridBridge(host, options) {
|
|
|
1550
1550
|
return { id: String(f.id), value: String(f.value) };
|
|
1551
1551
|
});
|
|
1552
1552
|
const previous = adapter.getState();
|
|
1553
|
-
|
|
1553
|
+
commit2({ ...previous, filters }, "grid_filter", `Filtered ${filters.map((f) => f.id).join(", ") || "cleared"}`, previous);
|
|
1554
1554
|
return textResult(`Filtering on ${filters.map((f) => `${f.id}=${f.value}`).join(", ") || "nothing"}.`);
|
|
1555
1555
|
},
|
|
1556
1556
|
true,
|
|
@@ -1573,7 +1573,7 @@ function registerGridBridge(host, options) {
|
|
|
1573
1573
|
const previous = adapter.getState();
|
|
1574
1574
|
const rowSelection = {};
|
|
1575
1575
|
for (const id of ids) rowSelection[id] = true;
|
|
1576
|
-
|
|
1576
|
+
commit2({ ...previous, rowSelection }, "grid_select_rows", `Selected ${ids.length} row${ids.length === 1 ? "" : "s"}`, previous);
|
|
1577
1577
|
return textResult(`Selected ${ids.length} row${ids.length === 1 ? "" : "s"}.`);
|
|
1578
1578
|
},
|
|
1579
1579
|
true
|
|
@@ -1816,7 +1816,31 @@ function parseTriple(v) {
|
|
|
1816
1816
|
}
|
|
1817
1817
|
|
|
1818
1818
|
// src/bridges/screens.ts
|
|
1819
|
+
init_registry();
|
|
1819
1820
|
var DEFAULT_AGENT7 = { id: "agent", name: "Agent", color: "#a855f7" };
|
|
1821
|
+
function hostErrorMessage(e, fallback) {
|
|
1822
|
+
let msg;
|
|
1823
|
+
if (e instanceof Error) msg = e.message;
|
|
1824
|
+
else if (typeof e === "string") msg = e;
|
|
1825
|
+
else if (e && typeof e === "object" && typeof e.message === "string") {
|
|
1826
|
+
msg = e.message;
|
|
1827
|
+
}
|
|
1828
|
+
const firstFrame = msg ? msg.search(/\n\s+at\s/) : -1;
|
|
1829
|
+
if (msg && firstFrame >= 0) msg = msg.slice(0, firstFrame);
|
|
1830
|
+
msg = msg?.trim();
|
|
1831
|
+
return msg ? msg : fallback;
|
|
1832
|
+
}
|
|
1833
|
+
async function commit(run, fallback) {
|
|
1834
|
+
try {
|
|
1835
|
+
const r = await run();
|
|
1836
|
+
if (r && typeof r === "object" && r.ok === false) {
|
|
1837
|
+
return { ok: false, error: hostErrorMessage(r.error, fallback) };
|
|
1838
|
+
}
|
|
1839
|
+
return { ok: true };
|
|
1840
|
+
} catch (e) {
|
|
1841
|
+
return { ok: false, error: hostErrorMessage(e, fallback) };
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1820
1844
|
function registerScreensBridge(host, options) {
|
|
1821
1845
|
const { adapter } = options;
|
|
1822
1846
|
const agent = { ...DEFAULT_AGENT7, ...options.agent ?? {} };
|
|
@@ -1832,7 +1856,7 @@ function registerScreensBridge(host, options) {
|
|
|
1832
1856
|
try {
|
|
1833
1857
|
return await handler(args);
|
|
1834
1858
|
} catch (e) {
|
|
1835
|
-
return errorResult(e
|
|
1859
|
+
return errorResult(hostErrorMessage(e, `${name} failed.`));
|
|
1836
1860
|
}
|
|
1837
1861
|
};
|
|
1838
1862
|
const final = isMutation ? wrapToolWithActivity(wrapped, {
|
|
@@ -1894,20 +1918,40 @@ function registerScreensBridge(host, options) {
|
|
|
1894
1918
|
config: { type: "object", description: "Template-specific config (e.g. { fields: [...] } for a form)." }
|
|
1895
1919
|
},
|
|
1896
1920
|
["id", "kind"],
|
|
1897
|
-
(args) => {
|
|
1898
|
-
|
|
1921
|
+
async (args) => {
|
|
1922
|
+
const createScreen = adapter.createScreen;
|
|
1923
|
+
if (!createScreen) return errorResult("Host did not provide createScreen.");
|
|
1899
1924
|
const id = String(args.id);
|
|
1900
1925
|
const kind = String(args.kind);
|
|
1901
1926
|
if (adapter.listScreens().find((s) => s.id === id)) {
|
|
1902
1927
|
return errorResult(`Screen ${id} already exists. Use screens_destroy first or pick a fresh id.`);
|
|
1903
1928
|
}
|
|
1904
|
-
|
|
1929
|
+
const created = await commit(() => createScreen({
|
|
1905
1930
|
id,
|
|
1906
1931
|
title: typeof args.title === "string" ? args.title : void 0,
|
|
1907
1932
|
kind,
|
|
1908
1933
|
config: args.config && typeof args.config === "object" ? args.config : void 0
|
|
1909
|
-
});
|
|
1910
|
-
|
|
1934
|
+
}), `Host failed to create screen "${id}".`);
|
|
1935
|
+
if (!created.ok) return errorResult(created.error);
|
|
1936
|
+
const activated = await commit(() => adapter.setActive(id), `Host failed to activate screen "${id}".`);
|
|
1937
|
+
if (!activated.ok) {
|
|
1938
|
+
const state = { id, kind, created: true, activated: false };
|
|
1939
|
+
fancyAutoCommon.emitActivity({
|
|
1940
|
+
agentId: agent.id,
|
|
1941
|
+
agentName: agent.name,
|
|
1942
|
+
agentColor: agent.color,
|
|
1943
|
+
target: target(id),
|
|
1944
|
+
action: "screens_create",
|
|
1945
|
+
timestamp: Date.now(),
|
|
1946
|
+
meta: state
|
|
1947
|
+
});
|
|
1948
|
+
return {
|
|
1949
|
+
...errorResult(
|
|
1950
|
+
`Screen "${id}" was created but not activated: ${activated.error} The screen exists; do not call screens_create again. Call screens_navigate to show it, or screens_destroy to remove it.`
|
|
1951
|
+
),
|
|
1952
|
+
structuredContent: state
|
|
1953
|
+
};
|
|
1954
|
+
}
|
|
1911
1955
|
return textResult(`Created ${kind} screen "${id}"`, { id, kind });
|
|
1912
1956
|
},
|
|
1913
1957
|
true,
|
|
@@ -1918,13 +1962,15 @@ function registerScreensBridge(host, options) {
|
|
|
1918
1962
|
"Remove a previously-created screen. Active screen falls back to the first remaining one (or null).",
|
|
1919
1963
|
{ id: { type: "string" } },
|
|
1920
1964
|
["id"],
|
|
1921
|
-
(args) => {
|
|
1922
|
-
|
|
1965
|
+
async (args) => {
|
|
1966
|
+
const destroyScreen = adapter.destroyScreen;
|
|
1967
|
+
if (!destroyScreen) return errorResult("Host did not provide destroyScreen.");
|
|
1923
1968
|
const id = String(args.id);
|
|
1924
1969
|
if (!adapter.listScreens().find((s) => s.id === id)) {
|
|
1925
1970
|
return errorResult(`No screen with id ${id}`);
|
|
1926
1971
|
}
|
|
1927
|
-
|
|
1972
|
+
const done = await commit(() => destroyScreen(id), `Host failed to destroy screen "${id}".`);
|
|
1973
|
+
if (!done.ok) return errorResult(done.error);
|
|
1928
1974
|
return textResult(`Destroyed screen ${id}`, { id });
|
|
1929
1975
|
},
|
|
1930
1976
|
true,
|
|
@@ -1938,9 +1984,15 @@ function registerScreensBridge(host, options) {
|
|
|
1938
1984
|
layout: { type: "string", enum: ["single", "split-h", "split-v", "grid-2x2", "stack"] }
|
|
1939
1985
|
},
|
|
1940
1986
|
["id", "layout"],
|
|
1941
|
-
(args) => {
|
|
1942
|
-
|
|
1943
|
-
|
|
1987
|
+
async (args) => {
|
|
1988
|
+
const updateScreenContent = adapter.updateScreenContent;
|
|
1989
|
+
if (!updateScreenContent) return errorResult("Host did not provide updateScreenContent.");
|
|
1990
|
+
const id = String(args.id);
|
|
1991
|
+
const done = await commit(
|
|
1992
|
+
() => updateScreenContent(id, { layout: String(args.layout) }),
|
|
1993
|
+
`Host failed to change the layout of screen "${id}".`
|
|
1994
|
+
);
|
|
1995
|
+
if (!done.ok) return errorResult(done.error);
|
|
1944
1996
|
return textResult(`Layout of ${args.id} \u2192 ${args.layout}`, { id: args.id, layout: args.layout });
|
|
1945
1997
|
},
|
|
1946
1998
|
true,
|
|
@@ -1954,11 +2006,13 @@ function registerScreensBridge(host, options) {
|
|
|
1954
2006
|
partial: { type: "object", description: "Shallow-merged into the screen's config." }
|
|
1955
2007
|
},
|
|
1956
2008
|
["id", "partial"],
|
|
1957
|
-
(args) => {
|
|
1958
|
-
|
|
2009
|
+
async (args) => {
|
|
2010
|
+
const updateScreenContent = adapter.updateScreenContent;
|
|
2011
|
+
if (!updateScreenContent) return errorResult("Host did not provide updateScreenContent.");
|
|
1959
2012
|
const id = String(args.id);
|
|
1960
2013
|
const partial = args.partial && typeof args.partial === "object" ? args.partial : {};
|
|
1961
|
-
|
|
2014
|
+
const done = await commit(() => updateScreenContent(id, partial), `Host failed to update screen "${id}".`);
|
|
2015
|
+
if (!done.ok) return errorResult(done.error);
|
|
1962
2016
|
return textResult(`Updated content of ${id}`, { id });
|
|
1963
2017
|
},
|
|
1964
2018
|
true,
|
|
@@ -1969,13 +2023,14 @@ function registerScreensBridge(host, options) {
|
|
|
1969
2023
|
"Switch the human's view to a different screen. The host updates its router / tab state and re-renders.",
|
|
1970
2024
|
{ screen: { type: "string", description: "Screen id to activate." } },
|
|
1971
2025
|
["screen"],
|
|
1972
|
-
(args) => {
|
|
2026
|
+
async (args) => {
|
|
1973
2027
|
const screenId = String(args.screen ?? "");
|
|
1974
2028
|
const screens = adapter.listScreens();
|
|
1975
2029
|
if (!screens.find((s) => s.id === screenId)) {
|
|
1976
2030
|
return errorResult(`No screen registered with id "${screenId}". Call screens_list first.`);
|
|
1977
2031
|
}
|
|
1978
|
-
adapter.setActive(screenId);
|
|
2032
|
+
const done = await commit(() => adapter.setActive(screenId), `Host failed to navigate to screen "${screenId}".`);
|
|
2033
|
+
if (!done.ok) return errorResult(done.error);
|
|
1979
2034
|
return textResult(`Navigated to ${screenId}`, { screen: screenId });
|
|
1980
2035
|
},
|
|
1981
2036
|
true,
|
|
@@ -4446,7 +4501,7 @@ function registerDocBridge(host, options) {
|
|
|
4446
4501
|
};
|
|
4447
4502
|
const target = (elementId) => ({ kind: surface, screenId: adapter.screenId, elementId });
|
|
4448
4503
|
const pending = /* @__PURE__ */ new Map();
|
|
4449
|
-
function
|
|
4504
|
+
function commit2(op, label, targetId) {
|
|
4450
4505
|
const prev = adapter.get();
|
|
4451
4506
|
const next = reducer.reduce(prev, op);
|
|
4452
4507
|
adapter.set(next);
|
|
@@ -4467,7 +4522,7 @@ function registerDocBridge(host, options) {
|
|
|
4467
4522
|
options.onPending?.({ id: pendingId, op, label });
|
|
4468
4523
|
return { staged: true, id: targetId, pendingId };
|
|
4469
4524
|
}
|
|
4470
|
-
|
|
4525
|
+
commit2(op, label, targetId);
|
|
4471
4526
|
return { staged: false, id: targetId };
|
|
4472
4527
|
}
|
|
4473
4528
|
const reg = (verb, description, properties, required, handler, isMutation, resolveTarget) => {
|
|
@@ -4647,7 +4702,7 @@ function registerDocBridge(host, options) {
|
|
|
4647
4702
|
const p = pending.get(id);
|
|
4648
4703
|
if (!p) throw new Error(`No pending op ${id}`);
|
|
4649
4704
|
pending.delete(id);
|
|
4650
|
-
|
|
4705
|
+
commit2(p.op, p.label, p.targetId);
|
|
4651
4706
|
return { ok: true, applied: p.label, id: p.targetId, _text: `applied ${p.label}` };
|
|
4652
4707
|
},
|
|
4653
4708
|
true,
|