@agent-native/core 0.85.5 → 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.
- package/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +6 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/client/AssistantChat.tsx +1 -1
- package/corpus/templates/design/AGENTS.md +7 -3
- package/corpus/templates/design/actions/edit-design.ts +5 -3
- package/corpus/templates/design/actions/present-design-variants.ts +10 -6
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +23 -2
- package/corpus/templates/design/app/hooks/use-question-flow.ts +2 -2
- package/corpus/templates/design/app/pages/DesignEditor.tsx +2 -2
- package/corpus/templates/design/changelog/2026-07-02-creating-two-frames-in-a-row-no-longer-freezes-and-reloads-t.md +6 -0
- package/corpus/templates/design/changelog/2026-07-03-design-retries-stalled-screen-edits-with-a-smaller-safer-fol.md +6 -0
- package/corpus/templates/design/server/plugins/agent-chat.ts +1 -1
- package/dist/client/AssistantChat.js +1 -1
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/observability/routes.d.ts +5 -5
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +2 -2
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/package.json +1 -1
package/corpus/README.md
CHANGED
package/corpus/core/CHANGELOG.md
CHANGED
package/corpus/core/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.85.
|
|
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": {
|
|
@@ -244,7 +244,7 @@ const ACTIVE_RUN_POLL_INTERVAL_MS = 150;
|
|
|
244
244
|
const AUTO_RESUME_STATUS_TIMEOUT_MS = 30_000;
|
|
245
245
|
const MAX_RECONNECT_AUTO_RECOVERIES = 3;
|
|
246
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. 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.";
|
|
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.";
|
|
248
248
|
// How long a single activity (model call, tool prep, long tool) must stay
|
|
249
249
|
// in-flight before its label is surfaced in the running indicator. Below this
|
|
250
250
|
// the indicator stays a steady "Thinking" so normal fast turns don't flicker
|
|
@@ -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.
|
|
250
|
-
|
|
251
|
-
|
|
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
|
|
146
|
-
"
|
|
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;
|
|
47
|
-
"
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
];
|
|
@@ -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
|
|
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
|
|
|
@@ -71,7 +71,7 @@ const BACKGROUND_ACTIVE_RUN_STUCK_THRESHOLD_MS = 13 * 60_000;
|
|
|
71
71
|
const ACTIVE_RUN_POLL_INTERVAL_MS = 150;
|
|
72
72
|
const AUTO_RESUME_STATUS_TIMEOUT_MS = 30_000;
|
|
73
73
|
const MAX_RECONNECT_AUTO_RECOVERIES = 3;
|
|
74
|
-
const RECONNECT_NO_PROGRESS_CONTINUE_MESSAGE = "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.";
|
|
74
|
+
const RECONNECT_NO_PROGRESS_CONTINUE_MESSAGE = "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.";
|
|
75
75
|
// How long a single activity (model call, tool prep, long tool) must stay
|
|
76
76
|
// in-flight before its label is surfaced in the running indicator. Below this
|
|
77
77
|
// the indicator stays a steady "Thinking" so normal fast turns don't flicker
|