@agent-native/core 0.165.1 → 0.165.3

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 (68) hide show
  1. package/corpus/templates/analytics/CHANGELOG.md +37 -3
  2. package/corpus/templates/analytics/changelog/2026-08-20-staged-data-limit-recovery.md +6 -0
  3. package/corpus/templates/assets/CHANGELOG.md +36 -2
  4. package/corpus/templates/brain/CHANGELOG.md +33 -3
  5. package/corpus/templates/calendar/CHANGELOG.md +45 -2
  6. package/corpus/templates/chat/CHANGELOG.md +29 -3
  7. package/corpus/templates/clips/CHANGELOG.md +55 -2
  8. package/corpus/templates/clips/app/i18n/en-US.ts +6 -11
  9. package/corpus/templates/clips/app/root.tsx +2 -1
  10. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +3 -3
  11. package/corpus/templates/clips/app/routes/download.tsx +111 -17
  12. package/corpus/templates/clips/changelog/2026-08-20-cross-tab-recording-controls.md +6 -0
  13. package/corpus/templates/clips/changelog/2026-08-20-overlay-follow-review-fixes.md +6 -0
  14. package/corpus/templates/clips/changelog/2026-08-20-provider-key-recovery.md +6 -0
  15. package/corpus/templates/clips/chrome-extension/PERMISSIONS.md +29 -46
  16. package/corpus/templates/clips/chrome-extension/STORE_DRAFT.md +1 -1
  17. package/corpus/templates/clips/chrome-extension/public/manifest.json +9 -2
  18. package/corpus/templates/clips/chrome-extension/src/background.ts +65 -46
  19. package/corpus/templates/clips/chrome-extension/src/content-script.ts +25 -17
  20. package/corpus/templates/clips/chrome-extension/src/overlay-follow.ts +25 -0
  21. package/corpus/templates/clips/server/routes/api/clips-latest.json.get.ts +109 -46
  22. package/corpus/templates/content/CHANGELOG.md +45 -2
  23. package/corpus/templates/crm/CHANGELOG.md +28 -16
  24. package/corpus/templates/design/CHANGELOG.md +54 -2
  25. package/corpus/templates/dispatch/CHANGELOG.md +51 -2
  26. package/corpus/templates/factory/CHANGELOG.md +28 -2
  27. package/corpus/templates/forms/CHANGELOG.md +39 -3
  28. package/corpus/templates/macros/CHANGELOG.md +30 -2
  29. package/corpus/templates/mail/CHANGELOG.md +34 -3
  30. package/corpus/templates/plan/CHANGELOG.md +34 -3
  31. package/corpus/templates/slides/CHANGELOG.md +73 -2
  32. package/corpus/templates/tasks/CHANGELOG.md +35 -0
  33. package/corpus/templates/tasks/app/root.tsx +8 -1
  34. package/dist/changelog/parse.d.ts +12 -4
  35. package/dist/changelog/parse.js +61 -23
  36. package/dist/cli/changelog.js +9 -11
  37. package/dist/client/blocks/library/diagram.js +1 -1
  38. package/dist/client/chat/run-recovery.js +8 -3
  39. package/dist/collab/routes.d.ts +1 -1
  40. package/dist/deploy/workspace-deploy.js +7 -0
  41. package/dist/mcp-client/oauth-routes.d.ts +1 -0
  42. package/dist/mcp-client/oauth-routes.js +15 -2
  43. package/dist/mcp-client/remote-store.js +83 -43
  44. package/dist/notifications/routes.d.ts +3 -3
  45. package/dist/observability/routes.d.ts +5 -5
  46. package/dist/progress/routes.d.ts +1 -1
  47. package/dist/provider-api/actions/provider-api.js +16 -4
  48. package/dist/resources/handlers.d.ts +2 -2
  49. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  50. package/dist/server/google-oauth-credentials.js +14 -1
  51. package/dist/server/realtime-token.d.ts +1 -1
  52. package/dist/server/transcribe-voice.d.ts +1 -1
  53. package/dist/settings/index.d.ts +1 -1
  54. package/dist/settings/index.js +1 -1
  55. package/dist/settings/store.d.ts +7 -1
  56. package/dist/settings/store.js +25 -3
  57. package/dist/settings/user-settings.d.ts +2 -0
  58. package/dist/settings/user-settings.js +65 -2
  59. package/dist/templates/chat/CHANGELOG.md +29 -3
  60. package/docs/content/deployment.mdx +89 -14
  61. package/package.json +3 -3
  62. package/src/templates/chat/CHANGELOG.md +29 -3
  63. package/corpus/templates/.retired/issues/package.json +0 -7
  64. package/corpus/templates/.retired/meeting-notes/package.json +0 -7
  65. package/corpus/templates/.retired/recruiting/package.json +0 -7
  66. package/corpus/templates/.retired/scheduling/package.json +0 -7
  67. package/corpus/templates/.retired/voice/package.json +0 -7
  68. package/corpus/templates/voice/.agents/skills/upgrade-agent-native/SKILL.md +0 -87
