@agent-native/core 0.7.81 → 0.7.83

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 (257) hide show
  1. package/dist/action.d.ts +8 -0
  2. package/dist/action.d.ts.map +1 -1
  3. package/dist/action.js +4 -0
  4. package/dist/action.js.map +1 -1
  5. package/dist/agent/production-agent.d.ts +12 -2
  6. package/dist/agent/production-agent.d.ts.map +1 -1
  7. package/dist/agent/production-agent.js +58 -20
  8. package/dist/agent/production-agent.js.map +1 -1
  9. package/dist/agent/run-manager.d.ts +8 -1
  10. package/dist/agent/run-manager.d.ts.map +1 -1
  11. package/dist/agent/run-manager.js +11 -12
  12. package/dist/agent/run-manager.js.map +1 -1
  13. package/dist/agent/thread-data-builder.d.ts.map +1 -1
  14. package/dist/agent/thread-data-builder.js +13 -17
  15. package/dist/agent/thread-data-builder.js.map +1 -1
  16. package/dist/agent/types.d.ts +4 -0
  17. package/dist/agent/types.d.ts.map +1 -1
  18. package/dist/agent/types.js.map +1 -1
  19. package/dist/application-state/handlers.d.ts.map +1 -1
  20. package/dist/application-state/handlers.js +3 -8
  21. package/dist/application-state/handlers.js.map +1 -1
  22. package/dist/application-state/script-helpers.d.ts +2 -4
  23. package/dist/application-state/script-helpers.d.ts.map +1 -1
  24. package/dist/application-state/script-helpers.js +10 -47
  25. package/dist/application-state/script-helpers.js.map +1 -1
  26. package/dist/cli/create.d.ts +1 -1
  27. package/dist/cli/create.d.ts.map +1 -1
  28. package/dist/cli/create.js +35 -10
  29. package/dist/cli/create.js.map +1 -1
  30. package/dist/cli/workspace-dev.js +78 -15
  31. package/dist/cli/workspace-dev.js.map +1 -1
  32. package/dist/client/AgentPanel.d.ts.map +1 -1
  33. package/dist/client/AgentPanel.js +6 -2
  34. package/dist/client/AgentPanel.js.map +1 -1
  35. package/dist/client/AssistantChat.d.ts +0 -15
  36. package/dist/client/AssistantChat.d.ts.map +1 -1
  37. package/dist/client/AssistantChat.js +69 -57
  38. package/dist/client/AssistantChat.js.map +1 -1
  39. package/dist/client/ConnectBuilderCard.d.ts +7 -1
  40. package/dist/client/ConnectBuilderCard.d.ts.map +1 -1
  41. package/dist/client/ConnectBuilderCard.js +46 -5
  42. package/dist/client/ConnectBuilderCard.js.map +1 -1
  43. package/dist/client/ErrorBoundary.d.ts.map +1 -1
  44. package/dist/client/ErrorBoundary.js +20 -5
  45. package/dist/client/ErrorBoundary.js.map +1 -1
  46. package/dist/client/FeedbackButton.d.ts +3 -2
  47. package/dist/client/FeedbackButton.d.ts.map +1 -1
  48. package/dist/client/FeedbackButton.js +23 -15
  49. package/dist/client/FeedbackButton.js.map +1 -1
  50. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  51. package/dist/client/agent-chat-adapter.js +303 -169
  52. package/dist/client/agent-chat-adapter.js.map +1 -1
  53. package/dist/client/builder-frame.d.ts +36 -0
  54. package/dist/client/builder-frame.d.ts.map +1 -1
  55. package/dist/client/builder-frame.js +80 -9
  56. package/dist/client/builder-frame.js.map +1 -1
  57. package/dist/client/composer/ComposerPlusMenu.d.ts.map +1 -1
  58. package/dist/client/composer/ComposerPlusMenu.js +7 -2
  59. package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
  60. package/dist/client/composer/PastedTextChip.d.ts +9 -0
  61. package/dist/client/composer/PastedTextChip.d.ts.map +1 -0
  62. package/dist/client/composer/PastedTextChip.js +47 -0
  63. package/dist/client/composer/PastedTextChip.js.map +1 -0
  64. package/dist/client/composer/PromptComposer.d.ts +4 -2
  65. package/dist/client/composer/PromptComposer.d.ts.map +1 -1
  66. package/dist/client/composer/PromptComposer.js +33 -5
  67. package/dist/client/composer/PromptComposer.js.map +1 -1
  68. package/dist/client/composer/TiptapComposer.d.ts +13 -1
  69. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  70. package/dist/client/composer/TiptapComposer.js +61 -16
  71. package/dist/client/composer/TiptapComposer.js.map +1 -1
  72. package/dist/client/composer/VoiceButton.d.ts.map +1 -1
  73. package/dist/client/composer/VoiceButton.js +5 -1
  74. package/dist/client/composer/VoiceButton.js.map +1 -1
  75. package/dist/client/composer/pasted-text.d.ts +6 -0
  76. package/dist/client/composer/pasted-text.d.ts.map +1 -0
  77. package/dist/client/composer/pasted-text.js +49 -0
  78. package/dist/client/composer/pasted-text.js.map +1 -0
  79. package/dist/client/composer/useVoiceDictation.d.ts +1 -0
  80. package/dist/client/composer/useVoiceDictation.d.ts.map +1 -1
  81. package/dist/client/composer/useVoiceDictation.js +18 -0
  82. package/dist/client/composer/useVoiceDictation.js.map +1 -1
  83. package/dist/client/index.d.ts +0 -1
  84. package/dist/client/index.d.ts.map +1 -1
  85. package/dist/client/index.js +0 -1
  86. package/dist/client/index.js.map +1 -1
  87. package/dist/client/integrations/IntegrationCard.d.ts.map +1 -1
  88. package/dist/client/integrations/IntegrationCard.js +14 -2
  89. package/dist/client/integrations/IntegrationCard.js.map +1 -1
  90. package/dist/client/integrations/IntegrationsPanel.d.ts.map +1 -1
  91. package/dist/client/integrations/IntegrationsPanel.js +23 -4
  92. package/dist/client/integrations/IntegrationsPanel.js.map +1 -1
  93. package/dist/client/notifications/NotificationsBell.d.ts.map +1 -1
  94. package/dist/client/notifications/NotificationsBell.js +4 -42
  95. package/dist/client/notifications/NotificationsBell.js.map +1 -1
  96. package/dist/client/org/OrgSwitcher.d.ts +4 -6
  97. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  98. package/dist/client/org/OrgSwitcher.js +84 -74
  99. package/dist/client/org/OrgSwitcher.js.map +1 -1
  100. package/dist/client/org/TeamPage.d.ts.map +1 -1
  101. package/dist/client/org/TeamPage.js +3 -154
  102. package/dist/client/org/TeamPage.js.map +1 -1
  103. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  104. package/dist/client/resources/ResourcesPanel.js +13 -35
  105. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  106. package/dist/client/settings/SettingsPanel.js +1 -1
  107. package/dist/client/settings/SettingsPanel.js.map +1 -1
  108. package/dist/client/settings/useBuilderStatus.d.ts +6 -0
  109. package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
  110. package/dist/client/settings/useBuilderStatus.js +3 -0
  111. package/dist/client/settings/useBuilderStatus.js.map +1 -1
  112. package/dist/client/sse-event-processor.d.ts +15 -1
  113. package/dist/client/sse-event-processor.d.ts.map +1 -1
  114. package/dist/client/sse-event-processor.js +58 -54
  115. package/dist/client/sse-event-processor.js.map +1 -1
  116. package/dist/client/tools/ToolEditor.d.ts.map +1 -1
  117. package/dist/client/tools/ToolEditor.js +34 -4
  118. package/dist/client/tools/ToolEditor.js.map +1 -1
  119. package/dist/client/tools/ToolViewer.d.ts.map +1 -1
  120. package/dist/client/tools/ToolViewer.js +20 -1
  121. package/dist/client/tools/ToolViewer.js.map +1 -1
  122. package/dist/client/tools/ToolsListPage.d.ts.map +1 -1
  123. package/dist/client/tools/ToolsListPage.js +2 -1
  124. package/dist/client/tools/ToolsListPage.js.map +1 -1
  125. package/dist/client/tools/ToolsSidebarSection.js +1 -1
  126. package/dist/client/tools/ToolsSidebarSection.js.map +1 -1
  127. package/dist/client/transcription/BuilderTranscriptionCta.js +1 -1
  128. package/dist/client/transcription/BuilderTranscriptionCta.js.map +1 -1
  129. package/dist/client/use-chat-threads.d.ts.map +1 -1
  130. package/dist/client/use-chat-threads.js +7 -2
  131. package/dist/client/use-chat-threads.js.map +1 -1
  132. package/dist/collab/client.d.ts.map +1 -1
  133. package/dist/collab/client.js +26 -7
  134. package/dist/collab/client.js.map +1 -1
  135. package/dist/jobs/scheduler.js +0 -4
  136. package/dist/jobs/scheduler.js.map +1 -1
  137. package/dist/oauth-tokens/store.d.ts +0 -4
  138. package/dist/oauth-tokens/store.d.ts.map +1 -1
  139. package/dist/oauth-tokens/store.js +3 -24
  140. package/dist/oauth-tokens/store.js.map +1 -1
  141. package/dist/observability/routes.d.ts.map +1 -1
  142. package/dist/observability/routes.js +1 -9
  143. package/dist/observability/routes.js.map +1 -1
  144. package/dist/onboarding/default-steps.js +1 -1
  145. package/dist/onboarding/default-steps.js.map +1 -1
  146. package/dist/onboarding/plugin.d.ts.map +1 -1
  147. package/dist/onboarding/plugin.js +1 -8
  148. package/dist/onboarding/plugin.js.map +1 -1
  149. package/dist/org/accept-pending.d.ts.map +1 -1
  150. package/dist/org/accept-pending.js +1 -2
  151. package/dist/org/accept-pending.js.map +1 -1
  152. package/dist/org/context.d.ts +0 -2
  153. package/dist/org/context.d.ts.map +1 -1
  154. package/dist/org/context.js +0 -5
  155. package/dist/org/context.js.map +1 -1
  156. package/dist/resources/script-helpers.d.ts +3 -4
  157. package/dist/resources/script-helpers.d.ts.map +1 -1
  158. package/dist/resources/script-helpers.js +8 -15
  159. package/dist/resources/script-helpers.js.map +1 -1
  160. package/dist/scripts/chat/search-chats.d.ts.map +1 -1
  161. package/dist/scripts/chat/search-chats.js +4 -4
  162. package/dist/scripts/chat/search-chats.js.map +1 -1
  163. package/dist/scripts/manage-agent-loop-settings.js +2 -2
  164. package/dist/scripts/manage-agent-loop-settings.js.map +1 -1
  165. package/dist/scripts/resources/delete-memory.d.ts.map +1 -1
  166. package/dist/scripts/resources/delete-memory.js +4 -2
  167. package/dist/scripts/resources/delete-memory.js.map +1 -1
  168. package/dist/scripts/resources/delete.d.ts.map +1 -1
  169. package/dist/scripts/resources/delete.js +11 -4
  170. package/dist/scripts/resources/delete.js.map +1 -1
  171. package/dist/scripts/resources/list.d.ts.map +1 -1
  172. package/dist/scripts/resources/list.js +5 -3
  173. package/dist/scripts/resources/list.js.map +1 -1
  174. package/dist/scripts/resources/migrate-learnings.d.ts.map +1 -1
  175. package/dist/scripts/resources/migrate-learnings.js +5 -2
  176. package/dist/scripts/resources/migrate-learnings.js.map +1 -1
  177. package/dist/scripts/resources/read.d.ts.map +1 -1
  178. package/dist/scripts/resources/read.js +4 -2
  179. package/dist/scripts/resources/read.js.map +1 -1
  180. package/dist/scripts/resources/save-memory.d.ts.map +1 -1
  181. package/dist/scripts/resources/save-memory.js +4 -2
  182. package/dist/scripts/resources/save-memory.js.map +1 -1
  183. package/dist/scripts/resources/write.d.ts.map +1 -1
  184. package/dist/scripts/resources/write.js +11 -4
  185. package/dist/scripts/resources/write.js.map +1 -1
  186. package/dist/secrets/onboarding.d.ts.map +1 -1
  187. package/dist/secrets/onboarding.js +1 -9
  188. package/dist/secrets/onboarding.js.map +1 -1
  189. package/dist/secrets/routes.d.ts.map +1 -1
  190. package/dist/secrets/routes.js +2 -7
  191. package/dist/secrets/routes.js.map +1 -1
  192. package/dist/server/action-discovery.d.ts +15 -0
  193. package/dist/server/action-discovery.d.ts.map +1 -1
  194. package/dist/server/action-discovery.js +49 -0
  195. package/dist/server/action-discovery.js.map +1 -1
  196. package/dist/server/agent-chat-plugin.d.ts +5 -0
  197. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  198. package/dist/server/agent-chat-plugin.js +81 -20
  199. package/dist/server/agent-chat-plugin.js.map +1 -1
  200. package/dist/server/agent-discovery.d.ts.map +1 -1
  201. package/dist/server/agent-discovery.js +5 -7
  202. package/dist/server/agent-discovery.js.map +1 -1
  203. package/dist/server/auth.d.ts +16 -20
  204. package/dist/server/auth.d.ts.map +1 -1
  205. package/dist/server/auth.js +115 -333
  206. package/dist/server/auth.js.map +1 -1
  207. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  208. package/dist/server/core-routes-plugin.js +23 -16
  209. package/dist/server/core-routes-plugin.js.map +1 -1
  210. package/dist/server/credential-provider.d.ts.map +1 -1
  211. package/dist/server/credential-provider.js +1 -2
  212. package/dist/server/credential-provider.js.map +1 -1
  213. package/dist/server/google-oauth.d.ts +14 -2
  214. package/dist/server/google-oauth.d.ts.map +1 -1
  215. package/dist/server/google-oauth.js +32 -10
  216. package/dist/server/google-oauth.js.map +1 -1
  217. package/dist/server/index.d.ts +3 -3
  218. package/dist/server/index.d.ts.map +1 -1
  219. package/dist/server/index.js +2 -2
  220. package/dist/server/index.js.map +1 -1
  221. package/dist/server/oauth-helpers.d.ts +2 -4
  222. package/dist/server/oauth-helpers.d.ts.map +1 -1
  223. package/dist/server/oauth-helpers.js +2 -4
  224. package/dist/server/oauth-helpers.js.map +1 -1
  225. package/dist/server/transcribe-voice.d.ts.map +1 -1
  226. package/dist/server/transcribe-voice.js +2 -4
  227. package/dist/server/transcribe-voice.js.map +1 -1
  228. package/dist/triggers/dispatcher.d.ts.map +1 -1
  229. package/dist/triggers/dispatcher.js +0 -3
  230. package/dist/triggers/dispatcher.js.map +1 -1
  231. package/dist/vite/client.d.ts.map +1 -1
  232. package/dist/vite/client.js +13 -0
  233. package/dist/vite/client.js.map +1 -1
  234. package/docs/content/actions.md +1 -0
  235. package/docs/content/authentication.md +3 -20
  236. package/docs/content/creating-templates.md +1 -1
  237. package/docs/content/deployment.md +0 -1
  238. package/docs/content/security.md +0 -1
  239. package/docs/content/template-analytics.md +10 -0
  240. package/docs/content/template-calendar.md +10 -0
  241. package/docs/content/template-clips.md +10 -0
  242. package/docs/content/template-content.md +11 -1
  243. package/docs/content/template-dispatch.md +10 -0
  244. package/docs/content/template-forms.md +10 -0
  245. package/docs/content/template-mail.md +10 -0
  246. package/docs/content/template-slides.md +11 -1
  247. package/docs/content/template-starter.md +11 -1
  248. package/docs/content/template-video.md +10 -0
  249. package/package.json +1 -1
  250. package/dist/client/dev-mode.d.ts +0 -14
  251. package/dist/client/dev-mode.d.ts.map +0 -1
  252. package/dist/client/dev-mode.js +0 -14
  253. package/dist/client/dev-mode.js.map +0 -1
  254. package/dist/server/local-migration.d.ts +0 -41
  255. package/dist/server/local-migration.d.ts.map +0 -1
  256. package/dist/server/local-migration.js +0 -235
  257. package/dist/server/local-migration.js.map +0 -1
