@agent-native/core 0.23.0 → 0.24.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/agent/engine/builder-engine.d.ts.map +1 -1
  2. package/dist/agent/engine/builder-engine.js +5 -6
  3. package/dist/agent/engine/builder-engine.js.map +1 -1
  4. package/dist/agent/run-manager.d.ts +9 -2
  5. package/dist/agent/run-manager.d.ts.map +1 -1
  6. package/dist/agent/run-manager.js +9 -2
  7. package/dist/agent/run-manager.js.map +1 -1
  8. package/dist/cli/workspace-dev.d.ts.map +1 -1
  9. package/dist/cli/workspace-dev.js +101 -9
  10. package/dist/cli/workspace-dev.js.map +1 -1
  11. package/dist/client/AssistantChat.d.ts +4 -0
  12. package/dist/client/AssistantChat.d.ts.map +1 -1
  13. package/dist/client/AssistantChat.js +51 -15
  14. package/dist/client/AssistantChat.js.map +1 -1
  15. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  16. package/dist/client/MultiTabAssistantChat.js +2 -1
  17. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  18. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  19. package/dist/client/agent-chat-adapter.js +70 -10
  20. package/dist/client/agent-chat-adapter.js.map +1 -1
  21. package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
  22. package/dist/client/extensions/ExtensionViewer.js +157 -2
  23. package/dist/client/extensions/ExtensionViewer.js.map +1 -1
  24. package/dist/client/sse-event-processor.d.ts +6 -0
  25. package/dist/client/sse-event-processor.d.ts.map +1 -1
  26. package/dist/client/sse-event-processor.js +9 -2
  27. package/dist/client/sse-event-processor.js.map +1 -1
  28. package/dist/client/use-chat-threads.d.ts +3 -0
  29. package/dist/client/use-chat-threads.d.ts.map +1 -1
  30. package/dist/client/use-chat-threads.js +23 -4
  31. package/dist/client/use-chat-threads.js.map +1 -1
  32. package/dist/client/use-chat-threads.spec.js +59 -0
  33. package/dist/client/use-chat-threads.spec.js.map +1 -1
  34. package/dist/extensions/actions.d.ts.map +1 -1
  35. package/dist/extensions/actions.js +112 -2
  36. package/dist/extensions/actions.js.map +1 -1
  37. package/dist/extensions/routes.d.ts.map +1 -1
  38. package/dist/extensions/routes.js +37 -2
  39. package/dist/extensions/routes.js.map +1 -1
  40. package/dist/extensions/schema.d.ts +275 -0
  41. package/dist/extensions/schema.d.ts.map +1 -1
  42. package/dist/extensions/schema.js +53 -1
  43. package/dist/extensions/schema.js.map +1 -1
  44. package/dist/extensions/store.d.ts +40 -0
  45. package/dist/extensions/store.d.ts.map +1 -1
  46. package/dist/extensions/store.js +367 -3
  47. package/dist/extensions/store.js.map +1 -1
  48. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  49. package/dist/server/agent-chat-plugin.js +4 -0
  50. package/dist/server/agent-chat-plugin.js.map +1 -1
  51. package/dist/server/auth.d.ts.map +1 -1
  52. package/dist/server/auth.js +6 -2
  53. package/dist/server/auth.js.map +1 -1
  54. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  55. package/dist/server/core-routes-plugin.js +9 -13
  56. package/dist/server/core-routes-plugin.js.map +1 -1
  57. package/docs/content/extensions.md +5 -0
  58. package/package.json +1 -1
@@ -329,5 +329,64 @@ describe("useChatThreads", () => {
329
329
  scope: sourceThread.scope,
330
330
  });
331
331
  });
332
+ it("keeps generated titles when later thread saves update the preview", async () => {
333
+ const sourceThread = {
334
+ id: "thread-1",
335
+ title: "Using the Brain demo data for this example",
336
+ preview: "Using the Brain demo data for this example",
337
+ messageCount: 1,
338
+ createdAt: 1,
339
+ updatedAt: 2,
340
+ scope: null,
341
+ };
342
+ const fetchMock = vi.fn(async (url, init) => {
343
+ if (url === "/chat/threads" && !init) {
344
+ return jsonResponse({ threads: [sourceThread] });
345
+ }
346
+ if (url === "/chat/threads/thread-1" && init?.method === "PUT") {
347
+ return jsonResponse({ ok: true });
348
+ }
349
+ throw new Error(`Unexpected fetch: ${url}`);
350
+ });
351
+ vi.stubGlobal("fetch", fetchMock);
352
+ let hook = null;
353
+ function Harness() {
354
+ hook = useChatThreads("/chat", "title-test", null, {
355
+ autoCreate: false,
356
+ });
357
+ return null;
358
+ }
359
+ await act(async () => {
360
+ root.render(_jsx(Harness, {}));
361
+ });
362
+ await act(async () => {
363
+ await Promise.resolve();
364
+ await Promise.resolve();
365
+ });
366
+ await act(async () => {
367
+ await hook.saveThreadData("thread-1", {
368
+ threadData: "",
369
+ title: "Brain Demo Setup",
370
+ preview: "Using the Brain demo data for this example",
371
+ titleSource: "generated",
372
+ });
373
+ });
374
+ await act(async () => {
375
+ await hook.saveThreadData("thread-1", {
376
+ threadData: JSON.stringify({ messages: [] }),
377
+ title: "Using the Brain demo data for this example",
378
+ preview: "What should the demo answer cite?",
379
+ messageCount: 2,
380
+ });
381
+ });
382
+ const saveCalls = fetchMock.mock.calls.filter(([url, init]) => url === "/chat/threads/thread-1" && init?.method === "PUT");
383
+ expect(JSON.parse(saveCalls[0][1].body).title).toBe("Brain Demo Setup");
384
+ expect(JSON.parse(saveCalls[1][1].body).title).toBe("Brain Demo Setup");
385
+ expect(hook.threads.find((thread) => thread.id === "thread-1")).toMatchObject({
386
+ title: "Brain Demo Setup",
387
+ preview: "What should the demo answer cite?",
388
+ messageCount: 2,
389
+ });
390
+ });
332
391
  });
333
392
  //# sourceMappingURL=use-chat-threads.spec.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-chat-threads.spec.js","sourceRoot":"","sources":["../../src/client/use-chat-threads.spec.tsx"],"names":[],"mappings":"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","sourcesContent":["// @vitest-environment happy-dom\n\nimport React, { act } from \"react\";\nimport { createRoot, type Root } from \"react-dom/client\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport {\n useChatThreads,\n type ChatThreadScope,\n type ChatThreadSnapshot,\n type ChatThreadSummary,\n} from \"./use-chat-threads.js\";\n\nfunction jsonResponse(data: unknown) {\n return new Response(JSON.stringify(data), {\n headers: { \"Content-Type\": \"application/json\" },\n });\n}\n\ndescribe(\"useChatThreads\", () => {\n let container: HTMLDivElement;\n let root: Root;\n\n beforeEach(() => {\n vi.stubGlobal(\"IS_REACT_ACT_ENVIRONMENT\", true);\n vi.stubGlobal(\"crypto\", { randomUUID: () => \"forked-thread\" });\n window.localStorage.clear();\n container = document.createElement(\"div\");\n document.body.appendChild(container);\n root = createRoot(container);\n });\n\n afterEach(() => {\n act(() => {\n root.unmount();\n });\n container.remove();\n vi.unstubAllGlobals();\n });\n\n it(\"starts fresh when no active thread is saved, even if server history exists\", async () => {\n const oldThread: ChatThreadSummary = {\n id: \"old-project-thread\",\n title: \"Animated charting tool\",\n preview: \"make the chart more playful\",\n messageCount: 2,\n createdAt: 1,\n updatedAt: 2,\n scope: null,\n };\n const fetchMock = vi.fn(async (url: string, init?: RequestInit) => {\n if (url === \"/chat/threads\" && !init) {\n return jsonResponse({ threads: [oldThread] });\n }\n throw new Error(`Unexpected fetch: ${url}`);\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n let hook: ReturnType<typeof useChatThreads> | null = null;\n function Harness() {\n hook = useChatThreads(\"/chat\", \"analytics-project\");\n return null;\n }\n\n await act(async () => {\n root.render(<Harness />);\n });\n await act(async () => {\n await Promise.resolve();\n await Promise.resolve();\n });\n\n expect(hook!.activeThreadId).toBe(\"forked-thread\");\n expect(hook!.threads.map((thread) => thread.id)).toEqual([\n \"forked-thread\",\n \"old-project-thread\",\n ]);\n });\n\n it(\"keeps a saved active thread when it still exists on the server\", async () => {\n window.localStorage.setItem(\n \"agent-chat-active-thread:analytics-project\",\n \"old-project-thread\",\n );\n const oldThread: ChatThreadSummary = {\n id: \"old-project-thread\",\n title: \"Analytics for Academy\",\n preview: \"show weekly signups\",\n messageCount: 2,\n createdAt: 1,\n updatedAt: 2,\n scope: null,\n };\n const fetchMock = vi.fn(async (url: string, init?: RequestInit) => {\n if (url === \"/chat/threads\" && !init) {\n return jsonResponse({ threads: [oldThread] });\n }\n throw new Error(`Unexpected fetch: ${url}`);\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n let hook: ReturnType<typeof useChatThreads> | null = null;\n function Harness() {\n hook = useChatThreads(\"/chat\", \"analytics-project\");\n return null;\n }\n\n await act(async () => {\n root.render(<Harness />);\n });\n await act(async () => {\n await Promise.resolve();\n await Promise.resolve();\n });\n\n expect(hook!.activeThreadId).toBe(\"old-project-thread\");\n expect(hook!.threads.map((thread) => thread.id)).toEqual([\n \"old-project-thread\",\n ]);\n });\n\n it(\"keeps the active general chat visible when entering a scoped surface\", async () => {\n window.localStorage.setItem(\n \"agent-chat-active-thread:forms-app\",\n \"general-thread\",\n );\n const generalThread: ChatThreadSummary = {\n id: \"general-thread\",\n title: \"Create a form\",\n preview: \"make me a form\",\n messageCount: 2,\n createdAt: 1,\n updatedAt: 2,\n scope: null,\n };\n const formThread: ChatThreadSummary = {\n id: \"form-thread\",\n title: \"Form edits\",\n preview: \"add another question\",\n messageCount: 2,\n createdAt: 3,\n updatedAt: 4,\n scope: { type: \"form\", id: \"form-1\", label: \"Hackathon\" },\n };\n const fetchMock = vi.fn(async (url: string, init?: RequestInit) => {\n if (url === \"/chat/threads\" && !init) {\n return jsonResponse({ threads: [generalThread, formThread] });\n }\n throw new Error(`Unexpected fetch: ${url}`);\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n let hook: ReturnType<typeof useChatThreads> | null = null;\n function Harness({ scope }: { scope?: ChatThreadScope | null }) {\n hook = useChatThreads(\"/chat\", \"forms-app\", scope);\n return null;\n }\n\n await act(async () => {\n root.render(<Harness scope={null} />);\n });\n await act(async () => {\n await Promise.resolve();\n await Promise.resolve();\n });\n\n expect(hook!.activeThreadId).toBe(\"general-thread\");\n\n await act(async () => {\n root.render(\n <Harness scope={{ type: \"form\", id: \"form-1\", label: \"Hackathon\" }} />,\n );\n });\n await act(async () => {\n await Promise.resolve();\n await Promise.resolve();\n });\n\n expect(hook!.activeThreadId).toBe(\"general-thread\");\n expect(\n window.localStorage.getItem(\n \"agent-chat-active-thread:forms-app:scope:form:form-1\",\n ),\n ).toBeNull();\n expect(\n window.localStorage.getItem(\"agent-chat-active-thread:forms-app\"),\n ).toBe(\"general-thread\");\n });\n\n it(\"switches back to the general chat when leaving a scoped thread\", async () => {\n window.localStorage.setItem(\n \"agent-chat-active-thread:forms-app\",\n \"general-thread\",\n );\n window.localStorage.setItem(\n \"agent-chat-active-thread:forms-app:scope:form:form-1\",\n \"form-thread\",\n );\n const generalThread: ChatThreadSummary = {\n id: \"general-thread\",\n title: \"Create a form\",\n preview: \"make me a form\",\n messageCount: 2,\n createdAt: 1,\n updatedAt: 2,\n scope: null,\n };\n const formThread: ChatThreadSummary = {\n id: \"form-thread\",\n title: \"Form edits\",\n preview: \"add another question\",\n messageCount: 2,\n createdAt: 3,\n updatedAt: 4,\n scope: { type: \"form\", id: \"form-1\", label: \"Hackathon\" },\n };\n const fetchMock = vi.fn(async (url: string, init?: RequestInit) => {\n if (url === \"/chat/threads\" && !init) {\n return jsonResponse({ threads: [formThread, generalThread] });\n }\n throw new Error(`Unexpected fetch: ${url}`);\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n let hook: ReturnType<typeof useChatThreads> | null = null;\n function Harness({ scope }: { scope?: ChatThreadScope | null }) {\n hook = useChatThreads(\"/chat\", \"forms-app\", scope);\n return null;\n }\n\n await act(async () => {\n root.render(\n <Harness scope={{ type: \"form\", id: \"form-1\", label: \"Hackathon\" }} />,\n );\n });\n await act(async () => {\n await Promise.resolve();\n await Promise.resolve();\n });\n\n expect(hook!.activeThreadId).toBe(\"form-thread\");\n\n await act(async () => {\n root.render(<Harness scope={null} />);\n });\n await act(async () => {\n await Promise.resolve();\n await Promise.resolve();\n });\n\n expect(hook!.activeThreadId).toBe(\"general-thread\");\n });\n\n it(\"sends the current client snapshot when forking a thread\", async () => {\n const sourceThread: ChatThreadSummary = {\n id: \"source-thread\",\n title: \"Pipeline\",\n preview: \"make this slide better\",\n messageCount: 2,\n createdAt: 1,\n updatedAt: 2,\n scope: { type: \"dashboard\", id: \"dash-1\", label: \"Pipeline\" },\n };\n const fetchMock = vi.fn(async (url: string, init?: RequestInit) => {\n if (url === \"/chat/threads\" && !init) {\n return jsonResponse({ threads: [sourceThread] });\n }\n if (url === \"/chat/threads/source-thread/fork\") {\n return jsonResponse({\n ...sourceThread,\n id: \"forked-thread\",\n title: \"Pipeline (fork)\",\n });\n }\n throw new Error(`Unexpected fetch: ${url}`);\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n let hook: ReturnType<typeof useChatThreads> | null = null;\n function Harness() {\n hook = useChatThreads(\"/chat\", \"fork-test\");\n return null;\n }\n\n await act(async () => {\n root.render(<Harness />);\n });\n await act(async () => {\n await Promise.resolve();\n await Promise.resolve();\n });\n\n const snapshot: ChatThreadSnapshot = {\n threadData: JSON.stringify({ messages: [{ message: { id: \"m1\" } }] }),\n title: \"Pipeline\",\n preview: \"make this slide better\",\n messageCount: 1,\n };\n\n let forkedId: string | null = null;\n await act(async () => {\n forkedId = await hook!.forkThread(\"source-thread\", snapshot);\n });\n\n expect(forkedId).toBe(\"forked-thread\");\n const forkCall = fetchMock.mock.calls.find(\n ([url]) => url === \"/chat/threads/source-thread/fork\",\n );\n expect(forkCall).toBeDefined();\n expect(JSON.parse(forkCall![1]!.body as string)).toEqual({\n id: \"forked-thread\",\n source: { ...snapshot, scope: sourceThread.scope },\n });\n });\n\n it(\"creates a fork from the client snapshot when the fork endpoint cannot find the source\", async () => {\n const sourceThread: ChatThreadSummary = {\n id: \"source-thread\",\n title: \"Pipeline\",\n preview: \"make this slide better\",\n messageCount: 2,\n createdAt: 1,\n updatedAt: 2,\n scope: { type: \"deck\", id: \"deck-1\", label: \"Pipeline deck\" },\n };\n const fetchMock = vi.fn(async (url: string, init?: RequestInit) => {\n if (url === \"/chat/threads\" && !init) {\n return jsonResponse({ threads: [sourceThread] });\n }\n if (url === \"/chat/threads/source-thread/fork\") {\n return new Response(JSON.stringify({ error: \"Thread not found\" }), {\n status: 404,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n if (url === \"/chat/threads\" && init?.method === \"POST\") {\n return jsonResponse({\n id: \"forked-thread\",\n title: \"Pipeline (fork)\",\n preview: \"\",\n messageCount: 0,\n createdAt: 3,\n updatedAt: 3,\n scope: sourceThread.scope,\n });\n }\n if (url === \"/chat/threads/forked-thread\" && init?.method === \"PUT\") {\n return jsonResponse({ ok: true });\n }\n throw new Error(`Unexpected fetch: ${url}`);\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n let hook: ReturnType<typeof useChatThreads> | null = null;\n function Harness() {\n hook = useChatThreads(\"/chat\", \"fork-test\");\n return null;\n }\n\n await act(async () => {\n root.render(<Harness />);\n });\n await act(async () => {\n await Promise.resolve();\n await Promise.resolve();\n });\n\n const snapshot: ChatThreadSnapshot = {\n threadData: JSON.stringify({ messages: [{ message: { id: \"m1\" } }] }),\n title: \"Pipeline\",\n preview: \"make this slide better\",\n messageCount: 1,\n };\n\n let forkedId: string | null = null;\n await act(async () => {\n forkedId = await hook!.forkThread(\"source-thread\", snapshot);\n });\n\n expect(forkedId).toBe(\"forked-thread\");\n const createCall = fetchMock.mock.calls.find(\n ([url, init]) => url === \"/chat/threads\" && init?.method === \"POST\",\n );\n expect(createCall).toBeDefined();\n expect(JSON.parse(createCall![1]!.body as string)).toEqual({\n id: \"forked-thread\",\n title: \"Pipeline (fork)\",\n scope: sourceThread.scope,\n });\n const saveCall = fetchMock.mock.calls.find(\n ([url, init]) =>\n url === \"/chat/threads/forked-thread\" && init?.method === \"PUT\",\n );\n expect(saveCall).toBeDefined();\n expect(JSON.parse(saveCall![1]!.body as string)).toEqual({\n threadData: snapshot.threadData,\n title: \"Pipeline (fork)\",\n preview: snapshot.preview,\n messageCount: snapshot.messageCount,\n scope: sourceThread.scope,\n });\n });\n});\n"]}
