@agent-native/core 0.101.12 → 0.101.13

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 (59) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +8 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/cli/create.ts +45 -8
  5. package/corpus/core/src/client/assistant-ui-recovery.tsx +9 -3
  6. package/corpus/core/src/client/chat/message-components.tsx +25 -2
  7. package/corpus/core/src/client/chat/tool-call-display.tsx +6 -9
  8. package/corpus/core/src/mcp/server.ts +10 -1
  9. package/corpus/core/src/server/agent-chat/framework-prompts.ts +0 -3
  10. package/corpus/core/src/server/agent-chat-plugin.ts +2 -58
  11. package/corpus/core/src/server/prompts/framework-core-compact.ts +0 -1
  12. package/corpus/core/src/server/prompts/framework-core.ts +0 -30
  13. package/corpus/core/src/server/prompts/index.ts +1 -4
  14. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +0 -14
  15. package/corpus/templates/chat/changelog/2026-07-15-chat-navigation-focuses-on-chat-and-agent.md +6 -0
  16. package/dist/cli/create.d.ts.map +1 -1
  17. package/dist/cli/create.js +31 -7
  18. package/dist/cli/create.js.map +1 -1
  19. package/dist/client/assistant-ui-recovery.d.ts +2 -0
  20. package/dist/client/assistant-ui-recovery.d.ts.map +1 -1
  21. package/dist/client/assistant-ui-recovery.js +5 -2
  22. package/dist/client/assistant-ui-recovery.js.map +1 -1
  23. package/dist/client/chat/message-components.d.ts +6 -0
  24. package/dist/client/chat/message-components.d.ts.map +1 -1
  25. package/dist/client/chat/message-components.js +14 -1
  26. package/dist/client/chat/message-components.js.map +1 -1
  27. package/dist/client/chat/tool-call-display.d.ts +1 -1
  28. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  29. package/dist/client/chat/tool-call-display.js +5 -8
  30. package/dist/client/chat/tool-call-display.js.map +1 -1
  31. package/dist/collab/awareness.d.ts +2 -2
  32. package/dist/collab/awareness.d.ts.map +1 -1
  33. package/dist/collab/struct-routes.d.ts +1 -1
  34. package/dist/mcp/server.d.ts.map +1 -1
  35. package/dist/mcp/server.js +10 -1
  36. package/dist/mcp/server.js.map +1 -1
  37. package/dist/resources/handlers.d.ts +2 -2
  38. package/dist/server/agent-chat/framework-prompts.d.ts.map +1 -1
  39. package/dist/server/agent-chat/framework-prompts.js +0 -3
  40. package/dist/server/agent-chat/framework-prompts.js.map +1 -1
  41. package/dist/server/agent-chat-plugin.d.ts +0 -22
  42. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  43. package/dist/server/agent-chat-plugin.js +2 -51
  44. package/dist/server/agent-chat-plugin.js.map +1 -1
  45. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  46. package/dist/server/prompts/framework-core-compact.d.ts +0 -1
  47. package/dist/server/prompts/framework-core-compact.d.ts.map +1 -1
  48. package/dist/server/prompts/framework-core-compact.js +0 -1
  49. package/dist/server/prompts/framework-core-compact.js.map +1 -1
  50. package/dist/server/prompts/framework-core.d.ts +0 -9
  51. package/dist/server/prompts/framework-core.d.ts.map +1 -1
  52. package/dist/server/prompts/framework-core.js +0 -29
  53. package/dist/server/prompts/framework-core.js.map +1 -1
  54. package/dist/server/prompts/index.d.ts +1 -1
  55. package/dist/server/prompts/index.d.ts.map +1 -1
  56. package/dist/server/prompts/index.js +1 -1
  57. package/dist/server/prompts/index.js.map +1 -1
  58. package/dist/server/transcribe-voice.d.ts +1 -1
  59. package/package.json +1 -1
package/corpus/README.md CHANGED
@@ -28,4 +28,4 @@ rg -n "defineAction|useActionQuery" node_modules/@agent-native/core/corpus
28
28
  ## Generated Counts
29
29
 
30
30
  - core files: 2258
31
- - template files: 5674
31
+ - template files: 5675
@@ -1,5 +1,13 @@
1
1
  # @agent-native/core
2
2
 