@@ -3,8 +3,39 @@
3
3
  All notable user-facing changes to Agent-Native Plan are documented here. Open it any
4
4
  time from the command menu (Cmd+K → "What's new").
5
5
 
6
- ## 2026-06-23
6
+ Older updates live in [the changelog folder](./changelog/) and are included in the in-app "What's new" view.
7
7
 
8
- ### Added
8
+ ## 2026-08-19
9
9
 
10
- - See what's new right inside Agent-Native Plan — a changelog now lives in the command menu (Cmd+K).
10
+ ### Improved
11
+
12
+ - Plan prompts now guide you to connect AI before sending and offer a clear retry after setup.
13
+
14
+ ## 2026-08-12
15
+
16
+ ### Improved
17
+
18
+ - Shared plans now distinguish read-only viewers from commenters who can add review feedback without editing the plan.
19
+
20
+ ## 2026-08-11
21
+
22
+ ### Improved
23
+
24
+ - Plan sharing now identifies viewers who can add comments
25
+
26
+ ### Fixed
27
+
28
+ - Chrome no longer offers to install Plan as a desktop app.
29
+ - Plan no longer reloads when runtime state changes
30
+
31
+ ## 2026-08-10
32
+
33
+ ### Improved
34
+
35
+ - Full-page chat now uses the available width up to 1000px for more comfortable prompts and responses.
36
+
37
+ ## 2026-08-07
38
+
39
+ ### Improved
40
+
41
+ - Inline help icons now stay visually balanced with nearby text
@@ -3,8 +3,79 @@
3
3
  All notable user-facing changes to Agent-Native Slides are documented here. Open it any
4
4
  time from the command menu (Cmd+K → "What's new").
5
5
 
6
- ## 2026-06-23
6
+ Older updates live in [the changelog folder](./changelog/) and are included in the in-app "What's new" view.
7
+
8
+ ## 2026-08-18
9
+
10
+ ### Improved
11
+
12
+ - Private deck links now explain access and let viewers notify the owner
13
+
14
+ ### Fixed
15
+
16
+ - Decks now appear correctly under Mine.
17
+ - Generated slides now preserve requested speaker notes.
18
+
19
+ ## 2026-08-17
20
+
21
+ ### Improved
22
+
23
+ - Slides now keep generated layouts stable, surface both-axis overflow, and make slide and text-box editing easier to discover.
24
+
25
+ ## 2026-08-13
7
26
 
8
27
  ### Added
9
28
 
