@agent-native/core 0.85.4 → 0.85.6

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 (30) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +12 -0
  3. package/corpus/core/docs/content/tracking.mdx +1 -1
  4. package/corpus/core/package.json +1 -1
  5. package/corpus/core/src/agent/run-manager.ts +10 -0
  6. package/corpus/core/src/client/AssistantChat.tsx +74 -1
  7. package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +1 -1
  8. package/corpus/templates/design/AGENTS.md +7 -3
  9. package/corpus/templates/design/actions/edit-design.ts +5 -3
  10. package/corpus/templates/design/actions/present-design-variants.ts +10 -6
  11. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +23 -2
  12. package/corpus/templates/design/app/hooks/use-question-flow.ts +2 -2
  13. package/corpus/templates/design/app/pages/DesignEditor.tsx +2 -2
  14. package/corpus/templates/design/changelog/2026-07-02-creating-two-frames-in-a-row-no-longer-freezes-and-reloads-t.md +6 -0
  15. package/corpus/templates/design/changelog/2026-07-03-design-retries-stalled-screen-edits-with-a-smaller-safer-fol.md +6 -0
  16. package/corpus/templates/design/server/plugins/agent-chat.ts +1 -1
  17. package/dist/agent/run-manager.d.ts.map +1 -1
  18. package/dist/agent/run-manager.js +8 -0
  19. package/dist/agent/run-manager.js.map +1 -1
  20. package/dist/client/AssistantChat.d.ts.map +1 -1
  21. package/dist/client/AssistantChat.js +49 -2
  22. package/dist/client/AssistantChat.js.map +1 -1
  23. package/dist/collab/awareness.d.ts +2 -2
  24. package/dist/collab/awareness.d.ts.map +1 -1
  25. package/dist/collab/struct-routes.d.ts +1 -1
  26. package/dist/observability/routes.d.ts +3 -3
  27. package/dist/progress/routes.d.ts +1 -1
  28. package/dist/secrets/routes.d.ts +3 -3
  29. package/docs/content/tracking.mdx +1 -1
  30. 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: 2046
31
- - template files: 5039
31
+ - template files: 5041
@@ -1,5 +1,17 @@
1
1
  # @agent-native/core
2
2
 
3
+ ## 0.85.6
4
+
5
+ ### Patch Changes
6
+
7
+ - be6d307: Make stalled chat auto-continues change strategy instead of repeating oversized action inputs.
8
+
9
+ ## 0.85.5
10
+
11
+ ### Patch Changes
12
+
13
+ - bd7c040: Auto-continue active chat reconnects when action preparation stalls, and count first action-prep events as durable progress.
14
+
3
15
  ## 0.85.4
4
16
 
5
17
  ### Patch Changes
@@ -235,7 +235,7 @@ Privacy defaults are intentionally conservative but still useful for playback:
235
235
  - URLs are scrubbed with the same `scrubUrl()` helper used by browser analytics.
236
236
  - Replay capture is web-only and opt-in; it does not record native desktop screens.
237
237
 
238
- While recording, session replay also captures browser console output (`log`, `info`, `warn`, `error`, `debug`, plus window `error` / `unhandledrejection`) and network request metadata (`fetch` and XHR) as tagged rrweb custom events, so agents and the replay viewer can debug user-reported issues. Capture is on by default when replay is enabled; tune or disable it with the `sessionReplay.console` and `sessionReplay.network` options, each accepting a boolean or an options object. Request/response bodies and headers are never captured, URLs are scrubbed, messages are truncated, the recorder's own ingest/tracking traffic is excluded, and per-session budgets (1000 console / 2000 network events) add a truncation notice when exceeded.
238
+ While recording, session replay also captures browser console output (`log`, `info`, `warn`, `error`, `debug`, plus window `error` / `unhandledrejection`) and network request metadata (`fetch` and XHR) as tagged rrweb custom events, so agents and the replay viewer can debug user-reported issues. Capture is on by default when replay is enabled; tune or disable it with the `sessionReplay.console` and `sessionReplay.network` options, each accepting a boolean or an options object (`{ maxEvents?: number }`). Request/response bodies and headers are never captured, URLs are scrubbed, messages are truncated, the recorder's own ingest/tracking traffic is excluded, and per-session budgets (1000 console / 2000 network events) add a truncation notice when exceeded.
239
239
 