3
+ ## 0.101.13
4
+
5
+ ### Patch Changes
6
+
7
+ - e503433: Keep CLI repository downloads asynchronous and challenge bare loopback MCP URLs for OAuth clients.
8
+ - e503433: Keep completed chat work disclosures collapsed and stable when submitting a later message.
9
+ - e503433: Remove the automatic first-session personalization questions from agent chat so new requests are handled directly.
10
+
3
11
  ## 0.101.12
4
12
 
5
13
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.101.12",
3
+ "version": "0.101.13",
4
4
  "description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -1,4 +1,4 @@
1
- import { execFileSync } from "child_process";
1
+ import { execFile, execFileSync } from "child_process";
2
2
  import fs from "fs";
3
3
  import path from "path";
4
4
  import { fileURLToPath, pathToFileURL } from "url";
@@ -1363,18 +1363,53 @@ function tarExtractArgs(
1363
1363
  return ["xzf", tarPath, "--strip-components=1", ...excludes, "-C", destDir];
1364
1364
  }
1365
1365
 
1366
- function downloadAndExtract(
1366
+ function execFileBuffer(
1367
+ command: string,
1368
+ args: string[],
1369
+ options: { maxBuffer: number },
1370
+ ): Promise<Buffer> {
1371
+ return new Promise((resolve, reject) => {
1372
+ execFile(
1373
+ command,
1374
+ args,
1375
+ { ...options, encoding: "buffer" },
1376
+ (error, stdout, stderr) => {
1377
+ if (error) {
1378
+ const detail = stderr?.toString().trim();
1379
+ if (detail) error.message = `${error.message}: ${detail}`;
1380
+ reject(error);
1381
+ return;
1382
+ }
1383
+ resolve(Buffer.isBuffer(stdout) ? stdout : Buffer.from(stdout));
1384
+ },
1385
+ );
1386
+ });
1387
+ }
1388
+
1389
+ async function downloadAndExtract(
1367
1390
  url: string,
1368
1391
  destDir: string,
1369
1392
  options: { skipAgentSymlinks?: boolean } = {},
1370
- ): void {
1393
+ ): Promise<void> {
1371
1394
  fs.mkdirSync(destDir, { recursive: true });
1372
1395
  // --fail-with-body so curl exits non-zero on HTTP 4xx/5xx instead of writing
1373
1396
  // the error body (HTML/JSON) to disk where tar then fails with the opaque
1374
1397
  // "Unrecognized archive format" message.
1375
- const tarball = execFileSync("curl", ["--fail-with-body", "-sL", url], {
1376
- maxBuffer: 100 * 1024 * 1024,
1377
- });
1398
+ // Keep this asynchronous: a synchronous curl blocks the event loop, which
1399
+ // makes the create command's spinner look frozen during the GitHub fetch.
1400
+ const tarball = await execFileBuffer(
1401
+ "curl",
1402
+ [
1403
+ "--fail-with-body",
1404
+ "--connect-timeout",
1405
+ "10",
1406
+ "--max-time",
1407
+ "120",
1408
+ "-sL",
1409
+ url,
1410
+ ],
1411
+ { maxBuffer: 100 * 1024 * 1024 },
1412
+ );
1378
1413
  const tarPath = path.join(destDir, ".download.tar.gz");
1379
1414
  fs.writeFileSync(tarPath, tarball);
1380
1415
  try {
@@ -1407,7 +1442,9 @@ async function downloadGitHubSubdir(
1407
1442
  `.agent-native-tmp-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
1408
1443
  );
1409
1444
  try {
1410
- downloadAndExtract(tarUrl, tmpDir, { skipAgentSymlinks: repo === REPO });
1445
+ await downloadAndExtract(tarUrl, tmpDir, {
1446
+ skipAgentSymlinks: repo === REPO,
1447
+ });
1411
1448
  const srcDir = path.join(tmpDir, subdir);
1412
1449
  if (!fs.existsSync(srcDir)) {
1413
1450
  throw new Error(
@@ -1435,7 +1472,7 @@ async function downloadGitHubRepo(
1435
1472
  ): Promise<void> {
1436
1473
  validateRepoName(repo);
1437
1474
  const tarUrl = `https://api.github.com/repos/${repo}/tarball/main`;
1438
- downloadAndExtract(tarUrl, targetDir);
1475
+ await downloadAndExtract(tarUrl, targetDir);
1439
1476
  }
1440
1477
 
1441
1478
  /* ─────────────────────────────────────────────────────────────────────────
@@ -38,6 +38,8 @@ export function isAssistantUiRecoverableRenderError(error: unknown): boolean {
38
38
 
39
39
  type AssistantUiStaleIndexErrorBoundaryProps = {
40
40
  resetKey: string;
41
+ /** Remount children when the recovery scope changes. */
42
+ remountOnResetKey?: boolean;
41
43
  componentName?: string;
42
44
  children: React.ReactNode;
43
45
  };
@@ -173,10 +175,13 @@ export class AssistantUiStaleIndexErrorBoundary extends React.Component<
173
175
  return null;
174
176
  }
175
177
 
178
+ const fragmentKey =
179
+ this.props.remountOnResetKey === false
180
+ ? String(this.state.retryToken)
181
+ : `${this.props.resetKey}:${this.state.retryToken}`;
182
+
176
183
  return (
177
- <React.Fragment key={`${this.props.resetKey}:${this.state.retryToken}`}>
178
- {this.props.children}
179
- </React.Fragment>
184
+ <React.Fragment key={fragmentKey}>{this.props.children}</React.Fragment>
180
185
  );
181
186
  }