10
- - See what's new right inside Agent-Native Slides — a changelog now lives in the command menu (Cmd+K).
29
+ - Slide transitions can be set from a visible control in the slide toolbar instead of being agent-only
30
+
31
+ ### Fixed
32
+
33
+ - Clicking a slide thumbnail now focuses it, so the slide copy, paste, and delete shortcuts work after a plain click
34
+ - Duplicating or undoing the deletion of a slide now keeps its transition, animations, and image data after reload
35
+ - Opening presentation mode from the agent now starts on the requested slide instead of the first one
36
+
37
+ ## 2026-08-12
38
+
39
+ ### Added
40
+
41
+ - Duplicate a slide from the film strip with Cmd/Ctrl+C then Cmd/Ctrl+V
42
+
43
+ ### Improved
44
+
45
+ - Shared decks now distinguish read-only viewers from commenters who can add comments without editing slides.
46
+
47
+ ### Fixed
48
+
49
+ - Arrow-key navigation in the slide film strip now scrolls slides below the fold into view
50
+ - Presenting a deck now returns you to the slide you were viewing when you exit
51
+
52
+ ## 2026-08-11
53
+
54
+ ### Added
55
+
56
+ - Slides can copy and paste element styles with Cmd+Option+C/V and the context menu
57
+
58
+ ### Improved
59
+
60
+ - Agent chat now follows the current slide and selection
61
+ - Faster Slides chat deck reads
62
+ - History now opens from the deck overflow menu
63
+ - Images can be dropped directly onto slides and resized or repositioned freely
64
+ - Selected slide layers can be nudged precisely with arrow keys
65
+ - Share dialog roles now use Commenter terminology for people who can view and add comments.
66
+ - Slides chat can read one slide without loading the full deck
67
+ - Slides clearly indicate when an AI agent is editing alongside you.
68
+ - Slides support atomic code-style HTML patches without regenerating whole slides
69
+ - The style toolbar now uses the full available width
70
+
71
+ ### Fixed
72
+
73
+ - Chrome no longer offers to install Slides as a desktop app.
74
+ - Imported decks now use slide content for their title instead of a placeholder filename.
75
+ - New decks now transition directly to a full-page editor loading state
76
+ - PDF requests to restyle and preserve a source deck now import the full deck before editing
77
+ - Slide edits preserve their layout without introducing hidden duplicate elements or stale click reveals
78
+ - Slides reliably imports uploaded PDFs and presentations
79
+ - Slides shows one compact AI marker and keeps your current slide selected while new slides load as skeletons
80
+ - Text edits preserve slide layout when no changes are made
81
+ - Undo and redo now move one visible slide state at a time
@@ -0,0 +1,35 @@
1
+ # Changelog
2
+
3
+ All notable user-facing changes to this app are documented here.
4
+
5
+ Older updates live in [the changelog folder](./changelog/) and are included in the in-app "What's new" view.
6
+
7
+ ## 2026-08-11
8
+
9
+ ### Fixed
10
+
11
+ - Chrome no longer offers to install Tasks as a desktop app.
12
+
13
+ ## 2026-08-03
14
+
15
+ ### Fixed
16
+
17
+ - The Agent sidebar now opens the full Agent workspace for context, resources, connections, automations, and access.
18
+
19
+ ## 2026-07-31
20
+
21
+ ### Improved
22
+
23
+ - Clicking the Agent Native logo now toggles the app sidebar.
24
+
25
+ ## 2026-07-29
26
+
27
+ ### Improved
28
+
29
+ - Sidebar footers now keep Feedback, Search, and Collapse together, with language preferences available in Settings.
30
+
31
+ ## 2026-07-24
32
+
33
+ ### Improved
34
+
35
+ - Secondary controls and dashboard surfaces now use quieter borderless styling.
@@ -26,6 +26,8 @@ import { i18nCatalog } from "@/i18n";
26
26
  import { APP_TITLE } from "@/lib/app-config";
27
27
  import { TAB_ID } from "@/lib/tab-id";
28
28
 
29
+ import changelog from "../CHANGELOG.md?raw";
30
+
29
31
  import stylesheet from "./global.css?url";
30
32
 