@@ -6,10 +6,9 @@
6
6
  * Usage:
7
7
  * pnpm action resource-list [--prefix <path>] [--scope personal|shared|all] [--format json|text]
8
8
  */
9
- import { parseArgs } from "../utils.js";
9
+ import { parseArgs, fail } from "../utils.js";
10
10
  import { resourceList, resourceListAccessible, ensurePersonalDefaults, SHARED_OWNER, } from "../../resources/store.js";
11
11
  import { getRequestUserEmail } from "../../server/request-context.js";
12
- import { DEV_MODE_USER_EMAIL } from "../../server/auth.js";
13
12
  export default async function resourceListScript(args) {
14
13
  const parsed = parseArgs(args);
15
14
  if (parsed.help === "true") {
@@ -25,7 +24,10 @@ Options:
25
24
  const prefix = parsed.prefix;
26
25
  const scope = parsed.scope ?? "all";
27
26
  const format = parsed.format ?? "text";
28
- const owner = getRequestUserEmail() ?? DEV_MODE_USER_EMAIL;
27
+ const owner = getRequestUserEmail() ?? process.env.AGENT_USER_EMAIL;
28
+ if (!owner) {
29
+ fail("resource-list requires an authenticated user (request context or AGENT_USER_EMAIL env var).");
30
+ }
29
31
  // Seed personal AGENTS.md + LEARNINGS.md on first access
30
32
  if (scope !== "shared") {
31
33
  await ensurePersonalDefaults(owner);
@@ -1 +1 @@
1
- {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/scripts/resources/list.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EACL,YAAY,EACZ,sBAAsB,EACtB,sBAAsB,EACtB,YAAY,GACb,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE3D,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,kBAAkB,CAC9C,IAAc;IAEd,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAE/B,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC;;;;;;sDAMsC,CAAC,CAAC;QACpD,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC7B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC;IACpC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC;IACvC,MAAM,KAAK,GAAG,mBAAmB,EAAE,IAAI,mBAAmB,CAAC;IAE3D,yDAAyD;IACzD,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvB,MAAM,sBAAsB,CAAC,KAAK,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,SAAS,CAAC;IACd,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;QACzB,SAAS,GAAG,MAAM,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAChD,CAAC;SAAM,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,SAAS,GAAG,MAAM,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IACvD,CAAC;SAAM,CAAC;QACN,SAAS,GAAG,MAAM,sBAAsB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC1D,CAAC;IAED,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAChD,OAAO;IACT,CAAC;IAED,wBAAwB;IACxB,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QACnC,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,cAAc,SAAS,CAAC,MAAM,IAAI,CAAC,CAAC;IAEhD,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,KAAK,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC;QAC1E,MAAM,SAAS,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,UAAU,GAAG,SAAS,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IACvE,CAAC;AACH,CAAC","sourcesContent":["/**\n * Core script: resource-list\n *\n * List resources stored in the SQL resource store.\n *\n * Usage:\n * pnpm action resource-list [--prefix <path>] [--scope personal|shared|all] [--format json|text]\n */\n\nimport { parseArgs } from \"../utils.js\";\nimport {\n resourceList,\n resourceListAccessible,\n ensurePersonalDefaults,\n SHARED_OWNER,\n} from \"../../resources/store.js\";\nimport { getRequestUserEmail } from \"../../server/request-context.js\";\nimport { DEV_MODE_USER_EMAIL } from \"../../server/auth.js\";\n\nexport default async function resourceListScript(\n args: string[],\n): Promise<void> {\n const parsed = parseArgs(args);\n\n if (parsed.help === \"true\") {\n console.log(`Usage: pnpm action resource-list [options]\n\nOptions:\n --prefix <path> Filter by path prefix\n --scope personal|shared|all Scope to list (default: all)\n --format json|text Output format (default: text)\n --help Show this help message`);\n return;\n }\n\n const prefix = parsed.prefix;\n const scope = parsed.scope ?? \"all\";\n const format = parsed.format ?? \"text\";\n const owner = getRequestUserEmail() ?? DEV_MODE_USER_EMAIL;\n\n // Seed personal AGENTS.md + LEARNINGS.md on first access\n if (scope !== \"shared\") {\n await ensurePersonalDefaults(owner);\n }\n\n let resources;\n if (scope === \"personal\") {\n resources = await resourceList(owner, prefix);\n } else if (scope === \"shared\") {\n resources = await resourceList(SHARED_OWNER, prefix);\n } else {\n resources = await resourceListAccessible(owner, prefix);\n }\n\n if (format === \"json\") {\n console.log(JSON.stringify(resources, null, 2));\n return;\n }\n\n // Human-readable output\n if (resources.length === 0) {\n console.log(\"No resources found.\");\n return;\n }\n\n console.log(`Resources: ${resources.length}\\n`);\n\n for (const r of resources) {\n const ownerLabel = r.owner === SHARED_OWNER ? \"[shared]\" : `[${r.owner}]`;\n const sizeLabel = r.size != null ? ` (${r.size} bytes)` : \"\";\n console.log(` ${r.path} ${ownerLabel}${sizeLabel} ${r.mimeType}`);\n }\n}\n"]}
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/scripts/resources/list.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EACL,YAAY,EACZ,sBAAsB,EACtB,sBAAsB,EACtB,YAAY,GACb,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAEtE,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,kBAAkB,CAC9C,IAAc;IAEd,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAE/B,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC;;;;;;sDAMsC,CAAC,CAAC;QACpD,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC7B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC;IACpC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC;IACvC,MAAM,KAAK,GAAG,mBAAmB,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IACpE,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,IAAI,CACF,6FAA6F,CAC9F,CAAC;IACJ,CAAC;IAED,yDAAyD;IACzD,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvB,MAAM,sBAAsB,CAAC,KAAK,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,SAAS,CAAC;IACd,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;QACzB,SAAS,GAAG,MAAM,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAChD,CAAC;SAAM,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,SAAS,GAAG,MAAM,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IACvD,CAAC;SAAM,CAAC;QACN,SAAS,GAAG,MAAM,sBAAsB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC1D,CAAC;IAED,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAChD,OAAO;IACT,CAAC;IAED,wBAAwB;IACxB,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QACnC,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,cAAc,SAAS,CAAC,MAAM,IAAI,CAAC,CAAC;IAEhD,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,KAAK,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC;QAC1E,MAAM,SAAS,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,UAAU,GAAG,SAAS,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IACvE,CAAC;AACH,CAAC","sourcesContent":["/**\n * Core script: resource-list\n *\n * List resources stored in the SQL resource store.\n *\n * Usage:\n * pnpm action resource-list [--prefix <path>] [--scope personal|shared|all] [--format json|text]\n */\n\nimport { parseArgs, fail } from \"../utils.js\";\nimport {\n resourceList,\n resourceListAccessible,\n ensurePersonalDefaults,\n SHARED_OWNER,\n} from \"../../resources/store.js\";\nimport { getRequestUserEmail } from \"../../server/request-context.js\";\n\nexport default async function resourceListScript(\n args: string[],\n): Promise<void> {\n const parsed = parseArgs(args);\n\n if (parsed.help === \"true\") {\n console.log(`Usage: pnpm action resource-list [options]\n\nOptions:\n --prefix <path> Filter by path prefix\n --scope personal|shared|all Scope to list (default: all)\n --format json|text Output format (default: text)\n --help Show this help message`);\n return;\n }\n\n const prefix = parsed.prefix;\n const scope = parsed.scope ?? \"all\";\n const format = parsed.format ?? \"text\";\n const owner = getRequestUserEmail() ?? process.env.AGENT_USER_EMAIL;\n if (!owner) {\n fail(\n \"resource-list requires an authenticated user (request context or AGENT_USER_EMAIL env var).\",\n );\n }\n\n // Seed personal AGENTS.md + LEARNINGS.md on first access\n if (scope !== \"shared\") {\n await ensurePersonalDefaults(owner);\n }\n\n let resources;\n if (scope === \"personal\") {\n resources = await resourceList(owner, prefix);\n } else if (scope === \"shared\") {\n resources = await resourceList(SHARED_OWNER, prefix);\n } else {\n resources = await resourceListAccessible(owner, prefix);\n }\n\n if (format === \"json\") {\n console.log(JSON.stringify(resources, null, 2));\n return;\n }\n\n // Human-readable output\n if (resources.length === 0) {\n console.log(\"No resources found.\");\n return;\n }\n\n console.log(`Resources: ${resources.length}\\n`);\n\n for (const r of resources) {\n const ownerLabel = r.owner === SHARED_OWNER ? \"[shared]\" : `[${r.owner}]`;\n const sizeLabel = r.size != null ? ` (${r.size} bytes)` : \"\";\n console.log(` ${r.path} ${ownerLabel}${sizeLabel} ${r.mimeType}`);\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"migrate-learnings.d.ts","sourceRoot":"","sources":["../../../src/scripts/resources/migrate-learnings.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH,wBAA8B,sBAAsB,CAClD,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,IAAI,CAAC,CAoBf"}
1
+ {"version":3,"file":"migrate-learnings.d.ts","sourceRoot":"","sources":["../../../src/scripts/resources/migrate-learnings.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH,wBAA8B,sBAAsB,CAClD,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,IAAI,CAAC,CAyBf"}
@@ -10,7 +10,7 @@ import fs from "fs";
10
10
  import path from "path";
11
11
  import { resourcePut } from "../../resources/store.js";
12
12
  import { getRequestUserEmail } from "../../server/request-context.js";
13
- import { DEV_MODE_USER_EMAIL } from "../../server/auth.js";
13
+ import { fail } from "../utils.js";
14
14
  export default async function migrateLearningsScript(args) {
15
15
  const filePath = path.resolve(process.cwd(), "learnings.md");
16
16
  if (!fs.existsSync(filePath)) {
@@ -18,7 +18,10 @@ export default async function migrateLearningsScript(args) {
18
18
  return;
19
19
  }
20
20
  const content = fs.readFileSync(filePath, "utf-8");
21
- const owner = getRequestUserEmail() ?? DEV_MODE_USER_EMAIL;
21
+ const owner = getRequestUserEmail() ?? process.env.AGENT_USER_EMAIL;
22
+ if (!owner) {
23
+ fail("migrate-learnings requires an authenticated user (request context or AGENT_USER_EMAIL env var).");
24
+ }
22
25
  const resource = await resourcePut(owner, "learnings.md", content, "text/markdown");
23
26
  console.log(`Migrated learnings.md to resource store (${resource.size} bytes)`);
24
27
  }
@@ -1 +1 @@
1
- {"version":3,"file":"migrate-learnings.js","sourceRoot":"","sources":["../../../src/scripts/resources/migrate-learnings.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE3D,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,sBAAsB,CAClD,IAAc;IAEd,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,CAAC,CAAC;IAE7D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QACrC,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,mBAAmB,EAAE,IAAI,mBAAmB,CAAC;IAE3D,MAAM,QAAQ,GAAG,MAAM,WAAW,CAChC,KAAK,EACL,cAAc,EACd,OAAO,EACP,eAAe,CAChB,CAAC;IACF,OAAO,CAAC,GAAG,CACT,4CAA4C,QAAQ,CAAC,IAAI,SAAS,CACnE,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Core script: migrate-learnings\n *\n * Migrate a learnings.md file from the project root into the SQL resource store.\n *\n * Usage:\n * pnpm action migrate-learnings\n */\n\nimport fs from \"fs\";\nimport path from \"path\";\nimport { resourcePut } from \"../../resources/store.js\";\nimport { getRequestUserEmail } from \"../../server/request-context.js\";\nimport { DEV_MODE_USER_EMAIL } from \"../../server/auth.js\";\n\nexport default async function migrateLearningsScript(\n args: string[],\n): Promise<void> {\n const filePath = path.resolve(process.cwd(), \"learnings.md\");\n\n if (!fs.existsSync(filePath)) {\n console.log(\"No learnings.md found\");\n return;\n }\n\n const content = fs.readFileSync(filePath, \"utf-8\");\n const owner = getRequestUserEmail() ?? DEV_MODE_USER_EMAIL;\n\n const resource = await resourcePut(\n owner,\n \"learnings.md\",\n content,\n \"text/markdown\",\n );\n console.log(\n `Migrated learnings.md to resource store (${resource.size} bytes)`,\n );\n}\n"]}
1
+ {"version":3,"file":"migrate-learnings.js","sourceRoot":"","sources":["../../../src/scripts/resources/migrate-learnings.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAEnC,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,sBAAsB,CAClD,IAAc;IAEd,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,CAAC,CAAC;IAE7D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QACrC,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,mBAAmB,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IACpE,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,IAAI,CACF,iGAAiG,CAClG,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,WAAW,CAChC,KAAK,EACL,cAAc,EACd,OAAO,EACP,eAAe,CAChB,CAAC;IACF,OAAO,CAAC,GAAG,CACT,4CAA4C,QAAQ,CAAC,IAAI,SAAS,CACnE,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Core script: migrate-learnings\n *\n * Migrate a learnings.md file from the project root into the SQL resource store.\n *\n * Usage:\n * pnpm action migrate-learnings\n */\n\nimport fs from \"fs\";\nimport path from \"path\";\nimport { resourcePut } from \"../../resources/store.js\";\nimport { getRequestUserEmail } from \"../../server/request-context.js\";\nimport { fail } from \"../utils.js\";\n\nexport default async function migrateLearningsScript(\n args: string[],\n): Promise<void> {\n const filePath = path.resolve(process.cwd(), \"learnings.md\");\n\n if (!fs.existsSync(filePath)) {\n console.log(\"No learnings.md found\");\n return;\n }\n\n const content = fs.readFileSync(filePath, \"utf-8\");\n const owner = getRequestUserEmail() ?? process.env.AGENT_USER_EMAIL;\n if (!owner) {\n fail(\n \"migrate-learnings requires an authenticated user (request context or AGENT_USER_EMAIL env var).\",\n );\n }\n\n const resource = await resourcePut(\n owner,\n \"learnings.md\",\n content,\n \"text/markdown\",\n );\n console.log(\n `Migrated learnings.md to resource store (${resource.size} bytes)`,\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../src/scripts/resources/read.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAWH,wBAA8B,kBAAkB,CAC9C,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,IAAI,CAAC,CA8Df"}
1
+ {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../src/scripts/resources/read.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH,wBAA8B,kBAAkB,CAC9C,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,IAAI,CAAC,CAmEf"}
@@ -9,7 +9,6 @@
9
9
  import { parseArgs, fail } from "../utils.js";
10
10
  import { resourceGetByPath, ensurePersonalDefaults, SHARED_OWNER, } from "../../resources/store.js";
11
11
  import { getRequestUserEmail } from "../../server/request-context.js";
12
- import { DEV_MODE_USER_EMAIL } from "../../server/auth.js";
13
12
  export default async function resourceReadScript(args) {
14
13
  const parsed = parseArgs(args);
15
14
  if (parsed.help === "true") {
@@ -26,7 +25,10 @@ Options:
26
25
  fail("--path is required. Example: --path LEARNINGS.md");
27
26
  }
28
27
  const scope = parsed.scope;
29
- const owner = getRequestUserEmail() ?? DEV_MODE_USER_EMAIL;
28
+ const owner = getRequestUserEmail() ?? process.env.AGENT_USER_EMAIL;
29
+ if (!owner) {
30
+ fail("resource-read requires an authenticated user (request context or AGENT_USER_EMAIL env var).");
31
+ }
30
32
  // Seed personal AGENTS.md + LEARNINGS.md on first access
31
33
  if (scope !== "shared") {
32
34
  await ensurePersonalDefaults(owner);
@@ -1 +1 @@
1
- {"version":3,"file":"read.js","sourceRoot":"","sources":["../../../src/scripts/resources/read.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,YAAY,GACb,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE3D,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,kBAAkB,CAC9C,IAAc;IAEd,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAE/B,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC;;;;;kDAKkC,CAAC,CAAC;QAChD,OAAO;IACT,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC;IACjC,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,IAAI,CAAC,kDAAkD,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IAC3B,MAAM,KAAK,GAAG,mBAAmB,EAAE,IAAI,mBAAmB,CAAC;IAE3D,yDAAyD;IACzD,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvB,MAAM,sBAAsB,CAAC,KAAK,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;QACrE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CACT,uBAAuB,YAAY,0DAA0D,CAC9F,CAAC;YACF,OAAO;QACT,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACvC,OAAO;IACT,CAAC;IAED,mDAAmD;IACnD,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;IAC9D,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACvC,OAAO;IACT,CAAC;IAED,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;QACzB,4CAA4C;QAC5C,OAAO,CAAC,GAAG,CACT,uBAAuB,YAAY,4DAA4D,CAChG,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;IACnE,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACrC,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CACT,uBAAuB,YAAY,0CAA0C,CAC9E,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Core script: resource-read\n *\n * Read a resource and output its content to stdout.\n *\n * Usage:\n * pnpm action resource-read --path <path> [--scope personal|shared]\n */\n\nimport { parseArgs, fail } from \"../utils.js\";\nimport {\n resourceGetByPath,\n ensurePersonalDefaults,\n SHARED_OWNER,\n} from \"../../resources/store.js\";\nimport { getRequestUserEmail } from \"../../server/request-context.js\";\nimport { DEV_MODE_USER_EMAIL } from \"../../server/auth.js\";\n\nexport default async function resourceReadScript(\n args: string[],\n): Promise<void> {\n const parsed = parseArgs(args);\n\n if (parsed.help === \"true\") {\n console.log(`Usage: pnpm action resource-read --path <path> [options]\n\nOptions:\n --path <path> Resource path (required)\n --scope personal|shared Scope to read from (default: personal, falls back to shared)\n --help Show this help message`);\n return;\n }\n\n const resourcePath = parsed.path;\n if (!resourcePath) {\n fail(\"--path is required. Example: --path LEARNINGS.md\");\n }\n\n const scope = parsed.scope;\n const owner = getRequestUserEmail() ?? DEV_MODE_USER_EMAIL;\n\n // Seed personal AGENTS.md + LEARNINGS.md on first access\n if (scope !== \"shared\") {\n await ensurePersonalDefaults(owner);\n }\n\n if (scope === \"shared\") {\n const resource = await resourceGetByPath(SHARED_OWNER, resourcePath);\n if (!resource) {\n console.log(\n `Resource not found: ${resourcePath} (scope: shared). You can create it with resource-write.`,\n );\n return;\n }\n process.stdout.write(resource.content);\n return;\n }\n\n // Default: try personal first, fall back to shared\n const personal = await resourceGetByPath(owner, resourcePath);\n if (personal) {\n process.stdout.write(personal.content);\n return;\n }\n\n if (scope === \"personal\") {\n // Explicit personal scope — don't fall back\n console.log(\n `Resource not found: ${resourcePath} (scope: personal). You can create it with resource-write.`,\n );\n return;\n }\n\n const shared = await resourceGetByPath(SHARED_OWNER, resourcePath);\n if (shared) {\n process.stdout.write(shared.content);\n return;\n }\n\n console.log(\n `Resource not found: ${resourcePath}. You can create it with resource-write.`,\n );\n}\n"]}
1
+ {"version":3,"file":"read.js","sourceRoot":"","sources":["../../../src/scripts/resources/read.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,YAAY,GACb,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAEtE,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,kBAAkB,CAC9C,IAAc;IAEd,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAE/B,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC;;;;;kDAKkC,CAAC,CAAC;QAChD,OAAO;IACT,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC;IACjC,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,IAAI,CAAC,kDAAkD,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IAC3B,MAAM,KAAK,GAAG,mBAAmB,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IACpE,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,IAAI,CACF,6FAA6F,CAC9F,CAAC;IACJ,CAAC;IAED,yDAAyD;IACzD,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvB,MAAM,sBAAsB,CAAC,KAAK,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;QACrE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CACT,uBAAuB,YAAY,0DAA0D,CAC9F,CAAC;YACF,OAAO;QACT,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACvC,OAAO;IACT,CAAC;IAED,mDAAmD;IACnD,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;IAC9D,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACvC,OAAO;IACT,CAAC;IAED,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;QACzB,4CAA4C;QAC5C,OAAO,CAAC,GAAG,CACT,uBAAuB,YAAY,4DAA4D,CAChG,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;IACnE,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACrC,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CACT,uBAAuB,YAAY,0CAA0C,CAC9E,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Core script: resource-read\n *\n * Read a resource and output its content to stdout.\n *\n * Usage:\n * pnpm action resource-read --path <path> [--scope personal|shared]\n */\n\nimport { parseArgs, fail } from \"../utils.js\";\nimport {\n resourceGetByPath,\n ensurePersonalDefaults,\n SHARED_OWNER,\n} from \"../../resources/store.js\";\nimport { getRequestUserEmail } from \"../../server/request-context.js\";\n\nexport default async function resourceReadScript(\n args: string[],\n): Promise<void> {\n const parsed = parseArgs(args);\n\n if (parsed.help === \"true\") {\n console.log(`Usage: pnpm action resource-read --path <path> [options]\n\nOptions:\n --path <path> Resource path (required)\n --scope personal|shared Scope to read from (default: personal, falls back to shared)\n --help Show this help message`);\n return;\n }\n\n const resourcePath = parsed.path;\n if (!resourcePath) {\n fail(\"--path is required. Example: --path LEARNINGS.md\");\n }\n\n const scope = parsed.scope;\n const owner = getRequestUserEmail() ?? process.env.AGENT_USER_EMAIL;\n if (!owner) {\n fail(\n \"resource-read requires an authenticated user (request context or AGENT_USER_EMAIL env var).\",\n );\n }\n\n // Seed personal AGENTS.md + LEARNINGS.md on first access\n if (scope !== \"shared\") {\n await ensurePersonalDefaults(owner);\n }\n\n if (scope === \"shared\") {\n const resource = await resourceGetByPath(SHARED_OWNER, resourcePath);\n if (!resource) {\n console.log(\n `Resource not found: ${resourcePath} (scope: shared). You can create it with resource-write.`,\n );\n return;\n }\n process.stdout.write(resource.content);\n return;\n }\n\n // Default: try personal first, fall back to shared\n const personal = await resourceGetByPath(owner, resourcePath);\n if (personal) {\n process.stdout.write(personal.content);\n return;\n }\n\n if (scope === \"personal\") {\n // Explicit personal scope — don't fall back\n console.log(\n `Resource not found: ${resourcePath} (scope: personal). You can create it with resource-write.`,\n );\n return;\n }\n\n const shared = await resourceGetByPath(SHARED_OWNER, resourcePath);\n if (shared) {\n process.stdout.write(shared.content);\n return;\n }\n\n console.log(\n `Resource not found: ${resourcePath}. You can create it with resource-write.`,\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"save-memory.d.ts","sourceRoot":"","sources":["../../../src/scripts/resources/save-memory.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAYH,wBAA8B,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA4E5E"}
1
+ {"version":3,"file":"save-memory.d.ts","sourceRoot":"","sources":["../../../src/scripts/resources/save-memory.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAWH,wBAA8B,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAiF5E"}
@@ -8,7 +8,6 @@
8
8
  import { parseArgs, fail } from "../utils.js";
9
9
  import { resourcePut, resourceGetByPath } from "../../resources/store.js";
10
10
  import { getRequestUserEmail } from "../../server/request-context.js";
11
- import { DEV_MODE_USER_EMAIL } from "../../server/auth.js";
12
11
  const VALID_TYPES = ["user", "feedback", "project", "reference"];
13
12
  const EMPTY_INDEX = `# Memory Index
14
13
  `;
@@ -27,7 +26,10 @@ export default async function saveMemoryScript(args) {
27
26
  const content = parsed.content;
28
27
  if (!content)
29
28
  fail("--content is required");
30
- const owner = getRequestUserEmail() ?? DEV_MODE_USER_EMAIL;
29
+ const owner = getRequestUserEmail() ?? process.env.AGENT_USER_EMAIL;
30
+ if (!owner) {
31
+ fail("save-memory requires an authenticated user (request context or AGENT_USER_EMAIL env var).");
32
+ }
31
33
  const memoryPath = `memory/${name}.md`;
32
34
  const indexPath = "memory/MEMORY.md";
33
35
  const now = new Date().toISOString().slice(0, 10);
@@ -1 +1 @@
1
- {"version":3,"file":"save-memory.js","sourceRoot":"","sources":["../../../src/scripts/resources/save-memory.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Core script: save-memory\n *\n * Create or update a structured memory entry and its index.\n * Stores memory as a resource at `memory/<name>.md` (personal scope)\n * and maintains a `memory/MEMORY.md` index.\n */\n\nimport { parseArgs, fail } from \"../utils.js\";\nimport { resourcePut, resourceGetByPath } from \"../../resources/store.js\";\nimport { getRequestUserEmail } from \"../../server/request-context.js\";\nimport { DEV_MODE_USER_EMAIL } from \"../../server/auth.js\";\n\nconst VALID_TYPES = [\"user\", \"feedback\", \"project\", \"reference\"] as const;\n\nconst EMPTY_INDEX = `# Memory Index\n`;\n\nexport default async function saveMemoryScript(args: string[]): Promise<void> {\n const parsed = parseArgs(args);\n\n const name = parsed.name;\n if (!name) fail(\"--name is required (e.g. 'coding-style', 'project-alpha')\");\n\n const type = parsed.type;\n if (!type || !VALID_TYPES.includes(type as any)) {\n fail(`--type is required. Must be one of: ${VALID_TYPES.join(\", \")}`);\n }\n\n const description = parsed.description;\n if (!description) fail(\"--description is required (one-line summary)\");\n\n const content = parsed.content;\n if (!content) fail(\"--content is required\");\n\n const owner = getRequestUserEmail() ?? DEV_MODE_USER_EMAIL;\n const memoryPath = `memory/${name}.md`;\n const indexPath = \"memory/MEMORY.md\";\n const now = new Date().toISOString().slice(0, 10);\n\n // Build the memory file with frontmatter\n const fileContent = `---\ntype: ${type}\ndescription: ${description}\nupdated: ${now}\n---\n\n${content}`;\n\n // Write the memory file\n await resourcePut(owner, memoryPath, fileContent, \"text/markdown\");\n\n // Update the index\n let index: string;\n try {\n const existing = await resourceGetByPath(owner, indexPath);\n index = existing?.content ?? EMPTY_INDEX;\n } catch {\n index = EMPTY_INDEX;\n }\n\n // Parse existing entries (simple line-based: `- [name](file) — description`)\n const lines = index.split(\"\\n\");\n const entryLine = `- [${name}](${name}.md) — ${description}`;\n const entryPrefix = `- [${name}]`;\n\n // Find and replace or append\n let found = false;\n const updatedLines = lines.map((line) => {\n if (line.startsWith(entryPrefix)) {\n found = true;\n return entryLine;\n }\n return line;\n });\n\n if (!found) {\n // Append after the header\n updatedLines.push(entryLine);\n }\n\n const updatedIndex = updatedLines.join(\"\\n\").trimEnd() + \"\\n\";\n\n // Check size\n const lineCount = updatedIndex.split(\"\\n\").length;\n if (lineCount > 200) {\n console.log(\n `Warning: Memory index has ${lineCount} lines (recommended: <200). Consider consolidating or removing old memories.`,\n );\n }\n\n await resourcePut(owner, indexPath, updatedIndex, \"text/markdown\");\n\n console.log(`Saved memory \"${name}\" (${type}): ${description}`);\n}\n"]}
1
+ {"version":3,"file":"save-memory.js","sourceRoot":"","sources":["../../../src/scripts/resources/save-memory.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Core script: save-memory\n *\n * Create or update a structured memory entry and its index.\n * Stores memory as a resource at `memory/<name>.md` (personal scope)\n * and maintains a `memory/MEMORY.md` index.\n */\n\nimport { parseArgs, fail } from \"../utils.js\";\nimport { resourcePut, resourceGetByPath } from \"../../resources/store.js\";\nimport { getRequestUserEmail } from \"../../server/request-context.js\";\n\nconst VALID_TYPES = [\"user\", \"feedback\", \"project\", \"reference\"] as const;\n\nconst EMPTY_INDEX = `# Memory Index\n`;\n\nexport default async function saveMemoryScript(args: string[]): Promise<void> {\n const parsed = parseArgs(args);\n\n const name = parsed.name;\n if (!name) fail(\"--name is required (e.g. 'coding-style', 'project-alpha')\");\n\n const type = parsed.type;\n if (!type || !VALID_TYPES.includes(type as any)) {\n fail(`--type is required. Must be one of: ${VALID_TYPES.join(\", \")}`);\n }\n\n const description = parsed.description;\n if (!description) fail(\"--description is required (one-line summary)\");\n\n const content = parsed.content;\n if (!content) fail(\"--content is required\");\n\n const owner = getRequestUserEmail() ?? process.env.AGENT_USER_EMAIL;\n if (!owner) {\n fail(\n \"save-memory requires an authenticated user (request context or AGENT_USER_EMAIL env var).\",\n );\n }\n const memoryPath = `memory/${name}.md`;\n const indexPath = \"memory/MEMORY.md\";\n const now = new Date().toISOString().slice(0, 10);\n\n // Build the memory file with frontmatter\n const fileContent = `---\ntype: ${type}\ndescription: ${description}\nupdated: ${now}\n---\n\n${content}`;\n\n // Write the memory file\n await resourcePut(owner, memoryPath, fileContent, \"text/markdown\");\n\n // Update the index\n let index: string;\n try {\n const existing = await resourceGetByPath(owner, indexPath);\n index = existing?.content ?? EMPTY_INDEX;\n } catch {\n index = EMPTY_INDEX;\n }\n\n // Parse existing entries (simple line-based: `- [name](file) — description`)\n const lines = index.split(\"\\n\");\n const entryLine = `- [${name}](${name}.md) — ${description}`;\n const entryPrefix = `- [${name}]`;\n\n // Find and replace or append\n let found = false;\n const updatedLines = lines.map((line) => {\n if (line.startsWith(entryPrefix)) {\n found = true;\n return entryLine;\n }\n return line;\n });\n\n if (!found) {\n // Append after the header\n updatedLines.push(entryLine);\n }\n\n const updatedIndex = updatedLines.join(\"\\n\").trimEnd() + \"\\n\";\n\n // Check size\n const lineCount = updatedIndex.split(\"\\n\").length;\n if (lineCount > 200) {\n console.log(\n `Warning: Memory index has ${lineCount} lines (recommended: <200). Consider consolidating or removing old memories.`,\n );\n }\n\n await resourcePut(owner, indexPath, updatedIndex, \"text/markdown\");\n\n console.log(`Saved memory \"${name}\" (${type}): ${description}`);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../../src/scripts/resources/write.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAmCH,wBAA8B,mBAAmB,CAC/C,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,IAAI,CAAC,CAoCf"}
1
+ {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../../src/scripts/resources/write.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAkCH,wBAA8B,mBAAmB,CAC/C,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,IAAI,CAAC,CA4Cf"}
@@ -9,7 +9,6 @@
9
9
  import { parseArgs, fail } from "../utils.js";
10
10
  import { resourcePut, SHARED_OWNER } from "../../resources/store.js";
11
11
  import { getRequestUserEmail } from "../../server/request-context.js";
12
- import { DEV_MODE_USER_EMAIL } from "../../server/auth.js";
13
12
  const EXTENSION_MIME_MAP = {
14
13
  ".md": "text/markdown",
15
14
  ".ts": "text/typescript",
@@ -60,9 +59,17 @@ Options:
60
59
  }
61
60
  const scope = parsed.scope ?? "personal";
62
61
  const mimeType = parsed.mime ?? inferMimeType(resourcePath);
63
- const owner = scope === "shared"
64
- ? SHARED_OWNER
65
- : (getRequestUserEmail() ?? DEV_MODE_USER_EMAIL);
62
+ let owner;
63
+ if (scope === "shared") {
64
+ owner = SHARED_OWNER;
65
+ }
66
+ else {
67
+ const personalOwner = getRequestUserEmail() ?? process.env.AGENT_USER_EMAIL;
68
+ if (!personalOwner) {
69
+ fail("resource-write --scope=personal requires an authenticated user (request context or AGENT_USER_EMAIL env var).");
70
+ }
71
+ owner = personalOwner;
72
+ }
66
73
  const resource = await resourcePut(owner, resourcePath, content, mimeType);
67
74
  console.log(`Wrote resource: ${resource.path} (${resource.size} bytes)`);
68
75
  }
@@ -1 +1 @@
1
- {"version":3,"file":"write.js","sourceRoot":"","sources":["../../../src/scripts/resources/write.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE3D,MAAM,kBAAkB,GAA2B;IACjD,KAAK,EAAE,eAAe;IACtB,KAAK,EAAE,iBAAiB;IACxB,MAAM,EAAE,iBAAiB;IACzB,KAAK,EAAE,iBAAiB;IACxB,MAAM,EAAE,iBAAiB;IACzB,OAAO,EAAE,kBAAkB;IAC3B,OAAO,EAAE,WAAW;IACpB,MAAM,EAAE,UAAU;IAClB,OAAO,EAAE,WAAW;IACpB,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,iBAAiB;IACzB,MAAM,EAAE,eAAe;IACvB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,UAAU;IAClB,MAAM,EAAE,UAAU;IAClB,KAAK,EAAE,oBAAoB;IAC3B,KAAK,EAAE,eAAe;IACtB,OAAO,EAAE,WAAW;CACrB,CAAC;AAEF,SAAS,aAAa,CAAC,QAAgB;IACrC,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC3C,IAAI,QAAQ,KAAK,CAAC,CAAC;QAAE,OAAO,YAAY,CAAC;IACzC,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACnD,OAAO,kBAAkB,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC;AACjD,CAAC;AAED,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,mBAAmB,CAC/C,IAAc;IAEd,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAE/B,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CACT;;;;;;;kDAO4C,CAC7C,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC;IACjC,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,IAAI,CAAC,mDAAmD,CAAC,CAAC;IAC5D,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;IAC/B,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QAC9C,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACjC,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,UAAU,CAAC;IACzC,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,IAAI,aAAa,CAAC,YAAY,CAAC,CAAC;IAC5D,MAAM,KAAK,GACT,KAAK,KAAK,QAAQ;QAChB,CAAC,CAAC,YAAY;QACd,CAAC,CAAC,CAAC,mBAAmB,EAAE,IAAI,mBAAmB,CAAC,CAAC;IAErD,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC3E,OAAO,CAAC,GAAG,CAAC,mBAAmB,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI,SAAS,CAAC,CAAC;AAC3E,CAAC","sourcesContent":["/**\n * Core script: resource-write\n *\n * Write (create or update) a resource in the SQL store.\n *\n * Usage:\n * pnpm action resource-write --path <path> --content <content> [--scope personal|shared] [--mime <mime-type>]\n */\n\nimport { parseArgs, fail } from \"../utils.js\";\nimport { resourcePut, SHARED_OWNER } from \"../../resources/store.js\";\nimport { getRequestUserEmail } from \"../../server/request-context.js\";\nimport { DEV_MODE_USER_EMAIL } from \"../../server/auth.js\";\n\nconst EXTENSION_MIME_MAP: Record<string, string> = {\n \".md\": \"text/markdown\",\n \".ts\": \"text/typescript\",\n \".tsx\": \"text/typescript\",\n \".js\": \"text/javascript\",\n \".jsx\": \"text/javascript\",\n \".json\": \"application/json\",\n \".html\": \"text/html\",\n \".css\": \"text/css\",\n \".yaml\": \"text/yaml\",\n \".yml\": \"text/yaml\",\n \".xml\": \"application/xml\",\n \".svg\": \"image/svg+xml\",\n \".txt\": \"text/plain\",\n \".csv\": \"text/csv\",\n \".sql\": \"text/sql\",\n \".sh\": \"text/x-shellscript\",\n \".py\": \"text/x-python\",\n \".toml\": \"text/toml\",\n};\n\nfunction inferMimeType(filePath: string): string {\n const dotIndex = filePath.lastIndexOf(\".\");\n if (dotIndex === -1) return \"text/plain\";\n const ext = filePath.slice(dotIndex).toLowerCase();\n return EXTENSION_MIME_MAP[ext] ?? \"text/plain\";\n}\n\nexport default async function resourceWriteScript(\n args: string[],\n): Promise<void> {\n const parsed = parseArgs(args);\n\n if (parsed.help === \"true\") {\n console.log(\n `Usage: pnpm action resource-write --path <path> --content <content> [options]\n\nOptions:\n --path <path> Resource path (required)\n --content <content> Content to write (required)\n --scope personal|shared Scope to write to (default: personal)\n --mime <mime-type> MIME type (default: inferred from extension)\n --help Show this help message`,\n );\n return;\n }\n\n const resourcePath = parsed.path;\n if (!resourcePath) {\n fail(\"--path is required. Example: --path notes/todo.md\");\n }\n\n const content = parsed.content;\n if (content === undefined || content === null) {\n fail(\"--content is required.\");\n }\n\n const scope = parsed.scope ?? \"personal\";\n const mimeType = parsed.mime ?? inferMimeType(resourcePath);\n const owner =\n scope === \"shared\"\n ? SHARED_OWNER\n : (getRequestUserEmail() ?? DEV_MODE_USER_EMAIL);\n\n const resource = await resourcePut(owner, resourcePath, content, mimeType);\n console.log(`Wrote resource: ${resource.path} (${resource.size} bytes)`);\n}\n"]}
1
+ {"version":3,"file":"write.js","sourceRoot":"","sources":["../../../src/scripts/resources/write.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAEtE,MAAM,kBAAkB,GAA2B;IACjD,KAAK,EAAE,eAAe;IACtB,KAAK,EAAE,iBAAiB;IACxB,MAAM,EAAE,iBAAiB;IACzB,KAAK,EAAE,iBAAiB;IACxB,MAAM,EAAE,iBAAiB;IACzB,OAAO,EAAE,kBAAkB;IAC3B,OAAO,EAAE,WAAW;IACpB,MAAM,EAAE,UAAU;IAClB,OAAO,EAAE,WAAW;IACpB,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,iBAAiB;IACzB,MAAM,EAAE,eAAe;IACvB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,UAAU;IAClB,MAAM,EAAE,UAAU;IAClB,KAAK,EAAE,oBAAoB;IAC3B,KAAK,EAAE,eAAe;IACtB,OAAO,EAAE,WAAW;CACrB,CAAC;AAEF,SAAS,aAAa,CAAC,QAAgB;IACrC,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC3C,IAAI,QAAQ,KAAK,CAAC,CAAC;QAAE,OAAO,YAAY,CAAC;IACzC,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACnD,OAAO,kBAAkB,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC;AACjD,CAAC;AAED,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,mBAAmB,CAC/C,IAAc;IAEd,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAE/B,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CACT;;;;;;;kDAO4C,CAC7C,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC;IACjC,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,IAAI,CAAC,mDAAmD,CAAC,CAAC;IAC5D,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;IAC/B,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QAC9C,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACjC,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,UAAU,CAAC;IACzC,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,IAAI,aAAa,CAAC,YAAY,CAAC,CAAC;IAC5D,IAAI,KAAa,CAAC;IAClB,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvB,KAAK,GAAG,YAAY,CAAC;IACvB,CAAC;SAAM,CAAC;QACN,MAAM,aAAa,GAAG,mBAAmB,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;QAC5E,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,IAAI,CACF,+GAA+G,CAChH,CAAC;QACJ,CAAC;QACD,KAAK,GAAG,aAAa,CAAC;IACxB,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC3E,OAAO,CAAC,GAAG,CAAC,mBAAmB,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI,SAAS,CAAC,CAAC;AAC3E,CAAC","sourcesContent":["/**\n * Core script: resource-write\n *\n * Write (create or update) a resource in the SQL store.\n *\n * Usage:\n * pnpm action resource-write --path <path> --content <content> [--scope personal|shared] [--mime <mime-type>]\n */\n\nimport { parseArgs, fail } from \"../utils.js\";\nimport { resourcePut, SHARED_OWNER } from \"../../resources/store.js\";\nimport { getRequestUserEmail } from \"../../server/request-context.js\";\n\nconst EXTENSION_MIME_MAP: Record<string, string> = {\n \".md\": \"text/markdown\",\n \".ts\": \"text/typescript\",\n \".tsx\": \"text/typescript\",\n \".js\": \"text/javascript\",\n \".jsx\": \"text/javascript\",\n \".json\": \"application/json\",\n \".html\": \"text/html\",\n \".css\": \"text/css\",\n \".yaml\": \"text/yaml\",\n \".yml\": \"text/yaml\",\n \".xml\": \"application/xml\",\n \".svg\": \"image/svg+xml\",\n \".txt\": \"text/plain\",\n \".csv\": \"text/csv\",\n \".sql\": \"text/sql\",\n \".sh\": \"text/x-shellscript\",\n \".py\": \"text/x-python\",\n \".toml\": \"text/toml\",\n};\n\nfunction inferMimeType(filePath: string): string {\n const dotIndex = filePath.lastIndexOf(\".\");\n if (dotIndex === -1) return \"text/plain\";\n const ext = filePath.slice(dotIndex).toLowerCase();\n return EXTENSION_MIME_MAP[ext] ?? \"text/plain\";\n}\n\nexport default async function resourceWriteScript(\n args: string[],\n): Promise<void> {\n const parsed = parseArgs(args);\n\n if (parsed.help === \"true\") {\n console.log(\n `Usage: pnpm action resource-write --path <path> --content <content> [options]\n\nOptions:\n --path <path> Resource path (required)\n --content <content> Content to write (required)\n --scope personal|shared Scope to write to (default: personal)\n --mime <mime-type> MIME type (default: inferred from extension)\n --help Show this help message`,\n );\n return;\n }\n\n const resourcePath = parsed.path;\n if (!resourcePath) {\n fail(\"--path is required. Example: --path notes/todo.md\");\n }\n\n const content = parsed.content;\n if (content === undefined || content === null) {\n fail(\"--content is required.\");\n }\n\n const scope = parsed.scope ?? \"personal\";\n const mimeType = parsed.mime ?? inferMimeType(resourcePath);\n let owner: string;\n if (scope === \"shared\") {\n owner = SHARED_OWNER;\n } else {\n const personalOwner = getRequestUserEmail() ?? process.env.AGENT_USER_EMAIL;\n if (!personalOwner) {\n fail(\n \"resource-write --scope=personal requires an authenticated user (request context or AGENT_USER_EMAIL env var).\",\n );\n }\n owner = personalOwner;\n }\n\n const resource = await resourcePut(owner, resourcePath, content, mimeType);\n console.log(`Wrote resource: ${resource.path} (${resource.size} bytes)`);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"onboarding.d.ts","sourceRoot":"","sources":["../../src/secrets/onboarding.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAYH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGtD;;;;;;GAMG;AACH,wBAAgB,iCAAiC,CAC/C,MAAM,EAAE,gBAAgB,GACvB,IAAI,CAmFN"}
1
+ {"version":3,"file":"onboarding.d.ts","sourceRoot":"","sources":["../../src/secrets/onboarding.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGtD;;;;;;GAMG;AACH,wBAAgB,iCAAiC,CAC/C,MAAM,EAAE,gBAAgB,GACvB,IAAI,CAyEN"}
@@ -7,8 +7,7 @@
7
7
  * env var, by looking at oauth-tokens, or by reading `app_secrets`.
8
8
  */
9
9
  import { registerOnboardingStep } from "../onboarding/registry.js";
10
- import { hasOAuthTokens, listOAuthAccountsByOwner, } from "../oauth-tokens/store.js";
11
- import { DEV_MODE_USER_EMAIL } from "../server/auth.js";
10
+ import { listOAuthAccountsByOwner } from "../oauth-tokens/store.js";
12
11
  import { readAppSecretMeta } from "./storage.js";
13
12
  /**
14
13
  * If the secret is marked `required`, register a matching onboarding step.
@@ -60,13 +59,6 @@ export function maybeRegisterSecretOnboardingStep(secret) {
60
59
  return false;
61
60
  if (secret.kind === "oauth" && secret.oauthProvider) {
62
61
  try {
63
- // hasOAuthTokens now requires an owner — pass the dev sentinel for
64
- // local-dev's "any row exists" wildcard, otherwise the user email
65
- // so onboarding only marks the step complete for the user who
66
- // actually connected.
67
- if (userEmail === DEV_MODE_USER_EMAIL) {
68
- return await hasOAuthTokens(secret.oauthProvider, DEV_MODE_USER_EMAIL);
69
- }
70
62
  const accounts = await listOAuthAccountsByOwner(secret.oauthProvider, userEmail);
71
63
  return accounts.length > 0;
72
64
  }
@@ -1 +1 @@
1
- {"version":3,"file":"onboarding.js","sourceRoot":"","sources":["../../src/secrets/onboarding.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Onboarding integration for the secrets registry.\n *\n * When a secret is registered with `required: true`, we inject an onboarding\n * step so the sidebar checklist nudges the user to configure it. The step's\n * completion resolver consults the live status — either by checking for an\n * env var, by looking at oauth-tokens, or by reading `app_secrets`.\n */\n\nimport { registerOnboardingStep } from \"../onboarding/registry.js\";\nimport type {\n OnboardingResolveContext,\n OnboardingStep,\n} from \"../onboarding/types.js\";\nimport {\n hasOAuthTokens,\n listOAuthAccountsByOwner,\n} from \"../oauth-tokens/store.js\";\nimport { DEV_MODE_USER_EMAIL } from \"../server/auth.js\";\nimport type { RegisteredSecret } from \"./register.js\";\nimport { readAppSecretMeta } from \"./storage.js\";\n\n/**\n * If the secret is marked `required`, register a matching onboarding step.\n * Called by `registerRequiredSecret()`. No-op for non-required secrets.\n *\n * Step `order` sits at 60 by default so framework steps (10/20/30/40) stay\n * at the top; the caller can bump this by re-registering the step.\n */\nexport function maybeRegisterSecretOnboardingStep(\n secret: RegisteredSecret,\n): void {\n if (!secret.required) return;\n\n const step: OnboardingStep = {\n id: `secret:${secret.key}`,\n order: 60,\n required: true,\n title: secret.label,\n description:\n secret.description ??\n `Set up \"${secret.key}\" to finish configuring the app.`,\n methods: [\n secret.kind === \"oauth\"\n ? {\n id: \"connect\",\n kind: \"link\",\n primary: true,\n label: `Connect ${secret.label}`,\n description: \"Opens the OAuth flow.\",\n payload: {\n url: secret.oauthConnectUrl ?? \"#open-secrets-settings\",\n external: false,\n },\n }\n : {\n id: \"open-settings\",\n kind: \"link\",\n primary: true,\n label: `Open ${secret.label} settings`,\n description:\n \"Paste the key in the sidebar's API Keys & Connections section.\",\n payload: {\n // Fragment handled by the sidebar — expands the Secrets section\n // and focuses the matching input.\n url: `#secrets:${secret.key}`,\n external: false,\n },\n },\n ],\n isComplete: async (context?: OnboardingResolveContext) => {\n const userEmail = context?.userEmail;\n if (!userEmail) return false;\n\n if (secret.kind === \"oauth\" && secret.oauthProvider) {\n try {\n // hasOAuthTokens now requires an owner — pass the dev sentinel for\n // local-dev's \"any row exists\" wildcard, otherwise the user email\n // so onboarding only marks the step complete for the user who\n // actually connected.\n if (userEmail === DEV_MODE_USER_EMAIL) {\n return await hasOAuthTokens(\n secret.oauthProvider,\n DEV_MODE_USER_EMAIL,\n );\n }\n const accounts = await listOAuthAccountsByOwner(\n secret.oauthProvider,\n userEmail,\n );\n return accounts.length > 0;\n } catch {\n return false;\n }\n }\n\n try {\n const scopeId =\n secret.scope === \"workspace\"\n ? (context?.orgId ?? `solo:${userEmail}`)\n : userEmail;\n const meta = await readAppSecretMeta({\n key: secret.key,\n scope: secret.scope,\n scopeId,\n });\n return !!meta;\n } catch {\n return false;\n }\n },\n };\n\n registerOnboardingStep(step);\n}\n"]}
1
+ {"version":3,"file":"onboarding.js","sourceRoot":"","sources":["../../src/secrets/onboarding.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAKnE,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD;;;;;;GAMG;AACH,MAAM,UAAU,iCAAiC,CAC/C,MAAwB;IAExB,IAAI,CAAC,MAAM,CAAC,QAAQ;QAAE,OAAO;IAE7B,MAAM,IAAI,GAAmB;QAC3B,EAAE,EAAE,UAAU,MAAM,CAAC,GAAG,EAAE;QAC1B,KAAK,EAAE,EAAE;QACT,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,WAAW,EACT,MAAM,CAAC,WAAW;YAClB,WAAW,MAAM,CAAC,GAAG,kCAAkC;QACzD,OAAO,EAAE;YACP,MAAM,CAAC,IAAI,KAAK,OAAO;gBACrB,CAAC,CAAC;oBACE,EAAE,EAAE,SAAS;oBACb,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE,IAAI;oBACb,KAAK,EAAE,WAAW,MAAM,CAAC,KAAK,EAAE;oBAChC,WAAW,EAAE,uBAAuB;oBACpC,OAAO,EAAE;wBACP,GAAG,EAAE,MAAM,CAAC,eAAe,IAAI,wBAAwB;wBACvD,QAAQ,EAAE,KAAK;qBAChB;iBACF;gBACH,CAAC,CAAC;oBACE,EAAE,EAAE,eAAe;oBACnB,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE,IAAI;oBACb,KAAK,EAAE,QAAQ,MAAM,CAAC,KAAK,WAAW;oBACtC,WAAW,EACT,gEAAgE;oBAClE,OAAO,EAAE;wBACP,gEAAgE;wBAChE,kCAAkC;wBAClC,GAAG,EAAE,YAAY,MAAM,CAAC,GAAG,EAAE;wBAC7B,QAAQ,EAAE,KAAK;qBAChB;iBACF;SACN;QACD,UAAU,EAAE,KAAK,EAAE,OAAkC,EAAE,EAAE;YACvD,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,CAAC;YACrC,IAAI,CAAC,SAAS;gBAAE,OAAO,KAAK,CAAC;YAE7B,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;gBACpD,IAAI,CAAC;oBACH,MAAM,QAAQ,GAAG,MAAM,wBAAwB,CAC7C,MAAM,CAAC,aAAa,EACpB,SAAS,CACV,CAAC;oBACF,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;gBAC7B,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,KAAK,CAAC;gBACf,CAAC;YACH,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,OAAO,GACX,MAAM,CAAC,KAAK,KAAK,WAAW;oBAC1B,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK,IAAI,QAAQ,SAAS,EAAE,CAAC;oBACzC,CAAC,CAAC,SAAS,CAAC;gBAChB,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC;oBACnC,GAAG,EAAE,MAAM,CAAC,GAAG;oBACf,KAAK,EAAE,MAAM,CAAC,KAAK;oBACnB,OAAO;iBACR,CAAC,CAAC;gBACH,OAAO,CAAC,CAAC,IAAI,CAAC;YAChB,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;KACF,CAAC;IAEF,sBAAsB,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC","sourcesContent":["/**\n * Onboarding integration for the secrets registry.\n *\n * When a secret is registered with `required: true`, we inject an onboarding\n * step so the sidebar checklist nudges the user to configure it. The step's\n * completion resolver consults the live status — either by checking for an\n * env var, by looking at oauth-tokens, or by reading `app_secrets`.\n */\n\nimport { registerOnboardingStep } from \"../onboarding/registry.js\";\nimport type {\n OnboardingResolveContext,\n OnboardingStep,\n} from \"../onboarding/types.js\";\nimport { listOAuthAccountsByOwner } from \"../oauth-tokens/store.js\";\nimport type { RegisteredSecret } from \"./register.js\";\nimport { readAppSecretMeta } from \"./storage.js\";\n\n/**\n * If the secret is marked `required`, register a matching onboarding step.\n * Called by `registerRequiredSecret()`. No-op for non-required secrets.\n *\n * Step `order` sits at 60 by default so framework steps (10/20/30/40) stay\n * at the top; the caller can bump this by re-registering the step.\n */\nexport function maybeRegisterSecretOnboardingStep(\n secret: RegisteredSecret,\n): void {\n if (!secret.required) return;\n\n const step: OnboardingStep = {\n id: `secret:${secret.key}`,\n order: 60,\n required: true,\n title: secret.label,\n description:\n secret.description ??\n `Set up \"${secret.key}\" to finish configuring the app.`,\n methods: [\n secret.kind === \"oauth\"\n ? {\n id: \"connect\",\n kind: \"link\",\n primary: true,\n label: `Connect ${secret.label}`,\n description: \"Opens the OAuth flow.\",\n payload: {\n url: secret.oauthConnectUrl ?? \"#open-secrets-settings\",\n external: false,\n },\n }\n : {\n id: \"open-settings\",\n kind: \"link\",\n primary: true,\n label: `Open ${secret.label} settings`,\n description:\n \"Paste the key in the sidebar's API Keys & Connections section.\",\n payload: {\n // Fragment handled by the sidebar — expands the Secrets section\n // and focuses the matching input.\n url: `#secrets:${secret.key}`,\n external: false,\n },\n },\n ],\n isComplete: async (context?: OnboardingResolveContext) => {\n const userEmail = context?.userEmail;\n if (!userEmail) return false;\n\n if (secret.kind === \"oauth\" && secret.oauthProvider) {\n try {\n const accounts = await listOAuthAccountsByOwner(\n secret.oauthProvider,\n userEmail,\n );\n return accounts.length > 0;\n } catch {\n return false;\n }\n }\n\n try {\n const scopeId =\n secret.scope === \"workspace\"\n ? (context?.orgId ?? `solo:${userEmail}`)\n : userEmail;\n const meta = await readAppSecretMeta({\n key: secret.key,\n scope: secret.scope,\n scopeId,\n });\n return !!meta;\n } catch {\n return false;\n }\n },\n };\n\n registerOnboardingStep(step);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/secrets/routes.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAyCH,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,eAAe,CAAC;AAUvB,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,WAAW,CAAC;IACnB,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,qFAAqF;IACrF,MAAM,EAAE,KAAK,GAAG,OAAO,GAAG,SAAS,CAAC;IACpC,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0DAA0D;IAC1D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAgDD,wEAAwE;AACxE,wBAAgB,wBAAwB;;IA0DvC;AAED,yDAAyD;AACzD,wBAAgB,wBAAwB;;;;;;;;;;;;;;;;IAyBvC;AAiHD;;;GAGG;AACH,wBAAgB,uBAAuB;;;;;;;;;;;;;;;;IAiEtC;AAMD,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAiBD;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB;;;;;;;;;;IAiBvC"}
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/secrets/routes.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAsCH,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,eAAe,CAAC;AAUvB,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,WAAW,CAAC;IACnB,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,qFAAqF;IACrF,MAAM,EAAE,KAAK,GAAG,OAAO,GAAG,SAAS,CAAC;IACpC,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0DAA0D;IAC1D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA2CD,wEAAwE;AACxE,wBAAgB,wBAAwB;;IA0DvC;AAED,yDAAyD;AACzD,wBAAgB,wBAAwB;;;;;;;;;;;;;;;;IAyBvC;AAiHD;;;GAGG;AACH,wBAAgB,uBAAuB;;;;;;;;;;;;;;;;IAiEtC;AAMD,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAiBD;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB;;;;;;;;;;IAiBvC"}
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import { defineEventHandler, getMethod, setResponseStatus, } from "h3";
9
9
  import { readBody } from "../server/h3-helpers.js";
10
- import { DEV_MODE_USER_EMAIL, getSession } from "../server/auth.js";
10
+ import { getSession } from "../server/auth.js";
11
11
  import { getOrgContext } from "../org/context.js";
12
12
  /**
13
13
  * Workspace-scoped secret writes/deletes are deployment-wide for every
@@ -33,7 +33,7 @@ async function canMutateWorkspaceScope(event, scopeId) {
33
33
  return true;
34
34
  return ctx.role === "owner" || ctx.role === "admin";
35
35
  }
36
- import { hasOAuthTokens, listOAuthAccountsByOwner, } from "../oauth-tokens/store.js";
36
+ import { listOAuthAccountsByOwner } from "../oauth-tokens/store.js";
37
37
  import { listRequiredSecrets, getRequiredSecret, } from "./register.js";
38
38
  import { writeAppSecret, deleteAppSecret, getAppSecretMeta, readAppSecret, listAppSecretsForScope, } from "./storage.js";
39
39
  function redactSecretFromMessage(message, secretValue) {
@@ -47,11 +47,6 @@ async function hasOAuthSecretForEvent(event, secret) {
47
47
  const session = await getSession(event).catch(() => null);
48
48
  if (!session?.email)
49
49
  return false;
50
- // hasOAuthTokens now requires an explicit owner — passing the dev sentinel
51
- // preserves the "any row exists" wildcard behaviour for local-dev only.
52
- if (session.email === DEV_MODE_USER_EMAIL) {
53
- return hasOAuthTokens(secret.oauthProvider, DEV_MODE_USER_EMAIL);
54
- }
55
50
  const accounts = await listOAuthAccountsByOwner(secret.oauthProvider, session.email);
56
51
  return accounts.length > 0;
57
52
  }
@@ -1 +1 @@
1
- {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/secrets/routes.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * H3 event handlers for the framework secrets registry.\n *\n * Mounted under `/_agent-native/secrets/*` by `core-routes-plugin`.\n *\n * NEVER return a secret's plain-text value from any of these handlers.\n */\n\nimport {\n defineEventHandler,\n getMethod,\n setResponseStatus,\n type H3Event,\n} from \"h3\";\nimport { readBody } from \"../server/h3-helpers.js\";\nimport { DEV_MODE_USER_EMAIL, getSession } from \"../server/auth.js\";\nimport { getOrgContext } from \"../org/context.js\";\n\n/**\n * Workspace-scoped secret writes/deletes are deployment-wide for every\n * org member who shares the resolved scopeId — a curious or malicious\n * member could otherwise overwrite `OPENAI_API_KEY` (or any unregistered\n * key) with their own value, redirecting every other member's automations\n * through their key for skimming, billing abuse, or DoS by deletion.\n *\n * Allow workspace-scope writes only for org owners/admins. The \"solo\"\n * fallback scopeId (`solo:<email>`) is single-user, so it bypasses the\n * check. A normal session with no active org also passes — there's no\n * privilege gradient to enforce in that case.\n *\n * Returns true if the request is allowed to write/delete this scope.\n */\nasync function canMutateWorkspaceScope(\n event: H3Event,\n scopeId: string,\n): Promise<boolean> {\n // Solo / dev fallback scope — single user, no privilege gradient.\n if (scopeId.startsWith(\"solo:\")) return true;\n const ctx = await getOrgContext(event).catch(() => null);\n // No active org — single-tenant flow, allow.\n if (!ctx?.orgId) return true;\n return ctx.role === \"owner\" || ctx.role === \"admin\";\n}\nimport {\n hasOAuthTokens,\n listOAuthAccountsByOwner,\n} from \"../oauth-tokens/store.js\";\nimport {\n listRequiredSecrets,\n getRequiredSecret,\n type RegisteredSecret,\n type SecretScope,\n} from \"./register.js\";\nimport {\n writeAppSecret,\n deleteAppSecret,\n getAppSecretMeta,\n readAppSecret,\n listAppSecretsForScope,\n type SecretMeta,\n} from \"./storage.js\";\n\nexport interface SecretStatusPayload {\n key: string;\n label: string;\n description?: string;\n docsUrl?: string;\n scope: SecretScope;\n kind: \"api-key\" | \"oauth\";\n required: boolean;\n /** \"set\" = value present; \"unset\" = not configured; \"invalid\" = validator failed. */\n status: \"set\" | \"unset\" | \"invalid\";\n /** Last 4 chars — only populated when status === \"set\" for api-key kind. */\n last4?: string;\n /** Timestamp (ms) of the last write — only populated when status === \"set\". */\n updatedAt?: number;\n /** OAuth-kind: the provider id backing this secret. */\n oauthProvider?: string;\n /** OAuth-kind: url the Connect button should point at. */\n oauthConnectUrl?: string;\n /** Validator error message if status === \"invalid\". */\n error?: string;\n}\n\nfunction redactSecretFromMessage(message: string, secretValue: string): string {\n if (!message || !secretValue) return message;\n return message.split(secretValue).join(\"[redacted]\");\n}\n\nasync function hasOAuthSecretForEvent(\n event: H3Event,\n secret: RegisteredSecret,\n): Promise<boolean> {\n if (!secret.oauthProvider) return false;\n const session = await getSession(event).catch(() => null);\n if (!session?.email) return false;\n // hasOAuthTokens now requires an explicit owner — passing the dev sentinel\n // preserves the \"any row exists\" wildcard behaviour for local-dev only.\n if (session.email === DEV_MODE_USER_EMAIL) {\n return hasOAuthTokens(secret.oauthProvider, DEV_MODE_USER_EMAIL);\n }\n const accounts = await listOAuthAccountsByOwner(\n secret.oauthProvider,\n session.email,\n );\n return accounts.length > 0;\n}\n\n/** Resolve the scopeId for a given scope, given the current session. */\nasync function resolveScopeId(\n event: H3Event,\n scope: SecretScope,\n): Promise<{ scopeId: string | null; reason?: string }> {\n if (scope === \"user\") {\n const session = await getSession(event).catch(() => null);\n if (!session?.email) {\n return { scopeId: null, reason: \"Authentication required\" };\n }\n return { scopeId: session.email };\n }\n // workspace\n const ctx = await getOrgContext(event).catch(() => null);\n if (ctx?.orgId) return { scopeId: ctx.orgId };\n // Fall back to session email in solo/dev mode so secrets still work without\n // an active organisation.\n const session = await getSession(event).catch(() => null);\n if (session?.email) return { scopeId: `solo:${session.email}` };\n return { scopeId: null, reason: \"No workspace or session context\" };\n}\n\n/** GET /_agent-native/secrets — list registered secrets with status. */\nexport function createListSecretsHandler() {\n return defineEventHandler(async (event: H3Event) => {\n if (getMethod(event) !== \"GET\") {\n setResponseStatus(event, 405);\n return { error: \"Method not allowed\" };\n }\n\n const secrets = listRequiredSecrets();\n const payload: SecretStatusPayload[] = [];\n\n for (const secret of secrets) {\n const base: SecretStatusPayload = {\n key: secret.key,\n label: secret.label,\n description: secret.description,\n docsUrl: secret.docsUrl,\n scope: secret.scope,\n kind: secret.kind,\n required: !!secret.required,\n status: \"unset\",\n };\n\n if (secret.kind === \"oauth\") {\n base.oauthProvider = secret.oauthProvider;\n base.oauthConnectUrl = secret.oauthConnectUrl;\n if (secret.oauthProvider) {\n try {\n const has = await hasOAuthSecretForEvent(event, secret);\n base.status = has ? \"set\" : \"unset\";\n } catch {\n base.status = \"unset\";\n }\n }\n payload.push(base);\n continue;\n }\n\n // api-key: look up the stored row in app_secrets.\n const { scopeId } = await resolveScopeId(event, secret.scope);\n if (!scopeId) {\n payload.push(base);\n continue;\n }\n const meta = await getAppSecretMeta({\n key: secret.key,\n scope: secret.scope,\n scopeId,\n }).catch(() => null);\n if (meta) {\n base.status = \"set\";\n base.last4 = meta.last4;\n base.updatedAt = meta.updatedAt;\n }\n payload.push(base);\n }\n\n return payload;\n });\n}\n\n/** POST /_agent-native/secrets/:key — write a secret. */\nexport function createWriteSecretHandler() {\n return defineEventHandler(async (event: H3Event) => {\n const method = getMethod(event);\n const key = extractKeyFromEvent(event);\n\n if (!key) {\n setResponseStatus(event, 400);\n return { error: \"Secret key required\" };\n }\n\n const secret = getRequiredSecret(key);\n if (!secret) {\n setResponseStatus(event, 404);\n return { error: `Secret \"${key}\" is not registered` };\n }\n\n if (method === \"POST\" || method === \"PUT\") {\n return handleWrite(event, secret);\n }\n if (method === \"DELETE\") {\n return handleDelete(event, secret);\n }\n setResponseStatus(event, 405);\n return { error: \"Method not allowed\" };\n });\n}\n\nasync function handleWrite(event: H3Event, secret: RegisteredSecret) {\n if (secret.kind === \"oauth\") {\n setResponseStatus(event, 400);\n return {\n error: `\"${secret.key}\" is an OAuth-kind secret — connect via ${secret.oauthConnectUrl ?? \"the OAuth flow\"} instead`,\n };\n }\n const body = (await readBody(event).catch(() => ({}))) as {\n value?: unknown;\n };\n\n const value = typeof body.value === \"string\" ? body.value.trim() : \"\";\n if (!value) {\n setResponseStatus(event, 400);\n return { error: \"value is required\" };\n }\n\n const { scopeId, reason } = await resolveScopeId(event, secret.scope);\n if (!scopeId) {\n setResponseStatus(event, 401);\n return { error: reason ?? \"Unable to resolve scope\" };\n }\n\n if (\n secret.scope === \"workspace\" &&\n !(await canMutateWorkspaceScope(event, scopeId))\n ) {\n setResponseStatus(event, 403);\n return {\n error:\n \"Only organization owners and admins can set workspace-scoped secrets\",\n };\n }\n\n // Run validator if registered — return the validator's error on failure.\n if (secret.validator) {\n try {\n const result = await secret.validator(value);\n const ok = typeof result === \"boolean\" ? result : result?.ok === true;\n if (!ok) {\n setResponseStatus(event, 400);\n const err =\n typeof result === \"object\" && result && result.error\n ? String(result.error)\n : \"Validator rejected the value\";\n return { error: redactSecretFromMessage(err, value) };\n }\n } catch (err) {\n setResponseStatus(event, 400);\n const message =\n err instanceof Error\n ? `Validator threw: ${err.message}`\n : \"Validator threw\";\n return {\n error: redactSecretFromMessage(message, value),\n };\n }\n }\n\n try {\n await writeAppSecret({\n key: secret.key,\n value,\n scope: secret.scope,\n scopeId,\n });\n } catch (err) {\n // Scrub: never surface the value in any error path.\n setResponseStatus(event, 500);\n const message =\n err instanceof Error\n ? `Failed to save secret: ${err.message}`\n : \"Failed to save secret\";\n return {\n error: redactSecretFromMessage(message, value),\n };\n }\n\n return { ok: true, status: \"set\" };\n}\n\nasync function handleDelete(event: H3Event, secret: RegisteredSecret) {\n if (secret.kind === \"oauth\") {\n setResponseStatus(event, 400);\n return {\n error: `\"${secret.key}\" is an OAuth-kind secret — disconnect via the OAuth flow instead`,\n };\n }\n const { scopeId, reason } = await resolveScopeId(event, secret.scope);\n if (!scopeId) {\n setResponseStatus(event, 401);\n return { error: reason ?? \"Unable to resolve scope\" };\n }\n if (\n secret.scope === \"workspace\" &&\n !(await canMutateWorkspaceScope(event, scopeId))\n ) {\n setResponseStatus(event, 403);\n return {\n error:\n \"Only organization owners and admins can delete workspace-scoped secrets\",\n };\n }\n const removed = await deleteAppSecret({\n key: secret.key,\n scope: secret.scope,\n scopeId,\n });\n return { ok: true, removed };\n}\n\n/**\n * POST /_agent-native/secrets/:key/test — re-run the validator against the\n * current stored value without changing anything. Useful for the \"Test\" button.\n */\nexport function createTestSecretHandler() {\n return defineEventHandler(async (event: H3Event) => {\n if (getMethod(event) !== \"POST\") {\n setResponseStatus(event, 405);\n return { error: \"Method not allowed\" };\n }\n const key = extractKeyFromEvent(event, { suffix: \"/test\" });\n if (!key) {\n setResponseStatus(event, 400);\n return { error: \"Secret key required\" };\n }\n const secret = getRequiredSecret(key);\n if (!secret) {\n setResponseStatus(event, 404);\n return { error: `Secret \"${key}\" is not registered` };\n }\n if (secret.kind === \"oauth\") {\n // For OAuth we just report whether tokens exist.\n const has = await hasOAuthSecretForEvent(event, secret).catch(\n () => false,\n );\n return { ok: has };\n }\n if (!secret.validator) {\n return { ok: true, note: \"No validator registered\" };\n }\n const { scopeId } = await resolveScopeId(event, secret.scope);\n if (!scopeId) {\n setResponseStatus(event, 401);\n return { error: \"Unable to resolve scope\" };\n }\n const stored = await readAppSecret({\n key: secret.key,\n scope: secret.scope,\n scopeId,\n });\n if (!stored) {\n setResponseStatus(event, 404);\n return { error: \"No value stored\" };\n }\n try {\n const result = await secret.validator(stored.value);\n const ok = typeof result === \"boolean\" ? result : result?.ok === true;\n if (!ok) {\n const err =\n typeof result === \"object\" && result && result.error\n ? String(result.error)\n : \"Validator rejected the value\";\n return {\n ok: false,\n error: redactSecretFromMessage(err, stored.value),\n };\n }\n return { ok: true };\n } catch (err) {\n const message =\n err instanceof Error\n ? `Validator threw: ${err.message}`\n : \"Validator threw\";\n return {\n ok: false,\n error: redactSecretFromMessage(message, stored.value),\n };\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// Ad-hoc secrets — user-/agent-created keys not in the registry\n// ---------------------------------------------------------------------------\n\nexport interface AdHocSecretPayload {\n name: string;\n scope: SecretScope;\n scopeId: string;\n description: string | null;\n last4: string;\n urlAllowlist: string[] | null;\n createdAt: number;\n updatedAt: number;\n}\n\nconst AD_HOC_NAME_REGEX = /^[A-Za-z0-9_-]+$/;\n\nfunction metaToPayload(meta: SecretMeta): AdHocSecretPayload {\n return {\n name: meta.key,\n scope: meta.scope,\n scopeId: meta.scopeId,\n description: meta.description,\n last4: meta.last4,\n urlAllowlist: meta.urlAllowlist,\n createdAt: meta.createdAt,\n updatedAt: meta.updatedAt,\n };\n}\n\n/**\n * Handler for `/_agent-native/secrets/adhoc[/:name]`.\n *\n * - GET (no name) — list all ad-hoc keys for the user's scope\n * - POST (no name) — create or update an ad-hoc key\n * - DELETE (with name) — delete an ad-hoc key\n *\n * Ad-hoc keys are arbitrary named secrets users or the agent create at\n * runtime for automation use (e.g. \"SLACK_WEBHOOK\", \"HUBSPOT_API_KEY\").\n * They differ from registered secrets (`registerRequiredSecret`) in that\n * they have no template-defined metadata, validator, or onboarding step.\n */\nexport function createAdHocSecretHandler() {\n return defineEventHandler(async (event: H3Event) => {\n const method = getMethod(event);\n const name = extractAdHocName(event);\n\n if (method === \"GET\" && !name) {\n return handleAdHocList(event);\n }\n if (method === \"POST\" && !name) {\n return handleAdHocWrite(event);\n }\n if (method === \"DELETE\" && name) {\n return handleAdHocDelete(event, name);\n }\n setResponseStatus(event, 405);\n return { error: \"Method not allowed\" };\n });\n}\n\nasync function handleAdHocList(event: H3Event) {\n const scope: SecretScope = \"user\";\n const { scopeId, reason } = await resolveScopeId(event, scope);\n if (!scopeId) {\n setResponseStatus(event, 401);\n return { error: reason ?? \"Unable to resolve scope\" };\n }\n\n const registered = new Set(listRequiredSecrets().map((s) => s.key));\n const userRows = await listAppSecretsForScope(\"user\", scopeId);\n const workspaceContext = await resolveScopeId(event, \"workspace\");\n const workspaceRows = workspaceContext.scopeId\n ? await listAppSecretsForScope(\"workspace\", workspaceContext.scopeId)\n : [];\n\n const payload: AdHocSecretPayload[] = [];\n for (const row of [...userRows, ...workspaceRows]) {\n if (registered.has(row.key)) continue;\n payload.push(metaToPayload(row));\n }\n return payload;\n}\n\nasync function handleAdHocWrite(event: H3Event) {\n const body = (await readBody(event).catch(() => ({}))) as {\n name?: unknown;\n value?: unknown;\n description?: unknown;\n scope?: unknown;\n urlAllowlist?: unknown;\n };\n\n const name = typeof body.name === \"string\" ? body.name.trim() : \"\";\n if (!name || !AD_HOC_NAME_REGEX.test(name)) {\n setResponseStatus(event, 400);\n return {\n error:\n \"name is required and may only contain letters, digits, underscores, and dashes\",\n };\n }\n if (getRequiredSecret(name)) {\n setResponseStatus(event, 400);\n return {\n error: `\"${name}\" is a registered secret — use POST /_agent-native/secrets/${name} instead`,\n };\n }\n\n const value = typeof body.value === \"string\" ? body.value.trim() : \"\";\n if (!value) {\n setResponseStatus(event, 400);\n return { error: \"value is required\" };\n }\n\n const scope: SecretScope = body.scope === \"workspace\" ? \"workspace\" : \"user\";\n\n const description =\n typeof body.description === \"string\" && body.description.trim()\n ? body.description.trim()\n : undefined;\n\n let urlAllowlistJson: string | undefined;\n if (body.urlAllowlist !== undefined && body.urlAllowlist !== null) {\n const normalized = normalizeUrlAllowlist(body.urlAllowlist);\n if (normalized.ok === false) {\n setResponseStatus(event, 400);\n return { error: normalized.error };\n }\n urlAllowlistJson = JSON.stringify(normalized.origins);\n }\n\n const { scopeId, reason } = await resolveScopeId(event, scope);\n if (!scopeId) {\n setResponseStatus(event, 401);\n return { error: reason ?? \"Unable to resolve scope\" };\n }\n\n if (\n scope === \"workspace\" &&\n !(await canMutateWorkspaceScope(event, scopeId))\n ) {\n setResponseStatus(event, 403);\n return {\n error:\n \"Only organization owners and admins can set workspace-scoped secrets\",\n };\n }\n\n try {\n await writeAppSecret({\n key: name,\n value,\n scope,\n scopeId,\n description,\n urlAllowlist: urlAllowlistJson,\n });\n } catch (err) {\n setResponseStatus(event, 500);\n const message =\n err instanceof Error\n ? `Failed to save secret: ${err.message}`\n : \"Failed to save secret\";\n return {\n error: redactSecretFromMessage(message, value),\n };\n }\n\n return { ok: true, key: name };\n}\n\nasync function handleAdHocDelete(event: H3Event, name: string) {\n if (getRequiredSecret(name)) {\n setResponseStatus(event, 400);\n return {\n error: `\"${name}\" is a registered secret — delete via the registered route instead`,\n };\n }\n const scope: SecretScope = \"user\";\n const { scopeId, reason } = await resolveScopeId(event, scope);\n if (!scopeId) {\n setResponseStatus(event, 401);\n return { error: reason ?? \"Unable to resolve scope\" };\n }\n const removed = await deleteAppSecret({ key: name, scope, scopeId });\n if (!removed) {\n // Fall back to workspace scope so the agent / UI can clean up shared keys.\n // Gate the fallback behind the org-admin check so a regular member can't\n // DoS every other member's automations by deleting shared workspace keys.\n const workspaceContext = await resolveScopeId(event, \"workspace\");\n if (workspaceContext.scopeId) {\n if (!(await canMutateWorkspaceScope(event, workspaceContext.scopeId))) {\n // No-op silently for non-admins — the user-scope row didn't exist\n // and they don't have permission to touch the workspace row, so\n // there's nothing to remove from their point of view.\n return { ok: true, removed: false };\n }\n const removedWorkspace = await deleteAppSecret({\n key: name,\n scope: \"workspace\",\n scopeId: workspaceContext.scopeId,\n });\n return { ok: true, removed: removedWorkspace };\n }\n }\n return { ok: true, removed };\n}\n\nfunction extractAdHocName(event: H3Event): string | null {\n const pathname = (event.url?.pathname || \"\")\n .replace(/^\\/+/, \"\")\n .replace(/\\/+$/, \"\");\n if (!pathname) return null;\n const parts = pathname.split(\"/\");\n // The router strips the `/secrets/adhoc` prefix, so `parts[0]` (if present)\n // is the name. When the request is the bare `/adhoc` listing, parts is empty.\n const candidate = parts[0];\n if (!candidate) return null;\n return AD_HOC_NAME_REGEX.test(candidate) ? candidate : null;\n}\n\nfunction normalizeUrlAllowlist(\n input: unknown,\n): { ok: true; origins: string[] } | { ok: false; error: string } {\n if (!Array.isArray(input) || !input.every((v) => typeof v === \"string\")) {\n return { ok: false, error: \"urlAllowlist must be an array of strings\" };\n }\n\n const origins: string[] = [];\n for (const raw of input) {\n const value = raw.trim();\n if (!value) continue;\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n return {\n ok: false,\n error: `urlAllowlist entry \"${value}\" is not a valid URL`,\n };\n }\n if (url.protocol !== \"https:\" && url.protocol !== \"http:\") {\n return {\n ok: false,\n error: `urlAllowlist entry \"${value}\" must use http or https`,\n };\n }\n if (!origins.includes(url.origin)) origins.push(url.origin);\n }\n return { ok: true, origins };\n}\n\n/** Extract the key from `/:key` or `/:key/test` after the `/secrets` prefix strip. */\nfunction extractKeyFromEvent(\n event: H3Event,\n opts: { suffix?: string } = {},\n): string | null {\n const pathname = (event.url?.pathname || \"\")\n .replace(/^\\/+/, \"\")\n .replace(/\\/+$/, \"\");\n if (!pathname) return null;\n const parts = pathname.split(\"/\");\n if (opts.suffix === \"/test\") {\n if (parts.length < 2 || parts[parts.length - 1] !== \"test\") return null;\n return parts[0];\n }\n return parts[0];\n}\n"]}
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/secrets/routes.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * H3 event handlers for the framework secrets registry.\n *\n * Mounted under `/_agent-native/secrets/*` by `core-routes-plugin`.\n *\n * NEVER return a secret's plain-text value from any of these handlers.\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 { getOrgContext } from \"../org/context.js\";\n\n/**\n * Workspace-scoped secret writes/deletes are deployment-wide for every\n * org member who shares the resolved scopeId — a curious or malicious\n * member could otherwise overwrite `OPENAI_API_KEY` (or any unregistered\n * key) with their own value, redirecting every other member's automations\n * through their key for skimming, billing abuse, or DoS by deletion.\n *\n * Allow workspace-scope writes only for org owners/admins. The \"solo\"\n * fallback scopeId (`solo:<email>`) is single-user, so it bypasses the\n * check. A normal session with no active org also passes — there's no\n * privilege gradient to enforce in that case.\n *\n * Returns true if the request is allowed to write/delete this scope.\n */\nasync function canMutateWorkspaceScope(\n event: H3Event,\n scopeId: string,\n): Promise<boolean> {\n // Solo / dev fallback scope — single user, no privilege gradient.\n if (scopeId.startsWith(\"solo:\")) return true;\n const ctx = await getOrgContext(event).catch(() => null);\n // No active org — single-tenant flow, allow.\n if (!ctx?.orgId) return true;\n return ctx.role === \"owner\" || ctx.role === \"admin\";\n}\nimport { listOAuthAccountsByOwner } from \"../oauth-tokens/store.js\";\nimport {\n listRequiredSecrets,\n getRequiredSecret,\n type RegisteredSecret,\n type SecretScope,\n} from \"./register.js\";\nimport {\n writeAppSecret,\n deleteAppSecret,\n getAppSecretMeta,\n readAppSecret,\n listAppSecretsForScope,\n type SecretMeta,\n} from \"./storage.js\";\n\nexport interface SecretStatusPayload {\n key: string;\n label: string;\n description?: string;\n docsUrl?: string;\n scope: SecretScope;\n kind: \"api-key\" | \"oauth\";\n required: boolean;\n /** \"set\" = value present; \"unset\" = not configured; \"invalid\" = validator failed. */\n status: \"set\" | \"unset\" | \"invalid\";\n /** Last 4 chars — only populated when status === \"set\" for api-key kind. */\n last4?: string;\n /** Timestamp (ms) of the last write — only populated when status === \"set\". */\n updatedAt?: number;\n /** OAuth-kind: the provider id backing this secret. */\n oauthProvider?: string;\n /** OAuth-kind: url the Connect button should point at. */\n oauthConnectUrl?: string;\n /** Validator error message if status === \"invalid\". */\n error?: string;\n}\n\nfunction redactSecretFromMessage(message: string, secretValue: string): string {\n if (!message || !secretValue) return message;\n return message.split(secretValue).join(\"[redacted]\");\n}\n\nasync function hasOAuthSecretForEvent(\n event: H3Event,\n secret: RegisteredSecret,\n): Promise<boolean> {\n if (!secret.oauthProvider) return false;\n const session = await getSession(event).catch(() => null);\n if (!session?.email) return false;\n const accounts = await listOAuthAccountsByOwner(\n secret.oauthProvider,\n session.email,\n );\n return accounts.length > 0;\n}\n\n/** Resolve the scopeId for a given scope, given the current session. */\nasync function resolveScopeId(\n event: H3Event,\n scope: SecretScope,\n): Promise<{ scopeId: string | null; reason?: string }> {\n if (scope === \"user\") {\n const session = await getSession(event).catch(() => null);\n if (!session?.email) {\n return { scopeId: null, reason: \"Authentication required\" };\n }\n return { scopeId: session.email };\n }\n // workspace\n const ctx = await getOrgContext(event).catch(() => null);\n if (ctx?.orgId) return { scopeId: ctx.orgId };\n // Fall back to session email in solo/dev mode so secrets still work without\n // an active organisation.\n const session = await getSession(event).catch(() => null);\n if (session?.email) return { scopeId: `solo:${session.email}` };\n return { scopeId: null, reason: \"No workspace or session context\" };\n}\n\n/** GET /_agent-native/secrets — list registered secrets with status. */\nexport function createListSecretsHandler() {\n return defineEventHandler(async (event: H3Event) => {\n if (getMethod(event) !== \"GET\") {\n setResponseStatus(event, 405);\n return { error: \"Method not allowed\" };\n }\n\n const secrets = listRequiredSecrets();\n const payload: SecretStatusPayload[] = [];\n\n for (const secret of secrets) {\n const base: SecretStatusPayload = {\n key: secret.key,\n label: secret.label,\n description: secret.description,\n docsUrl: secret.docsUrl,\n scope: secret.scope,\n kind: secret.kind,\n required: !!secret.required,\n status: \"unset\",\n };\n\n if (secret.kind === \"oauth\") {\n base.oauthProvider = secret.oauthProvider;\n base.oauthConnectUrl = secret.oauthConnectUrl;\n if (secret.oauthProvider) {\n try {\n const has = await hasOAuthSecretForEvent(event, secret);\n base.status = has ? \"set\" : \"unset\";\n } catch {\n base.status = \"unset\";\n }\n }\n payload.push(base);\n continue;\n }\n\n // api-key: look up the stored row in app_secrets.\n const { scopeId } = await resolveScopeId(event, secret.scope);\n if (!scopeId) {\n payload.push(base);\n continue;\n }\n const meta = await getAppSecretMeta({\n key: secret.key,\n scope: secret.scope,\n scopeId,\n }).catch(() => null);\n if (meta) {\n base.status = \"set\";\n base.last4 = meta.last4;\n base.updatedAt = meta.updatedAt;\n }\n payload.push(base);\n }\n\n return payload;\n });\n}\n\n/** POST /_agent-native/secrets/:key — write a secret. */\nexport function createWriteSecretHandler() {\n return defineEventHandler(async (event: H3Event) => {\n const method = getMethod(event);\n const key = extractKeyFromEvent(event);\n\n if (!key) {\n setResponseStatus(event, 400);\n return { error: \"Secret key required\" };\n }\n\n const secret = getRequiredSecret(key);\n if (!secret) {\n setResponseStatus(event, 404);\n return { error: `Secret \"${key}\" is not registered` };\n }\n\n if (method === \"POST\" || method === \"PUT\") {\n return handleWrite(event, secret);\n }\n if (method === \"DELETE\") {\n return handleDelete(event, secret);\n }\n setResponseStatus(event, 405);\n return { error: \"Method not allowed\" };\n });\n}\n\nasync function handleWrite(event: H3Event, secret: RegisteredSecret) {\n if (secret.kind === \"oauth\") {\n setResponseStatus(event, 400);\n return {\n error: `\"${secret.key}\" is an OAuth-kind secret — connect via ${secret.oauthConnectUrl ?? \"the OAuth flow\"} instead`,\n };\n }\n const body = (await readBody(event).catch(() => ({}))) as {\n value?: unknown;\n };\n\n const value = typeof body.value === \"string\" ? body.value.trim() : \"\";\n if (!value) {\n setResponseStatus(event, 400);\n return { error: \"value is required\" };\n }\n\n const { scopeId, reason } = await resolveScopeId(event, secret.scope);\n if (!scopeId) {\n setResponseStatus(event, 401);\n return { error: reason ?? \"Unable to resolve scope\" };\n }\n\n if (\n secret.scope === \"workspace\" &&\n !(await canMutateWorkspaceScope(event, scopeId))\n ) {\n setResponseStatus(event, 403);\n return {\n error:\n \"Only organization owners and admins can set workspace-scoped secrets\",\n };\n }\n\n // Run validator if registered — return the validator's error on failure.\n if (secret.validator) {\n try {\n const result = await secret.validator(value);\n const ok = typeof result === \"boolean\" ? result : result?.ok === true;\n if (!ok) {\n setResponseStatus(event, 400);\n const err =\n typeof result === \"object\" && result && result.error\n ? String(result.error)\n : \"Validator rejected the value\";\n return { error: redactSecretFromMessage(err, value) };\n }\n } catch (err) {\n setResponseStatus(event, 400);\n const message =\n err instanceof Error\n ? `Validator threw: ${err.message}`\n : \"Validator threw\";\n return {\n error: redactSecretFromMessage(message, value),\n };\n }\n }\n\n try {\n await writeAppSecret({\n key: secret.key,\n value,\n scope: secret.scope,\n scopeId,\n });\n } catch (err) {\n // Scrub: never surface the value in any error path.\n setResponseStatus(event, 500);\n const message =\n err instanceof Error\n ? `Failed to save secret: ${err.message}`\n : \"Failed to save secret\";\n return {\n error: redactSecretFromMessage(message, value),\n };\n }\n\n return { ok: true, status: \"set\" };\n}\n\nasync function handleDelete(event: H3Event, secret: RegisteredSecret) {\n if (secret.kind === \"oauth\") {\n setResponseStatus(event, 400);\n return {\n error: `\"${secret.key}\" is an OAuth-kind secret — disconnect via the OAuth flow instead`,\n };\n }\n const { scopeId, reason } = await resolveScopeId(event, secret.scope);\n if (!scopeId) {\n setResponseStatus(event, 401);\n return { error: reason ?? \"Unable to resolve scope\" };\n }\n if (\n secret.scope === \"workspace\" &&\n !(await canMutateWorkspaceScope(event, scopeId))\n ) {\n setResponseStatus(event, 403);\n return {\n error:\n \"Only organization owners and admins can delete workspace-scoped secrets\",\n };\n }\n const removed = await deleteAppSecret({\n key: secret.key,\n scope: secret.scope,\n scopeId,\n });\n return { ok: true, removed };\n}\n\n/**\n * POST /_agent-native/secrets/:key/test — re-run the validator against the\n * current stored value without changing anything. Useful for the \"Test\" button.\n */\nexport function createTestSecretHandler() {\n return defineEventHandler(async (event: H3Event) => {\n if (getMethod(event) !== \"POST\") {\n setResponseStatus(event, 405);\n return { error: \"Method not allowed\" };\n }\n const key = extractKeyFromEvent(event, { suffix: \"/test\" });\n if (!key) {\n setResponseStatus(event, 400);\n return { error: \"Secret key required\" };\n }\n const secret = getRequiredSecret(key);\n if (!secret) {\n setResponseStatus(event, 404);\n return { error: `Secret \"${key}\" is not registered` };\n }\n if (secret.kind === \"oauth\") {\n // For OAuth we just report whether tokens exist.\n const has = await hasOAuthSecretForEvent(event, secret).catch(\n () => false,\n );\n return { ok: has };\n }\n if (!secret.validator) {\n return { ok: true, note: \"No validator registered\" };\n }\n const { scopeId } = await resolveScopeId(event, secret.scope);\n if (!scopeId) {\n setResponseStatus(event, 401);\n return { error: \"Unable to resolve scope\" };\n }\n const stored = await readAppSecret({\n key: secret.key,\n scope: secret.scope,\n scopeId,\n });\n if (!stored) {\n setResponseStatus(event, 404);\n return { error: \"No value stored\" };\n }\n try {\n const result = await secret.validator(stored.value);\n const ok = typeof result === \"boolean\" ? result : result?.ok === true;\n if (!ok) {\n const err =\n typeof result === \"object\" && result && result.error\n ? String(result.error)\n : \"Validator rejected the value\";\n return {\n ok: false,\n error: redactSecretFromMessage(err, stored.value),\n };\n }\n return { ok: true };\n } catch (err) {\n const message =\n err instanceof Error\n ? `Validator threw: ${err.message}`\n : \"Validator threw\";\n return {\n ok: false,\n error: redactSecretFromMessage(message, stored.value),\n };\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// Ad-hoc secrets — user-/agent-created keys not in the registry\n// ---------------------------------------------------------------------------\n\nexport interface AdHocSecretPayload {\n name: string;\n scope: SecretScope;\n scopeId: string;\n description: string | null;\n last4: string;\n urlAllowlist: string[] | null;\n createdAt: number;\n updatedAt: number;\n}\n\nconst AD_HOC_NAME_REGEX = /^[A-Za-z0-9_-]+$/;\n\nfunction metaToPayload(meta: SecretMeta): AdHocSecretPayload {\n return {\n name: meta.key,\n scope: meta.scope,\n scopeId: meta.scopeId,\n description: meta.description,\n last4: meta.last4,\n urlAllowlist: meta.urlAllowlist,\n createdAt: meta.createdAt,\n updatedAt: meta.updatedAt,\n };\n}\n\n/**\n * Handler for `/_agent-native/secrets/adhoc[/:name]`.\n *\n * - GET (no name) — list all ad-hoc keys for the user's scope\n * - POST (no name) — create or update an ad-hoc key\n * - DELETE (with name) — delete an ad-hoc key\n *\n * Ad-hoc keys are arbitrary named secrets users or the agent create at\n * runtime for automation use (e.g. \"SLACK_WEBHOOK\", \"HUBSPOT_API_KEY\").\n * They differ from registered secrets (`registerRequiredSecret`) in that\n * they have no template-defined metadata, validator, or onboarding step.\n */\nexport function createAdHocSecretHandler() {\n return defineEventHandler(async (event: H3Event) => {\n const method = getMethod(event);\n const name = extractAdHocName(event);\n\n if (method === \"GET\" && !name) {\n return handleAdHocList(event);\n }\n if (method === \"POST\" && !name) {\n return handleAdHocWrite(event);\n }\n if (method === \"DELETE\" && name) {\n return handleAdHocDelete(event, name);\n }\n setResponseStatus(event, 405);\n return { error: \"Method not allowed\" };\n });\n}\n\nasync function handleAdHocList(event: H3Event) {\n const scope: SecretScope = \"user\";\n const { scopeId, reason } = await resolveScopeId(event, scope);\n if (!scopeId) {\n setResponseStatus(event, 401);\n return { error: reason ?? \"Unable to resolve scope\" };\n }\n\n const registered = new Set(listRequiredSecrets().map((s) => s.key));\n const userRows = await listAppSecretsForScope(\"user\", scopeId);\n const workspaceContext = await resolveScopeId(event, \"workspace\");\n const workspaceRows = workspaceContext.scopeId\n ? await listAppSecretsForScope(\"workspace\", workspaceContext.scopeId)\n : [];\n\n const payload: AdHocSecretPayload[] = [];\n for (const row of [...userRows, ...workspaceRows]) {\n if (registered.has(row.key)) continue;\n payload.push(metaToPayload(row));\n }\n return payload;\n}\n\nasync function handleAdHocWrite(event: H3Event) {\n const body = (await readBody(event).catch(() => ({}))) as {\n name?: unknown;\n value?: unknown;\n description?: unknown;\n scope?: unknown;\n urlAllowlist?: unknown;\n };\n\n const name = typeof body.name === \"string\" ? body.name.trim() : \"\";\n if (!name || !AD_HOC_NAME_REGEX.test(name)) {\n setResponseStatus(event, 400);\n return {\n error:\n \"name is required and may only contain letters, digits, underscores, and dashes\",\n };\n }\n if (getRequiredSecret(name)) {\n setResponseStatus(event, 400);\n return {\n error: `\"${name}\" is a registered secret — use POST /_agent-native/secrets/${name} instead`,\n };\n }\n\n const value = typeof body.value === \"string\" ? body.value.trim() : \"\";\n if (!value) {\n setResponseStatus(event, 400);\n return { error: \"value is required\" };\n }\n\n const scope: SecretScope = body.scope === \"workspace\" ? \"workspace\" : \"user\";\n\n const description =\n typeof body.description === \"string\" && body.description.trim()\n ? body.description.trim()\n : undefined;\n\n let urlAllowlistJson: string | undefined;\n if (body.urlAllowlist !== undefined && body.urlAllowlist !== null) {\n const normalized = normalizeUrlAllowlist(body.urlAllowlist);\n if (normalized.ok === false) {\n setResponseStatus(event, 400);\n return { error: normalized.error };\n }\n urlAllowlistJson = JSON.stringify(normalized.origins);\n }\n\n const { scopeId, reason } = await resolveScopeId(event, scope);\n if (!scopeId) {\n setResponseStatus(event, 401);\n return { error: reason ?? \"Unable to resolve scope\" };\n }\n\n if (\n scope === \"workspace\" &&\n !(await canMutateWorkspaceScope(event, scopeId))\n ) {\n setResponseStatus(event, 403);\n return {\n error:\n \"Only organization owners and admins can set workspace-scoped secrets\",\n };\n }\n\n try {\n await writeAppSecret({\n key: name,\n value,\n scope,\n scopeId,\n description,\n urlAllowlist: urlAllowlistJson,\n });\n } catch (err) {\n setResponseStatus(event, 500);\n const message =\n err instanceof Error\n ? `Failed to save secret: ${err.message}`\n : \"Failed to save secret\";\n return {\n error: redactSecretFromMessage(message, value),\n };\n }\n\n return { ok: true, key: name };\n}\n\nasync function handleAdHocDelete(event: H3Event, name: string) {\n if (getRequiredSecret(name)) {\n setResponseStatus(event, 400);\n return {\n error: `\"${name}\" is a registered secret — delete via the registered route instead`,\n };\n }\n const scope: SecretScope = \"user\";\n const { scopeId, reason } = await resolveScopeId(event, scope);\n if (!scopeId) {\n setResponseStatus(event, 401);\n return { error: reason ?? \"Unable to resolve scope\" };\n }\n const removed = await deleteAppSecret({ key: name, scope, scopeId });\n if (!removed) {\n // Fall back to workspace scope so the agent / UI can clean up shared keys.\n // Gate the fallback behind the org-admin check so a regular member can't\n // DoS every other member's automations by deleting shared workspace keys.\n const workspaceContext = await resolveScopeId(event, \"workspace\");\n if (workspaceContext.scopeId) {\n if (!(await canMutateWorkspaceScope(event, workspaceContext.scopeId))) {\n // No-op silently for non-admins — the user-scope row didn't exist\n // and they don't have permission to touch the workspace row, so\n // there's nothing to remove from their point of view.\n return { ok: true, removed: false };\n }\n const removedWorkspace = await deleteAppSecret({\n key: name,\n scope: \"workspace\",\n scopeId: workspaceContext.scopeId,\n });\n return { ok: true, removed: removedWorkspace };\n }\n }\n return { ok: true, removed };\n}\n\nfunction extractAdHocName(event: H3Event): string | null {\n const pathname = (event.url?.pathname || \"\")\n .replace(/^\\/+/, \"\")\n .replace(/\\/+$/, \"\");\n if (!pathname) return null;\n const parts = pathname.split(\"/\");\n // The router strips the `/secrets/adhoc` prefix, so `parts[0]` (if present)\n // is the name. When the request is the bare `/adhoc` listing, parts is empty.\n const candidate = parts[0];\n if (!candidate) return null;\n return AD_HOC_NAME_REGEX.test(candidate) ? candidate : null;\n}\n\nfunction normalizeUrlAllowlist(\n input: unknown,\n): { ok: true; origins: string[] } | { ok: false; error: string } {\n if (!Array.isArray(input) || !input.every((v) => typeof v === \"string\")) {\n return { ok: false, error: \"urlAllowlist must be an array of strings\" };\n }\n\n const origins: string[] = [];\n for (const raw of input) {\n const value = raw.trim();\n if (!value) continue;\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n return {\n ok: false,\n error: `urlAllowlist entry \"${value}\" is not a valid URL`,\n };\n }\n if (url.protocol !== \"https:\" && url.protocol !== \"http:\") {\n return {\n ok: false,\n error: `urlAllowlist entry \"${value}\" must use http or https`,\n };\n }\n if (!origins.includes(url.origin)) origins.push(url.origin);\n }\n return { ok: true, origins };\n}\n\n/** Extract the key from `/:key` or `/:key/test` after the `/secrets` prefix strip. */\nfunction extractKeyFromEvent(\n event: H3Event,\n opts: { suffix?: string } = {},\n): string | null {\n const pathname = (event.url?.pathname || \"\")\n .replace(/^\\/+/, \"\")\n .replace(/\\/+$/, \"\");\n if (!pathname) return null;\n const parts = pathname.split(\"/\");\n if (opts.suffix === \"/test\") {\n if (parts.length < 2 || parts[parts.length - 1] !== \"test\") return null;\n return parts[0];\n }\n return parts[0];\n}\n"]}
@@ -26,6 +26,21 @@
26
26
  * ```
27
27
  */
28
28
  import type { ActionEntry } from "../agent/production-agent.js";
29
+ /**
30
+ * Register a map of actions contributed by a published package.
31
+ *
32
+ * Called from a package's server entrypoint via import side effects:
33
+ * ```ts
34
+ * // packages/dispatch/src/server/index.ts
35
+ * import { registerPackageActions } from "@agent-native/core/server";
36
+ * import { actions } from "../actions/index.js";
37
+ * registerPackageActions(actions);
38
+ * ```
39
+ *
40
+ * Idempotent — re-registering the same name from the same import is a no-op
41
+ * so HMR / repeated dynamic imports don't double-warn.
42
+ */
43
+ export declare function registerPackageActions(actions: Record<string, ActionEntry>): void;
29
44
  /**
30
45
  * Normalize a pre-bundled static action registry (name → raw module) into
31
46
  * the `Record<string, ActionEntry>` shape the agent-chat plugin expects.
@@ -1 +1 @@
1
- {"version":3,"file":"action-discovery.d.ts","sourceRoot":"","sources":["../../src/server/action-discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAiOhE;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAqC7B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAuFtC;AAED,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GACpC,OAAO,CAAC,IAAI,CAAC,CAiCf;AAED,oDAAoD;AACpD,eAAO,MAAM,mBAAmB,4BAAsB,CAAC"}
1
+ {"version":3,"file":"action-discovery.d.ts","sourceRoot":"","sources":["../../src/server/action-discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAqChE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GACnC,IAAI,CAKN;AAkND;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAqC7B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAgGtC;AAED,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GACpC,OAAO,CAAC,IAAI,CAAC,CAkCf;AAED,oDAAoD;AACpD,eAAO,MAAM,mBAAmB,4BAAsB,CAAC"}