@agent-native/core 0.161.23 → 0.163.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/real-time-sync/SKILL.md +1 -1
  3. package/corpus/templates/analytics/.agents/skills/sharing/SKILL.md +27 -2
  4. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +18 -2
  5. package/corpus/templates/assets/.agents/skills/real-time-sync/SKILL.md +1 -1
  6. package/corpus/templates/assets/.agents/skills/sharing/SKILL.md +27 -2
  7. package/corpus/templates/brain/.agents/skills/real-time-sync/SKILL.md +1 -1
  8. package/corpus/templates/brain/.agents/skills/sharing/SKILL.md +27 -2
  9. package/corpus/templates/calendar/.agents/skills/real-time-sync/SKILL.md +1 -1
  10. package/corpus/templates/calendar/.agents/skills/sharing/SKILL.md +27 -2
  11. package/corpus/templates/calendar/server/handlers/google-auth.ts +1 -8
  12. package/corpus/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
  13. package/corpus/templates/chat/.agents/skills/sharing/SKILL.md +27 -2
  14. package/corpus/templates/clips/app/components/recorder/pre-record-panel.tsx +88 -35
  15. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +36 -1
  16. package/corpus/templates/clips/app/i18n/en-US.ts +4 -3
  17. package/corpus/templates/clips/app/lib/camera-composite.ts +15 -1
  18. package/corpus/templates/clips/changelog/2026-08-18-clips-no-longer-crashes-when-a-camera-bubble-starts-at-a-tin.md +6 -0
  19. package/corpus/templates/clips/desktop/src/app.tsx +30 -40
  20. package/corpus/templates/clips/desktop/src/components/MicOffConfirmation.tsx +47 -0
  21. package/corpus/templates/clips/desktop/src/styles.css +110 -0
  22. package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +114 -7
  23. package/corpus/templates/clips/shared/recording-capture.ts +18 -13
  24. package/corpus/templates/content/.agents/skills/real-time-sync/SKILL.md +1 -1
  25. package/corpus/templates/content/.agents/skills/sharing/SKILL.md +27 -2
  26. package/corpus/templates/content/actions/create-content-database.ts +1 -1
  27. package/corpus/templates/content/actions/create-document.ts +1 -1
  28. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +3 -5
  29. package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +0 -3
  30. package/corpus/templates/content/app/components/editor/NotionConflictBanner.tsx +0 -4
  31. package/corpus/templates/content/app/components/editor/NotionSyncBar.tsx +4 -1
  32. package/corpus/templates/content/app/hooks/use-notion.ts +17 -15
  33. package/corpus/templates/crm/.agents/skills/real-time-sync/SKILL.md +1 -1
  34. package/corpus/templates/crm/.agents/skills/sharing/SKILL.md +27 -2
  35. package/corpus/templates/design/.agents/skills/real-time-sync/SKILL.md +1 -1
  36. package/corpus/templates/design/.agents/skills/sharing/SKILL.md +27 -2
  37. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +6 -1
  38. package/corpus/templates/dispatch/.agents/skills/real-time-sync/SKILL.md +1 -1
  39. package/corpus/templates/dispatch/.agents/skills/sharing/SKILL.md +27 -2
  40. package/corpus/templates/factory/.agents/skills/real-time-sync/SKILL.md +1 -1
  41. package/corpus/templates/factory/.agents/skills/sharing/SKILL.md +27 -2
  42. package/corpus/templates/forms/.agents/skills/real-time-sync/SKILL.md +1 -1
  43. package/corpus/templates/forms/.agents/skills/sharing/SKILL.md +27 -2
  44. package/corpus/templates/macros/.agents/skills/real-time-sync/SKILL.md +1 -1
  45. package/corpus/templates/macros/.agents/skills/sharing/SKILL.md +27 -2
  46. package/corpus/templates/mail/.agents/skills/real-time-sync/SKILL.md +1 -1
  47. package/corpus/templates/mail/.agents/skills/sharing/SKILL.md +27 -2
  48. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +18 -3
  49. package/corpus/templates/mail/server/handlers/google-auth.ts +1 -8
  50. package/corpus/templates/plan/.agents/skills/real-time-sync/SKILL.md +1 -1
  51. package/corpus/templates/plan/.agents/skills/sharing/SKILL.md +27 -2
  52. package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +4 -0
  53. package/corpus/templates/slides/.agents/skills/real-time-sync/SKILL.md +1 -1
  54. package/corpus/templates/slides/.agents/skills/sharing/SKILL.md +27 -2
  55. package/corpus/templates/slides/actions/_await-fit-check.ts +30 -5
  56. package/corpus/templates/slides/actions/add-slide.ts +6 -2
  57. package/corpus/templates/slides/actions/create-deck.ts +2 -1
  58. package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +3 -3
  59. package/corpus/templates/slides/app/components/editor/GoogleSlidesReferenceImport.tsx +3 -3
  60. package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +3 -1
  61. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +1 -1
  62. package/corpus/templates/slides/app/components/editor/slide-object-interactions.ts +1 -1
  63. package/corpus/templates/slides/app/lib/create-deck-generation.ts +1 -0
  64. package/corpus/templates/slides/app/pages/DeckEditor.tsx +35 -2
  65. package/corpus/templates/slides/app/routes/p.$id.tsx +3 -1
  66. package/corpus/templates/slides/changelog/2026-08-18-generated-slides-preserve-speaker-notes.md +6 -0
  67. package/corpus/templates/slides/server/handlers/assets.ts +23 -12
  68. package/corpus/templates/slides/server/handlers/design-system-decode-job-status.ts +15 -6
  69. package/corpus/templates/slides/server/handlers/design-system-upload-start.ts +15 -6
  70. package/corpus/templates/slides/server/handlers/index-design-system-sources.ts +34 -19
  71. package/corpus/templates/slides/server/handlers/request-auth-context.ts +1 -0
  72. package/corpus/templates/slides/server/handlers/share.ts +1 -1
  73. package/corpus/templates/slides/server/plugins/agent-chat.ts +1 -1
  74. package/corpus/templates/slides/server/routes/api/deck-agent-context.json.get.ts +1 -1
  75. package/corpus/templates/slides/server/routes/api/exports/[filename].get.ts +9 -3
  76. package/corpus/templates/slides/server/routes/api/exports/google-slides.post.ts +12 -5
  77. package/corpus/templates/slides/server/routes/api/exports/html.post.ts +9 -7
  78. package/corpus/templates/slides/server/routes/api/exports/pptx.post.ts +9 -7
  79. package/corpus/templates/slides/shared/api.ts +7 -1
  80. package/corpus/templates/tasks/.agents/skills/real-time-sync/SKILL.md +1 -1
  81. package/corpus/templates/tasks/.agents/skills/sharing/SKILL.md +27 -2
  82. package/dist/agent/engine/translate-anthropic.js +27 -2
  83. package/dist/agent/production-agent.d.ts +2 -2
  84. package/dist/agent/production-agent.js +16 -8
  85. package/dist/agent/thread-data-builder.d.ts +1 -0
  86. package/dist/agent/thread-data-builder.js +6 -4
  87. package/dist/agent/tool-approval-store.d.ts +10 -1
  88. package/dist/agent/tool-approval-store.js +19 -2
  89. package/dist/agent/types.d.ts +9 -0
  90. package/dist/app-config/schema.d.ts +1 -0
  91. package/dist/app-config/workspace.d.ts +1 -0
  92. package/dist/app-config/workspace.js +8 -0
  93. package/dist/chat-threads/schema.d.ts +2 -2
  94. package/dist/client/AssistantChat.js +14 -6
  95. package/dist/client/EnvironmentBadge.d.ts +15 -0
  96. package/dist/client/EnvironmentBadge.js +79 -0
  97. package/dist/client/MultiTabAssistantChat.js +73 -17
  98. package/dist/client/agent-chat-adapter.js +11 -1
  99. package/dist/client/api-path.js +14 -1
  100. package/dist/client/app-providers.js +2 -1
  101. package/dist/client/chat/tool-call-display.d.ts +12 -2
  102. package/dist/client/chat/tool-call-display.js +17 -7
  103. package/dist/client/chat/widgets/WorkspaceFileWidget.js +1 -1
  104. package/dist/client/chat/widgets/builtin-tool-renderers.d.ts +6 -0
  105. package/dist/client/chat/widgets/builtin-tool-renderers.js +19 -0
  106. package/dist/client/onboarding/FirstRunOnboarding.js +46 -32
  107. package/dist/client/onboarding/use-onboarding.d.ts +8 -1
  108. package/dist/client/onboarding/use-onboarding.js +22 -7
  109. package/dist/client/org/TeamPage.js +15 -2
  110. package/dist/client/org/hooks.d.ts +2 -0
  111. package/dist/client/org/hooks.js +12 -0
  112. package/dist/client/org/index.d.ts +2 -2
  113. package/dist/client/org/index.js +1 -1
  114. package/dist/client/session-replay.js +58 -15
  115. package/dist/client/settings/SettingsTabsPage.js +19 -6
  116. package/dist/client/sharing/ShareButton.js +43 -18
  117. package/dist/client/sharing/useShareButtonController.d.ts +12 -2
  118. package/dist/client/sharing/useShareButtonController.js +38 -8
  119. package/dist/client/sse-event-processor.d.ts +7 -0
  120. package/dist/client/sse-event-processor.js +4 -1
  121. package/dist/client/ui/index.d.ts +1 -0
  122. package/dist/client/ui/index.js +1 -0
  123. package/dist/client/use-action.js +26 -0
  124. package/dist/collab/struct-routes.d.ts +1 -1
  125. package/dist/config.d.ts +15 -0
  126. package/dist/config.js +53 -0
  127. package/dist/dashboard-storage/schema.d.ts +2 -2
  128. package/dist/data-programs/schema.d.ts +2 -2
  129. package/dist/extensions/fetch-tool.js +8 -2
  130. package/dist/extensions/schema.d.ts +2 -2
  131. package/dist/extensions/store.js +3 -0
  132. package/dist/localization/core-messages/ar-SA.js +1 -0
  133. package/dist/localization/core-messages/de-DE.js +1 -0
  134. package/dist/localization/core-messages/en-US.d.ts +1 -0
  135. package/dist/localization/core-messages/en-US.js +1 -0
  136. package/dist/localization/core-messages/es-ES.js +1 -0
  137. package/dist/localization/core-messages/fr-FR.js +1 -0
  138. package/dist/localization/core-messages/hi-IN.js +1 -0
  139. package/dist/localization/core-messages/ja-JP.js +1 -0
  140. package/dist/localization/core-messages/ko-KR.js +1 -0
  141. package/dist/localization/core-messages/pt-BR.js +1 -0
  142. package/dist/localization/core-messages/zh-CN.js +1 -0
  143. package/dist/localization/core-messages/zh-TW.js +1 -0
  144. package/dist/localization/core-messages.d.ts +1 -0
  145. package/dist/localization/default-messages.d.ts +4 -0
  146. package/dist/localization/default-messages.js +4 -0
  147. package/dist/mcp/embed-app.js +1 -1
  148. package/dist/notifications/routes.d.ts +1 -1
  149. package/dist/org/handlers.d.ts +6 -1
  150. package/dist/org/handlers.js +43 -0
  151. package/dist/org/index.d.ts +3 -3
  152. package/dist/org/index.js +2 -2
  153. package/dist/org/migrations.js +33 -0
  154. package/dist/org/plugin.js +10 -1
  155. package/dist/org/schema.d.ts +315 -0
  156. package/dist/org/schema.js +20 -1
  157. package/dist/org/types.d.ts +3 -0
  158. package/dist/org/workspace-app-access.d.ts +10 -0
  159. package/dist/org/workspace-app-access.js +179 -0
  160. package/dist/progress/routes.d.ts +1 -1
  161. package/dist/provider-api/actions/custom-provider-registration.d.ts +7 -7
  162. package/dist/provider-api/actions/provider-api.d.ts +7 -7
  163. package/dist/provider-api/index.d.ts +10 -0
  164. package/dist/provider-api/index.js +45 -9
  165. package/dist/resources/handlers.d.ts +1 -1
  166. package/dist/secrets/routes.d.ts +9 -9
  167. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  168. package/dist/server/auth.js +24 -4
  169. package/dist/server/poll.js +13 -3
  170. package/dist/server/sentry.d.ts +1 -1
  171. package/dist/sharing/access.d.ts +2 -2
  172. package/dist/sharing/access.js +56 -3
  173. package/dist/sharing/actions/list-resource-shares.d.ts +2 -0
  174. package/dist/sharing/actions/list-resource-shares.js +26 -1
  175. package/dist/sharing/actions/share-resource.d.ts +1 -1
  176. package/dist/sharing/actions/share-resource.js +23 -4
  177. package/dist/sharing/actions/unshare-resource.d.ts +1 -1
  178. package/dist/sharing/actions/unshare-resource.js +1 -1
  179. package/dist/sharing/registry.d.ts +12 -0
  180. package/dist/sharing/schema.d.ts +4 -4
  181. package/dist/sharing/schema.js +2 -2
  182. package/dist/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
  183. package/dist/templates/chat/.agents/skills/sharing/SKILL.md +27 -2
  184. package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
  185. package/dist/templates/default/.agents/skills/sharing/SKILL.md +27 -2
  186. package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
  187. package/dist/templates/workspace-core/.agents/skills/sharing/SKILL.md +27 -2
  188. package/dist/vite/client.d.ts +5 -0
  189. package/dist/vite/client.js +64 -2
  190. package/dist/workspace-connections/actions/list-workspace-user-groups.d.ts +9 -1
  191. package/dist/workspace-connections/actions/list-workspace-user-groups.js +9 -4
  192. package/dist/workspace-connections/groups.d.ts +2 -0
  193. package/dist/workspace-connections/groups.js +16 -5
  194. package/dist/workspace-files/actions.d.ts +1 -8
  195. package/dist/workspace-files/actions.js +5 -21
  196. package/dist/workspace-files/index.d.ts +1 -1
  197. package/dist/workspace-files/index.js +1 -1
  198. package/dist/workspace-files/store.d.ts +18 -0
  199. package/dist/workspace-files/store.js +24 -3
  200. package/package.json +3 -3
  201. package/src/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
  202. package/src/templates/chat/.agents/skills/sharing/SKILL.md +27 -2
  203. package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
  204. package/src/templates/default/.agents/skills/sharing/SKILL.md +27 -2
  205. package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
  206. package/src/templates/workspace-core/.agents/skills/sharing/SKILL.md +27 -2
