@agent-native/core 0.7.83 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. package/dist/action.js +1 -1
  2. package/dist/action.js.map +1 -1
  3. package/dist/agent/production-agent.d.ts.map +1 -1
  4. package/dist/agent/production-agent.js +8 -8
  5. package/dist/agent/production-agent.js.map +1 -1
  6. package/dist/agent/run-manager.d.ts +2 -0
  7. package/dist/agent/run-manager.d.ts.map +1 -1
  8. package/dist/agent/run-manager.js +44 -18
  9. package/dist/agent/run-manager.js.map +1 -1
  10. package/dist/agent/types.d.ts +1 -1
  11. package/dist/agent/types.d.ts.map +1 -1
  12. package/dist/agent/types.js.map +1 -1
  13. package/dist/cli/create.d.ts.map +1 -1
  14. package/dist/cli/create.js +54 -11
  15. package/dist/cli/create.js.map +1 -1
  16. package/dist/cli/workspacify.d.ts.map +1 -1
  17. package/dist/cli/workspacify.js +12 -9
  18. package/dist/cli/workspacify.js.map +1 -1
  19. package/dist/client/AgentPanel.d.ts +1 -1
  20. package/dist/client/AgentPanel.d.ts.map +1 -1
  21. package/dist/client/AgentPanel.js +22 -1
  22. package/dist/client/AgentPanel.js.map +1 -1
  23. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  24. package/dist/client/agent-chat-adapter.js +254 -29
  25. package/dist/client/agent-chat-adapter.js.map +1 -1
  26. package/dist/client/agent-chat.d.ts +2 -0
  27. package/dist/client/agent-chat.d.ts.map +1 -1
  28. package/dist/client/agent-chat.js +11 -2
  29. package/dist/client/agent-chat.js.map +1 -1
  30. package/dist/client/composer/ComposerPlusMenu.js +1 -1
  31. package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
  32. package/dist/client/composer/PromptComposer.js +1 -1
  33. package/dist/client/composer/PromptComposer.js.map +1 -1
  34. package/dist/client/composer/TiptapComposer.js +8 -8
  35. package/dist/client/composer/TiptapComposer.js.map +1 -1
  36. package/dist/client/composer/types.d.ts +1 -1
  37. package/dist/client/composer/types.d.ts.map +1 -1
  38. package/dist/client/composer/types.js.map +1 -1
  39. package/dist/client/extensions/EmbeddedExtension.d.ts +20 -0
  40. package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -0
  41. package/dist/client/{tools/EmbeddedTool.js → extensions/EmbeddedExtension.js} +41 -41
  42. package/dist/client/extensions/EmbeddedExtension.js.map +1 -0
  43. package/dist/client/extensions/ExtensionEditor.d.ts +5 -0
  44. package/dist/client/extensions/ExtensionEditor.d.ts.map +1 -0
  45. package/dist/client/extensions/ExtensionEditor.js +129 -0
  46. package/dist/client/extensions/ExtensionEditor.js.map +1 -0
  47. package/dist/client/{tools → extensions}/ExtensionSlot.d.ts +3 -3
  48. package/dist/client/extensions/ExtensionSlot.d.ts.map +1 -0
  49. package/dist/client/{tools → extensions}/ExtensionSlot.js +14 -14
  50. package/dist/client/extensions/ExtensionSlot.js.map +1 -0
  51. package/dist/client/extensions/ExtensionViewer.d.ts +5 -0
  52. package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -0
  53. package/dist/client/{tools/ToolViewer.js → extensions/ExtensionViewer.js} +67 -65
  54. package/dist/client/extensions/ExtensionViewer.js.map +1 -0
  55. package/dist/client/extensions/ExtensionViewerPage.d.ts +2 -0
  56. package/dist/client/extensions/ExtensionViewerPage.d.ts.map +1 -0
  57. package/dist/client/{tools/ToolViewerPage.js → extensions/ExtensionViewerPage.js} +8 -8
  58. package/dist/client/extensions/ExtensionViewerPage.js.map +1 -0
  59. package/dist/client/extensions/ExtensionsListPage.d.ts +2 -0
  60. package/dist/client/extensions/ExtensionsListPage.d.ts.map +1 -0
  61. package/dist/client/extensions/ExtensionsListPage.js +67 -0
  62. package/dist/client/extensions/ExtensionsListPage.js.map +1 -0
  63. package/dist/client/extensions/ExtensionsSidebarSection.d.ts +2 -0
  64. package/dist/client/extensions/ExtensionsSidebarSection.d.ts.map +1 -0
  65. package/dist/client/{tools/ToolsSidebarSection.js → extensions/ExtensionsSidebarSection.js} +58 -58
  66. package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -0
  67. package/dist/client/{tools/tool-order.d.ts → extensions/extension-order.d.ts} +2 -2
  68. package/dist/client/extensions/extension-order.d.ts.map +1 -0
  69. package/dist/client/{tools/tool-order.js → extensions/extension-order.js} +3 -3
  70. package/dist/client/extensions/extension-order.js.map +1 -0
  71. package/dist/client/{tools → extensions}/iframe-bridge.d.ts +11 -11
  72. package/dist/client/extensions/iframe-bridge.d.ts.map +1 -0
  73. package/dist/client/{tools → extensions}/iframe-bridge.js +24 -24
  74. package/dist/client/extensions/iframe-bridge.js.map +1 -0
  75. package/dist/client/extensions/index.d.ts +14 -0
  76. package/dist/client/extensions/index.d.ts.map +1 -0
  77. package/dist/client/extensions/index.js +19 -0
  78. package/dist/client/extensions/index.js.map +1 -0
  79. package/dist/client/sse-event-processor.d.ts +2 -1
  80. package/dist/client/sse-event-processor.d.ts.map +1 -1
  81. package/dist/client/sse-event-processor.js +87 -6
  82. package/dist/client/sse-event-processor.js.map +1 -1
  83. package/dist/extensions/actions.d.ts +3 -0
  84. package/dist/extensions/actions.d.ts.map +1 -0
  85. package/dist/{tools → extensions}/actions.js +54 -51
  86. package/dist/extensions/actions.js.map +1 -0
  87. package/dist/{tools → extensions}/fetch-tool.d.ts +4 -0
  88. package/dist/extensions/fetch-tool.d.ts.map +1 -0
  89. package/dist/{tools → extensions}/fetch-tool.js +12 -7
  90. package/dist/extensions/fetch-tool.js.map +1 -0
  91. package/dist/extensions/html-shell.d.ts +56 -0
  92. package/dist/extensions/html-shell.d.ts.map +1 -0
  93. package/dist/{tools → extensions}/html-shell.js +101 -83
  94. package/dist/extensions/html-shell.js.map +1 -0
  95. package/dist/{tools → extensions}/proxy-security.d.ts +2 -2
  96. package/dist/extensions/proxy-security.d.ts.map +1 -0
  97. package/dist/{tools → extensions}/proxy-security.js +3 -3
  98. package/dist/extensions/proxy-security.js.map +1 -0
  99. package/dist/extensions/routes.d.ts +2 -0
  100. package/dist/extensions/routes.d.ts.map +1 -0
  101. package/dist/{tools → extensions}/routes.js +73 -69
  102. package/dist/extensions/routes.js.map +1 -0
  103. package/dist/{tools → extensions}/schema.d.ts +44 -38
  104. package/dist/extensions/schema.d.ts.map +1 -0
  105. package/dist/{tools → extensions}/schema.js +41 -34
  106. package/dist/extensions/schema.js.map +1 -0
  107. package/dist/extensions/slots/routes.d.ts +15 -0
  108. package/dist/extensions/slots/routes.d.ts.map +1 -0
  109. package/dist/{tools → extensions}/slots/routes.js +26 -26
  110. package/dist/extensions/slots/routes.js.map +1 -0
  111. package/dist/{tools → extensions}/slots/schema.d.ts +24 -21
  112. package/dist/extensions/slots/schema.d.ts.map +1 -0
  113. package/dist/extensions/slots/schema.js +79 -0
  114. package/dist/extensions/slots/schema.js.map +1 -0
  115. package/dist/extensions/slots/store.d.ts +66 -0
  116. package/dist/extensions/slots/store.d.ts.map +1 -0
  117. package/dist/extensions/slots/store.js +238 -0
  118. package/dist/extensions/slots/store.js.map +1 -0
  119. package/dist/extensions/store.d.ts +40 -0
  120. package/dist/extensions/store.d.ts.map +1 -0
  121. package/dist/{tools → extensions}/store.js +59 -54
  122. package/dist/extensions/store.js.map +1 -0
  123. package/dist/extensions/theme.d.ts.map +1 -0
  124. package/dist/extensions/theme.js.map +1 -0
  125. package/dist/{tools → extensions}/url-safety.d.ts +5 -3
  126. package/dist/extensions/url-safety.d.ts.map +1 -0
  127. package/dist/{tools → extensions}/url-safety.js +11 -4
  128. package/dist/extensions/url-safety.js.map +1 -0
  129. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  130. package/dist/server/agent-chat-plugin.js +12 -10
  131. package/dist/server/agent-chat-plugin.js.map +1 -1
  132. package/dist/server/core-routes-plugin.d.ts +15 -0
  133. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  134. package/dist/server/core-routes-plugin.js +64 -10
  135. package/dist/server/core-routes-plugin.js.map +1 -1
  136. package/dist/server/csrf.d.ts +3 -2
  137. package/dist/server/csrf.d.ts.map +1 -1
  138. package/dist/server/csrf.js +3 -2
  139. package/dist/server/csrf.js.map +1 -1
  140. package/dist/shared/workspace-app-id.d.ts +1 -1
  141. package/dist/shared/workspace-app-id.d.ts.map +1 -1
  142. package/dist/shared/workspace-app-id.js +5 -1
  143. package/dist/shared/workspace-app-id.js.map +1 -1
  144. package/dist/templates/workspace-root/README.md +5 -4
  145. package/dist/usage/store.d.ts +1 -1
  146. package/dist/usage/store.d.ts.map +1 -1
  147. package/dist/usage/store.js +1 -1
  148. package/dist/usage/store.js.map +1 -1
  149. package/dist/vite/client.d.ts.map +1 -1
  150. package/dist/vite/client.js +10 -1
  151. package/dist/vite/client.js.map +1 -1
  152. package/docs/content/actions.md +10 -10
  153. package/docs/content/extensions.md +230 -0
  154. package/docs/content/key-concepts.md +2 -2
  155. package/docs/content/server.md +13 -13
  156. package/docs/content/sharing.md +2 -2
  157. package/docs/content/template-dispatch.md +5 -0
  158. package/docs/content/what-is-agent-native.md +1 -1
  159. package/package.json +22 -17
  160. package/src/templates/workspace-root/README.md +5 -4
  161. package/dist/client/tools/EmbeddedTool.d.ts +0 -20
  162. package/dist/client/tools/EmbeddedTool.d.ts.map +0 -1
  163. package/dist/client/tools/EmbeddedTool.js.map +0 -1
  164. package/dist/client/tools/ExtensionSlot.d.ts.map +0 -1
  165. package/dist/client/tools/ExtensionSlot.js.map +0 -1
  166. package/dist/client/tools/ToolEditor.d.ts +0 -5
  167. package/dist/client/tools/ToolEditor.d.ts.map +0 -1
  168. package/dist/client/tools/ToolEditor.js +0 -129
  169. package/dist/client/tools/ToolEditor.js.map +0 -1
  170. package/dist/client/tools/ToolViewer.d.ts +0 -5
  171. package/dist/client/tools/ToolViewer.d.ts.map +0 -1
  172. package/dist/client/tools/ToolViewer.js.map +0 -1
  173. package/dist/client/tools/ToolViewerPage.d.ts +0 -2
  174. package/dist/client/tools/ToolViewerPage.d.ts.map +0 -1
  175. package/dist/client/tools/ToolViewerPage.js.map +0 -1
  176. package/dist/client/tools/ToolsListPage.d.ts +0 -2
  177. package/dist/client/tools/ToolsListPage.d.ts.map +0 -1
  178. package/dist/client/tools/ToolsListPage.js +0 -67
  179. package/dist/client/tools/ToolsListPage.js.map +0 -1
  180. package/dist/client/tools/ToolsSidebarSection.d.ts +0 -2
  181. package/dist/client/tools/ToolsSidebarSection.d.ts.map +0 -1
  182. package/dist/client/tools/ToolsSidebarSection.js.map +0 -1
  183. package/dist/client/tools/iframe-bridge.d.ts.map +0 -1
  184. package/dist/client/tools/iframe-bridge.js.map +0 -1
  185. package/dist/client/tools/index.d.ts +0 -8
  186. package/dist/client/tools/index.d.ts.map +0 -1
  187. package/dist/client/tools/index.js +0 -8
  188. package/dist/client/tools/index.js.map +0 -1
  189. package/dist/client/tools/tool-order.d.ts.map +0 -1
  190. package/dist/client/tools/tool-order.js.map +0 -1
  191. package/dist/tools/actions.d.ts +0 -3
  192. package/dist/tools/actions.d.ts.map +0 -1
  193. package/dist/tools/actions.js.map +0 -1
  194. package/dist/tools/fetch-tool.d.ts.map +0 -1
  195. package/dist/tools/fetch-tool.js.map +0 -1
  196. package/dist/tools/html-shell.d.ts +0 -45
  197. package/dist/tools/html-shell.d.ts.map +0 -1
  198. package/dist/tools/html-shell.js.map +0 -1
  199. package/dist/tools/proxy-security.d.ts.map +0 -1
  200. package/dist/tools/proxy-security.js.map +0 -1
  201. package/dist/tools/routes.d.ts +0 -2
  202. package/dist/tools/routes.d.ts.map +0 -1
  203. package/dist/tools/routes.js.map +0 -1
  204. package/dist/tools/schema.d.ts.map +0 -1
  205. package/dist/tools/schema.js.map +0 -1
  206. package/dist/tools/slots/routes.d.ts +0 -15
  207. package/dist/tools/slots/routes.d.ts.map +0 -1
  208. package/dist/tools/slots/routes.js.map +0 -1
  209. package/dist/tools/slots/schema.d.ts.map +0 -1
  210. package/dist/tools/slots/schema.js +0 -76
  211. package/dist/tools/slots/schema.js.map +0 -1
  212. package/dist/tools/slots/store.d.ts +0 -66
  213. package/dist/tools/slots/store.d.ts.map +0 -1
  214. package/dist/tools/slots/store.js +0 -227
  215. package/dist/tools/slots/store.js.map +0 -1
  216. package/dist/tools/store.d.ts +0 -40
  217. package/dist/tools/store.d.ts.map +0 -1
  218. package/dist/tools/store.js.map +0 -1
  219. package/dist/tools/theme.d.ts.map +0 -1
  220. package/dist/tools/theme.js.map +0 -1
  221. package/dist/tools/url-safety.d.ts.map +0 -1
  222. package/dist/tools/url-safety.js.map +0 -1
  223. package/docs/content/tools.md +0 -205
  224. /package/dist/{tools → extensions}/theme.d.ts +0 -0
  225. /package/dist/{tools → extensions}/theme.js +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"file":"html-shell.js","sourceRoot":"","sources":["../../src/tools/html-shell.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAC1B,2YAA2Y,CAAC;AAE9Y,MAAM,CAAC,MAAM,oBAAoB,GAAG,eAAe,CAAC,OAAO,CACzD,8BAA8B,EAC9B,EAAE,CACH,CAAC;AA6CF,MAAM,UAAU,aAAa,CAC3B,OAAe,EACf,SAAiB,EACjB,MAAe,EACf,MAAe,EACf,OAA2B;IAE3B,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,UAAU,GAAG,mBAAmB,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;IACrD,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAChC,OAAO,IAAI;QACT,WAAW,EAAE,EAAE;QACf,WAAW,EAAE,EAAE;QACf,QAAQ,EAAE,IAAI;QACd,IAAI,EAAE,OAAO;KACd,CACF,CAAC;IAEF,OAAO;iBACQ,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE;;;;wDAIU,oBAAoB;IACxE,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,kDAAkD,mBAAmB,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WA8E7H,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBA4LA,UAAU;yBACL,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAiN5B,MAAM,CAAC,CAAC,CAAC,kBAAkB,UAAU,GAAG,CAAC,CAAC,CAAC,EAAE;GAClD,OAAO;;;;;;;;;;SAUD,CAAC;AACV,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAa;IACxC,OAAO,KAAK;SACT,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3B,CAAC","sourcesContent":["export const TOOL_IFRAME_CSP =\n \"default-src 'none'; script-src 'self' https://cdn.jsdelivr.net 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://fonts.googleapis.com; font-src https://fonts.gstatic.com; connect-src 'self'; img-src 'self' data: blob:; media-src 'self' data: blob:; frame-src 'none'; object-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'self';\";\n\nexport const TOOL_IFRAME_META_CSP = TOOL_IFRAME_CSP.replace(\n /\\s*frame-ancestors 'self';?$/,\n \"\",\n);\n\n/**\n * SECURITY — TOOL CONTENT IS UNTRUSTED.\n *\n * `${content}` (line ~Body) interpolates raw HTML/JS authored by a user. This\n * file is the boundary between framework-controlled HTML and user-controlled\n * HTML. Two non-negotiable invariants for every change here:\n *\n * 1. The iframe MUST be rendered with a `sandbox` attribute that does NOT\n * include `allow-same-origin`. The viewer (`ToolViewer.tsx`,\n * `EmbeddedTool.tsx`) sets `sandbox=\"allow-scripts allow-forms\"` — and\n * that is the only acceptable shape. Adding `allow-same-origin` would\n * give the tool full DOM access to the parent window via cross-frame\n * script.\n *\n * 2. Every reachable parent action must treat the postMessage payload as\n * hostile. The bridge in `iframe-bridge.ts` enforces a path allowlist,\n * header sanitization, and method allowlist; do not relax those gates\n * for \"convenience\" in this file or any caller.\n *\n * For the trust model rationale, see audit 05-tools-sandbox.md (C1) and the\n * `tools` skill. When in doubt, fail closed.\n */\n\nexport interface ToolRenderBinding {\n /** Email of the user who authored / owns the tool. */\n authorEmail: string;\n /** Email of the user currently viewing/running the tool. */\n viewerEmail: string;\n /** True when viewer === author. */\n isAuthor: boolean;\n /**\n * Resolved role for the viewer (\"owner\" | \"admin\" | \"editor\" | \"viewer\").\n *\n * TODO(security, audit H4): the host-side bridge does not yet gate any\n * helper based on this value — every viewer gets the same powers as the\n * author. The role is plumbed through so a follow-up PR can constrain\n * `appAction` / `dbExec` / `toolFetch` for non-author viewers (and\n * eventually require an explicit consent step before running a shared\n * tool, audit C1). For now this is metadata only.\n */\n role: \"owner\" | \"admin\" | \"editor\" | \"viewer\";\n}\n\nexport function buildToolHtml(\n content: string,\n themeVars: string,\n isDark: boolean,\n toolId?: string,\n binding?: ToolRenderBinding,\n): string {\n const toolIdJson = JSON.stringify(toolId ?? \"\");\n const toolIdAttr = escapeHtmlAttribute(toolId ?? \"\");\n const bindingJson = JSON.stringify(\n binding ?? {\n authorEmail: \"\",\n viewerEmail: \"\",\n isAuthor: true,\n role: \"owner\",\n },\n );\n\n return `<!DOCTYPE html>\n<html lang=\"en\"${isDark ? ' class=\"dark\"' : \"\"}>\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <meta http-equiv=\"Content-Security-Policy\" content=\"${TOOL_IFRAME_META_CSP}\" />\n ${binding && !binding.isAuthor ? `<meta name=\"agent-native-tool-author\" content=\"${escapeHtmlAttribute(binding.authorEmail)}\" />` : \"\"}\n <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\" />\n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin />\n <link href=\"https://fonts.googleapis.com/css2?family=Inter:wght@300..700&display=swap\" rel=\"stylesheet\" />\n <script>\n var _toolErrors = [];\n var _toolErrorDetails = [];\n var _consoleLogs = [];\n var _networkLogs = [];\n\n var _origConsole = { log: console.log, warn: console.warn, error: console.error, info: console.info };\n function _wrapConsole(level, orig) {\n return function() {\n var args = Array.prototype.slice.call(arguments);\n var msg = args.map(function(a) {\n try { return typeof a === 'object' ? JSON.stringify(a) : String(a); }\n catch(e) { return String(a); }\n }).join(' ');\n if (_consoleLogs.length >= 50) _consoleLogs.shift();\n _consoleLogs.push({ level: level, message: msg });\n orig.apply(console, arguments);\n };\n }\n console.log = _wrapConsole('log', _origConsole.log);\n console.warn = _wrapConsole('warn', _origConsole.warn);\n console.error = _wrapConsole('error', _origConsole.error);\n console.info = _wrapConsole('info', _origConsole.info);\n\n function _collectError(message, stack) {\n if (!message) return;\n if (message === 'Script error.' || message === 'Script error') message = 'Runtime error';\n if (_toolErrors.indexOf(message) !== -1) return;\n _toolErrors.push(message);\n _toolErrorDetails.push({ message: message, stack: stack || '' });\n var toast = document.getElementById('__tool-error-toast');\n if (!toast) return;\n var msg = document.getElementById('__tool-error-msg');\n if (_toolErrors.length === 1) {\n msg.textContent = _toolErrors[0];\n } else {\n msg.textContent = _toolErrors.length + ' errors — ' + _toolErrors[_toolErrors.length - 1];\n }\n toast.style.display = 'block';\n }\n\n window.addEventListener('error', function(event) {\n var msg = event.message || '';\n if (msg.indexOf('Alpine Expression Error') === 0) return;\n var stack = event.error && event.error.stack ? event.error.stack : '';\n _collectError(msg, stack);\n });\n\n window.addEventListener('unhandledrejection', function(event) {\n var msg = event.reason && event.reason.message ? event.reason.message : String(event.reason);\n var stack = event.reason && event.reason.stack ? event.reason.stack : '';\n _collectError(msg, stack);\n });\n </script>\n <!--\n SECURITY: pinned to exact patch versions + SRI integrity hashes. A\n malicious republish of @tailwindcss/browser@4.x or alpinejs@3.x would\n otherwise inject code into every tool. To bump these versions:\n 1. npm view @tailwindcss/browser version (or alpinejs)\n 2. curl -sL https://cdn.jsdelivr.net/npm/@tailwindcss/browser@<v> \\\n | openssl dgst -sha384 -binary | openssl base64 -A\n 3. Update the URL + integrity hash below in lockstep.\n -->\n <script\n src=\"https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4.2.4\"\n integrity=\"sha384-yNSZBFvuOWcmww494a9+1zNuvgUGEXoWkein7cxP8wHUTi3iXCU4vJ7hr3tzBCml\"\n crossorigin=\"anonymous\"\n ></script>\n <script\n defer\n src=\"https://cdn.jsdelivr.net/npm/alpinejs@3.15.11/dist/cdn.min.js\"\n integrity=\"sha384-WPtu0YHhJ3arcykfnv1JgUffWDSKRnqnDeTpJUbOc2os2moEmLkIdaeR0trPN4be\"\n crossorigin=\"anonymous\"\n ></script>\n <style>${themeVars}</style>\n <style type=\"text/tailwindcss\">\n @custom-variant dark (&:where(.dark, .dark *));\n @theme {\n --color-border: hsl(var(--border));\n --color-input: hsl(var(--input));\n --color-ring: hsl(var(--ring));\n --color-background: hsl(var(--background));\n --color-foreground: hsl(var(--foreground));\n --color-primary: hsl(var(--primary));\n --color-primary-foreground: hsl(var(--primary-foreground));\n --color-secondary: hsl(var(--secondary));\n --color-secondary-foreground: hsl(var(--secondary-foreground));\n --color-destructive: hsl(var(--destructive));\n --color-destructive-foreground: hsl(var(--destructive-foreground));\n --color-muted: hsl(var(--muted));\n --color-muted-foreground: hsl(var(--muted-foreground));\n --color-accent: hsl(var(--accent));\n --color-accent-foreground: hsl(var(--accent-foreground));\n --color-popover: hsl(var(--popover));\n --color-popover-foreground: hsl(var(--popover-foreground));\n --color-card: hsl(var(--card));\n --color-card-foreground: hsl(var(--card-foreground));\n --color-sidebar: hsl(var(--sidebar-background));\n --color-sidebar-foreground: hsl(var(--sidebar-foreground));\n --color-sidebar-primary: hsl(var(--sidebar-primary));\n --color-sidebar-primary-foreground: hsl(var(--sidebar-primary-foreground));\n --color-sidebar-accent: hsl(var(--sidebar-accent));\n --color-sidebar-accent-foreground: hsl(var(--sidebar-accent-foreground));\n --color-sidebar-border: hsl(var(--sidebar-border));\n --color-sidebar-ring: hsl(var(--sidebar-ring));\n --radius-lg: var(--radius);\n --radius-md: calc(var(--radius) - 2px);\n --radius-sm: calc(var(--radius) - 4px);\n }\n </style>\n\t <style>\n\t *, *::before, *::after { border-color: hsl(var(--border)); }\n\t body {\n\t --agent-native-tool-padding: clamp(16px, 2vw, 24px);\n\t box-sizing: border-box;\n\t font-family: 'Inter', sans-serif;\n\t margin: 0;\n\t min-height: 100vh;\n\t padding: var(--agent-native-tool-padding);\n\t }\n\t body:has(> [data-tool-layout=\"full-bleed\"]),\n\t body:has(> [data-tool-padding=\"none\"]),\n\t body:has(> .agent-native-tool-bleed) {\n\t padding: 0;\n\t }\n\t </style>\n\t <script>\n\t var _toolRequestSeq = 0;\n\t var _toolPendingRequests = {};\n\n\t window.addEventListener('message', function(event) {\n\t if (event.source !== window.parent) return;\n\t var message = event.data || {};\n\t if (message.type !== 'agent-native-tool-response') return;\n\t var pending = _toolPendingRequests[message.requestId];\n\t if (!pending) return;\n\t delete _toolPendingRequests[message.requestId];\n\t if (message.error) {\n\t pending.reject(new Error(message.error));\n\t } else {\n\t pending.resolve(message.response);\n\t }\n\t });\n\n\t function hostRequest(path, options) {\n\t options = options || {};\n\t return new Promise(function(resolve, reject) {\n\t var requestId = 'tool-req-' + (++_toolRequestSeq);\n\t _toolPendingRequests[requestId] = { resolve: resolve, reject: reject };\n\t window.parent.postMessage({\n\t type: 'agent-native-tool-request',\n\t requestId: requestId,\n\t path: path,\n\t options: {\n\t method: options.method || 'GET',\n\t headers: options.headers || {},\n\t body: options.body,\n\t },\n\t }, '*');\n\t setTimeout(function() {\n\t var pending = _toolPendingRequests[requestId];\n\t if (!pending) return;\n\t delete _toolPendingRequests[requestId];\n\t pending.reject(new Error('Tool host request timed out'));\n\t }, 30000);\n\t });\n\t }\n\n\t var _origHostRequest = hostRequest;\n\t hostRequest = function(path, options) {\n\t var entry = { path: path, method: (options && options.method) || 'GET' };\n\t return _origHostRequest(path, options).then(function(res) {\n\t entry.ok = res.ok;\n\t entry.status = res.status;\n\t if (!res.ok && res.body) {\n\t try { entry.error = typeof res.body === 'string' ? res.body.slice(0, 200) : JSON.stringify(res.body).slice(0, 200); } catch(e) {}\n\t }\n\t if (_networkLogs.length >= 20) _networkLogs.shift();\n\t _networkLogs.push(entry);\n\t return res;\n\t }, function(err) {\n\t entry.ok = false;\n\t entry.error = err.message;\n\t if (_networkLogs.length >= 20) _networkLogs.shift();\n\t _networkLogs.push(entry);\n\t throw err;\n\t });\n\t };\n\n\t function toolFetch(url, options) {\n\t var opts = options || {};\n\t return hostRequest('/_agent-native/tools/proxy', {\n\t method: 'POST',\n\t headers: { 'Content-Type': 'application/json' },\n\t body: JSON.stringify({\n\t url: url,\n method: opts.method || 'GET',\n headers: opts.headers,\n body: opts.body,\n }),\n\t }).then(function(res) {\n\t var data = res.body;\n\t if (data.error && data.status === undefined) {\n\t throw new Error(data.error);\n\t }\n return {\n ok: data.status >= 200 && data.status < 300,\n status: data.status,\n\t json: function() { return Promise.resolve(data.body); },\n\t text: function() { return Promise.resolve(typeof data.body === 'string' ? data.body : JSON.stringify(data.body)); },\n\t };\n\t });\n\t }\n\n\t async function appAction(name, params) {\n\t params = params || {};\n\t var res = await hostRequest('/_agent-native/actions/' + encodeURIComponent(name), {\n\t method: 'POST',\n\t headers: { 'Content-Type': 'application/json' },\n\t body: JSON.stringify(params),\n\t });\n\t if (!res.ok) {\n\t var err = res.body || { error: res.statusText };\n\t throw new Error(err.error || 'Action failed: ' + res.status);\n\t }\n\t return res.body;\n\t }\n\n\t async function appFetch(path, options) {\n\t options = options || {};\n\t var res = await hostRequest(path, {\n\t ...options,\n\t headers: {\n\t 'Content-Type': 'application/json',\n\t ...(options.headers || {}),\n\t },\n\t });\n\t if (!res.ok) {\n\t var err = typeof res.body === 'object' && res.body ? res.body : { error: res.statusText };\n\t throw new Error(err.error || 'Request failed: ' + res.status);\n\t }\n\t return res.body;\n\t }\n\n async function dbQuery(sql, args) {\n var body = { sql: sql };\n if (args) body.args = args;\n return appFetch('/_agent-native/tools/sql/query', {\n method: 'POST',\n body: JSON.stringify(body),\n });\n }\n\n async function dbExec(sql, args) {\n var body = { sql: sql };\n if (args) body.args = args;\n return appFetch('/_agent-native/tools/sql/exec', {\n method: 'POST',\n body: JSON.stringify(body),\n });\n }\n\n var _toolId = ${toolIdJson};\n var _toolBinding = ${bindingJson};\n window.toolBinding = _toolBinding;\n // SECURITY (audit H4): announce the resolved binding to the parent so the\n // host bridge can gate dangerous helpers based on viewer role. Sent\n // BEFORE the user-authored content has a chance to run, so a malicious\n // tool body cannot suppress or rewrite the announcement. The parent\n // ignores subsequent announcements for the same iframe; see\n // ToolViewer.tsx / EmbeddedTool.tsx.\n try {\n window.parent.postMessage(\n {\n type: 'agent-native-tool-binding',\n toolId: _toolId,\n binding: _toolBinding,\n },\n '*',\n );\n } catch (_) {}\n // SECURITY: when the viewer is not the author of this tool, emit a clear\n // console warning. The bridge currently runs every helper with the\n // viewer's session — a malicious shared tool can call any action, read\n // any owned table row in scope, and resolve any user-scope secret. A\n // full consent step is tracked as TODO C1 in audit 05-tools-sandbox.md.\n if (_toolBinding && !_toolBinding.isAuthor) {\n try {\n console.warn(\n '[agent-native] Shared tool — running with viewer\\\\'s session. ' +\n 'Author: ' + (_toolBinding.authorEmail || '<unknown>') + '. ' +\n 'Bridge calls (appAction, dbExec, toolFetch) execute under ' +\n 'your account; they are gated by your permissions, not the ' +\n 'author\\\\'s. Do not run untrusted shared tools.',\n );\n } catch (_) {}\n }\n\n var toolData = {\n\t async list(collection, opts) {\n\t var limit = (opts && opts.limit) || 100;\n\t var scope = (opts && opts.scope) || 'user';\n\t var res = await hostRequest('/_agent-native/tools/data/' + _toolId + '/' + encodeURIComponent(collection) + '?limit=' + limit + '&scope=' + scope);\n\t if (!res.ok) throw new Error('Failed to list tool data');\n\t return res.body;\n\t },\n async get(collection, id, opts) {\n var scope = (opts && opts.scope) || 'user';\n var items = await this.list(collection, { scope: scope });\n return (items || []).find(function(item) { return item.id === id; }) || null;\n },\n async set(collection, id, data, opts) {\n\t var scope = (opts && opts.scope) || 'user';\n\t var res = await hostRequest('/_agent-native/tools/data/' + _toolId + '/' + encodeURIComponent(collection), {\n\t method: 'POST',\n\t headers: { 'Content-Type': 'application/json' },\n\t body: JSON.stringify({ id: id, data: data, scope: scope }),\n\t });\n\t if (!res.ok) throw new Error('Failed to save tool data');\n\t return res.body;\n\t },\n\t async remove(collection, id, opts) {\n\t var scope = (opts && opts.scope) || 'user';\n\t var res = await hostRequest('/_agent-native/tools/data/' + _toolId + '/' + encodeURIComponent(collection) + '/' + encodeURIComponent(id) + '?scope=' + scope, {\n\t method: 'DELETE',\n\t });\n\t if (!res.ok) throw new Error('Failed to delete tool data');\n\t return res.body;\n\t },\n\t };\n\t </script>\n\t <style>\n\t #__tool-error-toast {\n\t display: none;\n\t position: fixed;\n\t bottom: 16px;\n\t right: 16px;\n\t max-width: 420px;\n\t background: hsl(var(--destructive));\n\t color: hsl(var(--destructive-foreground));\n\t border: 1px solid hsl(var(--destructive) / .6);\n\t border-radius: calc(var(--radius, .5rem) + 2px);\n\t padding: 12px 16px;\n\t font-size: 13px;\n\t line-height: 1.4;\n\t font-family: 'Inter', sans-serif;\n\t z-index: 9999;\n\t box-shadow: 0 4px 12px rgba(0,0,0,.15), 0 1px 3px rgba(0,0,0,.1);\n\t animation: __toast-in 0.2s ease-out;\n\t }\n\t @keyframes __toast-in {\n\t from { opacity: 0; transform: translateY(8px); }\n\t to { opacity: 1; transform: translateY(0); }\n\t }\n\t </style>\n\t <script>\n\t // Extension-point slot context: when a tool is rendered embedded inside an\n\t // ExtensionSlot, the host pushes a context object via postMessage. Tools\n\t // read it synchronously via window.slotContext or subscribe to changes\n\t // via window.onSlotContext(fn). When rendered full-page (no ?slot= param),\n\t // slotContext stays null and tools branch on that.\n\t window.slotContext = null;\n\t var _slotContextSubscribers = [];\n\t window.onSlotContext = function(fn) {\n\t _slotContextSubscribers.push(fn);\n\t if (window.slotContext !== null) {\n\t try { fn(window.slotContext); } catch(_) {}\n\t }\n\t return function() {\n\t _slotContextSubscribers = _slotContextSubscribers.filter(function(f) { return f !== fn; });\n\t };\n\t };\n\t window.addEventListener('message', function(event) {\n\t if (event.source !== window.parent) return;\n\t var msg = event.data;\n\t if (!msg || msg.type !== 'agent-native-slot-context') return;\n\t window.slotContext = msg.context || {};\n\t _slotContextSubscribers.forEach(function(fn) {\n\t try { fn(window.slotContext); } catch(_) {}\n\t });\n\t });\n\n\t // Auto-resize the iframe to its content when running in slot mode. The\n\t // host listens for agent-native-tool-resize and adjusts the iframe height.\n\t if (new URLSearchParams(location.search).get('slot')) {\n\t var _lastH = 0;\n\t var _reportHeight = function() {\n\t var h = Math.max(\n\t document.documentElement.scrollHeight,\n\t document.body ? document.body.scrollHeight : 0,\n\t );\n\t if (h !== _lastH) {\n\t _lastH = h;\n\t window.parent.postMessage({ type: 'agent-native-tool-resize', height: h }, '*');\n\t }\n\t };\n\t if (typeof ResizeObserver !== 'undefined') {\n\t var _ro = new ResizeObserver(_reportHeight);\n\t document.addEventListener('DOMContentLoaded', function() {\n\t _ro.observe(document.documentElement);\n\t if (document.body) _ro.observe(document.body);\n\t });\n\t }\n\t // Initial reports — Alpine takes a tick to render after DOMContentLoaded.\n\t setTimeout(_reportHeight, 50);\n\t setTimeout(_reportHeight, 250);\n\t }\n\n\t window.addEventListener('message', function(event) {\n\t if (event.source !== window.parent) return;\n\t var msg = event.data;\n\t if (!msg || msg.type !== 'agent-native-theme-update') return;\n\t var root = document.documentElement;\n\t if (msg.isDark !== undefined) {\n\t if (msg.isDark) root.classList.add('dark');\n\t else root.classList.remove('dark');\n\t }\n\t var vars = msg.vars || {};\n\t for (var key in vars) {\n\t if (vars.hasOwnProperty(key)) {\n\t root.style.setProperty(key, vars[key]);\n\t }\n\t }\n\t });\n\n\t document.addEventListener('keydown', function(e) {\n\t if ((e.metaKey || e.ctrlKey) && !e.altKey) {\n\t var key = e.key.toLowerCase();\n\t if (key === 'c' || key === 'v' || key === 'x' || key === 'a' || key === 'z' || key === 'y') return;\n\t e.preventDefault();\n\t e.stopPropagation();\n\t window.parent.postMessage({\n\t type: 'agent-native-tool-keydown',\n\t key: e.key, code: e.code,\n\t metaKey: e.metaKey, ctrlKey: e.ctrlKey,\n\t shiftKey: e.shiftKey, altKey: e.altKey,\n\t }, '*');\n\t return;\n\t }\n\t if (e.key === 'Escape') {\n\t window.parent.postMessage({\n\t type: 'agent-native-tool-keydown',\n\t key: e.key, code: e.code,\n\t metaKey: false, ctrlKey: false,\n\t shiftKey: false, altKey: false,\n\t }, '*');\n\t }\n\t });\n\n\t document.addEventListener('DOMContentLoaded', function() {\n\t var fixBtn = document.getElementById('__tool-error-fix');\n\t if (fixBtn) {\n\t fixBtn.addEventListener('click', function() {\n\t window.parent.postMessage({\n\t type: 'agent-native-tool-error-fix',\n\t errors: _toolErrors,\n\t errorDetails: _toolErrorDetails,\n\t consoleLogs: _consoleLogs.slice(-30),\n\t networkLogs: _networkLogs.slice(-15)\n\t }, '*');\n\t document.getElementById('__tool-error-toast').style.display = 'none';\n\t });\n\t }\n\t var dismissBtn = document.getElementById('__tool-error-dismiss');\n\t if (dismissBtn) {\n\t dismissBtn.addEventListener('click', function() {\n\t document.getElementById('__tool-error-toast').style.display = 'none';\n\t });\n\t }\n\t });\n\t </script>\n\t</head>\n\t<body${toolId ? ` data-tool-id=\"${toolIdAttr}\"` : \"\"} class=\"bg-background text-foreground\">\n\t${content}\n\t<div id=\"__tool-error-toast\">\n\t <div style=\"display:flex;align-items:flex-start;gap:8px;\">\n\t <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex-shrink:0;margin-top:1px;\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"/><line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"/></svg>\n\t <span id=\"__tool-error-msg\" style=\"flex:1;overflow:hidden;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;\"></span>\n\t <button id=\"__tool-error-fix\" style=\"cursor:pointer;border:none;background:rgba(255,255,255,.9);color:hsl(0 84.2% 40%);font-size:12px;font-weight:500;padding:4px 12px;border-radius:4px;flex-shrink:0;\">Fix</button>\n\t <button id=\"__tool-error-dismiss\" style=\"cursor:pointer;border:none;background:transparent;color:inherit;font-size:16px;padding:2px 6px;opacity:0.7;flex-shrink:0;\">&#215;</button>\n\t </div>\n\t</div>\n\t</body>\n\t</html>`;\n}\n\nfunction escapeHtmlAttribute(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\");\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"proxy-security.d.ts","sourceRoot":"","sources":["../../src/tools/proxy-security.ts"],"names":[],"mappings":"AAuBA,eAAO,MAAM,4BAA4B,QAAc,CAAC;AAWxD,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAGtE;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,GACb,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAexB;AAED,wBAAgB,mBAAmB,CACjC,GAAG,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC,GAC1C,MAAM,EAAE,CAQV;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,CAAC,CAiBpE;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,MAAM,CAQzE;AAaD,wBAAsB,yBAAyB,CAC7C,QAAQ,EAAE,QAAQ,EAClB,QAAQ,SAA+B,GACtC,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAyD7D"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"proxy-security.js","sourceRoot":"","sources":["../../src/tools/proxy-security.ts"],"names":[],"mappings":"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","sourcesContent":["const HEADER_NAME_RE = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;\n\nconst BLOCKED_OUTBOUND_HEADERS = new Set([\n \"connection\",\n \"content-length\",\n \"cookie\",\n \"forwarded\",\n \"host\",\n \"keep-alive\",\n \"origin\",\n \"proxy-authenticate\",\n \"proxy-authorization\",\n \"referer\",\n \"set-cookie\",\n \"te\",\n \"trailer\",\n \"transfer-encoding\",\n \"upgrade\",\n \"x-forwarded-for\",\n \"x-forwarded-host\",\n \"x-forwarded-proto\",\n]);\n\nexport const MAX_TOOL_PROXY_RESPONSE_SIZE = 1024 * 1024;\n\nconst ALLOWED_METHODS = new Set([\n \"GET\",\n \"POST\",\n \"PUT\",\n \"PATCH\",\n \"DELETE\",\n \"HEAD\",\n]);\n\nexport function normalizeToolProxyMethod(value: unknown): string | null {\n const method = String(value || \"GET\").toUpperCase();\n return ALLOWED_METHODS.has(method) ? method : null;\n}\n\nexport function sanitizeOutboundHeaders(\n value: unknown,\n): Record<string, string> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return {};\n\n const headers: Record<string, string> = {};\n for (const [name, rawValue] of Object.entries(value)) {\n const lower = name.toLowerCase();\n if (!HEADER_NAME_RE.test(name) || BLOCKED_OUTBOUND_HEADERS.has(lower)) {\n continue;\n }\n if (rawValue === undefined || rawValue === null) continue;\n const headerValue = String(rawValue);\n if (/[\\r\\n]/.test(headerValue)) continue;\n headers[name] = headerValue;\n }\n return headers;\n}\n\nexport function collectSecretValues(\n ...groups: Array<Array<string> | undefined>\n): string[] {\n const values = new Set<string>();\n for (const group of groups) {\n for (const value of group ?? []) {\n if (value) values.add(value);\n }\n }\n return [...values].sort((a, b) => b.length - a.length);\n}\n\nexport function redactSecrets<T>(value: T, secretValues: string[]): T {\n if (secretValues.length === 0) return value;\n if (typeof value === \"string\") {\n return redactString(value, secretValues) as T;\n }\n if (Array.isArray(value)) {\n return value.map((item) => redactSecrets(item, secretValues)) as T;\n }\n if (value && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value).map(([key, entry]) => [\n key,\n redactSecrets(entry, secretValues),\n ]),\n ) as T;\n }\n return value;\n}\n\nexport function redactString(text: string, secretValues: string[]): string {\n let out = text;\n for (const secret of secretValues) {\n for (const candidate of redactionCandidates(secret)) {\n if (candidate) out = out.split(candidate).join(\"[redacted]\");\n }\n }\n return out;\n}\n\nfunction redactionCandidates(secret: string): string[] {\n const candidates = new Set([secret]);\n try {\n candidates.add(encodeURIComponent(secret));\n } catch {}\n try {\n candidates.add(encodeURI(secret));\n } catch {}\n return [...candidates].sort((a, b) => b.length - a.length);\n}\n\nexport async function readResponseTextWithLimit(\n response: Response,\n maxBytes = MAX_TOOL_PROXY_RESPONSE_SIZE,\n): Promise<{ text: string; truncated: boolean; size: number }> {\n const contentLength = response.headers.get(\"content-length\");\n if (contentLength && Number(contentLength) > maxBytes) {\n return {\n text: `(response too large - ${contentLength} bytes, max ${maxBytes})`,\n truncated: true,\n size: Number(contentLength),\n };\n }\n\n const reader = response.body?.getReader?.();\n if (!reader) {\n const buffer = await response.arrayBuffer();\n if (buffer.byteLength > maxBytes) {\n return {\n text: `(response truncated - ${buffer.byteLength} bytes, max ${maxBytes})`,\n truncated: true,\n size: buffer.byteLength,\n };\n }\n return {\n text: new TextDecoder().decode(buffer),\n truncated: false,\n size: buffer.byteLength,\n };\n }\n\n const chunks: Uint8Array[] = [];\n let total = 0;\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (!value) continue;\n total += value.byteLength;\n if (total > maxBytes) {\n await reader.cancel().catch(() => {});\n return {\n text: `(response truncated - ${total} bytes, max ${maxBytes})`,\n truncated: true,\n size: total,\n };\n }\n chunks.push(value);\n }\n\n const buffer = new Uint8Array(total);\n let offset = 0;\n for (const chunk of chunks) {\n buffer.set(chunk, offset);\n offset += chunk.byteLength;\n }\n\n return {\n text: new TextDecoder().decode(buffer),\n truncated: false,\n size: total,\n };\n}\n"]}
@@ -1,2 +0,0 @@
1
- export declare function createToolsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<unknown>>;
2
- //# sourceMappingURL=routes.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/tools/routes.ts"],"names":[],"mappings":"AA+CA,wBAAgB,kBAAkB,2FA8BjC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/tools/routes.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport {\n defineEventHandler,\n getMethod,\n setResponseStatus,\n setResponseHeader,\n type H3Event,\n} from \"h3\";\nimport { readBody } from \"../server/h3-helpers.js\";\nimport { getSession } from \"../server/auth.js\";\nimport { recordChange } from \"../server/poll.js\";\nimport {\n runWithRequestContext,\n getRequestOrgId,\n} from \"../server/request-context.js\";\nimport { getOrgContext } from \"../org/context.js\";\nimport { getDbExec, isPostgres } from \"../db/client.js\";\nimport {\n listTools,\n getTool,\n createTool,\n updateTool,\n updateToolContent,\n deleteTool,\n ensureToolsTables,\n} from \"./store.js\";\nimport { buildToolHtml, TOOL_IFRAME_CSP } from \"./html-shell.js\";\nimport { getThemeVars } from \"./theme.js\";\nimport {\n resolveKeyReferences,\n validateUrlAllowlist,\n getKeyAllowlist,\n} from \"../secrets/substitution.js\";\nimport {\n collectSecretValues,\n normalizeToolProxyMethod,\n readResponseTextWithLimit,\n redactSecrets,\n redactString,\n sanitizeOutboundHeaders,\n} from \"./proxy-security.js\";\nimport {\n createSsrfSafeDispatcher,\n isBlockedToolUrlWithDns,\n} from \"./url-safety.js\";\nimport { ForbiddenError, resolveAccess } from \"../sharing/access.js\";\n\nexport function createToolsHandler() {\n return defineEventHandler(async (event: H3Event) => {\n const method = getMethod(event);\n const pathname = (event.url?.pathname || \"\")\n .replace(/^\\/+/, \"\")\n .replace(/\\/+$/, \"\");\n const parts = pathname ? pathname.split(\"/\") : [];\n\n const session = await getSession(event).catch(() => null);\n if (!session?.email) {\n setResponseStatus(event, 401);\n return { error: \"Authentication required\" };\n }\n\n const orgCtx = await getOrgContext(event).catch(() => null);\n const userEmail = session.email;\n const orgId = orgCtx?.orgId ?? undefined;\n\n try {\n return await runWithRequestContext({ userEmail, orgId }, () =>\n dispatch(event, method, parts, userEmail),\n );\n } catch (err) {\n if (err instanceof ForbiddenError) {\n setResponseStatus(event, 403);\n return { error: err.message };\n }\n throw err;\n }\n });\n}\n\nasync function dispatch(\n event: H3Event,\n method: string,\n parts: string[],\n userEmail: string,\n): Promise<unknown> {\n // POST /sql/query — read-only SQL for tool iframes\n if (\n method === \"POST\" &&\n parts.length === 2 &&\n parts[0] === \"sql\" &&\n parts[1] === \"query\"\n ) {\n return handleSqlQuery(event);\n }\n\n // POST /sql/exec — write SQL for tool iframes\n if (\n method === \"POST\" &&\n parts.length === 2 &&\n parts[0] === \"sql\" &&\n parts[1] === \"exec\"\n ) {\n return handleSqlExec(event);\n }\n\n // GET /data/:toolId/:collection — list items in a collection\n if (method === \"GET\" && parts.length === 3 && parts[0] === \"data\") {\n return handleToolDataList(event, parts[1], parts[2], userEmail);\n }\n\n // POST /data/:toolId/:collection — create/upsert an item\n if (method === \"POST\" && parts.length === 3 && parts[0] === \"data\") {\n return handleToolDataUpsert(event, parts[1], parts[2], userEmail);\n }\n\n // DELETE /data/:toolId/:collection/:itemId — delete an item\n if (method === \"DELETE\" && parts.length === 4 && parts[0] === \"data\") {\n return handleToolDataDelete(event, parts[1], parts[2], parts[3], userEmail);\n }\n\n // POST /proxy\n if (method === \"POST\" && parts.length === 1 && parts[0] === \"proxy\") {\n return handleProxy(event, userEmail);\n }\n\n // GET / — list\n if (method === \"GET\" && parts.length === 0) {\n return listTools();\n }\n\n // POST / — create\n if (method === \"POST\" && parts.length === 0) {\n const body = await readBody(event);\n if (!body.name) {\n setResponseStatus(event, 400);\n return { error: \"name is required\" };\n }\n const tool = await createTool(body);\n recordChange({ source: \"action\", type: \"change\" });\n setResponseStatus(event, 201);\n return tool;\n }\n\n // GET /:id/render\n if (method === \"GET\" && parts.length === 2 && parts[1] === \"render\") {\n const access = await resolveAccess(\"tool\", parts[0]);\n const tool = access?.resource;\n if (!tool) {\n setResponseStatus(event, 404);\n return { error: \"Tool not found\" };\n }\n const search = event.url?.search || \"\";\n const isDark = search.includes(\"dark=1\") || search.includes(\"dark=true\");\n const themeVars = getThemeVars(isDark);\n // Compute viewer-vs-author binding so the iframe can warn when the\n // viewer is NOT the author. The role is plumbed through to gate\n // dangerous bridge helpers in iframe-bridge.ts (audit H4).\n const isAuthor = tool.ownerEmail === userEmail;\n\n const html = buildToolHtml(tool.content, themeVars, isDark, parts[0], {\n authorEmail: tool.ownerEmail,\n viewerEmail: userEmail,\n isAuthor,\n role: access.role,\n });\n // Security headers per render. We set these explicitly here (rather than\n // rely on the global security-headers middleware) because:\n // - The global middleware sets X-Frame-Options: DENY which would break\n // the legitimate iframe usage of this route inside the app.\n // - frame-ancestors in the CSP must be set as an HTTP header to be\n // enforced; meta-CSP can't set it per spec.\n setResponseHeader(event, \"Content-Type\", \"text/html; charset=utf-8\");\n setResponseHeader(event, \"Content-Security-Policy\", TOOL_IFRAME_CSP);\n setResponseHeader(event, \"X-Frame-Options\", \"SAMEORIGIN\");\n setResponseHeader(event, \"X-Content-Type-Options\", \"nosniff\");\n setResponseHeader(event, \"Referrer-Policy\", \"no-referrer\");\n return html;\n }\n\n // GET /:id\n if (method === \"GET\" && parts.length === 1) {\n const tool = await getTool(parts[0]);\n if (!tool) {\n setResponseStatus(event, 404);\n return { error: \"Tool not found\" };\n }\n return tool;\n }\n\n // PUT /:id\n if (method === \"PUT\" && parts.length === 1) {\n const body = await readBody(event);\n const hasContentUpdate =\n body.content !== undefined || body.patches !== undefined;\n const hasMetaUpdate =\n body.name !== undefined ||\n body.description !== undefined ||\n body.icon !== undefined ||\n body.visibility !== undefined;\n\n let result = null;\n if (hasContentUpdate) {\n result = await updateToolContent(parts[0], {\n content: body.content,\n patches: body.patches,\n });\n }\n if (hasMetaUpdate) {\n result = await updateTool(parts[0], body);\n }\n if (!hasContentUpdate && !hasMetaUpdate) {\n result = await getTool(parts[0]);\n }\n if (!result) {\n setResponseStatus(event, 404);\n return { error: \"Tool not found\" };\n }\n recordChange({ source: \"action\", type: \"change\" });\n return result;\n }\n\n // DELETE /:id\n if (method === \"DELETE\" && parts.length === 1) {\n const ok = await deleteTool(parts[0]);\n if (!ok) {\n setResponseStatus(event, 404);\n return { error: \"Tool not found\" };\n }\n recordChange({ source: \"action\", type: \"change\" });\n return { ok: true };\n }\n\n setResponseStatus(event, 404);\n return { error: \"Not found\" };\n}\n\nasync function handleToolDataList(\n event: H3Event,\n toolId: string,\n collection: string,\n userEmail: string,\n): Promise<unknown> {\n await ensureToolsTables();\n const tool = await getTool(toolId);\n if (!tool) {\n setResponseStatus(event, 404);\n return { error: \"Tool not found\" };\n }\n const client = getDbExec();\n const url = event.url;\n const limitParam = url?.searchParams?.get(\"limit\");\n const limit = limitParam\n ? Math.min(Math.max(1, Number(limitParam)), 1000)\n : 100;\n const scope = url?.searchParams?.get(\"scope\") || \"user\";\n const orgId = getRequestOrgId();\n\n if (scope === \"org\") {\n if (!orgId) {\n setResponseStatus(event, 400);\n return { error: \"Org context required for scope=org\" };\n }\n const result = await client.execute({\n sql: `SELECT COALESCE(item_id, id) AS id, tool_id, collection, data, owner_email, scope, org_id, created_at, updated_at\n FROM tool_data\n WHERE tool_id = ? AND collection = ? AND scope = 'org' AND org_id = ?\n ORDER BY created_at DESC\n LIMIT ?`,\n args: [toolId, collection, orgId, limit],\n });\n return result.rows ?? [];\n }\n\n if (scope === \"all\") {\n const result = await client.execute({\n sql: `SELECT COALESCE(item_id, id) AS id, tool_id, collection, data, owner_email, scope, org_id, created_at, updated_at\n FROM tool_data\n WHERE tool_id = ? AND collection = ?\n AND ((scope = 'user' AND owner_email = ?) OR (scope = 'org' AND org_id = ?))\n ORDER BY created_at DESC\n LIMIT ?`,\n args: [toolId, collection, userEmail, orgId ?? \"\", limit],\n });\n return result.rows ?? [];\n }\n\n const result = await client.execute({\n sql: `SELECT COALESCE(item_id, id) AS id, tool_id, collection, data, owner_email, scope, org_id, created_at, updated_at\n FROM tool_data\n WHERE tool_id = ? AND collection = ? AND scope = 'user' AND owner_email = ?\n ORDER BY updated_at DESC\n LIMIT ?`,\n args: [toolId, collection, userEmail, limit],\n });\n return result.rows ?? [];\n}\n\nasync function handleToolDataUpsert(\n event: H3Event,\n toolId: string,\n collection: string,\n userEmail: string,\n): Promise<unknown> {\n await ensureToolsTables();\n const tool = await getTool(toolId);\n if (!tool) {\n setResponseStatus(event, 404);\n return { error: \"Tool not found\" };\n }\n const body = await readBody(event);\n if (body.data === undefined) {\n setResponseStatus(event, 400);\n return { error: \"data is required\" };\n }\n const itemId = String(body.id || randomUUID());\n const data =\n typeof body.data === \"string\" ? body.data : JSON.stringify(body.data);\n const now = new Date().toISOString();\n const scope = body.scope === \"org\" ? \"org\" : \"user\";\n const orgId = getRequestOrgId();\n\n if (scope === \"org\" && !orgId) {\n setResponseStatus(event, 400);\n return { error: \"Org context required for scope=org\" };\n }\n\n const scopeKey = scope === \"org\" ? `org:${orgId}` : userEmail;\n const client = getDbExec();\n const pg = isPostgres();\n const conflictClause = pg\n ? `ON CONFLICT (tool_id, collection, scope_key, item_id)\n DO UPDATE SET data = EXCLUDED.data, updated_at = EXCLUDED.updated_at`\n : `ON CONFLICT (tool_id, collection, scope_key, item_id)\n DO UPDATE SET data = excluded.data, updated_at = excluded.updated_at`;\n\n await client.execute({\n sql: `INSERT INTO tool_data (id, tool_id, collection, item_id, data, owner_email, scope, org_id, scope_key, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ${conflictClause}`,\n args: [\n randomUUID(),\n toolId,\n collection,\n itemId,\n data,\n userEmail,\n scope,\n scope === \"org\" ? orgId! : null,\n scopeKey,\n now,\n now,\n ],\n });\n return {\n id: itemId,\n toolId,\n collection,\n data,\n ownerEmail: userEmail,\n scope,\n orgId: scope === \"org\" ? orgId : null,\n createdAt: now,\n updatedAt: now,\n };\n}\n\nasync function handleToolDataDelete(\n event: H3Event,\n toolId: string,\n collection: string,\n itemId: string,\n userEmail: string,\n): Promise<unknown> {\n await ensureToolsTables();\n const tool = await getTool(toolId);\n if (!tool) {\n setResponseStatus(event, 404);\n return { error: \"Tool not found\" };\n }\n const url = event.url;\n const scope = url?.searchParams?.get(\"scope\") || \"user\";\n const orgId = getRequestOrgId();\n const client = getDbExec();\n\n if (scope === \"org\") {\n if (!orgId) {\n setResponseStatus(event, 400);\n return { error: \"Org context required for scope=org\" };\n }\n await client.execute({\n sql: `DELETE FROM tool_data WHERE COALESCE(item_id, id) = ? AND tool_id = ? AND collection = ? AND scope = 'org' AND org_id = ?`,\n args: [itemId, toolId, collection, orgId],\n });\n return { ok: true };\n }\n\n await client.execute({\n sql: `DELETE FROM tool_data WHERE COALESCE(item_id, id) = ? AND tool_id = ? AND collection = ? AND scope = 'user' AND owner_email = ?`,\n args: [itemId, toolId, collection, userEmail],\n });\n return { ok: true };\n}\n\nasync function handleProxy(\n event: H3Event,\n userEmail: string,\n): Promise<unknown> {\n const body = await readBody(event);\n const rawUrl = body.url;\n if (!rawUrl || typeof rawUrl !== \"string\") {\n setResponseStatus(event, 400);\n return { error: \"url is required\" };\n }\n\n const method = normalizeToolProxyMethod(body.method || \"GET\");\n if (!method) {\n setResponseStatus(event, 405);\n return {\n error:\n \"Unsupported HTTP method. Allowed methods: GET, POST, PUT, PATCH, DELETE, HEAD.\",\n };\n }\n const rawHeaders: Record<string, string> = body.headers || {};\n const rawBody = body.body;\n\n let resolvedUrl = rawUrl;\n let resolvedHeaders = JSON.stringify(rawHeaders);\n let resolvedBody = rawBody;\n const allUsedKeys: string[] = [];\n const allSecretValues: string[] = [];\n\n try {\n const urlResult = await resolveKeyReferences(rawUrl, \"user\", userEmail);\n resolvedUrl = urlResult.resolved;\n allUsedKeys.push(...urlResult.usedKeys);\n allSecretValues.push(...urlResult.secretValues);\n\n const headerResult = await resolveKeyReferences(\n resolvedHeaders,\n \"user\",\n userEmail,\n );\n resolvedHeaders = headerResult.resolved;\n allUsedKeys.push(...headerResult.usedKeys);\n allSecretValues.push(...headerResult.secretValues);\n\n if (rawBody) {\n const bodyResult = await resolveKeyReferences(\n typeof rawBody === \"string\" ? rawBody : JSON.stringify(rawBody),\n \"user\",\n userEmail,\n );\n resolvedBody = bodyResult.resolved;\n allUsedKeys.push(...bodyResult.usedKeys);\n allSecretValues.push(...bodyResult.secretValues);\n }\n } catch (err: any) {\n setResponseStatus(event, 400);\n return { error: `Key resolution failed: ${err?.message ?? err}` };\n }\n const secretValues = collectSecretValues(allSecretValues);\n\n if (await isBlockedToolUrlWithDns(resolvedUrl)) {\n setResponseStatus(event, 403);\n return { error: \"Requests to private/internal addresses are not allowed\" };\n }\n\n for (const keyName of new Set(allUsedKeys)) {\n const allowlist = await getKeyAllowlist(keyName, \"user\", userEmail);\n if (!validateUrlAllowlist(resolvedUrl, allowlist)) {\n setResponseStatus(event, 403);\n return {\n error: `Key \"${keyName}\" is not allowed for this URL origin`,\n };\n }\n }\n\n let headers: Record<string, string>;\n try {\n headers = sanitizeOutboundHeaders(JSON.parse(resolvedHeaders));\n } catch {\n headers = sanitizeOutboundHeaders(rawHeaders);\n }\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 15_000);\n\n // Best-effort connect-time SSRF guard. When undici is available (it ships\n // with Node 18+ but is not always exposed as an importable module), the\n // dispatcher re-checks the resolved IP at TCP-connect time, closing the\n // TOCTOU between the pre-flight `isBlockedToolUrlWithDns` lookup and the\n // actual fetch lookup. If undici is not importable, fall through to plain\n // fetch — the pre-flight remains the primary protection.\n const dispatcher = (await createSsrfSafeDispatcher()) ?? undefined;\n\n try {\n const fetchOpts: RequestInit & { dispatcher?: unknown } = {\n method,\n headers,\n signal: controller.signal,\n redirect: \"manual\",\n };\n if (dispatcher) fetchOpts.dispatcher = dispatcher;\n if (resolvedBody && [\"POST\", \"PUT\", \"PATCH\"].includes(method)) {\n const isStringBody = typeof resolvedBody === \"string\";\n fetchOpts.body = isStringBody\n ? resolvedBody\n : JSON.stringify(resolvedBody);\n // Only inject Content-Type when (a) the caller didn't set one and\n // (b) the body is actually JSON-shaped (object or stringified JSON).\n // Otherwise leave it unset so the runtime fetch picks an appropriate\n // default and we don't misrepresent text/plain bodies as JSON.\n const hasContentType = Object.keys(headers).some(\n (k) => k.toLowerCase() === \"content-type\",\n );\n if (!hasContentType) {\n const isJsonShaped =\n !isStringBody ||\n (typeof resolvedBody === \"string\" &&\n /^\\s*[{[]/.test(resolvedBody) &&\n isLikelyJson(resolvedBody));\n if (isJsonShaped) headers[\"Content-Type\"] = \"application/json\";\n }\n }\n\n const response = await fetch(resolvedUrl, fetchOpts);\n\n if (response.status >= 300 && response.status < 400) {\n const location = response.headers.get(\"location\");\n const redirectUrl = location ? new URL(location, resolvedUrl).href : null;\n if (redirectUrl && (await isBlockedToolUrlWithDns(redirectUrl))) {\n setResponseStatus(event, 403);\n return { error: \"Redirect to private/internal address blocked\" };\n }\n if (redirectUrl) {\n for (const keyName of new Set(allUsedKeys)) {\n const allowlist = await getKeyAllowlist(keyName, \"user\", userEmail);\n if (!validateUrlAllowlist(redirectUrl, allowlist)) {\n setResponseStatus(event, 403);\n return {\n error: `Redirect URL is not allowed for key \"${keyName}\"`,\n };\n }\n }\n }\n return {\n status: response.status,\n body: {\n redirect: redirectUrl\n ? redactString(redirectUrl, secretValues)\n : location,\n },\n };\n }\n\n const { text } = await readResponseTextWithLimit(response);\n let responseBody: unknown;\n try {\n responseBody = JSON.parse(text);\n } catch {\n responseBody = text;\n }\n\n return {\n status: response.status,\n body: redactSecrets(responseBody, secretValues),\n };\n } catch (err: any) {\n if (err?.name === \"AbortError\") {\n setResponseStatus(event, 504);\n return { error: \"Upstream request timed out\" };\n }\n setResponseStatus(event, 502);\n return {\n error: `Proxy request failed: ${redactSecrets(\n err?.message ?? String(err),\n secretValues,\n )}`,\n };\n } finally {\n clearTimeout(timeout);\n }\n}\n\n/**\n * Capture console output from a CLI script that uses console.log for results.\n * Same technique as wrapCliScript in agent-chat-plugin.ts.\n */\nlet captureCliOutputQueue: Promise<void> = Promise.resolve();\n\nasync function captureCliOutput(\n fn: (args: string[]) => Promise<void>,\n args: string[],\n): Promise<string> {\n const previousCapture = captureCliOutputQueue;\n let releaseCapture!: () => void;\n captureCliOutputQueue = new Promise<void>((resolve) => {\n releaseCapture = resolve;\n });\n await previousCapture;\n\n const logs: string[] = [];\n const origLog = console.log;\n const origError = console.error;\n const origStdoutWrite = process.stdout.write;\n console.log = (...a: unknown[]) => {\n logs.push(a.map(String).join(\" \"));\n };\n console.error = (...a: unknown[]) => {\n logs.push(a.map(String).join(\" \"));\n };\n process.stdout.write = ((chunk: any) => {\n if (typeof chunk === \"string\") logs.push(chunk);\n else if (Buffer.isBuffer(chunk)) logs.push(chunk.toString());\n return true;\n }) as any;\n try {\n await fn(args);\n } catch (err: any) {\n logs.push(`Error: ${err?.message ?? String(err)}`);\n } finally {\n console.log = origLog;\n console.error = origError;\n process.stdout.write = origStdoutWrite;\n releaseCapture();\n }\n return logs.join(\"\\n\") || \"(no output)\";\n}\n\nasync function handleSqlQuery(event: H3Event): Promise<unknown> {\n const body = await readBody(event);\n const sql = body.sql;\n if (!sql || typeof sql !== \"string\") {\n setResponseStatus(event, 400);\n return { error: \"sql is required\" };\n }\n\n const cleanSql = stripSqlComments(sql);\n if (!/^\\s*(SELECT|WITH)\\b/i.test(cleanSql)) {\n setResponseStatus(event, 403);\n return { error: \"Only SELECT queries are allowed from tools\" };\n }\n if (SENSITIVE_SQL_RE.test(cleanSql)) {\n setResponseStatus(event, 403);\n return { error: \"Sensitive framework tables are not readable from tools\" };\n }\n\n try {\n const mod = await import(\"../scripts/db/query.js\");\n const args = [\"--sql\", sql, \"--format\", \"json\"];\n if (body.limit) args.push(\"--limit\", String(body.limit));\n if (body.args !== undefined) {\n if (!Array.isArray(body.args)) {\n setResponseStatus(event, 400);\n return { error: \"args must be an array\" };\n }\n args.push(\"--args\", JSON.stringify(body.args));\n }\n const output = await captureCliOutput(mod.default, args);\n try {\n return JSON.parse(output);\n } catch {\n return { output };\n }\n } catch (err: any) {\n setResponseStatus(event, 500);\n return { error: err?.message ?? \"Query failed\" };\n }\n}\n\n// TODO(security): replace this regex blocklist with a SQL parser + an explicit\n// allowlist of tables a tool may read/write (e.g. only `tool_data`, plus a\n// per-template list). The current blocklist is best-effort defense in depth\n// and is by design bypassable via SQL constructions that don't include the\n// blocklisted token literally (string concat, dynamic SQL, etc). The temp-\n// view scoping in scripts/db/scoping.ts is the actual ownership boundary.\nconst DESTRUCTIVE_SQL_RE =\n /\\b(CREATE\\s+(?:(?:LOCAL|GLOBAL)\\s+)?(?:TEMPORARY|TEMP)?\\s*(TABLE|INDEX|VIEW|SCHEMA|DATABASE|TRIGGER|FUNCTION|EXTENSION|ROLE|TABLESPACE|PUBLICATION|SUBSCRIPTION)|DROP\\s+(TABLE|INDEX|VIEW|SCHEMA|DATABASE|TRIGGER|FUNCTION|EXTENSION|ROLE)|TRUNCATE|DELETE\\s+FROM\\s+(?!tool_data\\b)|ALTER\\s+(TABLE|VIEW|SCHEMA|DATABASE|FUNCTION|ROLE|EXTENSION|PUBLICATION)\\s+(?!tool_data\\b)|ATTACH|DETACH|VACUUM|REINDEX|PRAGMA|GRANT|REVOKE|SET\\s+ROLE|RESET\\s+ROLE|COPY)\\b/i;\n\n// Sensitive tables that tools must not touch directly. Includes Better Auth\n// identity tables, framework infrastructure (tracing, evals, automations,\n// integrations, notifications, scheduling, sharing/orgs), and Postgres\n// catalogs that would let a tool enumerate or read internals.\nconst SENSITIVE_SQL_RE =\n /\\b(app_secrets|user|users|session|sessions|account|accounts|verification|oauth_tokens|tools|tool_shares|tool_slots|tool_slot_installs|member|organization|invitation|jwks|agent_trace_spans|agent_trace_summaries|agent_feedback|agent_satisfaction_scores|agent_evals|agent_runs|agent_run_events|notifications|progress_runs|integration_configs|integration_pending_tasks|integration_thread_mappings|resources|org_members|org_invitations|bigquery_cache|dashboard_views|pg_catalog|information_schema|pg_class|pg_proc|pg_namespace|pg_user|pg_roles|pg_authid|pg_shadow)\\b/i;\n\n// Refuses positional INSERTs (no column list). `INSERT INTO recordings VALUES\n// (...)` would let a tool stuff arbitrary owner_email values into a row.\n// `INSERT INTO recordings (col1, col2) VALUES (...)` is required so the\n// downstream injectOwnership helper can append owner_email.\nconst POSITIONAL_INSERT_RE = /\\bINSERT\\s+INTO\\s+[\"'`]?\\w+[\"'`]?\\s+VALUES\\b/i;\n\nfunction stripSqlComments(sql: string): string {\n return sql.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \" \").replace(/--[^\\n]*/g, \" \");\n}\n\nfunction isLikelyJson(text: string): boolean {\n try {\n const parsed = JSON.parse(text);\n return parsed !== null && typeof parsed === \"object\";\n } catch {\n return false;\n }\n}\n\nasync function handleSqlExec(event: H3Event): Promise<unknown> {\n const body = await readBody(event);\n const sql = body.sql;\n if (!sql || typeof sql !== \"string\") {\n setResponseStatus(event, 400);\n return { error: \"sql is required\" };\n }\n\n const cleanSql = stripSqlComments(sql);\n if (DESTRUCTIVE_SQL_RE.test(cleanSql)) {\n setResponseStatus(event, 403);\n return {\n error: \"Schema changes and destructive SQL are not allowed from tools\",\n };\n }\n if (SENSITIVE_SQL_RE.test(cleanSql)) {\n setResponseStatus(event, 403);\n return { error: \"Sensitive framework tables are not writable from tools\" };\n }\n if (POSITIONAL_INSERT_RE.test(cleanSql)) {\n setResponseStatus(event, 400);\n return {\n error:\n \"INSERT must specify an explicit column list (e.g. INSERT INTO t (col1, col2) VALUES (?, ?)) so ownership can be injected.\",\n };\n }\n\n try {\n const mod = await import(\"../scripts/db/exec.js\");\n const args = [\"--sql\", sql, \"--format\", \"json\"];\n if (body.args !== undefined) {\n if (!Array.isArray(body.args)) {\n setResponseStatus(event, 400);\n return { error: \"args must be an array\" };\n }\n args.push(\"--args\", JSON.stringify(body.args));\n }\n const output = await captureCliOutput(mod.default, args);\n try {\n return JSON.parse(output);\n } catch {\n return { output };\n }\n } catch (err: any) {\n setResponseStatus(event, 500);\n return { error: err?.message ?? \"Exec failed\" };\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/tools/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAShB,CAAC;AAEH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAAmC,CAAC;AAE3D,eAAO,MAAM,gBAAgB,yZAW3B,CAAC;AAEH,eAAO,MAAM,mBAAmB,iYAW9B,CAAC;AAEH,eAAO,MAAM,sBAAsB,iSAQjC,CAAC;AAEH,eAAO,MAAM,yBAAyB,qRAQpC,CAAC;AAEH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAYnB,CAAC;AAEH,eAAO,MAAM,oBAAoB,ubAY/B,CAAC;AAEH,eAAO,MAAM,uBAAuB,+ZAYlC,CAAC;AAEH,eAAO,MAAM,wBAAwB,0HACoB,CAAC;AAE1D,eAAO,MAAM,2BAA2B,0HACiB,CAAC;AAE1D,eAAO,MAAM,4BAA4B,kDAAkD,CAAC;AAC5F,eAAO,MAAM,+BAA+B,kDAAkD,CAAC;AAE/F,eAAO,MAAM,qBAAqB,sEAAsE,CAAC;AACzG,eAAO,MAAM,mBAAmB,+DAA+D,CAAC;AAChG,eAAO,MAAM,8BAA8B,qFAAqF,CAAC;AAajI,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAKvB,CAAC;AAEH,eAAO,MAAM,wBAAwB,sPAMnC,CAAC;AAEH,eAAO,MAAM,2BAA2B,0OAMtC,CAAC;AAEH,eAAO,MAAM,8BAA8B,iGAAiG,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/tools/schema.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Drizzle schema for the framework tools system.\n *\n * Tools are mini Alpine.js apps that run inside sandboxed iframes. They can\n * call external APIs via a server-side proxy that resolves `${keys.NAME}`\n * secret references. Tools use the standard sharing model (private by default,\n * shareable with org/others).\n *\n * The tables are auto-created at server boot via `ensureTable()` in store.ts,\n * following the same pattern as `app_secrets`.\n */\n\nimport { table, text, now } from \"../db/schema.js\";\nimport { ownableColumns, createSharesTable } from \"../sharing/schema.js\";\n\nexport const tools = table(\"tools\", {\n id: text(\"id\").primaryKey(),\n name: text(\"name\").notNull(),\n description: text(\"description\").notNull().default(\"\"),\n content: text(\"content\").notNull().default(\"\"),\n icon: text(\"icon\"),\n createdAt: text(\"created_at\").notNull().default(now()),\n updatedAt: text(\"updated_at\").notNull().default(now()),\n ...ownableColumns(),\n});\n\nexport const toolShares = createSharesTable(\"tool_shares\");\n\nexport const TOOLS_CREATE_SQL = `CREATE TABLE IF NOT EXISTS tools (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n description TEXT NOT NULL DEFAULT '',\n content TEXT NOT NULL DEFAULT '',\n icon TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now')),\n owner_email TEXT NOT NULL DEFAULT 'local@localhost',\n org_id TEXT,\n visibility TEXT NOT NULL DEFAULT 'private'\n)`;\n\nexport const TOOLS_CREATE_SQL_PG = `CREATE TABLE IF NOT EXISTS tools (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n description TEXT NOT NULL DEFAULT '',\n content TEXT NOT NULL DEFAULT '',\n icon TEXT,\n created_at TEXT NOT NULL DEFAULT now(),\n updated_at TEXT NOT NULL DEFAULT now(),\n owner_email TEXT NOT NULL DEFAULT 'local@localhost',\n org_id TEXT,\n visibility TEXT NOT NULL DEFAULT 'private'\n)`;\n\nexport const TOOL_SHARES_CREATE_SQL = `CREATE TABLE IF NOT EXISTS tool_shares (\n id TEXT PRIMARY KEY,\n resource_id TEXT NOT NULL,\n principal_type TEXT NOT NULL,\n principal_id TEXT NOT NULL,\n role TEXT NOT NULL DEFAULT 'viewer',\n created_by TEXT NOT NULL,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n)`;\n\nexport const TOOL_SHARES_CREATE_SQL_PG = `CREATE TABLE IF NOT EXISTS tool_shares (\n id TEXT PRIMARY KEY,\n resource_id TEXT NOT NULL,\n principal_type TEXT NOT NULL,\n principal_id TEXT NOT NULL,\n role TEXT NOT NULL DEFAULT 'viewer',\n created_by TEXT NOT NULL,\n created_at TEXT NOT NULL DEFAULT now()\n)`;\n\nexport const toolData = table(\"tool_data\", {\n id: text(\"id\").primaryKey(),\n toolId: text(\"tool_id\").notNull(),\n collection: text(\"collection\").notNull(),\n itemId: text(\"item_id\"),\n data: text(\"data\").notNull(),\n ownerEmail: text(\"owner_email\").notNull().default(\"local@localhost\"),\n scope: text(\"scope\").notNull().default(\"user\"),\n orgId: text(\"org_id\"),\n scopeKey: text(\"scope_key\").notNull().default(\"local@localhost\"),\n createdAt: text(\"created_at\").notNull().default(now()),\n updatedAt: text(\"updated_at\").notNull().default(now()),\n});\n\nexport const TOOL_DATA_CREATE_SQL = `CREATE TABLE IF NOT EXISTS tool_data (\n id TEXT PRIMARY KEY,\n tool_id TEXT NOT NULL,\n collection TEXT NOT NULL,\n item_id TEXT,\n data TEXT NOT NULL,\n owner_email TEXT NOT NULL DEFAULT 'local@localhost',\n scope TEXT NOT NULL DEFAULT 'user',\n org_id TEXT,\n scope_key TEXT NOT NULL DEFAULT 'local@localhost',\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n)`;\n\nexport const TOOL_DATA_CREATE_SQL_PG = `CREATE TABLE IF NOT EXISTS tool_data (\n id TEXT PRIMARY KEY,\n tool_id TEXT NOT NULL,\n collection TEXT NOT NULL,\n item_id TEXT,\n data TEXT NOT NULL,\n owner_email TEXT NOT NULL DEFAULT 'local@localhost',\n scope TEXT NOT NULL DEFAULT 'user',\n org_id TEXT,\n scope_key TEXT NOT NULL DEFAULT 'local@localhost',\n created_at TEXT NOT NULL DEFAULT now(),\n updated_at TEXT NOT NULL DEFAULT now()\n)`;\n\nexport const TOOL_DATA_ITEM_INDEX_SQL = `CREATE UNIQUE INDEX IF NOT EXISTS tool_data_scoped_item_idx\n ON tool_data (tool_id, collection, scope_key, item_id)`;\n\nexport const TOOL_DATA_ITEM_INDEX_SQL_PG = `CREATE UNIQUE INDEX IF NOT EXISTS tool_data_scoped_item_idx\n ON tool_data (tool_id, collection, scope_key, item_id)`;\n\nexport const TOOL_DATA_DROP_OLD_INDEX_SQL = `DROP INDEX IF EXISTS tool_data_scope_item_idx`;\nexport const TOOL_DATA_DROP_OLD_INDEX_SQL_PG = `DROP INDEX IF EXISTS tool_data_scope_item_idx`;\n\nexport const TOOLS_OWNER_INDEX_SQL = `CREATE INDEX IF NOT EXISTS tools_owner_idx ON tools (owner_email)`;\nexport const TOOLS_ORG_INDEX_SQL = `CREATE INDEX IF NOT EXISTS tools_org_idx ON tools (org_id)`;\nexport const TOOL_SHARES_RESOURCE_INDEX_SQL = `CREATE INDEX IF NOT EXISTS tool_shares_resource_idx ON tool_shares (resource_id)`;\n\n// ---------------------------------------------------------------------------\n// tool_consents — vestigial, kept for additive-schema compliance\n// ---------------------------------------------------------------------------\n//\n// Originally added for an audit-C1 per-(viewer, tool, content_hash) consent\n// gate that prompted viewers to \"Run anyway\" before non-author tools could\n// execute. We removed the runtime gate after settling on intra-org trust\n// (tools are shared between trusted teammates; the org-level access controls\n// are sufficient). The table is kept here so deploys that already ran the\n// migration stay healthy — additive-only schema policy means we never drop.\n\nexport const toolConsents = table(\"tool_consents\", {\n viewerEmail: text(\"viewer_email\").notNull(),\n toolId: text(\"tool_id\").notNull(),\n contentHash: text(\"content_hash\").notNull(),\n grantedAt: text(\"granted_at\").notNull().default(now()),\n});\n\nexport const TOOL_CONSENTS_CREATE_SQL = `CREATE TABLE IF NOT EXISTS tool_consents (\n viewer_email TEXT NOT NULL,\n tool_id TEXT NOT NULL,\n content_hash TEXT NOT NULL,\n granted_at TEXT NOT NULL DEFAULT (datetime('now')),\n PRIMARY KEY (viewer_email, tool_id, content_hash)\n)`;\n\nexport const TOOL_CONSENTS_CREATE_SQL_PG = `CREATE TABLE IF NOT EXISTS tool_consents (\n viewer_email TEXT NOT NULL,\n tool_id TEXT NOT NULL,\n content_hash TEXT NOT NULL,\n granted_at TEXT NOT NULL DEFAULT now(),\n PRIMARY KEY (viewer_email, tool_id, content_hash)\n)`;\n\nexport const TOOL_CONSENTS_VIEWER_INDEX_SQL = `CREATE INDEX IF NOT EXISTS tool_consents_viewer_idx ON tool_consents (viewer_email, tool_id)`;\n"]}
@@ -1,15 +0,0 @@
1
- /**
2
- * HTTP handler for tool extension-point slots.
3
- *
4
- * Mounted at `/_agent-native/slots`. Routes:
5
- *
6
- * GET /:slotId/installs — current user's installed widgets for a slot
7
- * GET /:slotId/available — tools that declare this slot, scoped to user access
8
- * POST /:slotId/install — install a tool into a slot (body: { toolId, position?, config? })
9
- * DELETE /:slotId/install/:toolId — uninstall
10
- * GET /tool/:toolId — list slot declarations for a specific tool
11
- * POST /tool/:toolId — declare a slot target (body: { slotId, config? })
12
- * DELETE /tool/:toolId/:slotId — remove a slot declaration
13
- */
14
- export declare function createSlotsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<unknown>>;
15
- //# sourceMappingURL=routes.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/tools/slots/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAuBH,wBAAgB,kBAAkB,2FAsBjC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../../src/tools/slots/routes.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * HTTP handler for tool extension-point slots.\n *\n * Mounted at `/_agent-native/slots`. Routes:\n *\n * GET /:slotId/installs — current user's installed widgets for a slot\n * GET /:slotId/available — tools that declare this slot, scoped to user access\n * POST /:slotId/install — install a tool into a slot (body: { toolId, position?, config? })\n * DELETE /:slotId/install/:toolId — uninstall\n * GET /tool/:toolId — list slot declarations for a specific tool\n * POST /tool/:toolId — declare a slot target (body: { slotId, config? })\n * DELETE /tool/:toolId/:slotId — remove a slot declaration\n */\n\nimport {\n defineEventHandler,\n getMethod,\n setResponseStatus,\n type H3Event,\n} from \"h3\";\nimport { readBody } from \"../../server/h3-helpers.js\";\nimport { getSession } from \"../../server/auth.js\";\nimport { recordChange } from \"../../server/poll.js\";\nimport { runWithRequestContext } from \"../../server/request-context.js\";\nimport { getOrgContext } from \"../../org/context.js\";\nimport {\n addToolSlotTarget,\n removeToolSlotTarget,\n listSlotsForTool,\n listToolsForSlot,\n installToolSlot,\n uninstallToolSlot,\n listSlotInstallsForUser,\n} from \"./store.js\";\n\nexport function createSlotsHandler() {\n return defineEventHandler(async (event: H3Event) => {\n const method = getMethod(event);\n const pathname = (event.url?.pathname || \"\")\n .replace(/^\\/+/, \"\")\n .replace(/\\/+$/, \"\");\n const parts = pathname ? pathname.split(\"/\") : [];\n\n const session = await getSession(event).catch(() => null);\n if (!session?.email) {\n setResponseStatus(event, 401);\n return { error: \"Authentication required\" };\n }\n\n const orgCtx = await getOrgContext(event).catch(() => null);\n const userEmail = session.email;\n const orgId = orgCtx?.orgId ?? undefined;\n\n return runWithRequestContext({ userEmail, orgId }, () =>\n dispatch(event, method, parts),\n );\n });\n}\n\nasync function dispatch(\n event: H3Event,\n method: string,\n parts: string[],\n): Promise<unknown> {\n // GET /tool/:toolId — list a tool's slot declarations\n if (method === \"GET\" && parts.length === 2 && parts[0] === \"tool\") {\n return listSlotsForTool(parts[1]);\n }\n\n // POST /tool/:toolId — declare a slot target { slotId, config? }\n if (method === \"POST\" && parts.length === 2 && parts[0] === \"tool\") {\n const body = await readBody(event);\n const slotId = String(body?.slotId ?? \"\").trim();\n if (!slotId) {\n setResponseStatus(event, 400);\n return { error: \"slotId is required\" };\n }\n const row = await addToolSlotTarget(parts[1], slotId, body?.config);\n recordChange({ source: \"action\", type: \"change\" });\n return row;\n }\n\n // DELETE /tool/:toolId/:slotId — remove a slot declaration\n if (method === \"DELETE\" && parts.length === 3 && parts[0] === \"tool\") {\n await removeToolSlotTarget(parts[1], parts[2]);\n recordChange({ source: \"action\", type: \"change\" });\n return { ok: true };\n }\n\n // GET /:slotId/installs — current user's installs in slot\n if (method === \"GET\" && parts.length === 2 && parts[1] === \"installs\") {\n return listSlotInstallsForUser(parts[0]);\n }\n\n // GET /:slotId/available — tools that declare this slot the user can install\n if (method === \"GET\" && parts.length === 2 && parts[1] === \"available\") {\n return listToolsForSlot(parts[0]);\n }\n\n // POST /:slotId/install — install { toolId, position?, config? }\n if (method === \"POST\" && parts.length === 2 && parts[1] === \"install\") {\n const body = await readBody(event);\n const toolId = String(body?.toolId ?? \"\").trim();\n if (!toolId) {\n setResponseStatus(event, 400);\n return { error: \"toolId is required\" };\n }\n const row = await installToolSlot(toolId, parts[0], {\n position: body?.position,\n config: body?.config,\n });\n recordChange({ source: \"action\", type: \"change\" });\n return row;\n }\n\n // DELETE /:slotId/install/:toolId — uninstall\n if (method === \"DELETE\" && parts.length === 3 && parts[1] === \"install\") {\n await uninstallToolSlot(parts[2], parts[0]);\n recordChange({ source: \"action\", type: \"change\" });\n return { ok: true };\n }\n\n setResponseStatus(event, 404);\n return { error: \"Not found\" };\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/tools/slots/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAMpB,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAU3B,CAAC;AAEH,eAAO,MAAM,qBAAqB,iMAMhC,CAAC;AAEH,eAAO,MAAM,wBAAwB,qLAMnC,CAAC;AAEH,eAAO,MAAM,4BAA4B,8EAA8E,CAAC;AACxH,eAAO,MAAM,4BAA4B,8EAA8E,CAAC;AACxH,eAAO,MAAM,2BAA2B,6FAA6F,CAAC;AAEtI,eAAO,MAAM,6BAA6B,sVAUxC,CAAC;AAEH,eAAO,MAAM,gCAAgC,8TAU3C,CAAC;AAEH,eAAO,MAAM,yCAAyC,gHAAgH,CAAC;AACvK,eAAO,MAAM,mCAAmC,0HAA0H,CAAC"}
@@ -1,76 +0,0 @@
1
- /**
2
- * Drizzle schema for the tool extension-points system.
3
- *
4
- * Two tables:
5
- *
6
- * - `tool_slots` — declarations: "tool X can render in slot Y". Authored
7
- * once per tool, regardless of installer.
8
- * - `tool_slot_installs` — per-user installs: "user U wants tool X in slot Y at
9
- * position N". Always scoped by owner_email.
10
- *
11
- * Neither table spreads `ownableColumns()` — they're not first-class shareable
12
- * resources. Access to the underlying tool flows through the existing `tools`
13
- * table sharing model; install rows are personal preferences scoped to the
14
- * installing user.
15
- */
16
- import { table, text, integer, now } from "../../db/schema.js";
17
- export const toolSlots = table("tool_slots", {
18
- id: text("id").primaryKey(),
19
- toolId: text("tool_id").notNull(),
20
- slotId: text("slot_id").notNull(),
21
- config: text("config"),
22
- createdAt: text("created_at").notNull().default(now()),
23
- });
24
- export const toolSlotInstalls = table("tool_slot_installs", {
25
- id: text("id").primaryKey(),
26
- toolId: text("tool_id").notNull(),
27
- slotId: text("slot_id").notNull(),
28
- ownerEmail: text("owner_email").notNull(),
29
- orgId: text("org_id"),
30
- position: integer("position").notNull().default(0),
31
- config: text("config"),
32
- createdAt: text("created_at").notNull().default(now()),
33
- updatedAt: text("updated_at").notNull().default(now()),
34
- });
35
- export const TOOL_SLOTS_CREATE_SQL = `CREATE TABLE IF NOT EXISTS tool_slots (
36
- id TEXT PRIMARY KEY,
37
- tool_id TEXT NOT NULL,
38
- slot_id TEXT NOT NULL,
39
- config TEXT,
40
- created_at TEXT NOT NULL DEFAULT (datetime('now'))
41
- )`;
42
- export const TOOL_SLOTS_CREATE_SQL_PG = `CREATE TABLE IF NOT EXISTS tool_slots (
43
- id TEXT PRIMARY KEY,
44
- tool_id TEXT NOT NULL,
45
- slot_id TEXT NOT NULL,
46
- config TEXT,
47
- created_at TEXT NOT NULL DEFAULT now()
48
- )`;
49
- export const TOOL_SLOTS_BY_SLOT_INDEX_SQL = `CREATE INDEX IF NOT EXISTS tool_slots_by_slot_idx ON tool_slots (slot_id)`;
50
- export const TOOL_SLOTS_BY_TOOL_INDEX_SQL = `CREATE INDEX IF NOT EXISTS tool_slots_by_tool_idx ON tool_slots (tool_id)`;
51
- export const TOOL_SLOTS_UNIQUE_INDEX_SQL = `CREATE UNIQUE INDEX IF NOT EXISTS tool_slots_unique_idx ON tool_slots (tool_id, slot_id)`;
52
- export const TOOL_SLOT_INSTALLS_CREATE_SQL = `CREATE TABLE IF NOT EXISTS tool_slot_installs (
53
- id TEXT PRIMARY KEY,
54
- tool_id TEXT NOT NULL,
55
- slot_id TEXT NOT NULL,
56
- owner_email TEXT NOT NULL,
57
- org_id TEXT,
58
- position INTEGER NOT NULL DEFAULT 0,
59
- config TEXT,
60
- created_at TEXT NOT NULL DEFAULT (datetime('now')),
61
- updated_at TEXT NOT NULL DEFAULT (datetime('now'))
62
- )`;
63
- export const TOOL_SLOT_INSTALLS_CREATE_SQL_PG = `CREATE TABLE IF NOT EXISTS tool_slot_installs (
64
- id TEXT PRIMARY KEY,
65
- tool_id TEXT NOT NULL,
66
- slot_id TEXT NOT NULL,
67
- owner_email TEXT NOT NULL,
68
- org_id TEXT,
69
- position INTEGER NOT NULL DEFAULT 0,
70
- config TEXT,
71
- created_at TEXT NOT NULL DEFAULT now(),
72
- updated_at TEXT NOT NULL DEFAULT now()
73
- )`;
74
- export const TOOL_SLOT_INSTALLS_BY_USER_SLOT_INDEX_SQL = `CREATE INDEX IF NOT EXISTS tool_slot_installs_by_user_slot_idx ON tool_slot_installs (owner_email, slot_id)`;
75
- export const TOOL_SLOT_INSTALLS_UNIQUE_INDEX_SQL = `CREATE UNIQUE INDEX IF NOT EXISTS tool_slot_installs_unique_idx ON tool_slot_installs (owner_email, tool_id, slot_id)`;
76
- //# sourceMappingURL=schema.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/tools/slots/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAE/D,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,CAAC,YAAY,EAAE;IAC3C,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE;IAC3B,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE;IACjC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE;IACjC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtB,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;CACvD,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC,oBAAoB,EAAE;IAC1D,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE;IAC3B,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE;IACjC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE;IACjC,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,OAAO,EAAE;IACzC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAClD,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtB,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;IACtD,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;CACvD,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;EAMnC,CAAC;AAEH,MAAM,CAAC,MAAM,wBAAwB,GAAG;;;;;;EAMtC,CAAC;AAEH,MAAM,CAAC,MAAM,4BAA4B,GAAG,2EAA2E,CAAC;AACxH,MAAM,CAAC,MAAM,4BAA4B,GAAG,2EAA2E,CAAC;AACxH,MAAM,CAAC,MAAM,2BAA2B,GAAG,0FAA0F,CAAC;AAEtI,MAAM,CAAC,MAAM,6BAA6B,GAAG;;;;;;;;;;EAU3C,CAAC;AAEH,MAAM,CAAC,MAAM,gCAAgC,GAAG;;;;;;;;;;EAU9C,CAAC;AAEH,MAAM,CAAC,MAAM,yCAAyC,GAAG,6GAA6G,CAAC;AACvK,MAAM,CAAC,MAAM,mCAAmC,GAAG,uHAAuH,CAAC","sourcesContent":["/**\n * Drizzle schema for the tool extension-points system.\n *\n * Two tables:\n *\n * - `tool_slots` — declarations: \"tool X can render in slot Y\". Authored\n * once per tool, regardless of installer.\n * - `tool_slot_installs` — per-user installs: \"user U wants tool X in slot Y at\n * position N\". Always scoped by owner_email.\n *\n * Neither table spreads `ownableColumns()` — they're not first-class shareable\n * resources. Access to the underlying tool flows through the existing `tools`\n * table sharing model; install rows are personal preferences scoped to the\n * installing user.\n */\n\nimport { table, text, integer, now } from \"../../db/schema.js\";\n\nexport const toolSlots = table(\"tool_slots\", {\n id: text(\"id\").primaryKey(),\n toolId: text(\"tool_id\").notNull(),\n slotId: text(\"slot_id\").notNull(),\n config: text(\"config\"),\n createdAt: text(\"created_at\").notNull().default(now()),\n});\n\nexport const toolSlotInstalls = table(\"tool_slot_installs\", {\n id: text(\"id\").primaryKey(),\n toolId: text(\"tool_id\").notNull(),\n slotId: text(\"slot_id\").notNull(),\n ownerEmail: text(\"owner_email\").notNull(),\n orgId: text(\"org_id\"),\n position: integer(\"position\").notNull().default(0),\n config: text(\"config\"),\n createdAt: text(\"created_at\").notNull().default(now()),\n updatedAt: text(\"updated_at\").notNull().default(now()),\n});\n\nexport const TOOL_SLOTS_CREATE_SQL = `CREATE TABLE IF NOT EXISTS tool_slots (\n id TEXT PRIMARY KEY,\n tool_id TEXT NOT NULL,\n slot_id TEXT NOT NULL,\n config TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n)`;\n\nexport const TOOL_SLOTS_CREATE_SQL_PG = `CREATE TABLE IF NOT EXISTS tool_slots (\n id TEXT PRIMARY KEY,\n tool_id TEXT NOT NULL,\n slot_id TEXT NOT NULL,\n config TEXT,\n created_at TEXT NOT NULL DEFAULT now()\n)`;\n\nexport const TOOL_SLOTS_BY_SLOT_INDEX_SQL = `CREATE INDEX IF NOT EXISTS tool_slots_by_slot_idx ON tool_slots (slot_id)`;\nexport const TOOL_SLOTS_BY_TOOL_INDEX_SQL = `CREATE INDEX IF NOT EXISTS tool_slots_by_tool_idx ON tool_slots (tool_id)`;\nexport const TOOL_SLOTS_UNIQUE_INDEX_SQL = `CREATE UNIQUE INDEX IF NOT EXISTS tool_slots_unique_idx ON tool_slots (tool_id, slot_id)`;\n\nexport const TOOL_SLOT_INSTALLS_CREATE_SQL = `CREATE TABLE IF NOT EXISTS tool_slot_installs (\n id TEXT PRIMARY KEY,\n tool_id TEXT NOT NULL,\n slot_id TEXT NOT NULL,\n owner_email TEXT NOT NULL,\n org_id TEXT,\n position INTEGER NOT NULL DEFAULT 0,\n config TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n)`;\n\nexport const TOOL_SLOT_INSTALLS_CREATE_SQL_PG = `CREATE TABLE IF NOT EXISTS tool_slot_installs (\n id TEXT PRIMARY KEY,\n tool_id TEXT NOT NULL,\n slot_id TEXT NOT NULL,\n owner_email TEXT NOT NULL,\n org_id TEXT,\n position INTEGER NOT NULL DEFAULT 0,\n config TEXT,\n created_at TEXT NOT NULL DEFAULT now(),\n updated_at TEXT NOT NULL DEFAULT now()\n)`;\n\nexport const TOOL_SLOT_INSTALLS_BY_USER_SLOT_INDEX_SQL = `CREATE INDEX IF NOT EXISTS tool_slot_installs_by_user_slot_idx ON tool_slot_installs (owner_email, slot_id)`;\nexport const TOOL_SLOT_INSTALLS_UNIQUE_INDEX_SQL = `CREATE UNIQUE INDEX IF NOT EXISTS tool_slot_installs_unique_idx ON tool_slot_installs (owner_email, tool_id, slot_id)`;\n"]}
@@ -1,66 +0,0 @@
1
- export declare function ensureSlotTables(): Promise<void>;
2
- export interface ToolSlotRow {
3
- id: string;
4
- toolId: string;
5
- slotId: string;
6
- config: string | null;
7
- createdAt: string;
8
- }
9
- export interface ToolSlotInstallRow {
10
- id: string;
11
- toolId: string;
12
- slotId: string;
13
- ownerEmail: string;
14
- orgId: string | null;
15
- position: number;
16
- config: string | null;
17
- createdAt: string;
18
- updatedAt: string;
19
- }
20
- /**
21
- * Declare that a tool can render in a slot. Caller must have editor access on
22
- * the tool (only people who can edit a tool can change its slot targets).
23
- */
24
- export declare function addToolSlotTarget(toolId: string, slotId: string, config?: string): Promise<ToolSlotRow>;
25
- export declare function removeToolSlotTarget(toolId: string, slotId: string): Promise<boolean>;
26
- export declare function listSlotsForTool(toolId: string): Promise<ToolSlotRow[]>;
27
- /**
28
- * List tools that declare a slot — but only tools the current user has access
29
- * to. Joins through the tools access filter.
30
- */
31
- export declare function listToolsForSlot(slotId: string): Promise<Array<{
32
- toolId: string;
33
- name: string;
34
- description: string;
35
- icon: string | null;
36
- config: string | null;
37
- }>>;
38
- /**
39
- * Install a tool into a slot for the current user. Verifies the user has at
40
- * least viewer access to the tool. Idempotent — re-installing returns the
41
- * existing row.
42
- */
43
- export declare function installToolSlot(toolId: string, slotId: string, opts?: {
44
- position?: number;
45
- config?: string;
46
- }): Promise<ToolSlotInstallRow>;
47
- export declare function uninstallToolSlot(toolId: string, slotId: string): Promise<boolean>;
48
- /**
49
- * List the current user's installs for a slot. Joins with `tools` so the
50
- * caller gets tool name/description/icon/updatedAt without a second query.
51
- * Tools the user has lost access to are silently skipped (lazy garbage
52
- * collection).
53
- */
54
- export declare function listSlotInstallsForUser(slotId: string): Promise<Array<{
55
- installId: string;
56
- toolId: string;
57
- name: string;
58
- description: string;
59
- icon: string | null;
60
- updatedAt: string;
61
- position: number;
62
- config: string | null;
63
- }>>;
64
- /** Delete every slot/install row referencing a tool. Called from deleteTool. */
65
- export declare function cascadeDeleteToolSlots(toolId: string): Promise<void>;
66
- //# sourceMappingURL=store.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/tools/slots/store.ts"],"names":[],"mappings":"AA4BA,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAmBtD;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,WAAW,CAAC,CA+BtB;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,OAAO,CAAC,CAQlB;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAS7E;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAC7D,KAAK,CAAC;IACJ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC,CACH,CA8BA;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5C,OAAO,CAAC,kBAAkB,CAAC,CA+C7B;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,OAAO,CAAC,CAclB;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CACpE,KAAK,CAAC;IACJ,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC,CACH,CA4CA;AAED,gFAAgF;AAChF,wBAAsB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK1E"}