240
240
  The Analytics template stores replay metadata in SQL (`session_recordings`) and stores chunks through private blob refs (`session_replay_chunks`). Browsers and agents never receive provider URLs. Playback goes through scoped server routes and the default agent tools return summaries or bounded replay events, not raw chunk table access.
241
241
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.85.4",
3
+ "version": "0.85.6",
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": {
@@ -553,6 +553,16 @@ export function startRun(
553
553
  preparingActivityBytes.get(activityKey) ?? 0,
554
554
  restartHighWater,
555
555
  );
556
+ if (
557
+ !preparingActivityBytes.has(activityKey) &&
558
+ progressBytes === 0 &&
559
+ !preparingActivityRestartHighWater.has(toolKey)
560
+ ) {
561
+ preparingActivityTools.set(activityKey, toolKey);
562
+ preparingActivityBytes.set(activityKey, 0);
563
+ preparingActivityRestartHighWater.set(toolKey, 0);
564
+ return true;
565
+ }
556
566
  if (progressBytes <= previousBytes) {
557
567
  preparingActivityTools.set(activityKey, toolKey);
558
568
  preparingActivityBytes.set(
@@ -242,6 +242,9 @@ const ACTIVE_RUN_STUCK_THRESHOLD_MS = 90_000;
242
242
  const BACKGROUND_ACTIVE_RUN_STUCK_THRESHOLD_MS = 13 * 60_000;
243
243
  const ACTIVE_RUN_POLL_INTERVAL_MS = 150;
244
244
  const AUTO_RESUME_STATUS_TIMEOUT_MS = 30_000;
245
+ const MAX_RECONNECT_AUTO_RECOVERIES = 3;
246
+ const RECONNECT_NO_PROGRESS_CONTINUE_MESSAGE =
247
+ "Continue from where you stopped. Use the partial work above, verify what succeeded, and finish the original request. If the last visible step was preparing an app action and no tool result was returned, treat that action input as stalled or too large: change strategy, use a smaller bounded input, and preserve optional details as visible affordances instead of repeating the same giant action. Do not rerun the exact same failed tool input unless the failure was transient or the user explicitly asked for an exact rerun. Prefer dedicated app actions over raw database edits when they exist.";
245
248
  // How long a single activity (model call, tool prep, long tool) must stay
246
249
  // in-flight before its label is surfaced in the running indicator. Below this
247
250
  // the indicator stays a steady "Thinking" so normal fast turns don't flicker
@@ -262,6 +265,11 @@ type ActiveRunLookup = {
262
265
  serverNow?: number;
263
266
  };
264
267
 
268
+ type PendingReconnectRecovery = {
269
+ id: number;
270
+ message: string;
271
+ };
272
+
265
273
  function isReplayableTerminalRun(runInfo: ActiveRunLookup): boolean {
266
274
  const dispatchMode =
267
275
  typeof runInfo.dispatchMode === "string" ? runInfo.dispatchMode : "";
@@ -1568,6 +1576,9 @@ const AssistantChatInner = forwardRef<
1568
1576
  const reconnectTailOnlyRef = useRef(false);
1569
1577
  const reconnectCanMaterializeRef = useRef(false);
1570
1578
  const reconnectAbortRef = useRef<AbortController | null>(null);
1579
+ const reconnectAutoRecoveryCountRef = useRef(0);
1580
+ const [pendingReconnectRecovery, setPendingReconnectRecovery] =
1581
+ useState<PendingReconnectRecovery | null>(null);
1571
1582
  // Nuclear stop: user clicked stop. Clears the stop button/indicator AND
1572
1583
  // lets new submissions go through immediately — prevents the "stuck
1573
1584
  // queueing forever" state where isReconnecting or isRuntimeRunning gets
@@ -2134,6 +2145,38 @@ const AssistantChatInner = forwardRef<
2134
2145
  setReconnectFrozen(latestContent.length > 0);
2135
2146
  reconnectCanMaterializeRef.current = latestContent.length > 0;
2136
2147
  }
2148
+ const canAutoRecoverReconnect =
2149
+ reconnectTerminalReason !== "run_timeout" &&
2150
+ reconnectAutoRecoveryCountRef.current <
2151
+ MAX_RECONNECT_AUTO_RECOVERIES;
2152
+ if (canAutoRecoverReconnect) {
2153
+ reconnectAutoRecoveryCountRef.current += 1;
2154
+ setRunErrorInfo(null);
2155
+ setDismissedRunErrorKey(null);
2156
+ clearActiveRunIfMatches(threadId, runId);
2157
+ reconnectAbortRef.current = null;
2158
+ setIsReconnecting(false);
2159
+ reconnectRunIdRef.current = null;
2160
+ reconnectTailOnlyRef.current = false;
2161
+ if (afterSeq > 0) {
2162
+ reconnectCanMaterializeRef.current = false;
2163
+ }
2164
+ window.dispatchEvent(
2165
+ new CustomEvent("agent-chat:auto-continue", {
2166
+ detail: { tabId: tabId || threadId },
2167
+ }),
2168
+ );
2169
+ setPendingReconnectRecovery({
2170
+ id: Date.now(),
2171
+ message: RECONNECT_NO_PROGRESS_CONTINUE_MESSAGE,
2172
+ });
2173
+ window.dispatchEvent(
2174
+ new CustomEvent("agentNative.chatRunning", {
2175
+ detail: { isRunning: false, tabId: tabId || threadId },
2176
+ }),
2177
+ );
2178
+ return;
2179
+ }
2137
2180
  setRunErrorInfo({
2138
2181
  message:
2139
2182
  reconnectTerminalReason === "run_timeout"
@@ -2188,6 +2231,9 @@ const AssistantChatInner = forwardRef<
2188
2231
  if (loaded || afterSeq > 0 || latestContent.length === 0) {
2189
2232
  reconnectCanMaterializeRef.current = false;
2190
2233
  }
2234
+ if (loaded) {
2235
+ reconnectAutoRecoveryCountRef.current = 0;
2236
+ }
2191
2237
  window.dispatchEvent(
2192
2238
  new CustomEvent("agentNative.chatRunning", {
2193
2239
  detail: { isRunning: false, tabId: tabId || threadId },
@@ -3070,10 +3116,14 @@ const AssistantChatInner = forwardRef<
3070
3116
  recoveryAction?: AgentRecoveryAction,
3071
3117
  includeComposerContext = false,
3072
3118
  trackInRunsTray = false,
3119
+ preserveReconnectAutoRecoveryBudget = false,
3073
3120
  ) => {
3074
3121
  if (!(await ensureAgentEngineReadyForSubmit())) {
3075
3122
  return;
3076
3123
  }
3124
+ if (!preserveReconnectAutoRecoveryBudget) {
3125
+ reconnectAutoRecoveryCountRef.current = 0;
3126
+ }
3077
3127
  materializeFrozenReconnectContent();
3078
3128
  setShowContinue(false);
3079
3129
  setLoopLimitInfo(null);
@@ -3296,6 +3346,29 @@ const AssistantChatInner = forwardRef<
3296
3346
  ],
3297
3347
  );
3298
3348
 
3349
+ useEffect(() => {
3350
+ if (!pendingReconnectRecovery) return;
3351
+ const recovery = pendingReconnectRecovery;
3352
+ const timer = window.setTimeout(() => {
3353
+ setPendingReconnectRecovery((current) =>
3354
+ current?.id === recovery.id ? null : current,
3355
+ );
3356
+ addToQueue(
3357
+ recovery.message,
3358
+ undefined,
3359
+ undefined,
3360
+ undefined,
3361
+ undefined,
3362
+ "queued",
3363
+ "continue",
3364
+ false,
3365
+ false,
3366
+ true,
3367
+ );
3368
+ }, 0);
3369
+ return () => window.clearTimeout(timer);
3370
+ }, [addToQueue, pendingReconnectRecovery]);
3371
+
3299
3372
  // Expose imperative handle
3300
3373
  useImperativeHandle(
3301
3374
  ref,
@@ -3871,7 +3944,7 @@ const AssistantChatInner = forwardRef<
3871
3944
  onContinue={() => {
3872
3945
  setRunErrorInfo(null);
3873
3946
  addToQueue(
3874
- "Continue from where you stopped. Use the partial work above, verify what succeeded, and finish the original request. Do not rerun the exact same failed tool input unless the failure was transient or the user explicitly asked for an exact rerun. Prefer dedicated app actions over raw database edits when they exist.",
3947
+ RECONNECT_NO_PROGRESS_CONTINUE_MESSAGE,
3875
3948
  undefined,
3876
3949
  undefined,
3877
3950
  undefined,
@@ -46,7 +46,7 @@ agent answers about browser recordings in the Analytics template.
46
46
  custom events tagged `agent-native.console` and `agent-native.network`.
47
47
  - Capture is on by default whenever session replay is enabled. Tune or disable
48
48
  it with the `console` / `network` options on the session replay config; each
49
- accepts a boolean or an options object.
49
+ accepts a boolean or an options object (`{ maxEvents?: number }`).
50
50
  - Privacy bounds: request/response bodies and headers are never captured, URLs
51
51
  are scrubbed, messages are truncated, and recorder self-traffic (the replay
52
52
  ingest and tracking endpoints) is excluded.
@@ -246,9 +246,13 @@ patterns live in `.agents/skills/`.
246
246
  on that same `fileId` for follow-up refinement. The kept variant screen is a
247
247
  representative direction, not the final deliverable: use `mode:
248
248
  "replace-file"` to replace it with the actual requested app/product UI in the
249
- chosen visual style. Do not leave a direction board, variant brief, summary
250
- card, or prose description as the final screen. Do not repeat delete/snapshot
251
- cycles, and do not call `generate-design` after a variant pick.
249
+ chosen visual style. Keep the replacement complete but compact: prioritize
250
+ the primary workflow, and if the requested feature list is too large for one
251
+ reliable edit, represent secondary details as visible controls, states, or
252
+ affordances instead of expanding the action input. Do not leave a direction
253
+ board, variant brief, summary card, or prose description as the final screen.
254
+ Do not repeat delete/snapshot cycles, and do not call `generate-design` after
255
+ a variant pick.
252
256
  - If inline chat choice buttons are unavailable, the user can tell you the
253
257
  preferred screen name. Do not show a separate variant picker or ask them to
254
258
  paste a copyable handoff summary.
@@ -142,8 +142,10 @@ export default defineAction({
142
142
  "the snapshot with only the requested copy changed. After a variant pick " +
143
143
  "or any other selected-screen follow-up, pass the exact `fileId` from " +
144
144
  '`get-design-snapshot` and use `mode: "replace-file"` when replacing ' +
145
- "the representative placeholder with the full chosen direction. Use " +
146
- "`generate-design` instead only for brand-new files.",
145
+ "the representative placeholder with a complete but compact UI in the chosen " +
146
+ "direction; prioritize the primary workflow and render secondary details " +
147
+ "as visible controls, states, or affordances when needed. Use `generate-design` " +
148
+ "instead only for brand-new files.",
147
149
  schema: z
148
150
  .object({
149
151
  designId: z.string().describe("Design project ID"),
@@ -175,7 +177,7 @@ export default defineAction({
175
177
  .min(1)
176
178
  .optional()
177
179
  .describe(
178
- "Complete updated file content. Use only with mode=replace-file for selected variant expansion or broad copy-only changes; preserve all HTML structure, CSS, scripts, and tweaks from get-design-snapshot.",
180
+ "Complete updated file content. Use only with mode=replace-file for selected variant expansion or broad copy-only changes; preserve all HTML structure, CSS, scripts, and tweaks from get-design-snapshot. For selected variants, keep the replacement complete but compact instead of expanding secondary details into an oversized payload.",
179
181
  ),
180
182
  })
181
183
  .superRefine((value, ctx) => {
@@ -43,14 +43,18 @@ const FALLBACK_INSTRUCTIONS =
43
43
  "delete each other variant screen at most once, call get-design-snapshot with fileId for " +
44
44
  "the kept screen once, then call edit-design on that same fileId in a bounded pass. " +
45
45
  'Use mode "replace-file" to replace the representative direction screen with ' +
46
- "the actual requested product UI; do not leave a direction board, summary card, " +
47
- "or variant brief as the final result. " +
46
+ "the actual requested product UI; make the result complete but compact and " +
47
+ "prefer visible controls/affordances over exhaustive content if the request is large. " +
48
+ "Do not leave a direction board, summary card, or variant brief as the final result. " +
48
49
  "Do not call generate-design after a variant pick.";
49
50
 
50
51
  const VARIANT_PICK_SUBMIT_MESSAGE =
51
52
  "Use this design direction. Keep the selected screen, clean up each other " +
52
53
  "variant screen at most once, read only the kept screen, then update that " +
53
- "same screen in one bounded pass into the full requested app/product UI. " +
54
+ "same screen in one bounded pass into the requested app/product UI. Make it " +
55
+ "complete but compact: prioritize the primary workflow, and if the full feature " +
56
+ "list is too large for one reliable edit, render secondary details as visible " +
57
+ "controls, states, or affordances instead of expanding the action input. " +
54
58
  "The selected screen is only a representative direction; the final saved " +
55
59
  "screen must not be a direction board, variant brief, or summary card. " +
56
60
  "If a cleanup action reports a screen was " +
@@ -429,7 +433,7 @@ export default defineAction({
429
433
  "call get-design-snapshot with fileId for the kept screen before " +
430
434
  "calling edit-design on that same fileId in a bounded pass. Use " +
431
435
  '`mode: "replace-file"` when expanding the representative placeholder ' +
432
- "into the full chosen direction. Do not call generate-design after a " +
436
+ "into a complete but compact product UI in the chosen direction. Do not call generate-design after a " +
433
437
  "variant pick. Stop after the first successful edit-design save. For " +
434
438
  "complex apps, " +
435
439
  "make each variant a " +
@@ -613,7 +617,7 @@ export default defineAction({
613
617
  value:
614
618
  `Keep "${screen.label}" (${screen.filename}, file id ${screen.id}) ` +
615
619
  `from variant set ${variantSetId}. Delete each other variant screen at most once: ${otherScreens}. If delete-file says a screen is already missing, continue. ` +
616
- `Then call get-design-snapshot exactly once with designId ${designId} and fileId ${screen.id} (filename ${screen.filename}), then call edit-design with fileId ${screen.id} on that same kept file in a bounded single-file pass. Use mode "replace-file" to replace the representative direction screen with the full requested app/product UI in the chosen visual style. The final saved screen must be the actual usable UI requested by the user, not a direction board, variant brief, summary card, or description of the direction. Do not call generate-design after this variant pick, do not repeat delete/snapshot cycles, do not create index.html, and do not resend a huge payload. Stop after the first successful edit-design save.`,
620
+ `Then call get-design-snapshot exactly once with designId ${designId} and fileId ${screen.id} (filename ${screen.filename}), then call edit-design with fileId ${screen.id} on that same kept file in a bounded single-file pass. Use mode "replace-file" to replace the representative direction screen with a complete but compact requested app/product UI in the chosen visual style. Prioritize the primary workflow; if the full feature list is too large for one reliable edit, render secondary details as visible controls, states, or affordances instead of expanding the action input. The final saved screen must be the actual usable UI requested by the user, not a direction board, variant brief, summary card, or description of the direction. Do not call generate-design after this variant pick, do not repeat delete/snapshot cycles, do not create index.html, and do not resend a huge payload. Stop after the first successful edit-design save.`,
617
621
  };
618
622
  }),
619
623
  },
@@ -631,7 +635,7 @@ export default defineAction({
631
635
  embed: true,
632
636
  fallbackInstructions: FALLBACK_INSTRUCTIONS,
633
637
  nextRequiredAction:
634
- 'Wait for the user to pick a screen in chat. Then delete each unchosen variant screen with delete-file at most once, call get-design-snapshot exactly once with fileId for the chosen screen, and call edit-design with that same fileId in a bounded pass. Use mode "replace-file" to replace the representative direction screen with the full requested app/product UI in the chosen visual style. Do not leave a direction board, variant brief, or summary card as the final result. Do not repeat delete/snapshot cycles. Do not call generate-design after a variant pick. Stop after the first successful edit-design save.',
638
+ 'Wait for the user to pick a screen in chat. Then delete each unchosen variant screen with delete-file at most once, call get-design-snapshot exactly once with fileId for the chosen screen, and call edit-design with that same fileId in a bounded pass. Use mode "replace-file" to replace the representative direction screen with a complete but compact requested app/product UI in the chosen visual style. Prioritize the primary workflow and render secondary details as visible controls, states, or affordances if the full feature list is too large for one reliable edit. Do not leave a direction board, variant brief, or summary card as the final result. Do not repeat delete/snapshot cycles. Do not call generate-design after a variant pick. Stop after the first successful edit-design save.',
635
639
  };
636
640
  },
637
641
  link: ({ result }) => {
@@ -1400,14 +1400,32 @@ export function MultiScreenCanvas({
1400
1400
  onSelectionChangeRef.current = onSelectionChange;
1401
1401
  }, [onSelectionChange]);
1402
1402
 
1403
+ // Selection is dual-controlled: it is synced FROM the `selectedScreenIds`
1404
+ // prop (see the prop-sync effect below) and CHANGES are reported back to the
1405
+ // parent. Reporting a selection that merely mirrors the prop would round-trip
1406
+ // through the parent (which re-derives/filters the ids) and, when two screens
1407
+ // are created back-to-back, ping-pong the selection between them forever
1408
+ // ("Maximum update depth exceeded" → the editor appears to refresh). Track
1409
+ // the last prop-driven selection and only report genuine, local (user-driven)
1410
+ // divergences from it.
1411
+ const propSyncedSelectionRef = useRef<string[] | null>(null);
1412
+ const isEchoOfPropSelection = useCallback(
1413
+ (ids: string[]) =>
1414
+ propSyncedSelectionRef.current !== null &&
1415
+ sameIds(ids, propSyncedSelectionRef.current),
1416
+ [],
1417
+ );
1418
+
1403
1419
  useEffect(() => {
1404
1420
  selectedIdsRef.current = selectedIds;
1421
+ if (isEchoOfPropSelection(selectedIds)) return;
1405
1422
  onSelectionChangeRef.current?.(selectedIds);
1406
- }, [selectedIds]);
1423
+ }, [isEchoOfPropSelection, selectedIds]);
1407
1424
 
1408
1425
  useEffect(() => {
1426
+ if (isEchoOfPropSelection(selectedIds)) return;
1409
1427
  onScreenSelectionChange?.(selectedIds);
1410
- }, [onScreenSelectionChange, selectedIds]);
1428
+ }, [isEchoOfPropSelection, onScreenSelectionChange, selectedIds]);
1411
1429
 
1412
1430
  useEffect(() => {
1413
1431
  draftPrimitivesRef.current = draftPrimitives;
@@ -1488,6 +1506,9 @@ export function MultiScreenCanvas({
1488
1506
 
1489
1507
  useEffect(() => {
1490
1508
  if (!selectedScreenIds) return;
1509
+ // Remember the selection we're pushing in from the parent so the report
1510
+ // effects above can recognise (and not echo back) the resulting change.
1511
+ propSyncedSelectionRef.current = selectedScreenIds;
1491
1512
  updateSelectedIds(() => selectedScreenIds);
1492
1513
  }, [screens, selectedScreenIds, updateSelectedIds]);
1493
1514
 
@@ -41,7 +41,7 @@ export function useQuestionFlow(
41
41
  formattedAnswers,
42
42
  "",
43
43
  designId
44
- ? 'Now continue the design. Honor any answer about variations: if the user asked to explore options, call present-design-variants with 2-5 concise directions using label, description, accentColor, and feature bullets; omit large content HTML when needed because the action can render compact representative screens - wait for their chat pick, delete each unchosen variant screen at most once, call get-design-snapshot exactly once with fileId for the kept screen, then call edit-design exactly once on that same fileId in a bounded pass. Use mode "replace-file" when expanding the representative placeholder into the full chosen direction. Do not repeat delete/snapshot cycles. Do not call generate-design after a variant pick. Stop after the first successful edit-design save. Otherwise call generate-design with one complete, renderable index.html first. Do not ask another question unless a required decision is still genuinely missing.'
44
+ ? 'Now continue the design. Honor any answer about variations: if the user asked to explore options, call present-design-variants with 2-5 concise directions using label, description, accentColor, and feature bullets; omit large content HTML when needed because the action can render compact representative screens - wait for their chat pick, delete each unchosen variant screen at most once, call get-design-snapshot exactly once with fileId for the kept screen, then call edit-design exactly once on that same fileId in a bounded pass. Use mode "replace-file" when expanding the representative placeholder into a complete but compact product UI in the chosen direction. Prioritize the primary workflow and render secondary details as visible controls, states, or affordances if the feature list is too large for one reliable edit. Do not repeat delete/snapshot cycles. Do not call generate-design after a variant pick. Stop after the first successful edit-design save. Otherwise call generate-design with one complete, renderable index.html first. Do not ask another question unless a required decision is still genuinely missing.'
45
45
  : "Now continue the design. Honor any answer about variations: use variants only if requested; otherwise generate one polished direction.",
46
46
  ]
47
47
  .filter(Boolean)
@@ -79,7 +79,7 @@ export function useQuestionFlow(
79
79
  formattedAnswers,
80
80
  "",
81
81
  designId
82
- ? 'Now continue the design. Honor any answer about variations: if the user asked to explore options, call present-design-variants with 2-5 concise directions using label, description, accentColor, and feature bullets; omit large content HTML when needed because the action can render compact representative screens - wait for their chat pick, delete each unchosen variant screen at most once, call get-design-snapshot exactly once with fileId for the kept screen, then call edit-design exactly once on that same fileId in a bounded pass. Use mode "replace-file" when expanding the representative placeholder into the full chosen direction. Do not repeat delete/snapshot cycles. Do not call generate-design after a variant pick. Stop after the first successful edit-design save. Otherwise call generate-design with one complete, renderable index.html first. Do not ask another question unless a required decision is still genuinely missing.'
82
+ ? 'Now continue the design. Honor any answer about variations: if the user asked to explore options, call present-design-variants with 2-5 concise directions using label, description, accentColor, and feature bullets; omit large content HTML when needed because the action can render compact representative screens - wait for their chat pick, delete each unchosen variant screen at most once, call get-design-snapshot exactly once with fileId for the kept screen, then call edit-design exactly once on that same fileId in a bounded pass. Use mode "replace-file" when expanding the representative placeholder into a complete but compact product UI in the chosen direction. Prioritize the primary workflow and render secondary details as visible controls, states, or affordances if the feature list is too large for one reliable edit. Do not repeat delete/snapshot cycles. Do not call generate-design after a variant pick. Stop after the first successful edit-design save. Otherwise call generate-design with one complete, renderable index.html first. Do not ask another question unless a required decision is still genuinely missing.'
83
83
  : "Now continue the design. Honor any answer about variations: use variants only if requested; otherwise generate one polished direction.",
84
84
  ]
85
85
  .filter(Boolean)
@@ -1690,7 +1690,7 @@ function designVariantGenerationDirectives(
1690
1690
  ...designSystemGenerationDirectives(designSystemId),
1691
1691
  "The user's prompt already asks to explore multiple directions, so DO NOT call `show-design-questions` first and DO NOT call `generate-design` first.",
1692
1692
  "Call `present-design-variants` with 2-5 concise directions (3 when unspecified). Prefer label, description, accentColor, and feature bullets; omit large content HTML when needed because the action can render compact representative screens.",
1693
- 'Wait for the user\'s chat pick, delete each unchosen variant screen at most once, call `get-design-snapshot` exactly once with `fileId` for the kept screen, then call `edit-design` exactly once on that same `fileId` in a bounded pass. Use `mode: "replace-file"` when expanding the representative placeholder into the full chosen direction. Do not repeat delete/snapshot cycles. Do not call `generate-design` after a variant pick. Stop after the first successful `edit-design` save.',
1693
+ 'Wait for the user\'s chat pick, delete each unchosen variant screen at most once, call `get-design-snapshot` exactly once with `fileId` for the kept screen, then call `edit-design` exactly once on that same `fileId` in a bounded pass. Use `mode: "replace-file"` when expanding the representative placeholder into a complete but compact product UI in the chosen direction. Prioritize the primary workflow and render secondary details as visible controls, states, or affordances if the feature list is too large for one reliable edit. Do not repeat delete/snapshot cycles. Do not call `generate-design` after a variant pick. Stop after the first successful `edit-design` save.',
1694
1694
  ];
1695
1695
  }
1696
1696
 
@@ -1701,7 +1701,7 @@ function designGenerationDirectives(
1701
1701
  return [
1702
1702
  `Use the \`generate-design --designId="${designId}"\` action with exactly one complete, renderable \`index.html\` file first. The design already exists - DO NOT call create-design.`,
1703
1703
  ...designSystemGenerationDirectives(designSystemId),
1704
- 'If the user asked to explore variations, call `present-design-variants` with 2-5 concise directions. Prefer label, description, accentColor, and feature bullets; omit large content HTML when needed because the action can render compact representative screens. Wait for their chat pick, delete each unchosen variant screen at most once, call `get-design-snapshot` exactly once with `fileId` for the kept screen, then call `edit-design` exactly once on that same `fileId` in a bounded pass. Use `mode: "replace-file"` when expanding the representative placeholder into the full chosen direction. Do not repeat delete/snapshot cycles. Do not call `generate-design` after a variant pick. Stop after the first successful `edit-design` save. Otherwise generate one polished first direction.',
1704
+ 'If the user asked to explore variations, call `present-design-variants` with 2-5 concise directions. Prefer label, description, accentColor, and feature bullets; omit large content HTML when needed because the action can render compact representative screens. Wait for their chat pick, delete each unchosen variant screen at most once, call `get-design-snapshot` exactly once with `fileId` for the kept screen, then call `edit-design` exactly once on that same `fileId` in a bounded pass. Use `mode: "replace-file"` when expanding the representative placeholder into a complete but compact product UI in the chosen direction. Prioritize the primary workflow and render secondary details as visible controls, states, or affordances if the feature list is too large for one reliable edit. Do not repeat delete/snapshot cycles. Do not call `generate-design` after a variant pick. Stop after the first successful `edit-design` save. Otherwise generate one polished first direction.',
1705
1705
  "Keep the first pass bounded enough to finish quickly: one self-contained Alpine.js + Tailwind CDN HTML document, polished but concise. Add 3-6 tweaks only when they naturally fit the design.",
1706
1706
  "After generate-design succeeds, stop and summarize what was created.",
1707
1707
  ];
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-02
4
+ ---
5
+
6
+ Creating two frames in a row no longer freezes and reloads the editor
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-03
4
+ ---
5
+
6
+ Design retries stalled screen edits with a smaller, safer follow-up instead of repeating the same stuck update.
@@ -53,7 +53,7 @@ When the user asks for a new design and the current navigation view is list, set
53
53
 
54
54
  When the user asks you to refine an existing design, call view-screen if the open design is unclear, then read the live current file with get-design-snapshot before editing. For small localized changes, call edit-design with exact search/replace edits. For broad copy-only changes such as translating all visible text, call edit-design in replace-file mode with the complete updated file content from the snapshot so the HTML structure, scripts, styles, and tweaks are preserved without dozens of fragile search blocks. Do not claim the design is updated until the mutating action succeeds.
55
55
 
56
- When the user picks one direction from a set of presented variants, delete each unchosen variant screen at most once, then call get-design-snapshot exactly once for the kept screen's fileId and call edit-design on that same fileId. Use edit-design replace-file when expanding the placeholder into the full chosen direction. Do not call generate-design after a variant pick unless the user explicitly asks to create a separate new screen.
56
+ When the user picks one direction from a set of presented variants, delete each unchosen variant screen at most once, then call get-design-snapshot exactly once for the kept screen's fileId and call edit-design on that same fileId. Use edit-design replace-file when expanding the placeholder into a complete but compact product UI in the chosen direction. Prioritize the primary workflow and render secondary details as visible controls, states, or affordances if the feature list is too large for one reliable edit. Do not call generate-design after a variant pick unless the user explicitly asks to create a separate new screen.
57
57
 
58
58
  When the user asks to visually inspect or edit a running local app, use open-visual-edit. It registers the localhost bridge, creates or reuses the Design project, places URL-backed iframe screens, stores the active visual-edit context, and navigates to overview mode in one authenticated step. For follow-ups like adding a mobile viewport or another route state, reuse the current designId and connectionId and call open-visual-edit or add-localhost-screens with explicit routes/paths and viewport sizes.
59
59
 
@@ -1 +1 @@
1
- {"version":3,"file":"run-manager.d.ts","sourceRoot":"","sources":["../../src/agent/run-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run-manager.d.ts","sourceRoot":"","sources":["../../src/agent/run-manager.ts"],"names":[],"mappings":"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"}
@@ -406,6 +406,14 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
406
406
  return progressBytes > 0;
407
407
  }
408
408
  const previousBytes = Math.max(preparingActivityBytes.get(activityKey) ?? 0, restartHighWater);
409
+ if (!preparingActivityBytes.has(activityKey) &&
410
+ progressBytes === 0 &&
411
+ !preparingActivityRestartHighWater.has(toolKey)) {
412
+ preparingActivityTools.set(activityKey, toolKey);
413
+ preparingActivityBytes.set(activityKey, 0);
414
+ preparingActivityRestartHighWater.set(toolKey, 0);
415
+ return true;
416
+ }
409
417
  if (progressBytes <= previousBytes) {
410
418
  preparingActivityTools.set(activityKey, toolKey);
411
419
  preparingActivityBytes.set(activityKey, Math.max(previousBytes, progressBytes));