@agent-native/core 0.161.20 → 0.161.23

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 (57) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/clips/actions/finalize-meeting.ts +57 -21
  3. package/corpus/templates/clips/actions/get-meeting.ts +11 -3
  4. package/corpus/templates/clips/actions/request-transcript.ts +183 -8
  5. package/corpus/templates/clips/actions/update-meeting.ts +66 -14
  6. package/corpus/templates/clips/app/components/meetings/canvas-editor.tsx +80 -135
  7. package/corpus/templates/clips/app/i18n/en-US.ts +4 -0
  8. package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +470 -35
  9. package/corpus/templates/clips/changelog/2026-08-18-meeting-notes-support-rich-editing-for-personal-notes-summar.md +6 -0
  10. package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +13 -3
  11. package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +13 -7
  12. package/corpus/templates/design/app/hooks/use-navigation-state.ts +18 -21
  13. package/corpus/templates/design/app/pages/design-editor/editor-state.ts +2 -5
  14. package/corpus/templates/design/app/pages/design-editor/tool-state.ts +4 -12
  15. package/corpus/templates/design/app/pages/design-editor/types.ts +38 -1
  16. package/corpus/templates/design/changelog/2026-08-18-advanced-design-editor-panels-hidden-by-default.md +6 -0
  17. package/corpus/templates/design/playwright.config.ts +19 -2
  18. package/corpus/templates/mail/app/components/email/EmailList.tsx +74 -22
  19. package/corpus/templates/mail/app/components/email/infinite-pagination.ts +82 -0
  20. package/corpus/templates/mail/app/hooks/use-emails.ts +1 -0
  21. package/corpus/templates/mail/app/pages/InboxPage.tsx +15 -10
  22. package/corpus/templates/mail/app/pages/inbox-zero.ts +35 -0
  23. package/corpus/templates/mail/changelog/2026-08-18-pinned-labels-load-matches.md +6 -0
  24. package/corpus/templates/slides/actions/get-deck.ts +5 -1
  25. package/corpus/templates/slides/actions/list-decks.ts +29 -8
  26. package/corpus/templates/slides/actions/view-screen.ts +7 -3
  27. package/corpus/templates/slides/changelog/2026-08-18-decks-appear-under-mine.md +6 -0
  28. package/corpus/templates/slides/shared/ownership.ts +6 -0
  29. package/dist/agent/engine/builder-engine.js +15 -8
  30. package/dist/agent/production-agent.d.ts +15 -0
  31. package/dist/agent/production-agent.js +32 -9
  32. package/dist/app-config/schema.d.ts +2 -0
  33. package/dist/app-config/workspace.d.ts +2 -0
  34. package/dist/app-config/workspace.js +18 -0
  35. package/dist/catalog.json +23 -23
  36. package/dist/client/analytics.d.ts +1 -0
  37. package/dist/client/api-path.js +7 -3
  38. package/dist/client/frame.js +20 -6
  39. package/dist/client/org/workspace-app-links.js +10 -1
  40. package/dist/collab/awareness.d.ts +2 -2
  41. package/dist/collab/routes.d.ts +1 -1
  42. package/dist/deploy/build.js +26 -2
  43. package/dist/observability/routes.d.ts +2 -2
  44. package/dist/provider-api/actions/custom-provider-registration.d.ts +14 -14
  45. package/dist/provider-api/actions/provider-api.d.ts +15 -15
  46. package/dist/server/app-origin-config.d.ts +1 -0
  47. package/dist/server/app-origin-config.js +3 -0
  48. package/dist/server/auth.js +2 -2
  49. package/dist/server/cookie-namespace.js +17 -2
  50. package/dist/server/credential-provider.js +5 -2
  51. package/dist/server/derived-secret.js +3 -2
  52. package/dist/server/onboarding-html.js +34 -2
  53. package/dist/server/workspace-oauth.js +11 -6
  54. package/dist/shared/runtime-config.d.ts +2 -0
  55. package/dist/shared/runtime-config.js +12 -3
  56. package/dist/vite/client.js +5 -2
  57. package/package.json +2 -2
@@ -2,10 +2,11 @@ import { defineAction } from "@agent-native/core";
2
2
  import { buildDeepLink } from "@agent-native/core/server";
3
3
  import { getRequestUserEmail } from "@agent-native/core/server/request-context";
4
4
  import { accessFilter } from "@agent-native/core/sharing";
5
- import { and, desc, eq } from "drizzle-orm";
5
+ import { and, desc, eq, sql } from "drizzle-orm";
6
6
  import { z } from "zod";
7
7
 
8
8
  import { getDb, schema } from "../server/db/index.js";
9
+ import { normalizeOwnerEmail } from "../shared/ownership.js";
9
10
  import { getDeckUrl } from "./_app-url.js";