182
187
  }
@@ -191,6 +196,7 @@ export function AssistantMessageListErrorBoundary({
191
196
  return (
192
197
  <AssistantUiStaleIndexErrorBoundary
193
198
  resetKey={resetKey}
199
+ remountOnResetKey={false}
194
200
  componentName="AssistantMessageList"
195
201
  >
196
202
  {children}
@@ -848,6 +848,25 @@ export function shouldShowAssistantMessageFooter({
848
848
  return !chatRunning && statusIsTerminal;
849
849
  }
850
850
 
851
+ export function shouldShowAssistantWorkSummary({
852
+ isLast,
853
+ isComplete,
854
+ hasCollapsibleWork,
855
+ hasUnresolvedTool,
856
+ }: {
857
+ isLast: boolean;
858
+ isComplete: boolean;
859
+ hasCollapsibleWork: boolean;
860
+ hasUnresolvedTool: boolean;
861
+ }): boolean {
862
+ if (!hasCollapsibleWork || hasUnresolvedTool) return false;
863
+
864
+ // Keep completed historical work wrapped while a later turn is running.
865
+ // Removing the wrapper exposes/remounts ReasoningCell and resets its
866
+ // disclosure state to the default-open value on every new submission.
867
+ return isComplete || !isLast;
868
+ }
869
+
851
870
  function ReasoningMessagePart() {
852
871
  const part = useMessagePartReasoning();
853
872
  const partRuntime = useMessagePartRuntime();
@@ -1040,8 +1059,12 @@ export function AssistantMessage() {
1040
1059
  {({ part, children }) => {
1041
1060
  switch (part.type) {
1042
1061
  case "group-work": {
1043
- const showSummary =
1044
- isComplete && !chatRunning && hasCollapsibleWork;
1062
+ const showSummary = shouldShowAssistantWorkSummary({
1063
+ isLast,
1064
+ isComplete,
1065
+ hasCollapsibleWork,
1066
+ hasUnresolvedTool,
1067
+ });
1045
1068
  if (!showSummary) return <>{children}</>;
1046
1069
  return (
1047
1070
  <WorkedForSummary
@@ -1088,20 +1088,17 @@ export function WorkedForSummary({
1088
1088
  children,
1089
1089
  }: {
1090
1090
  durationMs?: number | null;
1091
- /** When true, start open then animate closed (post-run collapse). */
1091
+ /** When true, close the summary after a run has completed. */
1092
1092
  autoCollapse?: boolean;
1093
1093
  children: React.ReactNode;
1094
1094
  }) {
1095
- const [open, setOpen] = useState(autoCollapse);
1096
- const didAutoCollapseRef = useRef(false);
1095
+ // Start closed so a remounted completed message never flashes its work
1096
+ // details open while auto-collapse settles. If the summary was already
1097
+ // open when autoCollapse changes, AnimatedCollapse still animates it shut.
1098
+ const [open, setOpen] = useState(false);
1097
1099
 
1098
1100
  useEffect(() => {
1099
- if (!autoCollapse || didAutoCollapseRef.current) return;
1100
- didAutoCollapseRef.current = true;
1101
- const frame = requestAnimationFrame(() => {
1102
- setOpen(false);
1103
- });
1104
- return () => cancelAnimationFrame(frame);
1101
+ if (autoCollapse) setOpen(false);
1105
1102
  }, [autoCollapse]);
1106
1103
 
1107
1104
  const label =
@@ -310,9 +310,18 @@ export async function handleMcpRequest(
310
310
  // must fail closed rather than trust a spoofable owner-email header that
311
311
  // `fullSurface` would otherwise escalate to the full mutating surface.
312
312
  const requestMeta = deriveRequestMeta(event);
313
+ const hasLocalOwnerHint = Boolean(ownerEmailHeader?.trim());
313
314
  const authResult = await verifyAuth(authHeader, ownerEmailHeader, {
315
+ // A bare localhost URL is still a protected MCP resource. This lets
316
+ // OAuth-native hosts (Kiro, Claude Code, etc.) receive the standard 401
317
+ // challenge and open browser approval instead of silently getting the
318
+ // sparse anonymous dev surface. The stdio proxy remains zero-config for
319
+ // local installs because it forwards an owner hint; an explicit opt-in is
320
+ // available for local diagnostics.
314
321
  allowDevOpen:
315
- isLoopbackRequest(event) && isLoopbackOrigin(requestMeta.origin),
322
+ isLoopbackRequest(event) &&
323
+ isLoopbackOrigin(requestMeta.origin) &&
324
+ (hasLocalOwnerHint || process.env.AGENT_NATIVE_MCP_DEV_OPEN === "1"),
316
325
  resourceUrl: getMcpOAuthAudiences(event),
317
326
  });
318
327
  if (!authResult.authed) {
@@ -45,9 +45,6 @@ export function buildFrameworkPrompts(
45
45
  PROD_FRAMEWORK_PROMPT_COMPACT: string;
46
46
  DEV_FRAMEWORK_PROMPT_COMPACT: string;
47
47
  } {
48
- // Note: FIRST_SESSION_PERSONALIZATION is NOT appended here — it is injected
49
- // at per-request prompt-assembly time only for new threads (no prior messages).
50
- // This prevents the ~1.5KB block from appearing on every request forever.
51
48
  const FRAMEWORK_CORE = buildFrameworkCore(examples, options);
52
49
  const FRAMEWORK_CORE_COMPACT = buildFrameworkCoreCompact(examples, options);
53
50
  const extensionToolsEnabled = options?.extensionTools !== false;
@@ -86,7 +86,6 @@ import type {
86
86
  MentionProvider,
87
87
  } from "../agent/types.js";
88
88
  import { readAppStateForCurrentTab } from "../application-state/script-helpers.js";
89
- import { appStateGet } from "../application-state/store.js";
90
89
  import {
91
90
  createThread,
92
91
  forkThread,
@@ -167,10 +166,7 @@ import {
167
166
  } from "./framework-request-handler.js";
168
167
  import { getOrigin } from "./google-oauth.js";
169
168
  import { readBody } from "./h3-helpers.js";
170
- import {
171
- FIRST_SESSION_PERSONALIZATION,
172
- getModelFamilyOverlay,
173
- } from "./prompts/index.js";
169
+ import { getModelFamilyOverlay } from "./prompts/index.js";
174
170
  import { mountRealtimeVoiceRoutes } from "./realtime-voice.js";
175
171
  import {
176
172
  runWithRequestContext,
@@ -283,41 +279,6 @@ export function buildLeanRunPolicyPrompt(
283
279
  return codeEditingSurfaceRestriction + prodCodeExecPromptNote;
284
280
  }
285
281
 
286
- /**
287
- * Returns whether `owner` has already finished (or explicitly skipped) the
288
- * First-Session Personalization flow, via the owner-scoped
289
- * `application_state` "personalization" flag the agent itself writes
290
- * (`writeAppState("personalization", { done: true })` — see
291
- * FIRST_SESSION_PERSONALIZATION in prompts/framework-core.ts).
292
- *
293
- * This used to be gated on "does this thread have prior messages", which
294
- * flips false the instant a second request comes in for the SAME thread —
295
- * making turn 2's system prompt diverge from turn 1's and invalidating the
296
- * prompt-cache prefix on every thread's second request. The flow itself
297
- * spans two turns (turn 1 asks the personalization questions and waits;
298
- * turn 2 answers them and only then writes the "done" flag), so this flag
299
- * is still false when BOTH turns' system prompts are assembled — turn 1
300
- * and turn 2 come out byte-identical. It only flips once the flow
301
- * completes, and it never flips back, so every later turn (and every
302
- * later thread the same owner creates) stays consistent from then on. As
303
- * a bonus, it also fixes a latent waste: the old gate re-included the
304
- * ~1.5KB block on turn 1 of every new thread a user ever created, even
305
- * long after they'd completed personalization once.
306
- */
307
- export async function hasCompletedFirstSessionPersonalization(
308
- owner: string,
309
- ): Promise<boolean> {
310
- try {
311
- const state = await appStateGet(owner, "personalization");
312
- return state?.done === true;
313
- } catch {
314
- // Fail open to "not done" — same default as a brand-new user (block
315
- // shown) rather than silently skipping personalization because of a
316
- // transient appstate read error.
317
- return false;
318
- }
319
- }
320
-
321
282
  /**
322
283
  * In-memory rate-limit tracker for `/generate-title`. Keyed by user email,
323
284
  * value is recent invocation timestamps within the rolling window. Stale
@@ -2650,14 +2611,6 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
2650
2611
  )
2651
2612
  ? APP_RENDERED_CHAT_NO_DIRECT_CODE_PROMPT
2652
2613
  : "";
2653
- // Personalization block: included until this owner has finished (or
2654
- // skipped) the flow — see hasCompletedFirstSessionPersonalization
2655
- // for why this is gated on the owner-scoped appstate flag rather
2656
- // than "is this a new thread" (keeps turn 1 and turn 2 identical).
2657
- const personalizationBlock =
2658
- (await hasCompletedFirstSessionPersonalization(owner))
2659
- ? ""
2660
- : FIRST_SESSION_PERSONALIZATION;
2661
2614
  // Per-model overlay: nudge GPT/Gemini engines toward our behavioral norms.
2662
2615
  const modelOverlay = resolveModelOverlay();
2663
2616
  // Stable-first ordering: base prompt / schema / extra come before
@@ -2712,13 +2665,10 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
2712
2665
  modelOverlay,
2713
2666
  runtimeContext,
2714
2667
  additionalFramework:
2715
- personalizationBlock +
2716
- codeEditingSurfaceRestriction +
2717
- prodCodeExecPromptNote,
2668
+ codeEditingSurfaceRestriction + prodCodeExecPromptNote,
2718
2669
  });
2719
2670
  return setSystemPromptOnContext(
2720
2671
  basePrompt +
2721
- personalizationBlock +
2722
2672
  resources +
2723
2673
  schemaBlock +
2724
2674
  codeEditingSurfaceRestriction +
@@ -2940,10 +2890,6 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
2940
2890
  systemPrompt: async (event: any) => {
2941
2891
  const { owner, extra } = await prepareRun(event);
2942
2892
  const runtimeContext = runtimeContextForEvent(event);
2943
- const personalizationBlock =
2944
- (await hasCompletedFirstSessionPersonalization(owner))
2945
- ? ""
2946
- : FIRST_SESSION_PERSONALIZATION;
2947
2893
  const modelOverlay = resolveModelOverlay();
2948
2894
  // Stable-first ordering: runtimeContext (day-granular) is
2949
2895
  // appended LAST so a day rollover invalidates as little of the
@@ -2989,11 +2935,9 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
2989
2935
  extra,
2990
2936
  modelOverlay,
2991
2937
  runtimeContext,
2992
- additionalFramework: personalizationBlock,
2993
2938
  });
2994
2939
  return setSystemPromptOnContext(
2995
2940
  devPrompt +
2996
- personalizationBlock +
2997
2941
  resources +
2998
2942
  schemaBlock +
2999
2943
  extra +
@@ -7,7 +7,6 @@
7
7
  * - Verbose "Extended Capabilities" section (agent uses get-framework-context)
8
8
  * - Detailed "Parallel Tool Calls" prose (replaced with one-liner)
9
9
  * - Detailed "Resources" section (agent uses resources tool)
10
- * - "First-Session Personalization" (gated externally — see buildSystemPrompt)
11
10
  */
12
11
 
13
12
  import {
@@ -141,33 +141,3 @@ Each of these has a one-line pointer here and a full doc you can pull on demand
141
141
  - **Structured memory** — persist knowledge across sessions with \`save-memory\` / \`delete-memory\`; save proactively when you learn preferences, corrections, or project context. Detailed instructions: call \`get-framework-context\` with key \`memory\`.
142
142
  `;
143
143
  }
144
-
145
- /**
146
- * Build the First-Session Personalization block.
147
- * Gated by caller: only include when the session has no prior messages
148
- * (cheapest reliable signal that personalization hasn't run yet).
149
- * Recording happens via writeAppState("personalization", { done: true })
150
- * so the block is omitted from all subsequent requests once the agent
151
- * completes the flow.
152
- */
153
- export const FIRST_SESSION_PERSONALIZATION = `
154
- ### First-Session Personalization
155
-
156
- On the user's very first interaction in this app, before answering their actual request, briefly personalize the workspace.
157
-
158
- Check the application_state key \`personalization\` via \`readAppState("personalization")\`:
159
- - If it returns null (or has no \`done: true\`), this is the first session — run the flow below.
160
- - If \`done: true\` is set, skip the flow and answer normally.
161
-
162
- **The flow (keep it to one short message, then wait for their answer before continuing):**
163
-
164
- 1. Greet briefly in one sentence.
165
- 2. Ask **two** yes/no questions inline, on separate lines:
166
- - A theme question: _"Want me to pick a color theme for your workspace? I have a few presets — say a name or just 'yes' for my pick."_ Available presets: \`warm\`, \`ocean\`, \`forest\`, \`rose\`, \`slate\` (call \`change-appearance\` with one of these; or \`default\` to clear). When the user says yes without a name, pick one preset that fits this template's tone.
167
- - A template-specific question that the template's AGENTS.md / CLAUDE.md documents (e.g. for calendar: _"Want me to color-code meetings by attendee or by category?"_; for mail: _"Want me to surface emails that look like they need a reply at the top?"_). If the template doesn't suggest a question, ask one generic preference question (e.g. _"Do you prefer a denser layout or roomy spacing?"_).
168
- 3. After they answer (or decline), call \`change-appearance\` if appropriate, do whatever the second answer implies (e.g. set a calendar visual preference), and then write \`application_state.personalization\` = \`{ "done": true }\` via \`writeAppState\` so this flow doesn't run again.
169
-
170
- If the user's first message is clearly already on-task (e.g. "what's on my calendar today?"), answer it first — but still surface ONE line at the end like _"By the way, want me to set a theme for your workspace? Try \`change-appearance warm\` or just ask."_ — then mark personalization done so the offer never repeats.
171
-
172
- Do NOT block on this flow. If the user ignores it, just proceed; never re-ask the personalization questions in later sessions.
173
- `;
@@ -3,10 +3,7 @@
3
3
  * agent-chat-plugin.ts has a single clean import.
4
4
  */
5
5
 
6
- export {
7
- buildFrameworkCore,
8
- FIRST_SESSION_PERSONALIZATION,
9
- } from "./framework-core.js";
6
+ export { buildFrameworkCore } from "./framework-core.js";
10
7
  export { buildFrameworkCoreCompact } from "./framework-core-compact.js";
11
8
  export {
12
9
  sharedRule8,
@@ -9,10 +9,8 @@ import {
9
9
  import { ExtensionsSidebarSection } from "@agent-native/core/client/extensions";
10
10
  import { OrgSwitcher } from "@agent-native/core/client/org";
11
11
  import {
12
- IconActivity,
13
12
  IconArchive,
14
13
  IconBrain,
15
- IconDatabase,
16
14
  IconDots,
17
15
  IconEdit,
18
16
  IconLayoutSidebarLeftCollapse,
@@ -48,18 +46,6 @@ const navItems = [
48
46
  href: "/",
49
47
  view: "chat",
50
48
  },
51
- {
52
- icon: IconActivity,
53
- labelKey: "navigation.observability",
54
- href: "/observability",
55
- view: "observability",
56
- },
57
- {
58
- icon: IconDatabase,
59
- labelKey: "navigation.database",
60
- href: "/database",
61
- view: "database",
62
- },
63
49
  {
64
50
  icon: IconBrain,
65
51
  labelKey: "settings.agentTitle",
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: removed
3
+ date: 2026-07-15
4
+ ---
5
+
6
+ The main navigation is now focused on Chat, Agent, and essential workspace settings.
@@ -1 +1 @@
1
- {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/cli/create.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/cli/create.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { execFileSync } from "child_process";
1
+ import { execFile, execFileSync } from "child_process";
2
2
  import fs from "fs";
3
3
  import path from "path";
4
4
  import { fileURLToPath, pathToFileURL } from "url";
@@ -1102,14 +1102,36 @@ function tarExtractArgs(tarPath, destDir, options = {}) {
1102
1102
  : [];
1103
1103
  return ["xzf", tarPath, "--strip-components=1", ...excludes, "-C", destDir];
1104
1104
  }
1105
- function downloadAndExtract(url, destDir, options = {}) {
1105
+ function execFileBuffer(command, args, options) {
1106
+ return new Promise((resolve, reject) => {
1107
+ execFile(command, args, { ...options, encoding: "buffer" }, (error, stdout, stderr) => {
1108
+ if (error) {
1109
+ const detail = stderr?.toString().trim();
1110
+ if (detail)
1111
+ error.message = `${error.message}: ${detail}`;
1112
+ reject(error);
1113
+ return;
1114
+ }
1115
+ resolve(Buffer.isBuffer(stdout) ? stdout : Buffer.from(stdout));
1116
+ });
1117
+ });
1118
+ }
1119
+ async function downloadAndExtract(url, destDir, options = {}) {
1106
1120
  fs.mkdirSync(destDir, { recursive: true });
1107
1121
  // --fail-with-body so curl exits non-zero on HTTP 4xx/5xx instead of writing
1108
1122
  // the error body (HTML/JSON) to disk where tar then fails with the opaque
1109
1123
  // "Unrecognized archive format" message.
1110
- const tarball = execFileSync("curl", ["--fail-with-body", "-sL", url], {
1111
- maxBuffer: 100 * 1024 * 1024,
1112
- });
1124
+ // Keep this asynchronous: a synchronous curl blocks the event loop, which
1125
+ // makes the create command's spinner look frozen during the GitHub fetch.
1126
+ const tarball = await execFileBuffer("curl", [
1127
+ "--fail-with-body",
1128
+ "--connect-timeout",
1129
+ "10",
1130
+ "--max-time",
1131
+ "120",
1132
+ "-sL",
1133
+ url,
1134
+ ], { maxBuffer: 100 * 1024 * 1024 });
1113
1135
  const tarPath = path.join(destDir, ".download.tar.gz");
1114
1136
  fs.writeFileSync(tarPath, tarball);
1115
1137
  try {
@@ -1132,7 +1154,9 @@ async function downloadGitHubSubdir(repo, subdir, targetDir) {
1132
1154
  const tarUrl = `https://api.github.com/repos/${repo}/tarball/${encodeURIComponent(ref)}`;
1133
1155
  const tmpDir = path.join(targetDir, "..", `.agent-native-tmp-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`);
1134
1156
  try {
1135
- downloadAndExtract(tarUrl, tmpDir, { skipAgentSymlinks: repo === REPO });
1157
+ await downloadAndExtract(tarUrl, tmpDir, {
1158
+ skipAgentSymlinks: repo === REPO,
1159
+ });
1136
1160
  const srcDir = path.join(tmpDir, subdir);
1137
1161
  if (!fs.existsSync(srcDir)) {
1138
1162
  throw new Error(`Template directory "${subdir}" not found at ref "${ref}".`);
@@ -1152,7 +1176,7 @@ async function downloadGitHubSubdir(repo, subdir, targetDir) {
1152
1176
  async function downloadGitHubRepo(repo, targetDir) {
1153
1177
  validateRepoName(repo);
1154
1178
  const tarUrl = `https://api.github.com/repos/${repo}/tarball/main`;
1155
- downloadAndExtract(tarUrl, targetDir);
1179
+ await downloadAndExtract(tarUrl, targetDir);
1156
1180
  }
1157
1181
  /* ─────────────────────────────────────────────────────────────────────────
1158
1182
  * Text / filesystem helpers