package/dist/config.d.ts CHANGED
@@ -38,6 +38,11 @@ export interface AgentNativeRuntimeConfig {
38
38
  database?: AgentNativeRuntimeDatabaseConfig;
39
39
  environment?: AgentNativeRuntimeEnvironmentConfig;
40
40
  }
41
+ export type AgentNativeDeploymentEnvironment = "local" | "beta" | "production" | "preview";
42
+ export interface AgentNativeDeploymentConfig {
43
+ /** The release lane that produced the currently running client bundle. */
44
+ environment?: AgentNativeDeploymentEnvironment;
45
+ }
41
46
  export interface AgentNativeDiagnosticsConfig {
42
47
  /** Fail a production Vite build when runtime configuration has issues. */
43
48
  failOnBuild?: boolean;
@@ -73,6 +78,7 @@ export interface AgentNativeConfig {
73
78
  version?: typeof AGENT_NATIVE_CONFIG_VERSION;
74
79
  onboarding?: AgentNativeOnboardingConfig;
75
80
  runtime?: AgentNativeRuntimeConfig;
81
+ deployment?: AgentNativeDeploymentConfig;
76
82
  diagnostics?: AgentNativeDiagnosticsConfig;
77
83
  instructions?: AgentNativeInstructionsConfig;
78
84
  translations?: AgentNativeTranslationsConfig;
@@ -99,3 +105,12 @@ export declare function normalizeAgentNativeConfig(input: unknown, source?: stri
99
105
  export declare function mergeAgentNativeConfigs(base: AgentNativeConfig, override: AgentNativeConfig): AgentNativeConfig;
100
106
  export declare function resolveAgentNativeConfig(input: AgentNativeConfigInput | undefined, context: AgentNativeConfigContext): AgentNativeConfig;
101
107
  export declare function resolveFirstRunOnboardingMode(setting: AgentNativeFirstRunOnboardingSetting, context: AgentNativeConfigContext): AgentNativeFirstRunOnboardingMode;
108
+ export declare function isAgentNativeDeploymentEnvironment(value: unknown): value is AgentNativeDeploymentEnvironment;
109
+ /**
110
+ * Resolve the public deployment lane from hosting facts at build time.
111
+ *
112
+ * Netlify exposes `CONTEXT` and `BRANCH` to builds. Keeping this inference in
113
+ * the Vite/config boundary means browser code consumes typed public config and
114
+ * never parses process.env itself.
115
+ */
116
+ export declare function inferAgentNativeDeploymentEnvironment(env: Record<string, string | undefined>, mode?: string): AgentNativeDeploymentEnvironment | undefined;
package/dist/config.js CHANGED
@@ -26,6 +26,7 @@ export function normalizeAgentNativeConfig(input, source = "agent-native config"
26
26
  }
27
27
  const onboardingValue = input.onboarding;
28
28
  const runtimeValue = input.runtime;
29
+ const deploymentValue = input.deployment;
29
30
  const diagnosticsValue = input.diagnostics;
30
31
  const instructionsValue = input.instructions;
31
32
  const translationsValue = input.translations;
@@ -46,6 +47,9 @@ export function normalizeAgentNativeConfig(input, source = "agent-native config"
46
47
  if (runtimeValue !== undefined) {
47
48
  normalized.runtime = normalizeRuntimeConfig(runtimeValue, `${source}.runtime`);
48
49
  }
50
+ if (deploymentValue !== undefined) {
51
+ normalized.deployment = normalizeDeploymentConfig(deploymentValue, `${source}.deployment`);
52
+ }
49
53
  if (diagnosticsValue !== undefined) {
50
54
  normalized.diagnostics = normalizeDiagnosticsConfig(diagnosticsValue, `${source}.diagnostics`);
51
55
  }
@@ -101,6 +105,12 @@ export function mergeAgentNativeConfigs(base, override) {
101
105
  : undefined,
102
106
  }
103
107
  : undefined,
108
+ deployment: base.deployment || override.deployment
109
+ ? {
110
+ ...base.deployment,
111
+ ...override.deployment,
112
+ }
113
+ : undefined,
104
114
  diagnostics: base.diagnostics || override.diagnostics
105
115
  ? {
106
116
  ...base.diagnostics,
@@ -205,6 +215,18 @@ function normalizeRuntimeConfig(value, source) {
205
215
  }
206
216
  return result;
207
217
  }
218
+ function normalizeDeploymentConfig(value, source) {
219
+ if (!isRecord(value)) {
220
+ throw new Error(`${source} must be an object`);
221
+ }
222
+ const environment = value.environment;
223
+ if (environment === undefined)
224
+ return {};
225
+ if (!isAgentNativeDeploymentEnvironment(environment)) {
226
+ throw new Error(`${source}.environment must be "local", "beta", "production", or "preview"`);
227
+ }
228
+ return { environment };
229
+ }
208
230
  function normalizeDiagnosticsConfig(value, source) {
209
231
  if (!isRecord(value)) {
210
232
  throw new Error(`${source} must be an object`);
@@ -338,6 +360,37 @@ function isAgentNativeHarnessRuntime(value) {
338
360
  value === "pi" ||
339
361
  value === "opencode");
340
362
  }
363
+ export function isAgentNativeDeploymentEnvironment(value) {
364
+ return (value === "local" ||
365
+ value === "beta" ||
366
+ value === "production" ||
367
+ value === "preview");
368
+ }
369
+ /**
370
+ * Resolve the public deployment lane from hosting facts at build time.
371
+ *
372
+ * Netlify exposes `CONTEXT` and `BRANCH` to builds. Keeping this inference in
373
+ * the Vite/config boundary means browser code consumes typed public config and
374
+ * never parses process.env itself.
375
+ */
376
+ export function inferAgentNativeDeploymentEnvironment(env, mode) {
377
+ const context = env.CONTEXT?.trim().toLowerCase();
378
+ const branch = env.BRANCH?.trim().toLowerCase();
379
+ if (branch === "production" || context === "production") {
380
+ return "production";
381
+ }
382
+ if (branch === "beta" || (context === "branch-deploy" && branch === "main")) {
383
+ return "beta";
384
+ }
385
+ if (context === "deploy-preview" ||
386
+ context === "branch-deploy" ||
387
+ branch?.startsWith("deploy-preview")) {
388
+ return "preview";
389
+ }
390
+ if (mode === "development")
391
+ return "local";
392
+ return undefined;
393
+ }
341
394
  function isRecord(value) {
342
395
  return !!value && typeof value === "object" && !Array.isArray(value);
343
396
  }
@@ -464,14 +464,14 @@ export declare function createDashboardStorageSchema(options?: DashboardStorageS
464
464
  tableName: string;
465
465
  dataType: "string";
466
466
  columnType: "SQLiteText";
467
- data: "org" | "user";
467
+ data: "group" | "org" | "user";
468
468
  driverParam: string;
469
469
  notNull: true;
470
470
  hasDefault: false;
471
471
  isPrimaryKey: false;
472
472
  isAutoincrement: false;
473
473
  hasRuntimeDefault: false;
474
- enumValues: ["user", "org"];
474
+ enumValues: ["user", "group", "org"];
475
475
  baseColumn: never;
476
476
  identity: undefined;
477
477
  generated: undefined;
@@ -411,14 +411,14 @@ export declare const dataProgramShares: import("drizzle-orm/sqlite-core").SQLite
411
411
  tableName: string;
412
412
  dataType: "string";
413
413
  columnType: "SQLiteText";
414
- data: "org" | "user";
414
+ data: "group" | "org" | "user";
415
415
  driverParam: string;
416
416
  notNull: true;
417
417
  hasDefault: false;
418
418
  isPrimaryKey: false;
419
419
  isAutoincrement: false;
420
420
  hasRuntimeDefault: false;
421
- enumValues: ["user", "org"];
421
+ enumValues: ["user", "group", "org"];
422
422
  baseColumn: never;
423
423
  identity: undefined;
424
424
  generated: undefined;
@@ -306,7 +306,7 @@ export function createFetchToolEntry(opts = {}) {
306
306
  // saveToFile: write full body to workspace and return compact summary.
307
307
  if (saveToFilePath) {
308
308
  try {
309
- const { writeWorkspaceFile, SAVE_TO_FILE_MAX_BYTES } = await import("../workspace-files/store.js");
309
+ const { writeWorkspaceFile, SAVE_TO_FILE_MAX_BYTES, isScratchWorkspacePath, toWorkspaceFileCard, } = await import("../workspace-files/store.js");
310
310
  const { getRequestOrgId, getRequestUserEmail } = await import("../server/request-context.js");
311
311
  const orgId = getRequestOrgId();
312
312
  const email = getRequestUserEmail();
@@ -317,7 +317,7 @@ export function createFetchToolEntry(opts = {}) {
317
317
  : null;
318
318
  if (!scope)
319
319
  throw new Error("No authenticated context for saveToFile");
320
- await writeWorkspaceFile(scope, saveToFilePath, body, contentType, {
320
+ const meta = await writeWorkspaceFile(scope, saveToFilePath, body, contentType, {
321
321
  maxFileBytes: SAVE_TO_FILE_MAX_BYTES,
322
322
  });
323
323
  const bytes = Buffer.byteLength(body, "utf8");
@@ -330,6 +330,12 @@ export function createFetchToolEntry(opts = {}) {
330
330
  contentType,
331
331
  responseMode: processedMode,
332
332
  preview: preview.length < displayBody.length ? `${preview}…` : preview,
333
+ // A durable (non-scratch) file renders a download card the
334
+ // moment it's created — no separate show-workspace-file call
335
+ // needed to get a link.
336
+ ...(isScratchWorkspacePath(saveToFilePath)
337
+ ? {}
338
+ : { file: toWorkspaceFileCard(meta) }),
333
339
  });
334
340
  }
335
341
  catch (saveErr) {
@@ -316,14 +316,14 @@ export declare const extensionShares: import("drizzle-orm/sqlite-core").SQLiteTa
316
316
  tableName: string;
317
317
  dataType: "string";
318
318
  columnType: "SQLiteText";
319
- data: "org" | "user";
319
+ data: "group" | "org" | "user";
320
320
  driverParam: string;
321
321
  notNull: true;
322
322
  hasDefault: false;
323
323
  isPrimaryKey: false;
324
324
  isAutoincrement: false;
325
325
  hasRuntimeDefault: false;
326
- enumValues: ["user", "org"];
326
+ enumValues: ["user", "group", "org"];
327
327
  baseColumn: never;
328
328
  identity: undefined;
329
329
  generated: undefined;
@@ -244,6 +244,9 @@ async function extensionChangeTargetsForRow(row) {
244
244
  else if (share.principalType === "org") {
245
245
  addExtensionChangeTarget(targets, { orgId: share.principalId });
246
246
  }
247
+ else if (share.principalType === "group" && row.orgId) {
248
+ addExtensionChangeTarget(targets, { orgId: row.orgId });
249
+ }
247
250
  }
248
251
  return Array.from(targets.values());
249
252
  }
@@ -486,6 +486,7 @@ const messages = {
486
486
  "share.unknownPerson": "شخص غير معروف",
487
487
  "share.viewer": "مشاهد",
488
488
  "share.viewerDescription": "يمكنه العرض",
489
+ "share.userGroup": "مجموعة مستخدمين",
489
490
  "status.resuming": "جارٍ الاستئناف",
490
491
  "status.stillWorking": "لا يزال قيد العمل",
491
492
  "status.thinking": "يفكّر",
@@ -521,5 +521,6 @@ const messages = {
521
521
  "share.unknownPerson": "Unbekannte Person",
522
522
  "share.viewer": "Betrachter",
523
523
  "share.viewerDescription": "Kann ansehen",
524
+ "share.userGroup": "Benutzergruppe",
524
525
  };
525
526
  export default messages;
@@ -470,6 +470,7 @@ declare const messages: {
470
470
  readonly "share.unknownPerson": "Unknown person";
471
471
  readonly "share.viewer": "Viewer";
472
472
  readonly "share.viewerDescription": "Can view";
473
+ readonly "share.userGroup": "User group";
473
474
  readonly "status.resuming": "Resuming";
474
475
  readonly "status.stillWorking": "Still working";
475
476
  readonly "status.thinking": "Thinking";
@@ -470,6 +470,7 @@ const messages = {
470
470
  "share.unknownPerson": "Unknown person",
471
471
  "share.viewer": "Viewer",
472
472
  "share.viewerDescription": "Can view",
473
+ "share.userGroup": "User group",
473
474
  "status.resuming": "Resuming",
474
475
  "status.stillWorking": "Still working",
475
476
  "status.thinking": "Thinking",
@@ -528,5 +528,6 @@ const messages = {
528
528
  "share.unknownPerson": "Persona desconocida",
529
529
  "share.viewer": "Lector",
530
530
  "share.viewerDescription": "Puede ver",
531
+ "share.userGroup": "Grupo de usuarios",
531
532
  };
532
533
  export default messages;
@@ -528,5 +528,6 @@ const messages = {
528
528
  "share.unknownPerson": "Personne inconnue",
529
529
  "share.viewer": "Lecteur",
530
530
  "share.viewerDescription": "Peut consulter",
531
+ "share.userGroup": "Groupe d’utilisateurs",
531
532
  };
532
533
  export default messages;
@@ -470,6 +470,7 @@ const messages = {
470
470
  "share.unknownPerson": "अज्ञात व्यक्ति",
471
471
  "share.viewer": "दर्शक",
472
472
  "share.viewerDescription": "देख सकता है",
473
+ "share.userGroup": "उपयोगकर्ता समूह",
473
474
  "status.resuming": "फिर से शुरू हो रहा है",
474
475
  "status.stillWorking": "अभी काम जारी है",
475
476
  "status.thinking": "सोच रहा है",
@@ -466,6 +466,7 @@ const messages = {
466
466
  "share.unknownPerson": "不明なユーザー",
467
467
  "share.viewer": "閲覧者",
468
468
  "share.viewerDescription": "閲覧可能",
469
+ "share.userGroup": "ユーザーグループ",
469
470
  "status.resuming": "再開中",
470
471
  "status.stillWorking": "処理を続けています",
471
472
  "status.thinking": "思考中",
@@ -466,6 +466,7 @@ const messages = {
466
466
  "share.unknownPerson": "알 수 없는 사용자",
467
467
  "share.viewer": "뷰어",
468
468
  "share.viewerDescription": "보기 가능",
469
+ "share.userGroup": "사용자 그룹",
469
470
  "status.resuming": "재개 중",
470
471
  "status.stillWorking": "계속 작업 중",
471
472
  "status.thinking": "생각 중",
@@ -528,5 +528,6 @@ const messages = {
528
528
  "share.unknownPerson": "Pessoa desconhecida",
529
529
  "share.viewer": "Visualizador",
530
530
  "share.viewerDescription": "Pode visualizar",
531
+ "share.userGroup": "Grupo de usuários",
531
532
  };
532
533
  export default messages;
@@ -466,6 +466,7 @@ const messages = {
466
466
  "share.unknownPerson": "未知人员",
467
467
  "share.viewer": "查看者",
468
468
  "share.viewerDescription": "可以查看",
469
+ "share.userGroup": "用户组",
469
470
  "status.resuming": "正在恢复",
470
471
  "status.stillWorking": "仍在处理",
471
472
  "status.thinking": "正在思考",
@@ -466,6 +466,7 @@ const messages = {
466
466
  "share.unknownPerson": "未知人員",
467
467
  "share.viewer": "檢視者",
468
468
  "share.viewerDescription": "可以檢視",
469
+ "share.userGroup": "使用者群組",
469
470
  "status.resuming": "正在繼續",
470
471
  "status.stillWorking": "仍在處理",
471
472
  "status.thinking": "正在思考",
@@ -472,6 +472,7 @@ export declare const englishAgentChatMessages: {
472
472
  readonly "share.unknownPerson": "Unknown person";
473
473
  readonly "share.viewer": "Viewer";
474
474
  readonly "share.viewerDescription": "Can view";
475
+ readonly "share.userGroup": "User group";
475
476
  readonly "status.resuming": "Resuming";
476
477
  readonly "status.stillWorking": "Still working";
477
478
  readonly "status.thinking": "Thinking";
@@ -879,6 +879,10 @@ declare const messages: {
879
879
  owner: string;
880
880
  admin: string;
881
881
  member: string;
882
+ workspaceAppsDefaultPrivacy: string;
883
+ workspaceAppsDefaultPrivacyDescription: string;
884
+ workspaceAppsOrganization: string;
885
+ workspaceAppsCreatorOnly: string;
882
886
  members: string;
883
887
  inviteMembers: string;
884
888
  invited: string;
@@ -885,6 +885,10 @@ const messages = {
885
885
  owner: "Owner",
886
886
  admin: "Admin",
887
887
  member: "Member",
888
+ workspaceAppsDefaultPrivacy: "New app privacy",
889
+ workspaceAppsDefaultPrivacyDescription: "Choose whether new workspace apps start private to their creator or visible to the organization.",
890
+ workspaceAppsOrganization: "Organization",
891
+ workspaceAppsCreatorOnly: "Creator only",
888
892
  members: "Members",
889
893
  inviteMembers: "Invite members",
890
894
  invited: "Invited",
@@ -735,7 +735,7 @@ export function embedApp(options = {}) {
735
735
 
736
736
  function stripDevOnlyModuleImports(code) {
737
737
  return String(code).replace(
738
- /\\bimport\\s+(?:[^"']+\\s+from\\s+)?["'][^"']*(?:virtual:react-router\\/inject-hmr-runtime|__x00__virtual:react-router\\/inject-hmr-runtime)[^"']*["']\\s*;?/g,
738
+ /\\bimport\\s+(?:[^"']+\\s+from\\s+)?["'][^"']*(?:virtual:react-router\\/(?:inject-)?hmr-runtime|__x00__virtual:react-router\\/(?:inject-)?hmr-runtime)[^"']*["']\\s*;?/g,
739
739
  ""
740
740
  );
741
741
  }
@@ -28,6 +28,6 @@ export declare function createNotificationsHandler(): import("h3").EventHandlerW
28
28
  } | {
29
29
  count?: undefined;
30
30
  updated?: undefined;
31
- ok: boolean;
32
31
  error?: undefined;
32
+ ok: boolean;
33
33
  }>>;
@@ -1,4 +1,4 @@
1
- import type { OrgRole } from "./types.js";
1
+ import type { OrgRole, WorkspaceAppDefaultVisibility } from "./types.js";
2
2
  /** GET /_agent-native/org/me — current user's active org, all orgs, pending invitations */
3
3
  export declare const getMyOrgHandler: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
4
4
  email: string;
@@ -23,8 +23,13 @@ export declare const getMyOrgHandler: import("h3").EventHandlerWithFetch<import(
23
23
  allowedDomain: string;
24
24
  workspaceUrl: string;
25
25
  requiredAuthProvider: "google";
26
+ workspaceAppDefaultVisibility: WorkspaceAppDefaultVisibility;
26
27
  a2aSecretSet: boolean;
27
28
  }>>;
29
+ /** PUT /_agent-native/org/workspace-app-default-visibility - org admins only */
30
+ export declare const setWorkspaceAppDefaultVisibilityHandler: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
31
+ visibility: WorkspaceAppDefaultVisibility;
32
+ }>>;
28
33
  /** POST /_agent-native/org — create a new organization */
29
34
  export declare const createOrgHandler: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
30
35
  id: string;
@@ -35,6 +35,7 @@ import { getSession } from "../server/auth.js";
35
35
  import { renderInviteEmail } from "../server/email-templates.js";
36
36
  import { sendEmail, isEmailConfigured } from "../server/email.js";
37
37
  import { readBody } from "../server/h3-helpers.js";
38
+ import { getOrgSetting, putOrgSetting } from "../settings/org-settings.js";
38
39
  import { setActiveOrgId } from "./active-org.js";
39
40
  import { setRequiredAuthProvider } from "./auth-policy.js";
40
41
  import { invalidateDomainMatchCache } from "./auto-join-domain.js";
@@ -42,6 +43,14 @@ import { getOrgContext, createOrganization } from "./context.js";
42
43
  import { isFreeEmailProvider } from "./free-email-providers.js";
43
44
  import { invalidateMemberOrgCaches } from "./request-org-cache.js";
44
45
  import { parseWorkspaceUrl } from "./workspace-url.js";
46
+ const WORKSPACE_APP_DEFAULT_VISIBILITY_KEY = "workspace-app-default-visibility";
47
+ function normalizeWorkspaceAppDefaultVisibility(value) {
48
+ if (value === "private" || value === "org")
49
+ return value;
50
+ if (value == null)
51
+ return "org";
52
+ throw new Error("Workspace app default visibility is invalid; refusing to widen access.");
53
+ }
45
54
  function getInviteAppUrl(event) {
46
55
  return getAppProductionUrl(event);
47
56
  }
@@ -119,6 +128,11 @@ export const getMyOrgHandler = defineEventHandler(async (event) => {
119
128
  }
120
129
  }
121
130
  const isOwnerOrAdmin = ctx.role === "owner" || ctx.role === "admin";
131
+ let workspaceAppDefaultVisibility = "org";
132
+ if (ctx.orgId) {
133
+ const setting = await getOrgSetting(ctx.orgId, WORKSPACE_APP_DEFAULT_VISIBILITY_KEY);
134
+ workspaceAppDefaultVisibility = normalizeWorkspaceAppDefaultVisibility(setting?.visibility);
135
+ }
122
136
  const invitesRes = await e.execute({
123
137
  // Case-insensitive match: invitations are stored with whatever case
124
138
  // the inviter typed, but the session email may be normalized
@@ -147,6 +161,7 @@ export const getMyOrgHandler = defineEventHandler(async (event) => {
147
161
  allowedDomain,
148
162
  workspaceUrl,
149
163
  requiredAuthProvider,
164
+ workspaceAppDefaultVisibility,
150
165
  // Never serialize the A2A secret here. This route runs on every page load,
151
166
  // so the value would sit in JSON any script on the page can read, and it
152
167
  // signs the JWTs peers accept as first-party callers. Reveal is an explicit
@@ -154,6 +169,34 @@ export const getMyOrgHandler = defineEventHandler(async (event) => {
154
169
  a2aSecretSet: isOwnerOrAdmin ? a2aSecretSet : undefined,
155
170
  };
156
171
  });
172
+ /** PUT /_agent-native/org/workspace-app-default-visibility - org admins only */
173
+ export const setWorkspaceAppDefaultVisibilityHandler = defineEventHandler(async (event) => {
174
+ const ctx = await getOrgContext(event);
175
+ if (ctx.role !== "owner" && ctx.role !== "admin") {
176
+ throw createError({
177
+ statusCode: 403,
178
+ message: "Only organization admins can change app defaults.",
179
+ });
180
+ }
181
+ if (!ctx.orgId) {
182
+ throw createError({
183
+ statusCode: 400,
184
+ message: "Join an organization before changing app defaults.",
185
+ });
186
+ }
187
+ const body = await readBody(event);
188
+ if (body?.visibility !== "private" && body?.visibility !== "org") {
189
+ throw createError({
190
+ statusCode: 400,
191
+ message: "visibility must be either private or org.",
192
+ });
193
+ }
194
+ const visibility = body.visibility;
195
+ await putOrgSetting(ctx.orgId, WORKSPACE_APP_DEFAULT_VISIBILITY_KEY, {
196
+ visibility,
197
+ });
198
+ return { visibility };
199
+ });
157
200
  /** POST /_agent-native/org — create a new organization */
158
201
  export const createOrgHandler = defineEventHandler(async (event) => {
159
202
  const session = await getSession(event);
@@ -1,4 +1,4 @@
1
- export type { OrgRole, OrgContext, OrgSummary, OrgInvitationSummary, OrgInfo, OrgMember, OrgPendingInvitation, RequiredAuthProvider, } from "./types.js";
1
+ export type { OrgRole, OrgContext, OrgSummary, OrgInvitationSummary, OrgInfo, OrgMember, OrgPendingInvitation, RequiredAuthProvider, WorkspaceAppDefaultVisibility, } from "./types.js";
2
2
  export { canInviteOrgMembers, canManageOrg, canManageOrgDomain, orgRoleAtLeast, orgRoleRank, } from "./permissions.js";
3
3
  export { getOrgContext, getOrgDomain, getOrgA2ASecret, getA2ASecretByDomain, resolveOrgByDomain, resolveOrgIdForEmail, createOrganization, } from "./context.js";
4
4
  export { implicitServiceOrgRole, parseServiceIdentityEmail, } from "./service-identity.js";
@@ -11,8 +11,8 @@ export type { AppRoles, AppRolesDescriptor, AppRoleCaller, AppRoleLookup, AppMem
11
11
  export { ORG_MIGRATIONS } from "./migrations.js";
12
12
  export { getRequiredAuthProviderForEmail, getRequiredAuthProviderForOrg, isGoogleSignInRequiredForEmail, setRequiredAuthProvider, } from "./auth-policy.js";
13
13
  export { createOrgPlugin, defaultOrgPlugin } from "./plugin.js";
14
- export { organizations, orgMembers, orgInvitations, appMemberRoles, } from "./schema.js";
15
- export { getMyOrgHandler, createOrgHandler, updateOrgHandler, switchOrgHandler, listMembersHandler, removeMemberHandler, changeMemberRoleHandler, listInvitationsHandler, createInvitationHandler, acceptInvitationHandler, setA2ASecretHandler, syncA2ASecretHandler, receiveA2ASecretHandler, setRequiredAuthProviderHandler, } from "./handlers.js";
14
+ export { organizations, orgMembers, orgInvitations, appMemberRoles, workspaceApps, workspaceAppShares, } from "./schema.js";
15
+ export { getMyOrgHandler, createOrgHandler, updateOrgHandler, switchOrgHandler, listMembersHandler, removeMemberHandler, changeMemberRoleHandler, listInvitationsHandler, createInvitationHandler, acceptInvitationHandler, setA2ASecretHandler, syncA2ASecretHandler, receiveA2ASecretHandler, setRequiredAuthProviderHandler, setWorkspaceAppDefaultVisibilityHandler, } from "./handlers.js";
16
16
  export { listAppRolesHandler, setAppRoleHandler, } from "./app-roles-handlers.js";
17
17
  export { isFreeEmailProvider } from "./free-email-providers.js";
18
18
  export { isOrgMember } from "./membership.js";
package/dist/org/index.js CHANGED
@@ -10,10 +10,10 @@ export { getRequiredAuthProviderForEmail, getRequiredAuthProviderForOrg, isGoogl
10
10
  export { createOrgPlugin, defaultOrgPlugin } from "./plugin.js";
11
11
  // Drizzle schema (re-exported so templates can write typed queries against
12
12
  // org tables without redefining the schema themselves).
13
- export { organizations, orgMembers, orgInvitations, appMemberRoles, } from "./schema.js";
13
+ export { organizations, orgMembers, orgInvitations, appMemberRoles, workspaceApps, workspaceAppShares, } from "./schema.js";
14
14
  // Individual handlers — exported so templates can compose a custom org plugin
15
15
  // while still using the framework-provided handlers.
16
- export { getMyOrgHandler, createOrgHandler, updateOrgHandler, switchOrgHandler, listMembersHandler, removeMemberHandler, changeMemberRoleHandler, listInvitationsHandler, createInvitationHandler, acceptInvitationHandler, setA2ASecretHandler, syncA2ASecretHandler, receiveA2ASecretHandler, setRequiredAuthProviderHandler, } from "./handlers.js";
16
+ export { getMyOrgHandler, createOrgHandler, updateOrgHandler, switchOrgHandler, listMembersHandler, removeMemberHandler, changeMemberRoleHandler, listInvitationsHandler, createInvitationHandler, acceptInvitationHandler, setA2ASecretHandler, syncA2ASecretHandler, receiveA2ASecretHandler, setRequiredAuthProviderHandler, setWorkspaceAppDefaultVisibilityHandler, } from "./handlers.js";
17
17
  export { listAppRolesHandler, setAppRoleHandler, } from "./app-roles-handlers.js";
18
18
  export { isFreeEmailProvider } from "./free-email-providers.js";
19
19
  export { isOrgMember } from "./membership.js";
@@ -132,4 +132,37 @@ export const ORG_MIGRATIONS = [
132
132
  version: 1014,
133
133
  sql: `ALTER TABLE organizations ADD COLUMN IF NOT EXISTS required_auth_provider TEXT`,
134
134
  },
135
+ {
136
+ version: 1015,
137
+ sql: `CREATE TABLE IF NOT EXISTS workspace_apps (
138
+ id TEXT PRIMARY KEY,
139
+ owner_email TEXT NOT NULL,
140
+ org_id TEXT,
141
+ visibility TEXT NOT NULL DEFAULT 'org',
142
+ name TEXT NOT NULL,
143
+ description TEXT,
144
+ path TEXT NOT NULL,
145
+ created_at INTEGER NOT NULL,
146
+ updated_at INTEGER NOT NULL
147
+ )`,
148
+ },
149
+ {
150
+ version: 1016,
151
+ sql: `CREATE TABLE IF NOT EXISTS workspace_app_shares (
152
+ id TEXT PRIMARY KEY,
153
+ resource_id TEXT NOT NULL,
154
+ principal_type TEXT NOT NULL,
155
+ principal_id TEXT NOT NULL,
156
+ role TEXT NOT NULL DEFAULT 'viewer',
157
+ created_at TEXT NOT NULL,
158
+ created_by TEXT NOT NULL DEFAULT '',
159
+ UNIQUE(resource_id, principal_type, principal_id)
160
+ )`,
161
+ },
162
+ {
163
+ version: 1017,
164
+ name: "workspace-app-access-indexes",
165
+ sql: `CREATE INDEX IF NOT EXISTS workspace_apps_org_visibility_idx
166
+ ON workspace_apps (org_id, visibility)`,
167
+ },
135
168
  ];
@@ -2,7 +2,7 @@ import { defineEventHandler, setResponseStatus, getMethod, getRequestURL, } from
2
2
  import { runMigrations } from "../db/migrations.js";
3
3
  import { awaitBootstrap, getH3App, FRAMEWORK_PREFIX, markDefaultPluginProvided, } from "../server/framework-request-handler.js";
4
4
  import { listAppRolesHandler, setAppRoleHandler, } from "./app-roles-handlers.js";
5
- import { getMyOrgHandler, createOrgHandler, updateOrgHandler, deleteOrgHandler, switchOrgHandler, listMembersHandler, removeMemberHandler, changeMemberRoleHandler, listInvitationsHandler, createInvitationHandler, acceptInvitationHandler, joinByDomainHandler, setDomainHandler, setWorkspaceUrlHandler, setRequiredAuthProviderHandler, revealA2ASecretHandler, setA2ASecretHandler, syncA2ASecretHandler, receiveA2ASecretHandler, } from "./handlers.js";
5
+ import { getMyOrgHandler, createOrgHandler, updateOrgHandler, deleteOrgHandler, switchOrgHandler, listMembersHandler, removeMemberHandler, changeMemberRoleHandler, listInvitationsHandler, createInvitationHandler, acceptInvitationHandler, joinByDomainHandler, setDomainHandler, setWorkspaceUrlHandler, setRequiredAuthProviderHandler, revealA2ASecretHandler, setA2ASecretHandler, syncA2ASecretHandler, receiveA2ASecretHandler, setWorkspaceAppDefaultVisibilityHandler, } from "./handlers.js";
6
6
  import { ORG_MIGRATIONS } from "./migrations.js";
7
7
  const ORG_PREFIX = `${FRAMEWORK_PREFIX}/org`;
8
8
  /**
@@ -97,6 +97,15 @@ export function createOrgPlugin() {
97
97
  }
98
98
  return removeMemberHandler(event);
99
99
  }));
100
+ // PUT /workspace-app-default-visibility — org admins choose the default
101
+ // for newly created workspace apps. Existing apps retain their setting.
102
+ app.use(`${ORG_PREFIX}/workspace-app-default-visibility`, defineEventHandler(async (event) => {
103
+ if (getMethod(event) !== "PUT") {
104
+ setResponseStatus(event, 405);
105
+ return { error: "Method not allowed" };
106
+ }
107
+ return setWorkspaceAppDefaultVisibilityHandler(event);
108
+ }));
100
109
  // /invitations and /invitations/:id/accept — same pattern.
101
110
  app.use(`${ORG_PREFIX}/invitations`, defineEventHandler(async (event) => {
102
111
  const tail = getRequestURL(event).pathname || "/";