31
33
  configureTracking({
@@ -135,7 +137,12 @@ function AppContent() {
135
137
  useCommandMenuShortcut(useCallback(() => setCmdkOpen(true), []));
136
138
  return (
137
139
  <>
138
- <CommandMenu open={cmdkOpen} onOpenChange={setCmdkOpen}>
140
+ <CommandMenu
141
+ open={cmdkOpen}
142
+ onOpenChange={setCmdkOpen}
143
+ changelog={changelog}
144
+ changelogKey="tasks"
145
+ >
139
146
  <CommandMenu.Group heading="Actions">
140
147
  <CommandMenu.Item onSelect={() => {}}>Search</CommandMenu.Item>
141
148
  </CommandMenu.Group>
@@ -24,7 +24,7 @@ export interface ChangelogEntry {
24
24
  /** Markdown body beneath the heading (until the next `## ` section). */
25
25
  body: string;
26
26
  }
27
- /** A not-yet-released entry authored as a `changelog/<file>.md` file. */
27
+ /** A folder-backed entry authored as a `changelog/<file>.md` file. */
28
28
  export interface PendingChangelogEntry {
29
29
  /** Category — `added`, `improved`, `fixed`, `changed`, etc. */
30
30
  type: ChangelogChangeType;
@@ -34,6 +34,8 @@ export interface PendingChangelogEntry {
34
34
  text: string;
35
35
  }
36
36
  export type ChangelogChangeType = "added" | "improved" | "fixed" | "changed" | "removed" | "security";
37
+ export declare const DEFAULT_CHANGELOG_RELEASE_LIMIT = 5;
38
+ export declare const CHANGELOG_ARCHIVE_NOTE = "Older updates live in [the changelog folder](./changelog/) and are included in the in-app \"What's new\" view.";
37
39
  /**
38
40
  * Order changes are grouped under a release heading. Anything not listed here
39
41
  * falls back to the "changed" group, then renders in insertion order.
@@ -70,9 +72,15 @@ declare const CHANGELOG_HEADER: string;
70
72
  export declare function rollupChangelog(existing: string, pending: PendingChangelogEntry[], releaseDate: string): string;
71
73
  /**
72
74
  * Render an app-facing changelog that includes both released CHANGELOG.md
73
- * sections and adjacent pending `changelog/*.md` entries. Unlike `release`,
74
- * this is pure and non-destructive, so build/dev bundles can show current
75
- * product notes without deleting the conflict-free pending files.
75
+ * sections and adjacent folder-backed `changelog/*.md` entries. This is pure
76
+ * and non-destructive, so build/dev bundles can show current product notes
77
+ * without moving or deleting the conflict-free entry files.
76
78
  */
77
79
  export declare function mergePendingChangelog(existing: string, pending: PendingChangelogEntry[]): string;
80
+ /**
81
+ * Keep a short, human-readable release window in `CHANGELOG.md` while the
82
+ * dated `changelog/*.md` files remain the complete source for app history.
83
+ * The Vite raw-import path can still expand the full folder-backed history.
84
+ */
85
+ export declare function compactChangelog(existing: string, folderEntries: PendingChangelogEntry[], releaseLimit?: number): string;
78
86
  export { CHANGELOG_HEADER, GROUP_LABELS };
@@ -11,6 +11,8 @@
11
11
  * markdown shape is the conventional "Keep a Changelog" layout — a top-level
12
12
  * `# Changelog` heading followed by one `## <release>` section per release.
13
13
  */
14
+ export const DEFAULT_CHANGELOG_RELEASE_LIMIT = 5;
15
+ export const CHANGELOG_ARCHIVE_NOTE = 'Older updates live in [the changelog folder](./changelog/) and are included in the in-app "What\'s new" view.';
14
16
  /**
15
17
  * Order changes are grouped under a release heading. Anything not listed here
16
18
  * falls back to the "changed" group, then renders in insertion order.
@@ -218,48 +220,84 @@ function pendingSectionSort(a, b) {
218
220
  return 1;
219
221
  return a.localeCompare(b);
220
222
  }
223
+ function normalizedChangelogText(value) {
224
+ return value
225
+ .replace(/^\s*-\s?/gm, "")
226
+ .replace(/\s+/g, " ")
227
+ .trim();
228
+ }
221
229
  /**
222
230
  * Render an app-facing changelog that includes both released CHANGELOG.md
223
- * sections and adjacent pending `changelog/*.md` entries. Unlike `release`,
224
- * this is pure and non-destructive, so build/dev bundles can show current
225
- * product notes without deleting the conflict-free pending files.
231
+ * sections and adjacent folder-backed `changelog/*.md` entries. This is pure
232
+ * and non-destructive, so build/dev bundles can show current product notes
233
+ * without moving or deleting the conflict-free entry files.
226
234
  */
227
235
  export function mergePendingChangelog(existing, pending) {
228
- const pendingWithText = pending.filter((entry) => entry.text.trim());
236
+ const existingEntries = parseChangelog(existing);
237
+ const pendingWithText = pending.filter((entry) => {
238
+ const text = entry.text.trim();
239
+ if (!text)
240
+ return false;
241
+ return !existingEntries.some((existingEntry) => {
242
+ if (entry.date &&
243
+ existingEntry.date &&
244
+ entry.date !== existingEntry.date) {
245
+ return false;
246
+ }
247
+ return normalizedChangelogText(existingEntry.body).includes(normalizedChangelogText(text));
248
+ });
249
+ });
229
250
  if (pendingWithText.length === 0)
230
251
  return existing || CHANGELOG_HEADER;
231
- const existingEntries = parseChangelog(existing);
232
- const usedExistingIndexes = new Set();
233
252
  const pendingByTitle = new Map();
234
253
  for (const entry of pendingWithText) {
235
254
  const title = pendingSectionTitle(entry);
236
255
  pendingByTitle.set(title, [...(pendingByTitle.get(title) ?? []), entry]);
237
256
  }
238
- const sections = [];
257
+ const sections = existingEntries.map((entry) => ({
258
+ title: entry.title,
259
+ date: entry.date,
260
+ body: entry.body,
261
+ }));
239
262
  for (const title of [...pendingByTitle.keys()].sort(pendingSectionSort)) {
240
263
  const body = renderReleaseBody(pendingByTitle.get(title) ?? []);
241
264
  if (!body)
242
265
  continue;
243
- const existingIndex = existingEntries.findIndex((entry, index) => {
244
- if (usedExistingIndexes.has(index))
245
- return false;
266
+ const existingIndex = sections.findIndex((entry) => {
246
267
  return entry.date === title || entry.title === title;
247
268
  });
248
- if (existingIndex === -1) {
249
- sections.push(`## ${title}\n\n${body}`);
269
+ if (existingIndex !== -1) {
270
+ sections[existingIndex].body = [body, sections[existingIndex].body]
271
+ .filter(Boolean)
272
+ .join("\n\n");
250
273
  continue;
251
274
  }
252
- usedExistingIndexes.add(existingIndex);
253
- const existingEntry = existingEntries[existingIndex];
254
- sections.push(`## ${existingEntry.title}\n\n${[body, existingEntry.body]
255
- .filter(Boolean)
256
- .join("\n\n")}`);
275
+ const newSection = { title, date: title.match(ISO_DATE)?.[1], body };
276
+ const insertAt = newSection.date
277
+ ? sections.findIndex((entry) => entry.date && entry.date < newSection.date)
278
+ : 0;
279
+ sections.splice(insertAt === -1 ? sections.length : insertAt, 0, newSection);
257
280
  }
258
- existingEntries.forEach((entry, index) => {
259
- if (usedExistingIndexes.has(index))
260
- return;
261
- sections.push(`## ${entry.title}\n\n${entry.body}`);
262
- });
263
- return `${changelogHeader(existing)}\n\n${sections.join("\n\n")}\n`;
281
+ return `${changelogHeader(existing)}\n\n${sections
282
+ .map((entry) => `## ${entry.title}\n\n${entry.body}`)
283
+ .join("\n\n")}\n`;
284
+ }
285
+ /**
286
+ * Keep a short, human-readable release window in `CHANGELOG.md` while the
287
+ * dated `changelog/*.md` files remain the complete source for app history.
288
+ * The Vite raw-import path can still expand the full folder-backed history.
289
+ */
290
+ export function compactChangelog(existing, folderEntries, releaseLimit = DEFAULT_CHANGELOG_RELEASE_LIMIT) {
291
+ const merged = mergePendingChangelog(existing, folderEntries);
292
+ const entries = parseChangelog(merged).slice(0, Math.max(1, releaseLimit));
293
+ const header = changelogHeader(merged)
294
+ .replace(CHANGELOG_ARCHIVE_NOTE, "")
295
+ .replace(/\n{3,}/g, "\n\n")
296
+ .trim();
297
+ const sections = entries.map((entry) => `## ${entry.title}\n\n${entry.body}`);
298
+ if (sections.length === 0) {
299
+ return `${header || CHANGELOG_HEADER.trim()}\n\n${CHANGELOG_ARCHIVE_NOTE}\n`;
300
+ }
301
+ return `${header || CHANGELOG_HEADER.trim()}\n\n${CHANGELOG_ARCHIVE_NOTE}\n\n${sections.join("\n\n")}\n`;
264
302
  }
265
303
  export { CHANGELOG_HEADER, GROUP_LABELS };
@@ -3,18 +3,19 @@
3
3
  *
4
4
  * The model mirrors changesets: instead of editing the shared CHANGELOG.md
5
5
  * directly (which conflicts when many agents work in parallel), each change
6
- * drops a small pending entry file under `changelog/`. A later `release` rolls
7
- * every pending file up into a single dated section of CHANGELOG.md.
6
+ * drops a small dated entry file under `changelog/`. A later `release`
7
+ * refreshes the recent CHANGELOG.md window while retaining those files as the
8
+ * complete history.
8
9
  *
9
10
  * agent-native changelog add "Recordings can be trimmed before sharing" --type added
10
- * agent-native changelog release # roll pending → CHANGELOG.md (today)
11
+ * agent-native changelog release # refresh recent window
11
12
  * agent-native changelog list # show pending + released
12
13
  *
13
14
  * Runs in the current app directory (process.cwd()).
14
15
  */
15
16
  import fs from "fs";
16
17
  import path from "path";
17
- import { parsePendingEntry, parseChangelog, rollupChangelog, changelogSlug, CHANGELOG_HEADER, } from "../changelog/parse.js";
18
+ import { parsePendingEntry, parseChangelog, compactChangelog, changelogSlug, CHANGELOG_HEADER, } from "../changelog/parse.js";
18
19
  import { createAgentNativeConfigContext, loadResolvedAgentNativeConfig, } from "../vite/agent-native-config-loader.js";
19
20
  const CHANGELOG_FILE = "CHANGELOG.md";
20
21
  const PENDING_DIR = "changelog";
@@ -61,7 +62,7 @@ function printUsage() {
61
62
  " agent-native changelog list",
62
63
  "",
63
64
  "Entries are user-facing notes. `add` writes a pending file under",
64
- ` ${PENDING_DIR}/; \`release\` rolls all pending files into ${CHANGELOG_FILE}.`,
65
+ ` ${PENDING_DIR}/; \`release\` refreshes the recent window in ${CHANGELOG_FILE}.`,
65
66
  "Generation requires changelog.enabled: true in agent-native.config.ts.",
66
67
  ].join("\n"));
67
68
  }
@@ -126,17 +127,14 @@ async function cmdRelease(args) {
126
127
  console.log("No pending changelog entries to release.");
127
128
  return 0;
128
129
  }
129
- const pending = pendingFiles.map((p) => parsePendingEntry(p.content));
130
+ const pending = pendingFiles.map((p) => parsePendingEntry(p.content, path.basename(p.file).match(/^(\d{4}-\d{2}-\d{2})(?:-|\.md$)/)?.[1]));
130
131
  const changelogPath = path.resolve(CHANGELOG_FILE);
131
132
  const existing = fs.existsSync(changelogPath)
132
133
  ? fs.readFileSync(changelogPath, "utf-8")
133
134
  : "";
134
- const next = rollupChangelog(existing, pending, date);
135
+ const next = compactChangelog(existing, pending);
135
136
  fs.writeFileSync(changelogPath, next, "utf-8");
136
- // Remove the pending entries now that they're released.
137
- for (const p of pendingFiles)
138
- fs.rmSync(p.file);
139
- console.log(`Released ${pendingFiles.length} entr${pendingFiles.length === 1 ? "y" : "ies"} into ${CHANGELOG_FILE} (## ${date}).`);
137
+ console.log(`Refreshed ${CHANGELOG_FILE} from ${pendingFiles.length} folder entr${pendingFiles.length === 1 ? "y" : "ies"} (latest release date: ${date}).`);
140
138
  return 0;
141
139
  }
142
140
  function cmdList() {
@@ -63,7 +63,7 @@ function HtmlDiagram({ data, ctx, compact, }) {
63
63
  ? scopeDesignCss(safeCss, `[data-plan-diagram-scope="${scopeId}"]`)
64
64
  : "";
65
65
  }, [data.css, scopeId]);
66
- return (_jsxs("div", { ref: ref, className: cn("plan-diagram-shell", compact && "plan-diagram-compact"), children: [_jsxs("div", { className: "plan-diagram-frame", dir: ctx.textDirection, "data-theme": isDark ? "dark" : "light", "data-style": style, "data-frame": showFrame ? "show" : "hide", "data-text-direction": ctx.textDirection, "data-plan-diagram-scope": scopeId, children: [scopedCss && _jsx("style", { children: scopedCss }), _jsx("div", { className: "plan-diagram-frame-content", dangerouslySetInnerHTML: { __html: safeHtml } })] }), _jsx(RoughOverlay, { scopeRef: ref, enabled: !designMode && style === "sketchy", drawFrame: showFrame, selector: DIAGRAM_ROUGH_SELECTOR }), data.caption && !compact && (_jsx("p", { className: "mt-3 text-sm leading-6 text-muted-foreground", children: data.caption }))] }));
66
+ return (_jsxs("div", { ref: ref, className: cn("plan-diagram-shell", compact && "plan-diagram-compact"), children: [_jsxs("div", { className: "plan-diagram-frame", dir: ctx.textDirection, "data-theme": isDark ? "dark" : "light", "data-style": style, "data-frame": showFrame ? "show" : "hide", "data-text-direction": ctx.textDirection, "data-plan-diagram-scope": scopeId, children: [scopedCss && _jsx("style", { children: scopedCss }), _jsx("div", { className: "plan-diagram-frame-content", "data-theme": isDark ? "dark" : "light", dangerouslySetInnerHTML: { __html: safeHtml } })] }), _jsx(RoughOverlay, { scopeRef: ref, enabled: !designMode && style === "sketchy", drawFrame: showFrame, selector: DIAGRAM_ROUGH_SELECTOR }), data.caption && !compact && (_jsx("p", { className: "mt-3 text-sm leading-6 text-muted-foreground", children: data.caption }))] }));
67
67
  }
68
68
  function resolveVisualFrame(frame, ctx) {
69
69
  const resolved = frame && frame !== "auto" ? frame : (ctx.visualFrame ?? "show");
@@ -213,10 +213,15 @@ export function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDism
213
213
  const shouldShowMissingProviderSetup = isMissingLlmProviderRunError(info);
214
214
  const isProviderAuthError = isProviderAuthenticationError([info.message, info.details].filter(Boolean).join("\n"), info.errorCode);
215
215
  // Blocked on something the reader goes and fixes elsewhere, then comes back
216
- // to. Without a retry the card is a dead end and its own copy ("then retry")
217
- // points at a button that isn't there.
216
+ // to. Recoverable runs and email verification keep a retry path; rejected
217
+ // provider credentials use the setup flow below so the same bad key is not
218
+ // replayed.
218
219
  const isUnblockableExternally = info.errorCode === "email_verification_required";
219
- const canRetry = canRecover || isProviderAuthError || isUnblockableExternally;
220
+ // Rejected provider keys already have a recovery path: update/connect the
221
+ // credential, then let the setup callback re-run the turn. Exposing a
222
+ // separate retry button here just replays the same rejected credential and
223
+ // turns a permanent auth failure into a loop.
224
+ const canRetry = canRecover || isUnblockableExternally;
220
225
  const builderReconnectResolved = shouldShowBuilderReconnect &&
221
226
  builderReconnect.hasFetchedStatus &&
222
227
  builderReconnect.configured;
@@ -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;
@@ -27,6 +27,7 @@ import { assertEmittedBackgroundFunctionOnDisk, isRecurringJobsDeployEnabled, }
27
27
  import { cloneServerBundleForFunction } from "./function-bundle.js";
28
28
  import { collectImmutableAssetPaths, IMMUTABLE_ASSET_CACHE_HEADERS, } from "./immutable-assets.js";
29
29
  const NETLIFY_WORKSPACE_STATIC_DIR = "_workspace_static";
30
+ const DEFAULT_HOSTED_FEEDBACK_URL = "https://forms.agent-native.com/f/agent-native-feedback/_16ewV";
30
31
  const NETLIFY_PUBLIC_ASSET_EXTENSIONS = new Set([
31
32
  "avif",
32
33
  "css",
@@ -152,6 +153,12 @@ function buildOneApp(workspaceRoot, app, preset, execFile, workspaceApps) {
152
153
  AGENT_NATIVE_WORKSPACE_APP_ID: app,
153
154
  VITE_AGENT_NATIVE_WORKSPACE: "1",
154
155
  VITE_AGENT_NATIVE_WORKSPACE_APP_ID: app,
156
+ ...(preset === "netlify"
157
+ ? {
158
+ VITE_AGENT_NATIVE_FEEDBACK_URL: process.env.VITE_AGENT_NATIVE_FEEDBACK_URL ??
159
+ DEFAULT_HOSTED_FEEDBACK_URL,
160
+ }
161
+ : {}),
155
162
  APP_BASE_PATH: `/${app}`,
156
163
  VITE_APP_BASE_PATH: `/${app}`,
157
164
  AGENT_NATIVE_WORKSPACE_APP_AUDIENCE: workspaceAppAudience,
@@ -25,6 +25,7 @@ export interface McpOAuthRoutesOptions {
25
25
  export declare function redirectWithStagedCookies(event: H3Event, location: string): Response;
26
26
  export declare function mountMcpOAuthRoutes(nitroApp: any, options: McpOAuthRoutesOptions): void;
27
27
  export declare function resolveMcpOAuthScope(serverUrl: URL, requestedScope: unknown): RemoteMcpScope | null;
28
+ export declare function stripMcpOAuthAppBasePath(path: string, basePath: string): string;
28
29
  export declare function resolveManagedMcpOAuthClient(serverUrl: URL): Promise<StoredOAuthClientInformation | undefined>;
29
30
  export declare function setMcpOAuthFlowCookie(event: H3Event, flow: McpOAuthFlow, secure: boolean): void;
30
31
  export declare function readMcpOAuthFlowCookie(event: H3Event): McpOAuthFlow | null;
@@ -5,7 +5,7 @@ import { decryptSecretValue, encryptSecretValue } from "../secrets/crypto.js";
5
5
  import { getSession, safeReturnPath } from "../server/auth.js";
6
6
  import { resolveSecret } from "../server/credential-provider.js";
7
7
  import { getH3App } from "../server/framework-request-handler.js";
8
- import { getAppUrl, resolveOAuthRedirectUri } from "../server/google-oauth.js";
8
+ import { getAppBasePath, getAppUrl, resolveOAuthRedirectUri, } from "../server/google-oauth.js";
9
9
  import { runWithRequestContext } from "../server/request-context.js";
10
10
  import { finishMcpOAuthAuthorization, startMcpOAuthAuthorization, validateMcpOAuthCallbackIssuer, } from "./oauth-client.js";
11
11
  import { addOAuthRemoteServer, listRemoteServers, normalizeServerName, replaceOAuthRemoteServer, validateRemoteUrl, } from "./remote-store.js";
@@ -206,6 +206,19 @@ export function resolveMcpOAuthScope(serverUrl, requestedScope) {
206
206
  }
207
207
  return requestedScope === "org" ? "org" : "user";
208
208
  }
209
+ export function stripMcpOAuthAppBasePath(path, basePath) {
210
+ const normalizedBase = `/${basePath.replace(/^\/+|\/+$/g, "")}`;
211
+ if (normalizedBase === "/")
212
+ return path;
213
+ const suffixStart = path.search(/[?#]/);
214
+ const pathname = suffixStart === -1 ? path : path.slice(0, suffixStart);
215
+ const suffix = suffixStart === -1 ? "" : path.slice(suffixStart);
216
+ if (pathname === normalizedBase)
217
+ return `/${suffix}`;
218
+ return pathname.startsWith(`${normalizedBase}/`)
219
+ ? `${pathname.slice(normalizedBase.length)}${suffix}`
220
+ : path;
221
+ }
209
222
  export async function resolveManagedMcpOAuthClient(serverUrl) {
210
223
  const client = MANAGED_MCP_OAUTH_CLIENTS.find((candidate) => candidate.serverOrigin === serverUrl.origin);
211
224
  if (!client)
@@ -286,7 +299,7 @@ async function handleMcpOAuthCallback(event, options) {
286
299
  await options.reconfigure();
287
300
  const returnPath = flow.returnUrl ??
288
301
  `/settings/integrations?connected=mcp-${encodeURIComponent(flow.name)}`;
289
- return redirectWithStagedCookies(event, getAppUrl(event, returnPath));
302
+ return redirectWithStagedCookies(event, getAppUrl(event, stripMcpOAuthAppBasePath(returnPath, getAppBasePath())));
290
303
  }
291
304
  catch {
292
305
  setResponseStatus(event, 400);