1
+ {"version":3,"file":"use-chat-threads.spec.js","sourceRoot":"","sources":["../../src/client/use-chat-threads.spec.tsx"],"names":[],"mappings":"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","sourcesContent":["// @vitest-environment happy-dom\n\nimport React, { act } from \"react\";\nimport { createRoot, type Root } from \"react-dom/client\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport {\n useChatThreads,\n type ChatThreadScope,\n type ChatThreadSnapshot,\n type ChatThreadSummary,\n} from \"./use-chat-threads.js\";\n\nfunction jsonResponse(data: unknown) {\n return new Response(JSON.stringify(data), {\n headers: { \"Content-Type\": \"application/json\" },\n });\n}\n\ndescribe(\"useChatThreads\", () => {\n let container: HTMLDivElement;\n let root: Root;\n\n beforeEach(() => {\n vi.stubGlobal(\"IS_REACT_ACT_ENVIRONMENT\", true);\n vi.stubGlobal(\"crypto\", { randomUUID: () => \"forked-thread\" });\n window.localStorage.clear();\n container = document.createElement(\"div\");\n document.body.appendChild(container);\n root = createRoot(container);\n });\n\n afterEach(() => {\n act(() => {\n root.unmount();\n });\n container.remove();\n vi.unstubAllGlobals();\n });\n\n it(\"starts fresh when no active thread is saved, even if server history exists\", async () => {\n const oldThread: ChatThreadSummary = {\n id: \"old-project-thread\",\n title: \"Animated charting tool\",\n preview: \"make the chart more playful\",\n messageCount: 2,\n createdAt: 1,\n updatedAt: 2,\n scope: null,\n };\n const fetchMock = vi.fn(async (url: string, init?: RequestInit) => {\n if (url === \"/chat/threads\" && !init) {\n return jsonResponse({ threads: [oldThread] });\n }\n throw new Error(`Unexpected fetch: ${url}`);\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n let hook: ReturnType<typeof useChatThreads> | null = null;\n function Harness() {\n hook = useChatThreads(\"/chat\", \"analytics-project\");\n return null;\n }\n\n await act(async () => {\n root.render(<Harness />);\n });\n await act(async () => {\n await Promise.resolve();\n await Promise.resolve();\n });\n\n expect(hook!.activeThreadId).toBe(\"forked-thread\");\n expect(hook!.threads.map((thread) => thread.id)).toEqual([\n \"forked-thread\",\n \"old-project-thread\",\n ]);\n });\n\n it(\"keeps a saved active thread when it still exists on the server\", async () => {\n window.localStorage.setItem(\n \"agent-chat-active-thread:analytics-project\",\n \"old-project-thread\",\n );\n const oldThread: ChatThreadSummary = {\n id: \"old-project-thread\",\n title: \"Analytics for Academy\",\n preview: \"show weekly signups\",\n messageCount: 2,\n createdAt: 1,\n updatedAt: 2,\n scope: null,\n };\n const fetchMock = vi.fn(async (url: string, init?: RequestInit) => {\n if (url === \"/chat/threads\" && !init) {\n return jsonResponse({ threads: [oldThread] });\n }\n throw new Error(`Unexpected fetch: ${url}`);\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n let hook: ReturnType<typeof useChatThreads> | null = null;\n function Harness() {\n hook = useChatThreads(\"/chat\", \"analytics-project\");\n return null;\n }\n\n await act(async () => {\n root.render(<Harness />);\n });\n await act(async () => {\n await Promise.resolve();\n await Promise.resolve();\n });\n\n expect(hook!.activeThreadId).toBe(\"old-project-thread\");\n expect(hook!.threads.map((thread) => thread.id)).toEqual([\n \"old-project-thread\",\n ]);\n });\n\n it(\"keeps the active general chat visible when entering a scoped surface\", async () => {\n window.localStorage.setItem(\n \"agent-chat-active-thread:forms-app\",\n \"general-thread\",\n );\n const generalThread: ChatThreadSummary = {\n id: \"general-thread\",\n title: \"Create a form\",\n preview: \"make me a form\",\n messageCount: 2,\n createdAt: 1,\n updatedAt: 2,\n scope: null,\n };\n const formThread: ChatThreadSummary = {\n id: \"form-thread\",\n title: \"Form edits\",\n preview: \"add another question\",\n messageCount: 2,\n createdAt: 3,\n updatedAt: 4,\n scope: { type: \"form\", id: \"form-1\", label: \"Hackathon\" },\n };\n const fetchMock = vi.fn(async (url: string, init?: RequestInit) => {\n if (url === \"/chat/threads\" && !init) {\n return jsonResponse({ threads: [generalThread, formThread] });\n }\n throw new Error(`Unexpected fetch: ${url}`);\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n let hook: ReturnType<typeof useChatThreads> | null = null;\n function Harness({ scope }: { scope?: ChatThreadScope | null }) {\n hook = useChatThreads(\"/chat\", \"forms-app\", scope);\n return null;\n }\n\n await act(async () => {\n root.render(<Harness scope={null} />);\n });\n await act(async () => {\n await Promise.resolve();\n await Promise.resolve();\n });\n\n expect(hook!.activeThreadId).toBe(\"general-thread\");\n\n await act(async () => {\n root.render(\n <Harness scope={{ type: \"form\", id: \"form-1\", label: \"Hackathon\" }} />,\n );\n });\n await act(async () => {\n await Promise.resolve();\n await Promise.resolve();\n });\n\n expect(hook!.activeThreadId).toBe(\"general-thread\");\n expect(\n window.localStorage.getItem(\n \"agent-chat-active-thread:forms-app:scope:form:form-1\",\n ),\n ).toBeNull();\n expect(\n window.localStorage.getItem(\"agent-chat-active-thread:forms-app\"),\n ).toBe(\"general-thread\");\n });\n\n it(\"switches back to the general chat when leaving a scoped thread\", async () => {\n window.localStorage.setItem(\n \"agent-chat-active-thread:forms-app\",\n \"general-thread\",\n );\n window.localStorage.setItem(\n \"agent-chat-active-thread:forms-app:scope:form:form-1\",\n \"form-thread\",\n );\n const generalThread: ChatThreadSummary = {\n id: \"general-thread\",\n title: \"Create a form\",\n preview: \"make me a form\",\n messageCount: 2,\n createdAt: 1,\n updatedAt: 2,\n scope: null,\n };\n const formThread: ChatThreadSummary = {\n id: \"form-thread\",\n title: \"Form edits\",\n preview: \"add another question\",\n messageCount: 2,\n createdAt: 3,\n updatedAt: 4,\n scope: { type: \"form\", id: \"form-1\", label: \"Hackathon\" },\n };\n const fetchMock = vi.fn(async (url: string, init?: RequestInit) => {\n if (url === \"/chat/threads\" && !init) {\n return jsonResponse({ threads: [formThread, generalThread] });\n }\n throw new Error(`Unexpected fetch: ${url}`);\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n let hook: ReturnType<typeof useChatThreads> | null = null;\n function Harness({ scope }: { scope?: ChatThreadScope | null }) {\n hook = useChatThreads(\"/chat\", \"forms-app\", scope);\n return null;\n }\n\n await act(async () => {\n root.render(\n <Harness scope={{ type: \"form\", id: \"form-1\", label: \"Hackathon\" }} />,\n );\n });\n await act(async () => {\n await Promise.resolve();\n await Promise.resolve();\n });\n\n expect(hook!.activeThreadId).toBe(\"form-thread\");\n\n await act(async () => {\n root.render(<Harness scope={null} />);\n });\n await act(async () => {\n await Promise.resolve();\n await Promise.resolve();\n });\n\n expect(hook!.activeThreadId).toBe(\"general-thread\");\n });\n\n it(\"sends the current client snapshot when forking a thread\", async () => {\n const sourceThread: ChatThreadSummary = {\n id: \"source-thread\",\n title: \"Pipeline\",\n preview: \"make this slide better\",\n messageCount: 2,\n createdAt: 1,\n updatedAt: 2,\n scope: { type: \"dashboard\", id: \"dash-1\", label: \"Pipeline\" },\n };\n const fetchMock = vi.fn(async (url: string, init?: RequestInit) => {\n if (url === \"/chat/threads\" && !init) {\n return jsonResponse({ threads: [sourceThread] });\n }\n if (url === \"/chat/threads/source-thread/fork\") {\n return jsonResponse({\n ...sourceThread,\n id: \"forked-thread\",\n title: \"Pipeline (fork)\",\n });\n }\n throw new Error(`Unexpected fetch: ${url}`);\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n let hook: ReturnType<typeof useChatThreads> | null = null;\n function Harness() {\n hook = useChatThreads(\"/chat\", \"fork-test\");\n return null;\n }\n\n await act(async () => {\n root.render(<Harness />);\n });\n await act(async () => {\n await Promise.resolve();\n await Promise.resolve();\n });\n\n const snapshot: ChatThreadSnapshot = {\n threadData: JSON.stringify({ messages: [{ message: { id: \"m1\" } }] }),\n title: \"Pipeline\",\n preview: \"make this slide better\",\n messageCount: 1,\n };\n\n let forkedId: string | null = null;\n await act(async () => {\n forkedId = await hook!.forkThread(\"source-thread\", snapshot);\n });\n\n expect(forkedId).toBe(\"forked-thread\");\n const forkCall = fetchMock.mock.calls.find(\n ([url]) => url === \"/chat/threads/source-thread/fork\",\n );\n expect(forkCall).toBeDefined();\n expect(JSON.parse(forkCall![1]!.body as string)).toEqual({\n id: \"forked-thread\",\n source: { ...snapshot, scope: sourceThread.scope },\n });\n });\n\n it(\"creates a fork from the client snapshot when the fork endpoint cannot find the source\", async () => {\n const sourceThread: ChatThreadSummary = {\n id: \"source-thread\",\n title: \"Pipeline\",\n preview: \"make this slide better\",\n messageCount: 2,\n createdAt: 1,\n updatedAt: 2,\n scope: { type: \"deck\", id: \"deck-1\", label: \"Pipeline deck\" },\n };\n const fetchMock = vi.fn(async (url: string, init?: RequestInit) => {\n if (url === \"/chat/threads\" && !init) {\n return jsonResponse({ threads: [sourceThread] });\n }\n if (url === \"/chat/threads/source-thread/fork\") {\n return new Response(JSON.stringify({ error: \"Thread not found\" }), {\n status: 404,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n if (url === \"/chat/threads\" && init?.method === \"POST\") {\n return jsonResponse({\n id: \"forked-thread\",\n title: \"Pipeline (fork)\",\n preview: \"\",\n messageCount: 0,\n createdAt: 3,\n updatedAt: 3,\n scope: sourceThread.scope,\n });\n }\n if (url === \"/chat/threads/forked-thread\" && init?.method === \"PUT\") {\n return jsonResponse({ ok: true });\n }\n throw new Error(`Unexpected fetch: ${url}`);\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n let hook: ReturnType<typeof useChatThreads> | null = null;\n function Harness() {\n hook = useChatThreads(\"/chat\", \"fork-test\");\n return null;\n }\n\n await act(async () => {\n root.render(<Harness />);\n });\n await act(async () => {\n await Promise.resolve();\n await Promise.resolve();\n });\n\n const snapshot: ChatThreadSnapshot = {\n threadData: JSON.stringify({ messages: [{ message: { id: \"m1\" } }] }),\n title: \"Pipeline\",\n preview: \"make this slide better\",\n messageCount: 1,\n };\n\n let forkedId: string | null = null;\n await act(async () => {\n forkedId = await hook!.forkThread(\"source-thread\", snapshot);\n });\n\n expect(forkedId).toBe(\"forked-thread\");\n const createCall = fetchMock.mock.calls.find(\n ([url, init]) => url === \"/chat/threads\" && init?.method === \"POST\",\n );\n expect(createCall).toBeDefined();\n expect(JSON.parse(createCall![1]!.body as string)).toEqual({\n id: \"forked-thread\",\n title: \"Pipeline (fork)\",\n scope: sourceThread.scope,\n });\n const saveCall = fetchMock.mock.calls.find(\n ([url, init]) =>\n url === \"/chat/threads/forked-thread\" && init?.method === \"PUT\",\n );\n expect(saveCall).toBeDefined();\n expect(JSON.parse(saveCall![1]!.body as string)).toEqual({\n threadData: snapshot.threadData,\n title: \"Pipeline (fork)\",\n preview: snapshot.preview,\n messageCount: snapshot.messageCount,\n scope: sourceThread.scope,\n });\n });\n\n it(\"keeps generated titles when later thread saves update the preview\", async () => {\n const sourceThread: ChatThreadSummary = {\n id: \"thread-1\",\n title: \"Using the Brain demo data for this example\",\n preview: \"Using the Brain demo data for this example\",\n messageCount: 1,\n createdAt: 1,\n updatedAt: 2,\n scope: null,\n };\n const fetchMock = vi.fn(async (url: string, init?: RequestInit) => {\n if (url === \"/chat/threads\" && !init) {\n return jsonResponse({ threads: [sourceThread] });\n }\n if (url === \"/chat/threads/thread-1\" && init?.method === \"PUT\") {\n return jsonResponse({ ok: true });\n }\n throw new Error(`Unexpected fetch: ${url}`);\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n let hook: ReturnType<typeof useChatThreads> | null = null;\n function Harness() {\n hook = useChatThreads(\"/chat\", \"title-test\", null, {\n autoCreate: false,\n });\n return null;\n }\n\n await act(async () => {\n root.render(<Harness />);\n });\n await act(async () => {\n await Promise.resolve();\n await Promise.resolve();\n });\n\n await act(async () => {\n await hook!.saveThreadData(\"thread-1\", {\n threadData: \"\",\n title: \"Brain Demo Setup\",\n preview: \"Using the Brain demo data for this example\",\n titleSource: \"generated\",\n });\n });\n\n await act(async () => {\n await hook!.saveThreadData(\"thread-1\", {\n threadData: JSON.stringify({ messages: [] }),\n title: \"Using the Brain demo data for this example\",\n preview: \"What should the demo answer cite?\",\n messageCount: 2,\n });\n });\n\n const saveCalls = fetchMock.mock.calls.filter(\n ([url, init]) =>\n url === \"/chat/threads/thread-1\" && init?.method === \"PUT\",\n );\n expect(JSON.parse(saveCalls[0]![1]!.body as string).title).toBe(\n \"Brain Demo Setup\",\n );\n expect(JSON.parse(saveCalls[1]![1]!.body as string).title).toBe(\n \"Brain Demo Setup\",\n );\n expect(\n hook!.threads.find((thread) => thread.id === \"thread-1\"),\n ).toMatchObject({\n title: \"Brain Demo Setup\",\n preview: \"What should the demo answer cite?\",\n messageCount: 2,\n });\n });\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/extensions/actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AA4BhE,wBAAgB,4BAA4B,IAAI,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CA8f1E"}
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/extensions/actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AA+BhE,wBAAgB,4BAA4B,IAAI,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAknB1E"}
@@ -1,5 +1,5 @@
1
1
  import { writeAppState } from "../application-state/script-helpers.js";
2
- import { createExtension, deleteExtension, getHiddenExtensionIdsForCurrentUser, getExtension, hideExtension, listExtensions, unhideExtension, updateExtension, updateExtensionContent, } from "./store.js";
2
+ import { createExtension, deleteExtension, getHiddenExtensionIdsForCurrentUser, getExtension, getExtensionHistoryVersion, hideExtension, listExtensionHistory, listExtensions, restoreExtensionHistoryVersion, unhideExtension, updateExtension, updateExtensionContent, } from "./store.js";
3
3
  import { resolveAccess } from "../sharing/access.js";
4
4
  import { addExtensionSlotTarget, installExtensionSlot, uninstallExtensionSlot, listExtensionsForSlot, listSlotsForExtension, } from "./slots/store.js";
5
5
  import { extensionPath } from "./path.js";
@@ -91,9 +91,81 @@ export function createExtensionActionEntries() {
91
91
  },
92
92
  readOnly: true,
93
93
  },