10
11
 
11
12
  function slidesDeepLink(): string {
@@ -47,24 +48,28 @@ export default defineAction({
47
48
  run: async (args, ctx) => {
48
49
  const db = getDb();
49
50
  const ownerEmail = getRequestUserEmail();
51
+ const normalizedOwnerEmail = normalizeOwnerEmail(ownerEmail);
50
52
  if (
51
53
  args.includeSlides === "true" &&
52
54
  ctx?.caller === "frontend" &&
53
- !ownerEmail
55
+ normalizedOwnerEmail === null
54
56
  ) {
55
57
  const err = new Error("Unauthorized") as Error & { statusCode?: number };
56
58
  err.statusCode = 401;
57
59
  throw err;
58
60
  }
59
61
 
60
- if (args.createdBy === "me" && !ownerEmail) {
62
+ if (args.createdBy === "me" && normalizedOwnerEmail === null) {
61
63
  return { count: 0, decks: [] };
62
64
  }
63
65
 
64
66
  const visibleDecks = accessFilter(schema.decks, schema.deckShares);
65
67
  const where =
66
- args.createdBy === "me" && ownerEmail
67
- ? and(visibleDecks, eq(schema.decks.ownerEmail, ownerEmail))
68
+ args.createdBy === "me" && normalizedOwnerEmail !== null
69
+ ? and(
70
+ visibleDecks,
71
+ sql`lower(trim(${schema.decks.ownerEmail})) = ${normalizedOwnerEmail}`,
72
+ )
68
73
  : visibleDecks;
69
74
 
70
75
  if (args.light === "true") {
@@ -79,11 +84,23 @@ export default defineAction({
79
84
  title: schema.decks.title,
80
85
  updatedAt: schema.decks.updatedAt,
81
86
  visibility: schema.decks.visibility,
87
+ ownerEmail: schema.decks.ownerEmail,
82
88
  })
83
89
  .from(schema.decks)
84
90
  .where(where)
85
91
  .orderBy(desc(schema.decks.updatedAt));
86
- return { count: rows.length, decks: rows };
92
+ return {
93
+ count: rows.length,
94
+ decks: rows.map((row) => ({
95
+ id: row.id,
96
+ title: row.title,
97
+ updatedAt: row.updatedAt,
98
+ visibility: row.visibility,
99
+ createdByMe:
100
+ normalizedOwnerEmail !== null &&
101
+ normalizeOwnerEmail(row.ownerEmail) === normalizedOwnerEmail,
102
+ })),
103
+ };
87
104
  }
88
105
 
89
106
  if (args.includeSlides !== "true") {
@@ -112,7 +129,9 @@ export default defineAction({
112
129
  url: getDeckUrl(row.id),
113
130
  visibility: row.visibility,
114
131
  designSystemId: row.designSystemId ?? null,
115
- createdByMe: ownerEmail ? row.ownerEmail === ownerEmail : false,
132
+ createdByMe:
133
+ normalizedOwnerEmail !== null &&
134
+ normalizeOwnerEmail(row.ownerEmail) === normalizedOwnerEmail,
116
135
  createdAt: row.createdAt,
117
136
  updatedAt: row.updatedAt,
118
137
  })),
@@ -138,7 +157,9 @@ export default defineAction({
138
157
  id: row.id,
139
158
  title: row.title,
140
159
  visibility: row.visibility,
141
- createdByMe: ownerEmail ? row.ownerEmail === ownerEmail : false,
160
+ createdByMe:
161
+ normalizedOwnerEmail !== null &&
162
+ normalizeOwnerEmail(row.ownerEmail) === normalizedOwnerEmail,
142
163
  designSystemId: row.designSystemId ?? data.designSystemId ?? null,
143
164
  createdAt:
144
165
  typeof data.createdAt === "string" ? data.createdAt : row.createdAt,
@@ -8,6 +8,7 @@ import { and, desc, eq } from "drizzle-orm";
8
8
  import { z } from "zod";
9
9
 
10
10
  import { getDb, schema } from "../server/db/index.js";
11
+ import { normalizeOwnerEmail } from "../shared/ownership.js";
11
12
  import { hashSlideContent, type DeckFitState } from "../shared/slide-fit.js";
12
13
  import { readAppStateForCurrentTab } from "./_tab-state.js";
13
14
 
@@ -369,11 +370,14 @@ export default defineAction({
369
370
  .where(accessFilter(schema.decks, schema.deckShares))
370
371
  .orderBy(desc(schema.decks.updatedAt));
371
372
 
372
- const userEmail = getRequestUserEmail();
373
+ const normalizedUserEmail = normalizeOwnerEmail(getRequestUserEmail());
373
374
  const filteredRows =
374
375
  navigation?.deckFilter === "created-by-me"
375
- ? userEmail
376
- ? rows.filter((row) => row.ownerEmail === userEmail)
376
+ ? normalizedUserEmail !== null
377
+ ? rows.filter(
378
+ (row) =>
379
+ normalizeOwnerEmail(row.ownerEmail) === normalizedUserEmail,
380
+ )
377
381
  : []
378
382
  : rows;
379
383
  const lines: string[] = [];
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-08-18
4
+ ---
5
+
6
+ Decks now appear correctly under Mine.
@@ -0,0 +1,6 @@
1
+ export function normalizeOwnerEmail(
2
+ email: string | null | undefined,
3
+ ): string | null {
4
+ const normalized = email?.trim().toLowerCase();
5
+ return normalized || null;
6
+ }
@@ -138,10 +138,17 @@ class BuilderEngine {
138
138
  }, creditsLane);
139
139
  return;
140
140
  }
141
+ // The Builder gateway has an "auto" fallback mode, but Agent Native owns
142
+ // model selection. Always send a concrete model so the gateway cannot
143
+ // select an organization-level override or another fallback model.
144
+ const requestedModel = opts.model.trim();
145
+ const model = requestedModel.length === 0 || requestedModel === "auto"
146
+ ? BUILDER_DEFAULT_MODEL
147
+ : requestedModel;
141
148
  const messages = engineMessagesToBuilderGatewayAnthropic(opts.messages);
142
149
  const tools = engineToolsToAnthropic(opts.tools);
143
150
  const thinkingBudget = opts.providerOptions?.anthropic?.thinking?.budgetTokens;
144
- const reasoningEffort = normalizeReasoningEffortForModel(opts.model, opts.reasoningEffort ??
151
+ const reasoningEffort = normalizeReasoningEffortForModel(model, opts.reasoningEffort ??
145
152
  (typeof thinkingBudget === "number"
146
153
  ? mapReasoningEffort(thinkingBudget)
147
154
  : undefined));
@@ -200,13 +207,13 @@ class BuilderEngine {
200
207
  }
201
208
  }
202
209
  }
203
- const gptToolsRequireExplicitNoReasoning = cachedTools.length > 0 && isGPTReasoningModel(opts.model);
210
+ const gptToolsRequireExplicitNoReasoning = cachedTools.length > 0 && isGPTReasoningModel(model);
204
211
  const body = {
205
- model: opts.model,
212
+ model,
206
213
  messages: cachedMessages,
207
214
  ...(systemValue !== undefined ? { system: systemValue } : {}),
208
215
  ...(cachedTools.length > 0 ? { tools: cachedTools } : {}),
209
- max_tokens: resolveMaxOutputTokensForEngine(this.name, opts.maxOutputTokens, opts.model),
216
+ max_tokens: resolveMaxOutputTokensForEngine(this.name, opts.maxOutputTokens, model),
210
217
  ...(typeof opts.temperature === "number"
211
218
  ? { temperature: opts.temperature }
212
219
  : {}),
@@ -232,7 +239,7 @@ class BuilderEngine {
232
239
  // gateway outage are the same capture.
233
240
  const payload = JSON.stringify(body);
234
241
  const requestShape = {
235
- model: opts.model,
242
+ model,
236
243
  payloadBytes: new TextEncoder().encode(payload).length,
237
244
  toolCount: cachedTools.length,
238
245
  messageCount: cachedMessages.length,
@@ -242,7 +249,7 @@ class BuilderEngine {
242
249
  gatewayUrl.searchParams.set("apiKey", spaceId);
243
250
  const orgLabel = creds.orgName || "unknown-org";
244
251
  const tStart = Date.now();
245
- console.log(`[builder-engine] → POST ${gatewayUrl.origin}${gatewayUrl.pathname} model=${opts.model} tools=${tools.length} org=${orgLabel}`);
252
+ console.log(`[builder-engine] → POST ${gatewayUrl.origin}${gatewayUrl.pathname} model=${model} tools=${tools.length} org=${orgLabel}`);
246
253
  const gatewayTimeoutMs = getBuilderGatewayTimeoutMs();
247
254
  const gatewayAbort = createGatewayAbortSignal(opts.abortSignal, gatewayTimeoutMs);
248
255
  try {
@@ -269,7 +276,7 @@ class BuilderEngine {
269
276
  if (timedOut || isBuilderGatewayNetworkError(err)) {
270
277
  captureBuilderGatewayTransportError(err, {
271
278
  phase: "request",
272
- model: opts.model,
279
+ model,
273
280
  gatewayUrl,
274
281
  timeoutMs: gatewayAbort.effectiveTimeoutMs(),
275
282
  timedOut,
@@ -325,7 +332,7 @@ class BuilderEngine {
325
332
  }, creditsLane, requestShape);
326
333
  return;
327
334
  }
328
- yield* parseJsonlStream(reader, opts.model, {
335
+ yield* parseJsonlStream(reader, model, {
329
336
  creditsLane,
330
337
  abortSignal: gatewayAbort.signal,
331
338
  didGatewayTimeout: gatewayAbort.didTimeout,
@@ -1351,5 +1351,20 @@ export declare function resolveAgentRequestReasoningEffort({ model, requestEffor
1351
1351
  requestEffort?: unknown;
1352
1352
  configuredEffort?: ReasoningEffort;
1353
1353
  }): ReasoningEffort | undefined;
1354
+ export type AgentModelSelectionSource = "request" | "configured" | "stored" | "default";
1355
+ /**
1356
+ * Resolve the model before the engine boundary. `auto` is a UI sentinel, not
1357
+ * a model to forward to the gateway, so it gives way to an AN org/user
1358
+ * default, then the configured global engine default.
1359
+ */
1360
+ export declare function resolveAgentModelSelection(options: {
1361
+ requestModel?: string | null;
1362
+ configuredModel?: string | null;
1363
+ storedModel?: string | null;
1364
+ defaultModel: string;
1365
+ }): {
1366
+ model: string;
1367
+ source: AgentModelSelectionSource;
1368
+ };
1354
1369
  export declare function createProductionAgentHandler(options: ProductionAgentOptions): H3EventHandler;
1355
1370
  export { getActiveRunForThread, getActiveRunForThreadAsync, getRun, abortRun, abortRunDurably, abortTurnDurably, subscribeToRun, };
@@ -6275,6 +6275,27 @@ function progressStepFromAgentChatEvent(event) {
6275
6275
  export function resolveAgentRequestReasoningEffort({ model, requestEffort, configuredEffort, }) {
6276
6276
  return normalizeReasoningEffortForRequest(model, isReasoningEffort(requestEffort) ? requestEffort : configuredEffort);
6277
6277
  }
6278
+ function isConcreteModelSelection(model) {
6279
+ const normalized = typeof model === "string" ? model.trim() : "";
6280
+ return normalized.length > 0 && normalized !== "auto";
6281
+ }
6282
+ /**
6283
+ * Resolve the model before the engine boundary. `auto` is a UI sentinel, not
6284
+ * a model to forward to the gateway, so it gives way to an AN org/user
6285
+ * default, then the configured global engine default.
6286
+ */
6287
+ export function resolveAgentModelSelection(options) {
6288
+ if (isConcreteModelSelection(options.requestModel)) {
6289
+ return { model: options.requestModel, source: "request" };
6290
+ }
6291
+ if (isConcreteModelSelection(options.configuredModel)) {
6292
+ return { model: options.configuredModel, source: "configured" };
6293
+ }
6294
+ if (isConcreteModelSelection(options.storedModel)) {
6295
+ return { model: options.storedModel, source: "stored" };
6296
+ }
6297
+ return { model: options.defaultModel, source: "default" };
6298
+ }
6278
6299
  export function createProductionAgentHandler(options) {
6279
6300
  if (options.resolveActionSurface) {
6280
6301
  assertRequestActionSurfaceIsolation();
@@ -6644,21 +6665,23 @@ export function createProductionAgentHandler(options) {
6644
6665
  // DIAGNOSTIC-ONLY: bracket stored-model resolution (getStoredModelForEngine
6645
6666
  // settings read).
6646
6667
  workerStep("model_start");
6647
- const storedModel = requestModel == null && configuredModel == null
6668
+ const requestModelIsExplicit = isConcreteModelSelection(requestModel);
6669
+ const configuredModelIsExplicit = isConcreteModelSelection(configuredModel);
6670
+ const storedModel = !requestModelIsExplicit && !configuredModelIsExplicit
6648
6671
  ? await getStoredModelForEngine(engine, { appId: options.appId })
6649
6672
  : undefined;
6650
- const modelCandidate = requestModel ?? configuredModel ?? storedModel ?? engine.defaultModel;
6673
+ const modelSelection = resolveAgentModelSelection({
6674
+ requestModel,
6675
+ configuredModel,
6676
+ storedModel,
6677
+ defaultModel: engine.defaultModel,
6678
+ });
6679
+ const modelCandidate = modelSelection.model;
6651
6680
  // DIAGNOSTIC-ONLY: stored-model resolution finished.
6652
6681
  workerStep("model_done");
6653
6682
  const model = normalizeModelForEngine(engine, modelCandidate);
6654
6683
  let effectiveModel = model;
6655
- let modelSelectionSource = requestModel != null
6656
- ? "request"
6657
- : configuredModel != null
6658
- ? "configured"
6659
- : storedModel != null
6660
- ? "stored"
6661
- : "default";
6684
+ let modelSelectionSource = modelSelection.source;
6662
6685
  let experimentAssignments = [];
6663
6686
  // Database-backed experiments remain available to app operators.
6664
6687
  try {
@@ -40,6 +40,8 @@ export declare const appConfigSchema: z.ZodObject<{
40
40
  publicUploadFallback: z.ZodDefault<z.ZodBoolean>;
41
41
  }, z.core.$strip>>;
42
42
  workspace: z.ZodPrefault<z.ZodObject<{
43
+ isWorkspace: z.ZodOptional<z.ZodBoolean>;
44
+ appsJson: z.ZodOptional<z.ZodString>;
43
45
  gatewayUrl: z.ZodOptional<z.ZodString>;
44
46
  oauthOrigin: z.ZodOptional<z.ZodString>;
45
47
  }, z.core.$strip>>;
@@ -16,6 +16,8 @@ import { z } from "zod";
16
16
  * in the process down with it.
17
17
  */
18
18
  export declare const workspaceConfig: z.ZodObject<{
19
+ isWorkspace: z.ZodOptional<z.ZodBoolean>;
20
+ appsJson: z.ZodOptional<z.ZodString>;
19
21
  gatewayUrl: z.ZodOptional<z.ZodString>;
20
22
  oauthOrigin: z.ZodOptional<z.ZodString>;
21
23
  }, z.core.$strip>;
@@ -16,6 +16,24 @@ import { z } from "zod";
16
16
  * in the process down with it.
17
17
  */
18
18
  export const workspaceConfig = z.object({
19
+ isWorkspace: z
20
+ .boolean()
21
+ .optional()
22
+ .meta({
23
+ env: ["AGENT_NATIVE_WORKSPACE", "VITE_AGENT_NATIVE_WORKSPACE"],
24
+ doc: "Whether this app is mounted inside a shared workspace gateway.",
25
+ }),
26
+ appsJson: z
27
+ .string()
28
+ .min(1)
29
+ .optional()
30
+ .meta({
31
+ env: [
32
+ "AGENT_NATIVE_WORKSPACE_APPS_JSON",
33
+ "VITE_AGENT_NATIVE_WORKSPACE_APPS_JSON",
34
+ ],
35
+ doc: "Serialized workspace app manifest used by mounted app runtimes.",
36
+ }),
19
37
  gatewayUrl: z
20
38
  .string()
21
39
  .min(1)
package/dist/catalog.json CHANGED
@@ -7,28 +7,28 @@
7
7
  "@radix-ui/react-popover": "^1.1.19",
8
8
  "@radix-ui/react-select": "^2.3.3",
9
9
  "@radix-ui/react-tooltip": "^1.2.12",
10
- "@tiptap/core": "3.28.0",
11
- "@tiptap/extension-blockquote": "3.28.0",
12
- "@tiptap/extension-bubble-menu": "3.28.0",
13
- "@tiptap/extension-code-block-lowlight": "3.28.0",
14
- "@tiptap/extension-collaboration": "3.28.0",
15
- "@tiptap/extension-collaboration-caret": "3.28.0",
16
- "@tiptap/extension-color": "3.28.0",
17
- "@tiptap/extension-horizontal-rule": "3.28.0",
18
- "@tiptap/extension-image": "3.28.0",
19
- "@tiptap/extension-link": "3.28.0",
20
- "@tiptap/extension-list": "3.28.0",
21
- "@tiptap/extension-placeholder": "3.28.0",
22
- "@tiptap/extension-table": "3.28.0",
23
- "@tiptap/extension-table-cell": "3.28.0",
24
- "@tiptap/extension-table-header": "3.28.0",
25
- "@tiptap/extension-table-row": "3.28.0",
26
- "@tiptap/extension-task-item": "3.28.0",
27
- "@tiptap/extension-task-list": "3.28.0",
28
- "@tiptap/extension-text-style": "3.28.0",
29
- "@tiptap/pm": "3.28.0",
30
- "@tiptap/react": "3.28.0",
31
- "@tiptap/starter-kit": "3.28.0",
10
+ "@tiptap/core": "3.30.1",
11
+ "@tiptap/extension-blockquote": "3.30.1",
12
+ "@tiptap/extension-bubble-menu": "3.30.1",
13
+ "@tiptap/extension-code-block-lowlight": "3.30.1",
14
+ "@tiptap/extension-collaboration": "3.30.1",
15
+ "@tiptap/extension-collaboration-caret": "3.30.1",
16
+ "@tiptap/extension-color": "3.30.1",
17
+ "@tiptap/extension-horizontal-rule": "3.30.1",
18
+ "@tiptap/extension-image": "3.30.1",
19
+ "@tiptap/extension-link": "3.30.1",
20
+ "@tiptap/extension-list": "3.30.1",
21
+ "@tiptap/extension-placeholder": "3.30.1",
22
+ "@tiptap/extension-table": "3.30.1",
23
+ "@tiptap/extension-table-cell": "3.30.1",
24
+ "@tiptap/extension-table-header": "3.30.1",
25
+ "@tiptap/extension-table-row": "3.30.1",
26
+ "@tiptap/extension-task-item": "3.30.1",
27
+ "@tiptap/extension-task-list": "3.30.1",
28
+ "@tiptap/extension-text-style": "3.30.1",
29
+ "@tiptap/pm": "3.30.1",
30
+ "@tiptap/react": "3.30.1",
31
+ "@tiptap/starter-kit": "3.30.1",
32
32
  "@tiptap/y-tiptap": "3.0.7",
33
33
  "@tabler/icons-react": "^3.41.1",
34
34
  "@tailwindcss/vite": "^4.2.4",
@@ -56,5 +56,5 @@
56
56
  "vite": "8.1.0",
57
57
  "vitest": "^4.1.5",
58
58
  "y-protocols": "^1.0.7",
59
- "yjs": "^13.6.31"
59
+ "yjs": "^13.6.32"
60
60
  }
@@ -18,6 +18,7 @@ declare global {
18
18
  appUrl?: string;
19
19
  workspaceGatewayUrl?: string;
20
20
  workspaceOAuthOrigin?: string;
21
+ workspaceRuntime?: boolean;
21
22
  sentryDsn?: string;
22
23
  sentryEnvironment?: string;
23
24
  /**
@@ -1,3 +1,4 @@
1
+ import { isTruthyRuntimeValue } from "../shared/runtime-config.js";
1
2
  import { initializeAgentNativeClient } from "./client-bootstrap.js";
2
3
  const FRAMEWORK_ROUTE_PREFIX = "/_agent-native";
3
4
  function normalizeBasePath(value) {
@@ -34,8 +35,11 @@ function pathMatchesBasePath(pathname, basePath) {
34
35
  }
35
36
  function isWorkspaceRuntime() {
36
37
  const env = clientEnv();
37
- return (env?.VITE_AGENT_NATIVE_WORKSPACE === "1" ||
38
- env?.AGENT_NATIVE_WORKSPACE === "1" ||
38
+ const projected = typeof window !== "undefined" &&
39
+ window.__AGENT_NATIVE_CONFIG__?.workspaceRuntime === true;
40
+ return (projected ||
41
+ isTruthyRuntimeValue(env?.VITE_AGENT_NATIVE_WORKSPACE) ||
42
+ isTruthyRuntimeValue(env?.AGENT_NATIVE_WORKSPACE) ||
39
43
  typeof env?.VITE_AGENT_NATIVE_WORKSPACE_APPS_JSON === "string");
40
44
  }
41
45
  function workspacePathBasePath() {
@@ -78,7 +82,7 @@ export function appBasePath() {
78
82
  const configured = configuredBasePath();
79
83
  const derived = pathDerivedBasePath();
80
84
  if (!configured)
81
- return derived;
85
+ return derived || workspacePathBasePath();
82
86
  if (typeof window === "undefined")
83
87
  return configured;
84
88
  const pathname = window.location.pathname;
@@ -1,3 +1,4 @@
1
+ import { isTruthyRuntimeValue } from "../shared/runtime-config.js";
1
2
  import { agentNativePath } from "./api-path.js";
2
3
  /**
3
4
  * Frame Communication (browser)
@@ -174,8 +175,7 @@ export function getCallbackOrigin() {
174
175
  return typeof window !== "undefined" ? window.location.origin : "";
175
176
  }
176
177
  function envFlag(name) {
177
- const value = runtimeEnvValue(name);
178
- return value === "1" || value === "true" || value === true;
178
+ return isTruthyRuntimeValue(runtimeEnvValue(name));
179
179
  }
180
180
  function runtimeEnvValue(name) {
181
181
  const importMetaEnv = import.meta.env;
@@ -193,9 +193,21 @@ function workspaceOAuthOrigin() {
193
193
  // guaranteed — which is why the chain lists both and why it is not the
194
194
  // primary path any more.
195
195
  const shell = typeof window !== "undefined" ? window.__AGENT_NATIVE_CONFIG__ : undefined;
196
- const raw = shell?.workspaceOAuthOrigin ||
197
- shell?.appUrl ||
198
- shell?.workspaceGatewayUrl ||
196
+ const projectedRaw = shell?.workspaceOAuthOrigin || shell?.appUrl || shell?.workspaceGatewayUrl;
197
+ if (shell?.workspaceRuntime === true) {
198
+ if (typeof projectedRaw === "string" && projectedRaw.trim()) {
199
+ try {
200
+ return new URL(projectedRaw).origin;
201
+ }
202
+ catch {
203
+ // coercion-ok: a stale projected origin intentionally falls back below.
204
+ // Fall through to the current origin when the projected value is stale.
205
+ }
206
+ }
207
+ const currentOrigin = getCallbackOrigin();
208
+ return currentOrigin || null;
209
+ }
210
+ const raw = projectedRaw ||
199
211
  runtimeEnvValue("VITE_WORKSPACE_OAUTH_ORIGIN") ||
200
212
  runtimeEnvValue("WORKSPACE_OAUTH_ORIGIN") ||
201
213
  runtimeEnvValue("VITE_APP_URL") ||
@@ -214,7 +226,9 @@ function workspaceOAuthOrigin() {
214
226
  }
215
227
  }
216
228
  function shouldUseWorkspaceCallbackRelay(path) {
217
- return (envFlag("VITE_AGENT_NATIVE_WORKSPACE") &&
229
+ const projectedWorkspaceRuntime = typeof window !== "undefined" &&
230
+ window.__AGENT_NATIVE_CONFIG__?.workspaceRuntime === true;
231
+ return ((projectedWorkspaceRuntime || envFlag("VITE_AGENT_NATIVE_WORKSPACE")) &&
218
232
  path.startsWith("/_agent-native/") &&
219
233
  (path.endsWith("/callback") || path.includes("/callback/")));
220
234
  }
@@ -1,5 +1,6 @@
1
1
  import { useEffect, useMemo, useState } from "react";
2
2
  import { coreTemplates, getTemplate } from "../../cli/templates-meta.js";
3
+ import { isTruthyRuntimeValue } from "../../shared/runtime-config.js";
3
4
  const DISPATCH_ID = "dispatch";
4
5
  export const ORG_SWITCHER_MAX_APP_LINKS = 9;
5
6
  function runtimeEnv() {
@@ -9,6 +10,13 @@ function envString(env, key) {
9
10
  const value = env[key];
10
11
  return typeof value === "string" && value.trim() ? value.trim() : undefined;
11
12
  }
13
+ function envFlag(env, key) {
14
+ return isTruthyRuntimeValue(env[key]);
15
+ }
16
+ function projectedWorkspaceRuntime() {
17
+ return (typeof window !== "undefined" &&
18
+ window.__AGENT_NATIVE_CONFIG__?.workspaceRuntime === true);
19
+ }
12
20
  function titleCase(value) {
13
21
  return value
14
22
  .split(/[-_\s]+/)
@@ -170,7 +178,8 @@ export function defaultOrgAppLinks() {
170
178
  })));
171
179
  }
172
180
  export function isWorkspaceAppEnvironment(env = runtimeEnv()) {
173
- return (envString(env, "VITE_AGENT_NATIVE_WORKSPACE") === "1" ||
181
+ return (envFlag(env, "VITE_AGENT_NATIVE_WORKSPACE") ||
182
+ projectedWorkspaceRuntime() ||
174
183
  Boolean(envString(env, "VITE_WORKSPACE_GATEWAY_URL")) ||
175
184
  Boolean(envString(env, "VITE_AGENT_NATIVE_WORKSPACE_APPS_JSON")));
176
185
  }
@@ -62,11 +62,11 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
62
62
  error: string;
63
63
  states?: undefined;
64
64
  } | {
65
- error?: undefined;
66
65
  states: {
67
66
  clientId: number;
68
67
  state: string;
69
68
  }[];
69
+ error?: undefined;
70
70
  }>>;
71
71
  /**
72
72
  * GET /_agent-native/collab/:docId/users
@@ -77,9 +77,9 @@ export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("
77
77
  error: string;
78
78
  users?: undefined;
79
79
  } | {
80
- error?: undefined;
81
80
  users: {
82
81
  clientId: number;
83
82
  lastSeen: number;
84
83
  }[];
84
+ error?: undefined;
85
85
  }>>;
@@ -26,8 +26,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
26
26
  * Body: { update: string (base64), requestSource?: string }
27
27
  */
28
28
  export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
29
- ok?: undefined;
30
29
  error: string;
30
+ ok?: undefined;
31
31
  } | {
32
32
  error?: undefined;
33
33
  ok: boolean;
@@ -25,6 +25,7 @@ import { RECURRING_JOBS_SWEEP_PATH, RECURRING_JOBS_SWEEP_TOKEN_SUBJECT, } from "
25
25
  import { normalizeAppBasePath } from "../server/app-base-path.js";
26
26
  import { DEFAULT_SPECULATION_RULES_PATH, resolveSsrCacheHeaders, resolveSsrCacheKeyHeaders, } from "../shared/cache-control.js";
27
27
  import { mcpEmbedStaticAssetRouteRules } from "../shared/mcp-embed-headers.js";
28
+ import { isTruthyRuntimeValue } from "../shared/runtime-config.js";
28
29
  import { AGENT_NATIVE_SOCIAL_IMAGE_ALT, AGENT_NATIVE_SOCIAL_IMAGE_CACHE_BUSTER, AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT, AGENT_NATIVE_SOCIAL_IMAGE_PATH, AGENT_NATIVE_SOCIAL_IMAGE_TYPE, AGENT_NATIVE_SOCIAL_IMAGE_WIDTH, } from "../shared/social-meta.js";
29
30
  import { generateActionRegistryForProject } from "../vite/action-types-plugin.js";
30
31
  import { createAgentNativeConfigContext, loadResolvedAgentNativeConfig, } from "../vite/agent-native-config-loader.js";
@@ -882,6 +883,14 @@ function firstNonEmpty() {
882
883
  }
883
884
  }
884
885
 
886
+ function isTruthyRuntimeValue(value) {
887
+ if (typeof value === "boolean") return value;
888
+ if (typeof value !== "string") return false;
889
+ return ["1", "true", "yes", "on"].includes(
890
+ value.trim().toLowerCase(),
891
+ );
892
+ }
893
+
885
894
  function getSentryClientConfigScript() {
886
895
  const env = globalThis.process?.env || {};
887
896
  const key = firstNonEmpty(env.SENTRY_CLIENT_KEY, env.VITE_SENTRY_CLIENT_KEY);
@@ -993,10 +1002,21 @@ function getAppOriginClientConfigScript() {
993
1002
  env.WORKSPACE_OAUTH_ORIGIN,
994
1003
  env.VITE_WORKSPACE_OAUTH_ORIGIN,
995
1004
  );
1005
+ const workspaceRuntime = [
1006
+ env.AGENT_NATIVE_WORKSPACE,
1007
+ env.VITE_AGENT_NATIVE_WORKSPACE,
1008
+ ].some((value) => isTruthyRuntimeValue(value)) ||
1009
+ Boolean(
1010
+ firstNonEmpty(
1011
+ env.AGENT_NATIVE_WORKSPACE_APPS_JSON,
1012
+ env.VITE_AGENT_NATIVE_WORKSPACE_APPS_JSON,
1013
+ ),
1014
+ );
996
1015
  const config = {
997
1016
  ...(appUrl ? { appUrl } : {}),
998
1017
  ...(workspaceGatewayUrl ? { workspaceGatewayUrl } : {}),
999
1018
  ...(workspaceOAuthOrigin ? { workspaceOAuthOrigin } : {}),
1019
+ ...(workspaceRuntime ? { workspaceRuntime: true } : {}),
1000
1020
  };
1001
1021
  if (Object.keys(config).length === 0) return null;
1002
1022
  return (
@@ -3044,8 +3064,12 @@ function reportNetlifyFunctionSizes(internalDir, failures) {
3044
3064
  export function assertSingleTemplateNetlifyBuildOutput(projectCwd) {
3045
3065
  const failures = [];
3046
3066
  const publishDir = path.join(projectCwd, "dist");
3047
- const workspaceAppBasePath = process.env.AGENT_NATIVE_WORKSPACE === "1" ||
3048
- process.env.VITE_AGENT_NATIVE_WORKSPACE === "1"
3067
+ const workspaceAppBasePath = [
3068
+ process.env.AGENT_NATIVE_WORKSPACE,
3069
+ process.env.VITE_AGENT_NATIVE_WORKSPACE,
3070
+ ].some((value) => isTruthyRuntimeValue(value)) ||
3071
+ Boolean(process.env.AGENT_NATIVE_WORKSPACE_APPS_JSON?.trim()) ||
3072
+ Boolean(process.env.VITE_AGENT_NATIVE_WORKSPACE_APPS_JSON?.trim())
3049
3073
  ? normalizeConfiguredAppBasePath()
3050
3074
  : "";
3051
3075
  const assetsRelativeDir = workspaceAppBasePath
@@ -44,14 +44,14 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
44
44
  summary: import("./types.js").TraceSummary;
45
45
  spans: import("./types.js").TraceSpan[];
46
46
  id?: undefined;
47
- ok?: undefined;
48
47
  error?: undefined;
48
+ ok?: undefined;
49
49
  } | {
50
50
  summary?: undefined;
51
51
  spans?: undefined;
52
52
  id: string;
53
- ok?: undefined;
54
53
  error?: undefined;
54
+ ok?: undefined;
55
55
  } | {
56
56
  summary?: undefined;
57
57
  spans?: undefined;