94
+ "list-extension-history": {
95
+ tool: {
96
+ description: "List saved history snapshots for one extension. Use this when the user asks what changed, wants a changelog, or wants to pick an older version to restore. If the user is viewing the extension, use the extensionId from <current-screen> or <current-url>.",
97
+ parameters: {
98
+ type: "object",
99
+ properties: {
100
+ id: {
101
+ type: "string",
102
+ description: "Extension id whose history should be listed.",
103
+ },
104
+ limit: {
105
+ type: "number",
106
+ description: "Maximum versions to return. Defaults to 50.",
107
+ },
108
+ includeContent: {
109
+ type: "boolean",
110
+ description: "Include full HTML content for each version. Defaults to false.",
111
+ },
112
+ },
113
+ required: ["id"],
114
+ },
115
+ },
116
+ run: async (args) => {
117
+ const id = String(args?.id ?? "").trim();
118
+ if (!id)
119
+ return "Error: id is required.";
120
+ const history = await listExtensionHistory(id, {
121
+ limit: args?.limit === undefined ? undefined : coerceLimit(args.limit),
122
+ includeContent: coerceBoolean(args?.includeContent),
123
+ });
124
+ return {
125
+ ok: true,
126
+ count: history.length,
127
+ history,
128
+ };
129
+ },
130
+ readOnly: true,
131
+ },
132
+ "get-extension-history-version": {
133
+ tool: {
134
+ description: "Get one extension history version with its previous-version diff. Use after list-extension-history when the user wants to inspect exactly what changed.",
135
+ parameters: {
136
+ type: "object",
137
+ properties: {
138
+ id: {
139
+ type: "string",
140
+ description: "Extension id whose history version should be read.",
141
+ },
142
+ version: {
143
+ type: "number",
144
+ description: "History version number to inspect.",
145
+ },
146
+ },
147
+ required: ["id", "version"],
148
+ },
149
+ },
150
+ run: async (args) => {
151
+ const id = String(args?.id ?? "").trim();
152
+ if (!id)
153
+ return "Error: id is required.";
154
+ const version = Number(args?.version);
155
+ if (!Number.isInteger(version) || version < 1) {
156
+ return "Error: version must be a positive integer.";
157
+ }
158
+ const detail = await getExtensionHistoryVersion(id, version);
159
+ if (!detail) {
160
+ return `Error: extension history version not found: ${id}#${version}`;
161
+ }
162
+ return { ok: true, ...detail };
163
+ },
164
+ readOnly: true,
165
+ },
94
166
  "create-extension": {
95
167
  tool: {
96
- description: "Create a sandboxed Alpine.js mini-app extension. Use this when the user asks to create, build, or make an extension/widget/dashboard/calculator. Call this action exactly once per requested extension. The content must be a self-contained Alpine.js HTML body snippet that can use appAction(), appFetch(), dbQuery(), dbExec(), extensionFetch(), and extensionData. Prefer appAction(name, params) for app data and actions, including read actions mounted as GET; do not call template /api/* routes from appFetch because the extension bridge only allows framework /_agent-native/* paths. Parse JSON string action results before aggregating; use dbQuery()/dbExec() only for known existing SQL tables. For any non-trivial component (more than a couple of state fields, any methods, any string formatting, any branching) put the component in a <script> block via Alpine.data('name', () => ({...})) and reference it with x-data=\"name\" — do NOT cram methods, template literals, or branching logic into an inline x-data=\"{...}\" attribute (HTML parser pitfalls cause ReferenceError failures). Define every variable referenced from x-text/x-show/x-if/x-for on the data object's initial state. If the extension's value depends on an LLM call, require a real key via ${keys.OPENAI_API_KEY}/${keys.ANTHROPIC_API_KEY} (and tell the user to add it in Settings → Secrets if missing) or route the AI work to the agent chat — never ship a stubbed analysis step that renders a placeholder/boolean as the result.",
168
+ description: "Create a sandboxed Alpine.js mini-app extension. Use this when the user asks to create, build, or make an extension/widget/dashboard/calculator. Call this action exactly once per requested extension. The content must be a self-contained Alpine.js HTML body snippet that can use appAction(), appFetch(), dbQuery(), dbExec(), extensionFetch(), and extensionData. Prefer appAction(name, params) for app data and actions, including read actions mounted as GET; do not call template /api/* routes from appFetch because the extension bridge only allows framework /_agent-native/* paths. Parse JSON string action results before aggregating; use dbQuery()/dbExec() only for known existing SQL tables. Keep the initial create-extension payload compact and working; for complex extensions, create a useful v1 first, then use focused update-extension edits for refinements rather than assembling one enormous tool input. For any non-trivial component (more than a couple of state fields, any methods, any string formatting, any branching) put the component in a <script> block via Alpine.data('name', () => ({...})) and reference it with x-data=\"name\" — do NOT cram methods, template literals, or branching logic into an inline x-data=\"{...}\" attribute (HTML parser pitfalls cause ReferenceError failures). Define every variable referenced from x-text/x-show/x-if/x-for on the data object's initial state. If the extension's value depends on an LLM call, require a real key via \\${keys.OPENAI_API_KEY}/\\${keys.ANTHROPIC_API_KEY} (and tell the user to add it in Settings → Secrets if missing) or route the AI work to the agent chat — never ship a stubbed analysis step that renders a placeholder/boolean as the result.",
97
169
  parameters: {
98
170
  type: "object",
99
171
  properties: {
@@ -288,6 +360,44 @@ export function createExtensionActionEntries() {
288
360
  }
289
361
  },
290
362
  },
363
+ "restore-extension-history-version": {
364
+ tool: {
365
+ description: "Restore an extension's name, description, icon, and HTML content from a saved history version. Requires editor access. This does not restore sharing visibility or ownership.",
366
+ parameters: {
367
+ type: "object",
368
+ properties: {
369
+ id: {
370
+ type: "string",
371
+ description: "Extension id to restore.",
372
+ },
373
+ version: {
374
+ type: "number",
375
+ description: "Saved history version number to restore. Use list-extension-history first if unsure.",
376
+ },
377
+ },
378
+ required: ["id", "version"],
379
+ },
380
+ },
381
+ run: async (args) => {
382
+ const id = String(args?.id ?? "").trim();
383
+ if (!id)
384
+ return "Error: id is required.";
385
+ const version = Number(args?.version);
386
+ if (!Number.isInteger(version) || version < 1) {
387
+ return "Error: version must be a positive integer.";
388
+ }
389
+ const result = await restoreExtensionHistoryVersion(id, version);
390
+ if (!result) {
391
+ return `Error: extension history version not found: ${id}#${version}`;
392
+ }
393
+ const hiddenIds = await getHiddenExtensionIdsForCurrentUser();
394
+ return {
395
+ ok: true,
396
+ restoredVersion: version,
397
+ extension: await summarizeExtension(result, hiddenIds, false),
398
+ };
399
+ },
400
+ },
291
401
  "hide-extension": {
292
402
  tool: {
293
403
  description: "Hide an accessible extension from the current user's Extensions list/sidebar without deleting it for anyone else. Use this when the user says to remove a shared extension from their view, or when delete-extension reports that the current user is not owner/admin.",
@@ -1 +1 @@
1
- {"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/extensions/actions.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ActionEntry } from \"../agent/production-agent.js\";\nimport { writeAppState } from \"../application-state/script-helpers.js\";\nimport {\n createExtension,\n deleteExtension,\n getHiddenExtensionIdsForCurrentUser,\n getExtension,\n hideExtension,\n listExtensions,\n unhideExtension,\n updateExtension,\n updateExtensionContent,\n type ExtensionRow,\n} from \"./store.js\";\nimport { resolveAccess } from \"../sharing/access.js\";\nimport {\n addExtensionSlotTarget,\n installExtensionSlot,\n uninstallExtensionSlot,\n listExtensionsForSlot,\n listSlotsForExtension,\n} from \"./slots/store.js\";\nimport { extensionPath } from \"./path.js\";\nimport type {\n ExtensionContentEdit,\n ExtensionLegacyPatch,\n} from \"./content-patch.js\";\n\nexport function createExtensionActionEntries(): Record<string, ActionEntry> {\n return {\n \"list-extensions\": {\n tool: {\n description:\n \"List extensions visible in the current user's Extensions list/sidebar. Use this for browsing or when you only know a display name. If <current-screen> or <current-url> already contains extensionId for the current extension, use get-extension or update-extension with that id directly instead of listing. Do not query the legacy tools table directly for extension management.\",\n parameters: {\n type: \"object\",\n properties: {\n search: {\n type: \"string\",\n description:\n \"Optional case-insensitive filter matched against id, name, description, and owner email. Example: Connect Zoom.\",\n },\n includeHidden: {\n type: \"boolean\",\n description:\n \"Include extensions the current user has hidden from their list. Defaults to false.\",\n },\n includeContent: {\n type: \"boolean\",\n description:\n \"Include full Alpine.js content. Defaults to false to keep results concise.\",\n },\n limit: {\n type: \"number\",\n description: \"Maximum results to return. Defaults to 100.\",\n },\n },\n },\n },\n run: async (args) => {\n const includeHidden = coerceBoolean(args?.includeHidden);\n const includeContent = coerceBoolean(args?.includeContent);\n const search = String(args?.search ?? \"\")\n .trim()\n .toLowerCase();\n const limit = coerceLimit(args?.limit);\n const hiddenIds = await getHiddenExtensionIdsForCurrentUser();\n\n let rows = await listExtensions({ includeHidden });\n if (search) {\n rows = rows.filter((row) =>\n [row.id, row.name, row.description, row.ownerEmail]\n .join(\"\\n\")\n .toLowerCase()\n .includes(search),\n );\n }\n\n rows = rows.slice(0, limit);\n const extensions = await Promise.all(\n rows.map((row) => summarizeExtension(row, hiddenIds, includeContent)),\n );\n return {\n ok: true,\n count: extensions.length,\n extensions,\n };\n },\n readOnly: true,\n },\n\n \"get-extension\": {\n tool: {\n description:\n \"Get one existing extension by id. Use this when <current-screen> or <current-url> contains extensionId for the current extension; do not call list-extensions just to rediscover that id. Defaults to including the full Alpine.js content so you can make a targeted update-extension edit.\",\n parameters: {\n type: \"object\",\n properties: {\n id: {\n type: \"string\",\n description:\n \"Extension id to read. Prefer the extensionId from <current-screen> or <current-url> when the user refers to the current extension.\",\n },\n includeContent: {\n type: \"boolean\",\n description:\n \"Include full Alpine.js content. Defaults to true for targeted edits.\",\n },\n },\n required: [\"id\"],\n },\n },\n run: async (args) => {\n const id = String(args?.id ?? \"\").trim();\n if (!id) return \"Error: id is required.\";\n const includeContent =\n args?.includeContent === undefined\n ? true\n : coerceBoolean(args.includeContent);\n const extension = await getExtension(id);\n if (!extension) return `Error: extension not found: ${id}`;\n const hiddenIds = await getHiddenExtensionIdsForCurrentUser();\n return {\n ok: true,\n extension: await summarizeExtension(\n extension,\n hiddenIds,\n includeContent,\n ),\n };\n },\n readOnly: true,\n },\n\n \"create-extension\": {\n tool: {\n description:\n \"Create a sandboxed Alpine.js mini-app extension. Use this when the user asks to create, build, or make an extension/widget/dashboard/calculator. Call this action exactly once per requested extension. The content must be a self-contained Alpine.js HTML body snippet that can use appAction(), appFetch(), dbQuery(), dbExec(), extensionFetch(), and extensionData. Prefer appAction(name, params) for app data and actions, including read actions mounted as GET; do not call template /api/* routes from appFetch because the extension bridge only allows framework /_agent-native/* paths. Parse JSON string action results before aggregating; use dbQuery()/dbExec() only for known existing SQL tables. For any non-trivial component (more than a couple of state fields, any methods, any string formatting, any branching) put the component in a <script> block via Alpine.data('name', () => ({...})) and reference it with x-data=\\\"name\\\" — do NOT cram methods, template literals, or branching logic into an inline x-data=\\\"{...}\\\" attribute (HTML parser pitfalls cause ReferenceError failures). Define every variable referenced from x-text/x-show/x-if/x-for on the data object's initial state. If the extension's value depends on an LLM call, require a real key via ${keys.OPENAI_API_KEY}/${keys.ANTHROPIC_API_KEY} (and tell the user to add it in Settings → Secrets if missing) or route the AI work to the agent chat — never ship a stubbed analysis step that renders a placeholder/boolean as the result.\",\n parameters: {\n type: \"object\",\n properties: {\n name: {\n type: \"string\",\n description:\n 'Short display name for the extension. Do not include \"app\" — e.g. name a todo app \"Todos\", a weather app \"Weather\".',\n },\n description: {\n type: \"string\",\n description: \"One-sentence summary of what the extension does.\",\n },\n content: {\n type: \"string\",\n description:\n \"Self-contained Alpine.js HTML body snippet. The iframe canvas already has modest default padding, so avoid duplicate outer padding unless the design needs it. Use semantic Tailwind colors (bg-background, text-foreground, bg-primary, etc.) for native theming. Do not include a full app build, React code, or source files.\",\n },\n icon: {\n type: \"string\",\n description: \"Optional icon name or short label.\",\n },\n },\n required: [\"name\", \"content\"],\n },\n },\n run: async (args) => {\n const name = String(args?.name ?? \"\").trim();\n const content = String(args?.content ?? \"\").trim();\n if (!name) return \"Error: name is required.\";\n if (!content) return \"Error: content is required.\";\n\n const extension = await createExtension({\n name,\n description: String(args?.description ?? \"\").trim(),\n content,\n icon: args?.icon ? String(args.icon) : undefined,\n });\n const path = extensionPath(extension.id, extension.name);\n\n // Auto-navigate so the user lands on the new extension instead of\n // having to read the JSON response and click a link. Writes a\n // one-shot `navigate` app-state command the UI consumes and clears.\n try {\n await writeAppState(\"navigate\", {\n view: \"extensions\",\n extensionId: extension.id,\n path,\n // Unique-per-write token so the UI's `use-navigation-state` hook\n // can dedup race-driven re-reads of the same command.\n _writeId: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n });\n } catch {\n // Non-fatal — agent can still mention the path in its reply.\n }\n\n return {\n ok: true,\n extension: { ...extension, path },\n path,\n next: `Created. The user is being navigated to the new extension automatically — no further navigation tool calls needed.`,\n };\n },\n },\n\n \"update-extension\": {\n tool: {\n description:\n \"Update an existing sandboxed Alpine.js mini-app extension. If the user is viewing the extension, use the extensionId from <current-screen> or <current-url> directly; do not list extensions first just to find the current id. Prefer granular edits for surgical changes; use full content replacement only for broad rewrites. Supported edits include literal replace, insert-before/after marker, replace-between markers, replace-section/wrap-section/remove-section for <!-- agent-native:section name --> blocks, and regex-replace. Pass format=true to run Prettier on the final HTML.\",\n parameters: {\n type: \"object\",\n properties: {\n id: {\n type: \"string\",\n description:\n \"Extension id to update. Prefer the extensionId from <current-screen> or <current-url> for the current extension.\",\n },\n name: {\n type: \"string\",\n description: \"Optional new display name.\",\n },\n description: {\n type: \"string\",\n description: \"Optional new description.\",\n },\n content: {\n type: \"string\",\n description:\n \"Optional full replacement Alpine.js HTML body snippet.\",\n },\n patches: {\n type: \"string\",\n description:\n 'Legacy optional JSON array of { \"find\": \"...\", \"replace\": \"...\", \"all\"?: true, \"expectedMatches\"?: 1, \"required\"?: true } patches. Missing required targets fail instead of silently no-oping.',\n },\n edits: {\n type: \"string\",\n description:\n 'Preferred optional JSON array of granular edit operations. Examples: { \"op\": \"insert-after\", \"marker\": \"<!-- section:metrics -->\", \"content\": \"...\" }, { \"op\": \"replace-section\", \"section\": \"npm-chart\", \"content\": \"...\" }, { \"op\": \"wrap-section\", \"section\": \"charts\", \"before\": \"<div>\", \"after\": \"</div>\" }, { \"op\": \"regex-replace\", \"pattern\": \"...\", \"replace\": \"...\", \"expectedMatches\": 1 }.',\n },\n format: {\n type: \"boolean\",\n description:\n \"When true, format the final extension HTML with Prettier after applying content, patches, and edits.\",\n },\n icon: {\n type: \"string\",\n description: \"Optional icon name or short label.\",\n },\n visibility: {\n type: \"string\",\n description: \"Optional sharing visibility.\",\n enum: [\"private\", \"org\", \"public\"],\n },\n },\n required: [\"id\"],\n },\n },\n run: async (args) => {\n const id = String(args?.id ?? \"\").trim();\n if (!id) return \"Error: id is required.\";\n\n let result = null;\n const hasContentUpdate =\n args?.content !== undefined ||\n args?.patches !== undefined ||\n args?.edits !== undefined ||\n args?.format !== undefined;\n if (hasContentUpdate) {\n const patches = parsePatches((args as any).patches);\n if (args?.patches !== undefined && !patches) {\n return \"Error: patches must be a JSON array of { find, replace } objects.\";\n }\n const edits = parseEdits((args as any).edits);\n if (args?.edits !== undefined && !edits) {\n return \"Error: edits must be a JSON array of supported extension edit operations.\";\n }\n result = await updateExtensionContent(id, {\n content:\n args?.content !== undefined ? String(args.content) : undefined,\n patches,\n edits,\n format: coerceBoolean(args?.format),\n });\n }\n\n const meta: Record<string, string> = {};\n if (args?.name !== undefined) meta.name = String(args.name).trim();\n if (args?.description !== undefined) {\n meta.description = String(args.description).trim();\n }\n if (args?.icon !== undefined) meta.icon = String(args.icon);\n if (args?.visibility !== undefined) {\n meta.visibility = String(args.visibility);\n }\n if (Object.keys(meta).length > 0) {\n result = await updateExtension(id, meta as any);\n }\n\n if (!result) result = await getExtension(id);\n if (!result) return `Error: extension not found: ${id}`;\n const hiddenIds = await getHiddenExtensionIdsForCurrentUser();\n return {\n ok: true,\n extension: await summarizeExtension(result, hiddenIds, false),\n };\n },\n },\n\n \"delete-extension\": {\n tool: {\n description:\n \"Permanently delete an extension everywhere it is shared. Requires owner/admin access. If the user only wants a shared extension removed from their own sidebar/list, use hide-extension instead.\",\n parameters: {\n type: \"object\",\n properties: {\n id: {\n type: \"string\",\n description:\n \"Extension id to permanently delete. Use list-extensions first if you only know the display name.\",\n },\n },\n required: [\"id\"],\n },\n },\n run: async (args) => {\n const id = String(args?.id ?? \"\").trim();\n if (!id) return \"Error: id is required.\";\n const extension = await getExtension(id);\n if (!extension) return `Error: extension not found: ${id}`;\n\n try {\n const ok = await deleteExtension(id);\n if (!ok) return `Error: extension not found: ${id}`;\n return { ok: true, deleted: summarizeDeletedExtension(extension) };\n } catch (err: any) {\n return {\n ok: false,\n error: err?.message ?? String(err),\n next: \"If the user wants this gone only from their own view, call hide-extension with the same id.\",\n };\n }\n },\n },\n\n \"hide-extension\": {\n tool: {\n description:\n \"Hide an accessible extension from the current user's Extensions list/sidebar without deleting it for anyone else. Use this when the user says to remove a shared extension from their view, or when delete-extension reports that the current user is not owner/admin.\",\n parameters: {\n type: \"object\",\n properties: {\n id: {\n type: \"string\",\n description:\n \"Extension id to hide for the current user. Use list-extensions first if you only know the display name.\",\n },\n },\n required: [\"id\"],\n },\n },\n run: async (args) => {\n const id = String(args?.id ?? \"\").trim();\n if (!id) return \"Error: id is required.\";\n const extension = await getExtension(id);\n if (!extension) return `Error: extension not found: ${id}`;\n\n await hideExtension(id);\n return { ok: true, hidden: summarizeDeletedExtension(extension) };\n },\n },\n\n \"unhide-extension\": {\n tool: {\n description:\n \"Restore an extension the current user previously hid so it appears in their Extensions list/sidebar again. Use list-extensions with includeHidden=true to find hidden ids.\",\n parameters: {\n type: \"object\",\n properties: {\n id: {\n type: \"string\",\n description: \"Extension id to restore for the current user.\",\n },\n },\n required: [\"id\"],\n },\n },\n run: async (args) => {\n const id = String(args?.id ?? \"\").trim();\n if (!id) return \"Error: id is required.\";\n await unhideExtension(id);\n return { ok: true, id };\n },\n },\n\n \"add-extension-slot-target\": {\n tool: {\n description:\n 'Declare that an extension can render in a UI extension-point slot of an app (e.g. \"mail.contact-sidebar.bottom\"). Apps drop ExtensionSlot components in their UI; this action registers an extension as installable into one of those slots. Slot IDs follow the convention <app>.<area>.<position>. Caller must have editor access to the extension.',\n parameters: {\n type: \"object\",\n properties: {\n extensionId: { type: \"string\", description: \"Extension id.\" },\n slotId: {\n type: \"string\",\n description:\n 'Slot identifier — e.g. \"mail.contact-sidebar.bottom\".',\n },\n config: {\n type: \"string\",\n description:\n \"Optional JSON string with slot-specific config (defaults, hints, etc.).\",\n },\n },\n required: [\"extensionId\", \"slotId\"],\n },\n },\n run: async (args) => {\n const extensionId = String(args?.extensionId ?? \"\").trim();\n const slotId = String(args?.slotId ?? \"\").trim();\n if (!extensionId) return \"Error: extensionId is required.\";\n if (!slotId) return \"Error: slotId is required.\";\n const row = await addExtensionSlotTarget(\n extensionId,\n slotId,\n args?.config ? String(args.config) : undefined,\n );\n return { ok: true, slot: row };\n },\n },\n\n \"install-extension\": {\n tool: {\n description:\n \"Install an extension as a widget in an extension-point slot for the current user. The extension must already declare the slot via add-extension-slot-target. Per-user installation — only affects the calling user's view. Use after creating an extension that targets a slot, or when the user asks to add an existing widget to a slot.\",\n parameters: {\n type: \"object\",\n properties: {\n extensionId: {\n type: \"string\",\n description: \"Extension id to install.\",\n },\n slotId: {\n type: \"string\",\n description:\n 'Slot identifier — e.g. \"mail.contact-sidebar.bottom\".',\n },\n position: {\n type: \"number\",\n description:\n \"Optional integer position within the slot (lower = earlier). Defaults to end.\",\n },\n config: {\n type: \"string\",\n description:\n \"Optional JSON string with per-install config (overrides, settings).\",\n },\n },\n required: [\"extensionId\", \"slotId\"],\n },\n },\n run: async (args) => {\n const extensionId = String(args?.extensionId ?? \"\").trim();\n const slotId = String(args?.slotId ?? \"\").trim();\n if (!extensionId) return \"Error: extensionId is required.\";\n if (!slotId) return \"Error: slotId is required.\";\n const position =\n args?.position !== undefined && args.position !== null\n ? Number(args.position)\n : undefined;\n const row = await installExtensionSlot(extensionId, slotId, {\n position: Number.isFinite(position as number) ? position : undefined,\n config: args?.config ? String(args.config) : undefined,\n });\n return { ok: true, install: row };\n },\n },\n\n \"uninstall-extension\": {\n tool: {\n description:\n \"Remove an extension from an extension-point slot for the current user. Does not delete the extension itself.\",\n parameters: {\n type: \"object\",\n properties: {\n extensionId: { type: \"string\", description: \"Extension id.\" },\n slotId: { type: \"string\", description: \"Slot identifier.\" },\n },\n required: [\"extensionId\", \"slotId\"],\n },\n },\n run: async (args) => {\n const extensionId = String(args?.extensionId ?? \"\").trim();\n const slotId = String(args?.slotId ?? \"\").trim();\n if (!extensionId) return \"Error: extensionId is required.\";\n if (!slotId) return \"Error: slotId is required.\";\n await uninstallExtensionSlot(extensionId, slotId);\n return { ok: true };\n },\n },\n\n \"list-extensions-for-slot\": {\n tool: {\n description:\n \"List extensions the current user has access to that declare a given extension-point slot. Use to discover what's available to install into a slot the user mentioned.\",\n parameters: {\n type: \"object\",\n properties: {\n slotId: { type: \"string\", description: \"Slot identifier.\" },\n },\n required: [\"slotId\"],\n },\n },\n run: async (args) => {\n const slotId = String(args?.slotId ?? \"\").trim();\n if (!slotId) return \"Error: slotId is required.\";\n return { extensions: await listExtensionsForSlot(slotId) };\n },\n readOnly: true,\n },\n\n \"list-extension-slots\": {\n tool: {\n description:\n \"List the extension-point slots a specific extension declares it can render in. Caller must have viewer access to the extension.\",\n parameters: {\n type: \"object\",\n properties: {\n extensionId: { type: \"string\", description: \"Extension id.\" },\n },\n required: [\"extensionId\"],\n },\n },\n run: async (args) => {\n const extensionId = String(args?.extensionId ?? \"\").trim();\n if (!extensionId) return \"Error: extensionId is required.\";\n return { slots: await listSlotsForExtension(extensionId) };\n },\n readOnly: true,\n },\n };\n}\n\nasync function summarizeExtension(\n row: ExtensionRow,\n hiddenIds: Set<string>,\n includeContent: boolean,\n) {\n const access = await resolveAccess(\"extension\", row.id).catch(() => null);\n return {\n id: row.id,\n name: row.name,\n path: extensionPath(row.id, row.name),\n description: row.description,\n icon: row.icon,\n ownerEmail: row.ownerEmail,\n visibility: row.visibility,\n role: access?.role ?? null,\n canEdit: access\n ? [\"owner\", \"admin\", \"editor\"].includes(access.role)\n : false,\n canDelete: access ? [\"owner\", \"admin\"].includes(access.role) : false,\n hidden: hiddenIds.has(row.id),\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n ...(includeContent ? { content: row.content } : {}),\n };\n}\n\nfunction summarizeDeletedExtension(row: ExtensionRow) {\n return {\n id: row.id,\n name: row.name,\n ownerEmail: row.ownerEmail,\n visibility: row.visibility,\n };\n}\n\nfunction coerceBoolean(value: unknown): boolean {\n return value === true || value === \"true\";\n}\n\nfunction coerceLimit(value: unknown): number {\n const limit = Number(value ?? 100);\n if (!Number.isFinite(limit)) return 100;\n return Math.min(Math.max(1, Math.floor(limit)), 500);\n}\n\nfunction parsePatches(value: unknown): ExtensionLegacyPatch[] | undefined {\n if (value === undefined) return undefined;\n const parsed = typeof value === \"string\" ? JSON.parse(value) : value;\n if (!Array.isArray(parsed)) return undefined;\n if (\n parsed.some(\n (patch) =>\n !patch ||\n typeof patch.find !== \"string\" ||\n typeof patch.replace !== \"string\",\n )\n ) {\n return undefined;\n }\n return parsed;\n}\n\nfunction parseEdits(value: unknown): ExtensionContentEdit[] | undefined {\n if (value === undefined) return undefined;\n const parsed = typeof value === \"string\" ? JSON.parse(value) : value;\n if (!Array.isArray(parsed)) return undefined;\n return parsed.every(isValidContentEdit)\n ? (parsed as ExtensionContentEdit[])\n : undefined;\n}\n\nfunction isValidContentEdit(value: unknown): boolean {\n if (!value || typeof value !== \"object\") return false;\n const edit = value as Record<string, unknown>;\n const op = edit.op ?? \"replace\";\n if (typeof op !== \"string\") return false;\n\n switch (op) {\n case \"replace\":\n return typeof edit.find === \"string\" && typeof edit.replace === \"string\";\n case \"insert-before\":\n case \"insert-after\":\n return (\n typeof edit.marker === \"string\" && typeof edit.content === \"string\"\n );\n case \"replace-between\":\n return (\n typeof edit.start === \"string\" &&\n typeof edit.end === \"string\" &&\n typeof edit.content === \"string\"\n );\n case \"replace-section\":\n return (\n typeof edit.section === \"string\" && typeof edit.content === \"string\"\n );\n case \"wrap-section\":\n return (\n typeof edit.section === \"string\" &&\n typeof edit.before === \"string\" &&\n typeof edit.after === \"string\"\n );\n case \"remove-section\":\n return typeof edit.section === \"string\";\n case \"regex-replace\":\n return (\n typeof edit.pattern === \"string\" && typeof edit.replace === \"string\"\n );\n default:\n return false;\n }\n}\n"]}
1
+ {"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/extensions/actions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AACvE,OAAO,EACL,eAAe,EACf,eAAe,EACf,mCAAmC,EACnC,YAAY,EACZ,0BAA0B,EAC1B,aAAa,EACb,oBAAoB,EACpB,cAAc,EACd,8BAA8B,EAC9B,eAAe,EACf,eAAe,EACf,sBAAsB,GAEvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAM1C,MAAM,UAAU,4BAA4B;IAC1C,OAAO;QACL,iBAAiB,EAAE;YACjB,IAAI,EAAE;gBACJ,WAAW,EACT,wXAAwX;gBAC1X,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,MAAM,EAAE;4BACN,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,iHAAiH;yBACpH;wBACD,aAAa,EAAE;4BACb,IAAI,EAAE,SAAS;4BACf,WAAW,EACT,oFAAoF;yBACvF;wBACD,cAAc,EAAE;4BACd,IAAI,EAAE,SAAS;4BACf,WAAW,EACT,4EAA4E;yBAC/E;wBACD,KAAK,EAAE;4BACL,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,6CAA6C;yBAC3D;qBACF;iBACF;aACF;YACD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAClB,MAAM,aAAa,GAAG,aAAa,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;gBACzD,MAAM,cAAc,GAAG,aAAa,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;gBAC3D,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,CAAC;qBACtC,IAAI,EAAE;qBACN,WAAW,EAAE,CAAC;gBACjB,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBACvC,MAAM,SAAS,GAAG,MAAM,mCAAmC,EAAE,CAAC;gBAE9D,IAAI,IAAI,GAAG,MAAM,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC;gBACnD,IAAI,MAAM,EAAE,CAAC;oBACX,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CACzB,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,UAAU,CAAC;yBAChD,IAAI,CAAC,IAAI,CAAC;yBACV,WAAW,EAAE;yBACb,QAAQ,CAAC,MAAM,CAAC,CACpB,CAAC;gBACJ,CAAC;gBAED,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;gBAC5B,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,GAAG,CAClC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,kBAAkB,CAAC,GAAG,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC,CACtE,CAAC;gBACF,OAAO;oBACL,EAAE,EAAE,IAAI;oBACR,KAAK,EAAE,UAAU,CAAC,MAAM;oBACxB,UAAU;iBACX,CAAC;YACJ,CAAC;YACD,QAAQ,EAAE,IAAI;SACf;QAED,eAAe,EAAE;YACf,IAAI,EAAE;gBACJ,WAAW,EACT,8RAA8R;gBAChS,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,EAAE,EAAE;4BACF,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,oIAAoI;yBACvI;wBACD,cAAc,EAAE;4BACd,IAAI,EAAE,SAAS;4BACf,WAAW,EACT,sEAAsE;yBACzE;qBACF;oBACD,QAAQ,EAAE,CAAC,IAAI,CAAC;iBACjB;aACF;YACD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAClB,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACzC,IAAI,CAAC,EAAE;oBAAE,OAAO,wBAAwB,CAAC;gBACzC,MAAM,cAAc,GAClB,IAAI,EAAE,cAAc,KAAK,SAAS;oBAChC,CAAC,CAAC,IAAI;oBACN,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;gBACzC,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,EAAE,CAAC,CAAC;gBACzC,IAAI,CAAC,SAAS;oBAAE,OAAO,+BAA+B,EAAE,EAAE,CAAC;gBAC3D,MAAM,SAAS,GAAG,MAAM,mCAAmC,EAAE,CAAC;gBAC9D,OAAO;oBACL,EAAE,EAAE,IAAI;oBACR,SAAS,EAAE,MAAM,kBAAkB,CACjC,SAAS,EACT,SAAS,EACT,cAAc,CACf;iBACF,CAAC;YACJ,CAAC;YACD,QAAQ,EAAE,IAAI;SACf;QAED,wBAAwB,EAAE;YACxB,IAAI,EAAE;gBACJ,WAAW,EACT,8PAA8P;gBAChQ,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,EAAE,EAAE;4BACF,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,8CAA8C;yBAC5D;wBACD,KAAK,EAAE;4BACL,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,6CAA6C;yBAC3D;wBACD,cAAc,EAAE;4BACd,IAAI,EAAE,SAAS;4BACf,WAAW,EACT,gEAAgE;yBACnE;qBACF;oBACD,QAAQ,EAAE,CAAC,IAAI,CAAC;iBACjB;aACF;YACD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAClB,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACzC,IAAI,CAAC,EAAE;oBAAE,OAAO,wBAAwB,CAAC;gBACzC,MAAM,OAAO,GAAG,MAAM,oBAAoB,CAAC,EAAE,EAAE;oBAC7C,KAAK,EACH,IAAI,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC;oBACjE,cAAc,EAAE,aAAa,CAAC,IAAI,EAAE,cAAc,CAAC;iBACpD,CAAC,CAAC;gBACH,OAAO;oBACL,EAAE,EAAE,IAAI;oBACR,KAAK,EAAE,OAAO,CAAC,MAAM;oBACrB,OAAO;iBACR,CAAC;YACJ,CAAC;YACD,QAAQ,EAAE,IAAI;SACf;QAED,+BAA+B,EAAE;YAC/B,IAAI,EAAE;gBACJ,WAAW,EACT,yJAAyJ;gBAC3J,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,EAAE,EAAE;4BACF,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,oDAAoD;yBAClE;wBACD,OAAO,EAAE;4BACP,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,oCAAoC;yBAClD;qBACF;oBACD,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC;iBAC5B;aACF;YACD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAClB,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACzC,IAAI,CAAC,EAAE;oBAAE,OAAO,wBAAwB,CAAC;gBACzC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;gBACtC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;oBAC9C,OAAO,4CAA4C,CAAC;gBACtD,CAAC;gBACD,MAAM,MAAM,GAAG,MAAM,0BAA0B,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;gBAC7D,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,OAAO,+CAA+C,EAAE,IAAI,OAAO,EAAE,CAAC;gBACxE,CAAC;gBACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC;YACjC,CAAC;YACD,QAAQ,EAAE,IAAI;SACf;QAED,kBAAkB,EAAE;YAClB,IAAI,EAAE;gBACJ,WAAW,EACT,krDAAkrD;gBACprD,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,IAAI,EAAE;4BACJ,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,qHAAqH;yBACxH;wBACD,WAAW,EAAE;4BACX,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,kDAAkD;yBAChE;wBACD,OAAO,EAAE;4BACP,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,kUAAkU;yBACrU;wBACD,IAAI,EAAE;4BACJ,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,oCAAoC;yBAClD;qBACF;oBACD,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC;iBAC9B;aACF;YACD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAClB,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC7C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACnD,IAAI,CAAC,IAAI;oBAAE,OAAO,0BAA0B,CAAC;gBAC7C,IAAI,CAAC,OAAO;oBAAE,OAAO,6BAA6B,CAAC;gBAEnD,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC;oBACtC,IAAI;oBACJ,WAAW,EAAE,MAAM,CAAC,IAAI,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;oBACnD,OAAO;oBACP,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;iBACjD,CAAC,CAAC;gBACH,MAAM,IAAI,GAAG,aAAa,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;gBAEzD,kEAAkE;gBAClE,8DAA8D;gBAC9D,oEAAoE;gBACpE,IAAI,CAAC;oBACH,MAAM,aAAa,CAAC,UAAU,EAAE;wBAC9B,IAAI,EAAE,YAAY;wBAClB,WAAW,EAAE,SAAS,CAAC,EAAE;wBACzB,IAAI;wBACJ,iEAAiE;wBACjE,sDAAsD;wBACtD,QAAQ,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;qBACpE,CAAC,CAAC;gBACL,CAAC;gBAAC,MAAM,CAAC;oBACP,6DAA6D;gBAC/D,CAAC;gBAED,OAAO;oBACL,EAAE,EAAE,IAAI;oBACR,SAAS,EAAE,EAAE,GAAG,SAAS,EAAE,IAAI,EAAE;oBACjC,IAAI;oBACJ,IAAI,EAAE,oHAAoH;iBAC3H,CAAC;YACJ,CAAC;SACF;QAED,kBAAkB,EAAE;YAClB,IAAI,EAAE;gBACJ,WAAW,EACT,mkBAAmkB;gBACrkB,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,EAAE,EAAE;4BACF,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,kHAAkH;yBACrH;wBACD,IAAI,EAAE;4BACJ,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,4BAA4B;yBAC1C;wBACD,WAAW,EAAE;4BACX,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,2BAA2B;yBACzC;wBACD,OAAO,EAAE;4BACP,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,wDAAwD;yBAC3D;wBACD,OAAO,EAAE;4BACP,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,gMAAgM;yBACnM;wBACD,KAAK,EAAE;4BACL,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,yYAAyY;yBAC5Y;wBACD,MAAM,EAAE;4BACN,IAAI,EAAE,SAAS;4BACf,WAAW,EACT,sGAAsG;yBACzG;wBACD,IAAI,EAAE;4BACJ,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,oCAAoC;yBAClD;wBACD,UAAU,EAAE;4BACV,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,8BAA8B;4BAC3C,IAAI,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,CAAC;yBACnC;qBACF;oBACD,QAAQ,EAAE,CAAC,IAAI,CAAC;iBACjB;aACF;YACD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAClB,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACzC,IAAI,CAAC,EAAE;oBAAE,OAAO,wBAAwB,CAAC;gBAEzC,IAAI,MAAM,GAAG,IAAI,CAAC;gBAClB,MAAM,gBAAgB,GACpB,IAAI,EAAE,OAAO,KAAK,SAAS;oBAC3B,IAAI,EAAE,OAAO,KAAK,SAAS;oBAC3B,IAAI,EAAE,KAAK,KAAK,SAAS;oBACzB,IAAI,EAAE,MAAM,KAAK,SAAS,CAAC;gBAC7B,IAAI,gBAAgB,EAAE,CAAC;oBACrB,MAAM,OAAO,GAAG,YAAY,CAAE,IAAY,CAAC,OAAO,CAAC,CAAC;oBACpD,IAAI,IAAI,EAAE,OAAO,KAAK,SAAS,IAAI,CAAC,OAAO,EAAE,CAAC;wBAC5C,OAAO,mEAAmE,CAAC;oBAC7E,CAAC;oBACD,MAAM,KAAK,GAAG,UAAU,CAAE,IAAY,CAAC,KAAK,CAAC,CAAC;oBAC9C,IAAI,IAAI,EAAE,KAAK,KAAK,SAAS,IAAI,CAAC,KAAK,EAAE,CAAC;wBACxC,OAAO,2EAA2E,CAAC;oBACrF,CAAC;oBACD,MAAM,GAAG,MAAM,sBAAsB,CAAC,EAAE,EAAE;wBACxC,OAAO,EACL,IAAI,EAAE,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS;wBAChE,OAAO;wBACP,KAAK;wBACL,MAAM,EAAE,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC;qBACpC,CAAC,CAAC;gBACL,CAAC;gBAED,MAAM,IAAI,GAA2B,EAAE,CAAC;gBACxC,IAAI,IAAI,EAAE,IAAI,KAAK,SAAS;oBAAE,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;gBACnE,IAAI,IAAI,EAAE,WAAW,KAAK,SAAS,EAAE,CAAC;oBACpC,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC;gBACrD,CAAC;gBACD,IAAI,IAAI,EAAE,IAAI,KAAK,SAAS;oBAAE,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC5D,IAAI,IAAI,EAAE,UAAU,KAAK,SAAS,EAAE,CAAC;oBACnC,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAC5C,CAAC;gBACD,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACjC,MAAM,GAAG,MAAM,eAAe,CAAC,EAAE,EAAE,IAAW,CAAC,CAAC;gBAClD,CAAC;gBAED,IAAI,CAAC,MAAM;oBAAE,MAAM,GAAG,MAAM,YAAY,CAAC,EAAE,CAAC,CAAC;gBAC7C,IAAI,CAAC,MAAM;oBAAE,OAAO,+BAA+B,EAAE,EAAE,CAAC;gBACxD,MAAM,SAAS,GAAG,MAAM,mCAAmC,EAAE,CAAC;gBAC9D,OAAO;oBACL,EAAE,EAAE,IAAI;oBACR,SAAS,EAAE,MAAM,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC;iBAC9D,CAAC;YACJ,CAAC;SACF;QAED,kBAAkB,EAAE;YAClB,IAAI,EAAE;gBACJ,WAAW,EACT,kMAAkM;gBACpM,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,EAAE,EAAE;4BACF,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,kGAAkG;yBACrG;qBACF;oBACD,QAAQ,EAAE,CAAC,IAAI,CAAC;iBACjB;aACF;YACD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAClB,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACzC,IAAI,CAAC,EAAE;oBAAE,OAAO,wBAAwB,CAAC;gBACzC,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,EAAE,CAAC,CAAC;gBACzC,IAAI,CAAC,SAAS;oBAAE,OAAO,+BAA+B,EAAE,EAAE,CAAC;gBAE3D,IAAI,CAAC;oBACH,MAAM,EAAE,GAAG,MAAM,eAAe,CAAC,EAAE,CAAC,CAAC;oBACrC,IAAI,CAAC,EAAE;wBAAE,OAAO,+BAA+B,EAAE,EAAE,CAAC;oBACpD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,yBAAyB,CAAC,SAAS,CAAC,EAAE,CAAC;gBACrE,CAAC;gBAAC,OAAO,GAAQ,EAAE,CAAC;oBAClB,OAAO;wBACL,EAAE,EAAE,KAAK;wBACT,KAAK,EAAE,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC;wBAClC,IAAI,EAAE,6FAA6F;qBACpG,CAAC;gBACJ,CAAC;YACH,CAAC;SACF;QAED,mCAAmC,EAAE;YACnC,IAAI,EAAE;gBACJ,WAAW,EACT,+KAA+K;gBACjL,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,EAAE,EAAE;4BACF,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,0BAA0B;yBACxC;wBACD,OAAO,EAAE;4BACP,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,sFAAsF;yBACzF;qBACF;oBACD,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC;iBAC5B;aACF;YACD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAClB,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACzC,IAAI,CAAC,EAAE;oBAAE,OAAO,wBAAwB,CAAC;gBACzC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;gBACtC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;oBAC9C,OAAO,4CAA4C,CAAC;gBACtD,CAAC;gBACD,MAAM,MAAM,GAAG,MAAM,8BAA8B,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;gBACjE,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,OAAO,+CAA+C,EAAE,IAAI,OAAO,EAAE,CAAC;gBACxE,CAAC;gBACD,MAAM,SAAS,GAAG,MAAM,mCAAmC,EAAE,CAAC;gBAC9D,OAAO;oBACL,EAAE,EAAE,IAAI;oBACR,eAAe,EAAE,OAAO;oBACxB,SAAS,EAAE,MAAM,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC;iBAC9D,CAAC;YACJ,CAAC;SACF;QAED,gBAAgB,EAAE;YAChB,IAAI,EAAE;gBACJ,WAAW,EACT,wQAAwQ;gBAC1Q,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,EAAE,EAAE;4BACF,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,yGAAyG;yBAC5G;qBACF;oBACD,QAAQ,EAAE,CAAC,IAAI,CAAC;iBACjB;aACF;YACD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAClB,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACzC,IAAI,CAAC,EAAE;oBAAE,OAAO,wBAAwB,CAAC;gBACzC,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,EAAE,CAAC,CAAC;gBACzC,IAAI,CAAC,SAAS;oBAAE,OAAO,+BAA+B,EAAE,EAAE,CAAC;gBAE3D,MAAM,aAAa,CAAC,EAAE,CAAC,CAAC;gBACxB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,yBAAyB,CAAC,SAAS,CAAC,EAAE,CAAC;YACpE,CAAC;SACF;QAED,kBAAkB,EAAE;YAClB,IAAI,EAAE;gBACJ,WAAW,EACT,4KAA4K;gBAC9K,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,EAAE,EAAE;4BACF,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,+CAA+C;yBAC7D;qBACF;oBACD,QAAQ,EAAE,CAAC,IAAI,CAAC;iBACjB;aACF;YACD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAClB,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACzC,IAAI,CAAC,EAAE;oBAAE,OAAO,wBAAwB,CAAC;gBACzC,MAAM,eAAe,CAAC,EAAE,CAAC,CAAC;gBAC1B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;YAC1B,CAAC;SACF;QAED,2BAA2B,EAAE;YAC3B,IAAI,EAAE;gBACJ,WAAW,EACT,uVAAuV;gBACzV,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE;wBAC7D,MAAM,EAAE;4BACN,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,uDAAuD;yBAC1D;wBACD,MAAM,EAAE;4BACN,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,yEAAyE;yBAC5E;qBACF;oBACD,QAAQ,EAAE,CAAC,aAAa,EAAE,QAAQ,CAAC;iBACpC;aACF;YACD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAClB,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC3D,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACjD,IAAI,CAAC,WAAW;oBAAE,OAAO,iCAAiC,CAAC;gBAC3D,IAAI,CAAC,MAAM;oBAAE,OAAO,4BAA4B,CAAC;gBACjD,MAAM,GAAG,GAAG,MAAM,sBAAsB,CACtC,WAAW,EACX,MAAM,EACN,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAC/C,CAAC;gBACF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;YACjC,CAAC;SACF;QAED,mBAAmB,EAAE;YACnB,IAAI,EAAE;gBACJ,WAAW,EACT,4UAA4U;gBAC9U,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,WAAW,EAAE;4BACX,IAAI,EAAE,QAAQ;4BACd,WAAW,EAAE,0BAA0B;yBACxC;wBACD,MAAM,EAAE;4BACN,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,uDAAuD;yBAC1D;wBACD,QAAQ,EAAE;4BACR,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,+EAA+E;yBAClF;wBACD,MAAM,EAAE;4BACN,IAAI,EAAE,QAAQ;4BACd,WAAW,EACT,qEAAqE;yBACxE;qBACF;oBACD,QAAQ,EAAE,CAAC,aAAa,EAAE,QAAQ,CAAC;iBACpC;aACF;YACD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAClB,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC3D,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACjD,IAAI,CAAC,WAAW;oBAAE,OAAO,iCAAiC,CAAC;gBAC3D,IAAI,CAAC,MAAM;oBAAE,OAAO,4BAA4B,CAAC;gBACjD,MAAM,QAAQ,GACZ,IAAI,EAAE,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI;oBACpD,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;oBACvB,CAAC,CAAC,SAAS,CAAC;gBAChB,MAAM,GAAG,GAAG,MAAM,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE;oBAC1D,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAkB,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;oBACpE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;iBACvD,CAAC,CAAC;gBACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;YACpC,CAAC;SACF;QAED,qBAAqB,EAAE;YACrB,IAAI,EAAE;gBACJ,WAAW,EACT,8GAA8G;gBAChH,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE;wBAC7D,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kBAAkB,EAAE;qBAC5D;oBACD,QAAQ,EAAE,CAAC,aAAa,EAAE,QAAQ,CAAC;iBACpC;aACF;YACD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAClB,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC3D,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACjD,IAAI,CAAC,WAAW;oBAAE,OAAO,iCAAiC,CAAC;gBAC3D,IAAI,CAAC,MAAM;oBAAE,OAAO,4BAA4B,CAAC;gBACjD,MAAM,sBAAsB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;gBAClD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;YACtB,CAAC;SACF;QAED,0BAA0B,EAAE;YAC1B,IAAI,EAAE;gBACJ,WAAW,EACT,uKAAuK;gBACzK,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kBAAkB,EAAE;qBAC5D;oBACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;iBACrB;aACF;YACD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAClB,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACjD,IAAI,CAAC,MAAM;oBAAE,OAAO,4BAA4B,CAAC;gBACjD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7D,CAAC;YACD,QAAQ,EAAE,IAAI;SACf;QAED,sBAAsB,EAAE;YACtB,IAAI,EAAE;gBACJ,WAAW,EACT,iIAAiI;gBACnI,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE;qBAC9D;oBACD,QAAQ,EAAE,CAAC,aAAa,CAAC;iBAC1B;aACF;YACD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAClB,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC3D,IAAI,CAAC,WAAW;oBAAE,OAAO,iCAAiC,CAAC;gBAC3D,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC,WAAW,CAAC,EAAE,CAAC;YAC7D,CAAC;YACD,QAAQ,EAAE,IAAI;SACf;KACF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,kBAAkB,CAC/B,GAAiB,EACjB,SAAsB,EACtB,cAAuB;IAEvB,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,WAAW,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAC1E,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,IAAI,EAAE,aAAa,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC;QACrC,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,IAAI,EAAE,MAAM,EAAE,IAAI,IAAI,IAAI;QAC1B,OAAO,EAAE,MAAM;YACb,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC;YACpD,CAAC,CAAC,KAAK;QACT,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK;QACpE,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7B,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACpD,CAAC;AACJ,CAAC;AAED,SAAS,yBAAyB,CAAC,GAAiB;IAClD,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,UAAU,EAAE,GAAG,CAAC,UAAU;KAC3B,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,MAAM,CAAC;AAC5C,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IACjC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,GAAG,CAAC,CAAC;IACnC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IACxC,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,MAAM,MAAM,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACrE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAC;IAC7C,IACE,MAAM,CAAC,IAAI,CACT,CAAC,KAAK,EAAE,EAAE,CACR,CAAC,KAAK;QACN,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;QAC9B,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CACpC,EACD,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IAChC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,MAAM,MAAM,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACrE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAC;IAC7C,OAAO,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC;QACrC,CAAC,CAAE,MAAiC;QACpC,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAc;IACxC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,IAAI,GAAG,KAAgC,CAAC;IAC9C,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,IAAI,SAAS,CAAC;IAChC,IAAI,OAAO,EAAE,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAEzC,QAAQ,EAAE,EAAE,CAAC;QACX,KAAK,SAAS;YACZ,OAAO,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC;QAC3E,KAAK,eAAe,CAAC;QACrB,KAAK,cAAc;YACjB,OAAO,CACL,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CACpE,CAAC;QACJ,KAAK,iBAAiB;YACpB,OAAO,CACL,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ;gBAC9B,OAAO,IAAI,CAAC,GAAG,KAAK,QAAQ;gBAC5B,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CACjC,CAAC;QACJ,KAAK,iBAAiB;YACpB,OAAO,CACL,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CACrE,CAAC;QACJ,KAAK,cAAc;YACjB,OAAO,CACL,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ;gBAChC,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ;gBAC/B,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAC/B,CAAC;QACJ,KAAK,gBAAgB;YACnB,OAAO,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC;QAC1C,KAAK,eAAe;YAClB,OAAO,CACL,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CACrE,CAAC;QACJ;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC","sourcesContent":["import type { ActionEntry } from \"../agent/production-agent.js\";\nimport { writeAppState } from \"../application-state/script-helpers.js\";\nimport {\n createExtension,\n deleteExtension,\n getHiddenExtensionIdsForCurrentUser,\n getExtension,\n getExtensionHistoryVersion,\n hideExtension,\n listExtensionHistory,\n listExtensions,\n restoreExtensionHistoryVersion,\n unhideExtension,\n updateExtension,\n updateExtensionContent,\n type ExtensionRow,\n} from \"./store.js\";\nimport { resolveAccess } from \"../sharing/access.js\";\nimport {\n addExtensionSlotTarget,\n installExtensionSlot,\n uninstallExtensionSlot,\n listExtensionsForSlot,\n listSlotsForExtension,\n} from \"./slots/store.js\";\nimport { extensionPath } from \"./path.js\";\nimport type {\n ExtensionContentEdit,\n ExtensionLegacyPatch,\n} from \"./content-patch.js\";\n\nexport function createExtensionActionEntries(): Record<string, ActionEntry> {\n return {\n \"list-extensions\": {\n tool: {\n description:\n \"List extensions visible in the current user's Extensions list/sidebar. Use this for browsing or when you only know a display name. If <current-screen> or <current-url> already contains extensionId for the current extension, use get-extension or update-extension with that id directly instead of listing. Do not query the legacy tools table directly for extension management.\",\n parameters: {\n type: \"object\",\n properties: {\n search: {\n type: \"string\",\n description:\n \"Optional case-insensitive filter matched against id, name, description, and owner email. Example: Connect Zoom.\",\n },\n includeHidden: {\n type: \"boolean\",\n description:\n \"Include extensions the current user has hidden from their list. Defaults to false.\",\n },\n includeContent: {\n type: \"boolean\",\n description:\n \"Include full Alpine.js content. Defaults to false to keep results concise.\",\n },\n limit: {\n type: \"number\",\n description: \"Maximum results to return. Defaults to 100.\",\n },\n },\n },\n },\n run: async (args) => {\n const includeHidden = coerceBoolean(args?.includeHidden);\n const includeContent = coerceBoolean(args?.includeContent);\n const search = String(args?.search ?? \"\")\n .trim()\n .toLowerCase();\n const limit = coerceLimit(args?.limit);\n const hiddenIds = await getHiddenExtensionIdsForCurrentUser();\n\n let rows = await listExtensions({ includeHidden });\n if (search) {\n rows = rows.filter((row) =>\n [row.id, row.name, row.description, row.ownerEmail]\n .join(\"\\n\")\n .toLowerCase()\n .includes(search),\n );\n }\n\n rows = rows.slice(0, limit);\n const extensions = await Promise.all(\n rows.map((row) => summarizeExtension(row, hiddenIds, includeContent)),\n );\n return {\n ok: true,\n count: extensions.length,\n extensions,\n };\n },\n readOnly: true,\n },\n\n \"get-extension\": {\n tool: {\n description:\n \"Get one existing extension by id. Use this when <current-screen> or <current-url> contains extensionId for the current extension; do not call list-extensions just to rediscover that id. Defaults to including the full Alpine.js content so you can make a targeted update-extension edit.\",\n parameters: {\n type: \"object\",\n properties: {\n id: {\n type: \"string\",\n description:\n \"Extension id to read. Prefer the extensionId from <current-screen> or <current-url> when the user refers to the current extension.\",\n },\n includeContent: {\n type: \"boolean\",\n description:\n \"Include full Alpine.js content. Defaults to true for targeted edits.\",\n },\n },\n required: [\"id\"],\n },\n },\n run: async (args) => {\n const id = String(args?.id ?? \"\").trim();\n if (!id) return \"Error: id is required.\";\n const includeContent =\n args?.includeContent === undefined\n ? true\n : coerceBoolean(args.includeContent);\n const extension = await getExtension(id);\n if (!extension) return `Error: extension not found: ${id}`;\n const hiddenIds = await getHiddenExtensionIdsForCurrentUser();\n return {\n ok: true,\n extension: await summarizeExtension(\n extension,\n hiddenIds,\n includeContent,\n ),\n };\n },\n readOnly: true,\n },\n\n \"list-extension-history\": {\n tool: {\n description:\n \"List saved history snapshots for one extension. Use this when the user asks what changed, wants a changelog, or wants to pick an older version to restore. If the user is viewing the extension, use the extensionId from <current-screen> or <current-url>.\",\n parameters: {\n type: \"object\",\n properties: {\n id: {\n type: \"string\",\n description: \"Extension id whose history should be listed.\",\n },\n limit: {\n type: \"number\",\n description: \"Maximum versions to return. Defaults to 50.\",\n },\n includeContent: {\n type: \"boolean\",\n description:\n \"Include full HTML content for each version. Defaults to false.\",\n },\n },\n required: [\"id\"],\n },\n },\n run: async (args) => {\n const id = String(args?.id ?? \"\").trim();\n if (!id) return \"Error: id is required.\";\n const history = await listExtensionHistory(id, {\n limit:\n args?.limit === undefined ? undefined : coerceLimit(args.limit),\n includeContent: coerceBoolean(args?.includeContent),\n });\n return {\n ok: true,\n count: history.length,\n history,\n };\n },\n readOnly: true,\n },\n\n \"get-extension-history-version\": {\n tool: {\n description:\n \"Get one extension history version with its previous-version diff. Use after list-extension-history when the user wants to inspect exactly what changed.\",\n parameters: {\n type: \"object\",\n properties: {\n id: {\n type: \"string\",\n description: \"Extension id whose history version should be read.\",\n },\n version: {\n type: \"number\",\n description: \"History version number to inspect.\",\n },\n },\n required: [\"id\", \"version\"],\n },\n },\n run: async (args) => {\n const id = String(args?.id ?? \"\").trim();\n if (!id) return \"Error: id is required.\";\n const version = Number(args?.version);\n if (!Number.isInteger(version) || version < 1) {\n return \"Error: version must be a positive integer.\";\n }\n const detail = await getExtensionHistoryVersion(id, version);\n if (!detail) {\n return `Error: extension history version not found: ${id}#${version}`;\n }\n return { ok: true, ...detail };\n },\n readOnly: true,\n },\n\n \"create-extension\": {\n tool: {\n description:\n \"Create a sandboxed Alpine.js mini-app extension. Use this when the user asks to create, build, or make an extension/widget/dashboard/calculator. Call this action exactly once per requested extension. The content must be a self-contained Alpine.js HTML body snippet that can use appAction(), appFetch(), dbQuery(), dbExec(), extensionFetch(), and extensionData. Prefer appAction(name, params) for app data and actions, including read actions mounted as GET; do not call template /api/* routes from appFetch because the extension bridge only allows framework /_agent-native/* paths. Parse JSON string action results before aggregating; use dbQuery()/dbExec() only for known existing SQL tables. Keep the initial create-extension payload compact and working; for complex extensions, create a useful v1 first, then use focused update-extension edits for refinements rather than assembling one enormous tool input. For any non-trivial component (more than a couple of state fields, any methods, any string formatting, any branching) put the component in a <script> block via Alpine.data('name', () => ({...})) and reference it with x-data=\\\"name\\\" — do NOT cram methods, template literals, or branching logic into an inline x-data=\\\"{...}\\\" attribute (HTML parser pitfalls cause ReferenceError failures). Define every variable referenced from x-text/x-show/x-if/x-for on the data object's initial state. If the extension's value depends on an LLM call, require a real key via \\\\${keys.OPENAI_API_KEY}/\\\\${keys.ANTHROPIC_API_KEY} (and tell the user to add it in Settings → Secrets if missing) or route the AI work to the agent chat — never ship a stubbed analysis step that renders a placeholder/boolean as the result.\",\n parameters: {\n type: \"object\",\n properties: {\n name: {\n type: \"string\",\n description:\n 'Short display name for the extension. Do not include \"app\" — e.g. name a todo app \"Todos\", a weather app \"Weather\".',\n },\n description: {\n type: \"string\",\n description: \"One-sentence summary of what the extension does.\",\n },\n content: {\n type: \"string\",\n description:\n \"Self-contained Alpine.js HTML body snippet. The iframe canvas already has modest default padding, so avoid duplicate outer padding unless the design needs it. Use semantic Tailwind colors (bg-background, text-foreground, bg-primary, etc.) for native theming. Do not include a full app build, React code, or source files.\",\n },\n icon: {\n type: \"string\",\n description: \"Optional icon name or short label.\",\n },\n },\n required: [\"name\", \"content\"],\n },\n },\n run: async (args) => {\n const name = String(args?.name ?? \"\").trim();\n const content = String(args?.content ?? \"\").trim();\n if (!name) return \"Error: name is required.\";\n if (!content) return \"Error: content is required.\";\n\n const extension = await createExtension({\n name,\n description: String(args?.description ?? \"\").trim(),\n content,\n icon: args?.icon ? String(args.icon) : undefined,\n });\n const path = extensionPath(extension.id, extension.name);\n\n // Auto-navigate so the user lands on the new extension instead of\n // having to read the JSON response and click a link. Writes a\n // one-shot `navigate` app-state command the UI consumes and clears.\n try {\n await writeAppState(\"navigate\", {\n view: \"extensions\",\n extensionId: extension.id,\n path,\n // Unique-per-write token so the UI's `use-navigation-state` hook\n // can dedup race-driven re-reads of the same command.\n _writeId: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n });\n } catch {\n // Non-fatal — agent can still mention the path in its reply.\n }\n\n return {\n ok: true,\n extension: { ...extension, path },\n path,\n next: `Created. The user is being navigated to the new extension automatically — no further navigation tool calls needed.`,\n };\n },\n },\n\n \"update-extension\": {\n tool: {\n description:\n \"Update an existing sandboxed Alpine.js mini-app extension. If the user is viewing the extension, use the extensionId from <current-screen> or <current-url> directly; do not list extensions first just to find the current id. Prefer granular edits for surgical changes; use full content replacement only for broad rewrites. Supported edits include literal replace, insert-before/after marker, replace-between markers, replace-section/wrap-section/remove-section for <!-- agent-native:section name --> blocks, and regex-replace. Pass format=true to run Prettier on the final HTML.\",\n parameters: {\n type: \"object\",\n properties: {\n id: {\n type: \"string\",\n description:\n \"Extension id to update. Prefer the extensionId from <current-screen> or <current-url> for the current extension.\",\n },\n name: {\n type: \"string\",\n description: \"Optional new display name.\",\n },\n description: {\n type: \"string\",\n description: \"Optional new description.\",\n },\n content: {\n type: \"string\",\n description:\n \"Optional full replacement Alpine.js HTML body snippet.\",\n },\n patches: {\n type: \"string\",\n description:\n 'Legacy optional JSON array of { \"find\": \"...\", \"replace\": \"...\", \"all\"?: true, \"expectedMatches\"?: 1, \"required\"?: true } patches. Missing required targets fail instead of silently no-oping.',\n },\n edits: {\n type: \"string\",\n description:\n 'Preferred optional JSON array of granular edit operations. Examples: { \"op\": \"insert-after\", \"marker\": \"<!-- section:metrics -->\", \"content\": \"...\" }, { \"op\": \"replace-section\", \"section\": \"npm-chart\", \"content\": \"...\" }, { \"op\": \"wrap-section\", \"section\": \"charts\", \"before\": \"<div>\", \"after\": \"</div>\" }, { \"op\": \"regex-replace\", \"pattern\": \"...\", \"replace\": \"...\", \"expectedMatches\": 1 }.',\n },\n format: {\n type: \"boolean\",\n description:\n \"When true, format the final extension HTML with Prettier after applying content, patches, and edits.\",\n },\n icon: {\n type: \"string\",\n description: \"Optional icon name or short label.\",\n },\n visibility: {\n type: \"string\",\n description: \"Optional sharing visibility.\",\n enum: [\"private\", \"org\", \"public\"],\n },\n },\n required: [\"id\"],\n },\n },\n run: async (args) => {\n const id = String(args?.id ?? \"\").trim();\n if (!id) return \"Error: id is required.\";\n\n let result = null;\n const hasContentUpdate =\n args?.content !== undefined ||\n args?.patches !== undefined ||\n args?.edits !== undefined ||\n args?.format !== undefined;\n if (hasContentUpdate) {\n const patches = parsePatches((args as any).patches);\n if (args?.patches !== undefined && !patches) {\n return \"Error: patches must be a JSON array of { find, replace } objects.\";\n }\n const edits = parseEdits((args as any).edits);\n if (args?.edits !== undefined && !edits) {\n return \"Error: edits must be a JSON array of supported extension edit operations.\";\n }\n result = await updateExtensionContent(id, {\n content:\n args?.content !== undefined ? String(args.content) : undefined,\n patches,\n edits,\n format: coerceBoolean(args?.format),\n });\n }\n\n const meta: Record<string, string> = {};\n if (args?.name !== undefined) meta.name = String(args.name).trim();\n if (args?.description !== undefined) {\n meta.description = String(args.description).trim();\n }\n if (args?.icon !== undefined) meta.icon = String(args.icon);\n if (args?.visibility !== undefined) {\n meta.visibility = String(args.visibility);\n }\n if (Object.keys(meta).length > 0) {\n result = await updateExtension(id, meta as any);\n }\n\n if (!result) result = await getExtension(id);\n if (!result) return `Error: extension not found: ${id}`;\n const hiddenIds = await getHiddenExtensionIdsForCurrentUser();\n return {\n ok: true,\n extension: await summarizeExtension(result, hiddenIds, false),\n };\n },\n },\n\n \"delete-extension\": {\n tool: {\n description:\n \"Permanently delete an extension everywhere it is shared. Requires owner/admin access. If the user only wants a shared extension removed from their own sidebar/list, use hide-extension instead.\",\n parameters: {\n type: \"object\",\n properties: {\n id: {\n type: \"string\",\n description:\n \"Extension id to permanently delete. Use list-extensions first if you only know the display name.\",\n },\n },\n required: [\"id\"],\n },\n },\n run: async (args) => {\n const id = String(args?.id ?? \"\").trim();\n if (!id) return \"Error: id is required.\";\n const extension = await getExtension(id);\n if (!extension) return `Error: extension not found: ${id}`;\n\n try {\n const ok = await deleteExtension(id);\n if (!ok) return `Error: extension not found: ${id}`;\n return { ok: true, deleted: summarizeDeletedExtension(extension) };\n } catch (err: any) {\n return {\n ok: false,\n error: err?.message ?? String(err),\n next: \"If the user wants this gone only from their own view, call hide-extension with the same id.\",\n };\n }\n },\n },\n\n \"restore-extension-history-version\": {\n tool: {\n description:\n \"Restore an extension's name, description, icon, and HTML content from a saved history version. Requires editor access. This does not restore sharing visibility or ownership.\",\n parameters: {\n type: \"object\",\n properties: {\n id: {\n type: \"string\",\n description: \"Extension id to restore.\",\n },\n version: {\n type: \"number\",\n description:\n \"Saved history version number to restore. Use list-extension-history first if unsure.\",\n },\n },\n required: [\"id\", \"version\"],\n },\n },\n run: async (args) => {\n const id = String(args?.id ?? \"\").trim();\n if (!id) return \"Error: id is required.\";\n const version = Number(args?.version);\n if (!Number.isInteger(version) || version < 1) {\n return \"Error: version must be a positive integer.\";\n }\n const result = await restoreExtensionHistoryVersion(id, version);\n if (!result) {\n return `Error: extension history version not found: ${id}#${version}`;\n }\n const hiddenIds = await getHiddenExtensionIdsForCurrentUser();\n return {\n ok: true,\n restoredVersion: version,\n extension: await summarizeExtension(result, hiddenIds, false),\n };\n },\n },\n\n \"hide-extension\": {\n tool: {\n description:\n \"Hide an accessible extension from the current user's Extensions list/sidebar without deleting it for anyone else. Use this when the user says to remove a shared extension from their view, or when delete-extension reports that the current user is not owner/admin.\",\n parameters: {\n type: \"object\",\n properties: {\n id: {\n type: \"string\",\n description:\n \"Extension id to hide for the current user. Use list-extensions first if you only know the display name.\",\n },\n },\n required: [\"id\"],\n },\n },\n run: async (args) => {\n const id = String(args?.id ?? \"\").trim();\n if (!id) return \"Error: id is required.\";\n const extension = await getExtension(id);\n if (!extension) return `Error: extension not found: ${id}`;\n\n await hideExtension(id);\n return { ok: true, hidden: summarizeDeletedExtension(extension) };\n },\n },\n\n \"unhide-extension\": {\n tool: {\n description:\n \"Restore an extension the current user previously hid so it appears in their Extensions list/sidebar again. Use list-extensions with includeHidden=true to find hidden ids.\",\n parameters: {\n type: \"object\",\n properties: {\n id: {\n type: \"string\",\n description: \"Extension id to restore for the current user.\",\n },\n },\n required: [\"id\"],\n },\n },\n run: async (args) => {\n const id = String(args?.id ?? \"\").trim();\n if (!id) return \"Error: id is required.\";\n await unhideExtension(id);\n return { ok: true, id };\n },\n },\n\n \"add-extension-slot-target\": {\n tool: {\n description:\n 'Declare that an extension can render in a UI extension-point slot of an app (e.g. \"mail.contact-sidebar.bottom\"). Apps drop ExtensionSlot components in their UI; this action registers an extension as installable into one of those slots. Slot IDs follow the convention <app>.<area>.<position>. Caller must have editor access to the extension.',\n parameters: {\n type: \"object\",\n properties: {\n extensionId: { type: \"string\", description: \"Extension id.\" },\n slotId: {\n type: \"string\",\n description:\n 'Slot identifier — e.g. \"mail.contact-sidebar.bottom\".',\n },\n config: {\n type: \"string\",\n description:\n \"Optional JSON string with slot-specific config (defaults, hints, etc.).\",\n },\n },\n required: [\"extensionId\", \"slotId\"],\n },\n },\n run: async (args) => {\n const extensionId = String(args?.extensionId ?? \"\").trim();\n const slotId = String(args?.slotId ?? \"\").trim();\n if (!extensionId) return \"Error: extensionId is required.\";\n if (!slotId) return \"Error: slotId is required.\";\n const row = await addExtensionSlotTarget(\n extensionId,\n slotId,\n args?.config ? String(args.config) : undefined,\n );\n return { ok: true, slot: row };\n },\n },\n\n \"install-extension\": {\n tool: {\n description:\n \"Install an extension as a widget in an extension-point slot for the current user. The extension must already declare the slot via add-extension-slot-target. Per-user installation — only affects the calling user's view. Use after creating an extension that targets a slot, or when the user asks to add an existing widget to a slot.\",\n parameters: {\n type: \"object\",\n properties: {\n extensionId: {\n type: \"string\",\n description: \"Extension id to install.\",\n },\n slotId: {\n type: \"string\",\n description:\n 'Slot identifier — e.g. \"mail.contact-sidebar.bottom\".',\n },\n position: {\n type: \"number\",\n description:\n \"Optional integer position within the slot (lower = earlier). Defaults to end.\",\n },\n config: {\n type: \"string\",\n description:\n \"Optional JSON string with per-install config (overrides, settings).\",\n },\n },\n required: [\"extensionId\", \"slotId\"],\n },\n },\n run: async (args) => {\n const extensionId = String(args?.extensionId ?? \"\").trim();\n const slotId = String(args?.slotId ?? \"\").trim();\n if (!extensionId) return \"Error: extensionId is required.\";\n if (!slotId) return \"Error: slotId is required.\";\n const position =\n args?.position !== undefined && args.position !== null\n ? Number(args.position)\n : undefined;\n const row = await installExtensionSlot(extensionId, slotId, {\n position: Number.isFinite(position as number) ? position : undefined,\n config: args?.config ? String(args.config) : undefined,\n });\n return { ok: true, install: row };\n },\n },\n\n \"uninstall-extension\": {\n tool: {\n description:\n \"Remove an extension from an extension-point slot for the current user. Does not delete the extension itself.\",\n parameters: {\n type: \"object\",\n properties: {\n extensionId: { type: \"string\", description: \"Extension id.\" },\n slotId: { type: \"string\", description: \"Slot identifier.\" },\n },\n required: [\"extensionId\", \"slotId\"],\n },\n },\n run: async (args) => {\n const extensionId = String(args?.extensionId ?? \"\").trim();\n const slotId = String(args?.slotId ?? \"\").trim();\n if (!extensionId) return \"Error: extensionId is required.\";\n if (!slotId) return \"Error: slotId is required.\";\n await uninstallExtensionSlot(extensionId, slotId);\n return { ok: true };\n },\n },\n\n \"list-extensions-for-slot\": {\n tool: {\n description:\n \"List extensions the current user has access to that declare a given extension-point slot. Use to discover what's available to install into a slot the user mentioned.\",\n parameters: {\n type: \"object\",\n properties: {\n slotId: { type: \"string\", description: \"Slot identifier.\" },\n },\n required: [\"slotId\"],\n },\n },\n run: async (args) => {\n const slotId = String(args?.slotId ?? \"\").trim();\n if (!slotId) return \"Error: slotId is required.\";\n return { extensions: await listExtensionsForSlot(slotId) };\n },\n readOnly: true,\n },\n\n \"list-extension-slots\": {\n tool: {\n description:\n \"List the extension-point slots a specific extension declares it can render in. Caller must have viewer access to the extension.\",\n parameters: {\n type: \"object\",\n properties: {\n extensionId: { type: \"string\", description: \"Extension id.\" },\n },\n required: [\"extensionId\"],\n },\n },\n run: async (args) => {\n const extensionId = String(args?.extensionId ?? \"\").trim();\n if (!extensionId) return \"Error: extensionId is required.\";\n return { slots: await listSlotsForExtension(extensionId) };\n },\n readOnly: true,\n },\n };\n}\n\nasync function summarizeExtension(\n row: ExtensionRow,\n hiddenIds: Set<string>,\n includeContent: boolean,\n) {\n const access = await resolveAccess(\"extension\", row.id).catch(() => null);\n return {\n id: row.id,\n name: row.name,\n path: extensionPath(row.id, row.name),\n description: row.description,\n icon: row.icon,\n ownerEmail: row.ownerEmail,\n visibility: row.visibility,\n role: access?.role ?? null,\n canEdit: access\n ? [\"owner\", \"admin\", \"editor\"].includes(access.role)\n : false,\n canDelete: access ? [\"owner\", \"admin\"].includes(access.role) : false,\n hidden: hiddenIds.has(row.id),\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n ...(includeContent ? { content: row.content } : {}),\n };\n}\n\nfunction summarizeDeletedExtension(row: ExtensionRow) {\n return {\n id: row.id,\n name: row.name,\n ownerEmail: row.ownerEmail,\n visibility: row.visibility,\n };\n}\n\nfunction coerceBoolean(value: unknown): boolean {\n return value === true || value === \"true\";\n}\n\nfunction coerceLimit(value: unknown): number {\n const limit = Number(value ?? 100);\n if (!Number.isFinite(limit)) return 100;\n return Math.min(Math.max(1, Math.floor(limit)), 500);\n}\n\nfunction parsePatches(value: unknown): ExtensionLegacyPatch[] | undefined {\n if (value === undefined) return undefined;\n const parsed = typeof value === \"string\" ? JSON.parse(value) : value;\n if (!Array.isArray(parsed)) return undefined;\n if (\n parsed.some(\n (patch) =>\n !patch ||\n typeof patch.find !== \"string\" ||\n typeof patch.replace !== \"string\",\n )\n ) {\n return undefined;\n }\n return parsed;\n}\n\nfunction parseEdits(value: unknown): ExtensionContentEdit[] | undefined {\n if (value === undefined) return undefined;\n const parsed = typeof value === \"string\" ? JSON.parse(value) : value;\n if (!Array.isArray(parsed)) return undefined;\n return parsed.every(isValidContentEdit)\n ? (parsed as ExtensionContentEdit[])\n : undefined;\n}\n\nfunction isValidContentEdit(value: unknown): boolean {\n if (!value || typeof value !== \"object\") return false;\n const edit = value as Record<string, unknown>;\n const op = edit.op ?? \"replace\";\n if (typeof op !== \"string\") return false;\n\n switch (op) {\n case \"replace\":\n return typeof edit.find === \"string\" && typeof edit.replace === \"string\";\n case \"insert-before\":\n case \"insert-after\":\n return (\n typeof edit.marker === \"string\" && typeof edit.content === \"string\"\n );\n case \"replace-between\":\n return (\n typeof edit.start === \"string\" &&\n typeof edit.end === \"string\" &&\n typeof edit.content === \"string\"\n );\n case \"replace-section\":\n return (\n typeof edit.section === \"string\" && typeof edit.content === \"string\"\n );\n case \"wrap-section\":\n return (\n typeof edit.section === \"string\" &&\n typeof edit.before === \"string\" &&\n typeof edit.after === \"string\"\n );\n case \"remove-section\":\n return typeof edit.section === \"string\";\n case \"regex-replace\":\n return (\n typeof edit.pattern === \"string\" && typeof edit.replace === \"string\"\n );\n default:\n return false;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/extensions/routes.ts"],"names":[],"mappings":"AAmDA,wBAAgB,uBAAuB,2FAuCtC"}
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/extensions/routes.ts"],"names":[],"mappings":"AAsDA,wBAAgB,uBAAuB,2FAuCtC"}