@agent-native/core 0.84.8 → 0.84.10
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 +12 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/cli/skills.ts +6 -3
- package/corpus/core/src/client/agent-chat-adapter.ts +31 -11
- package/corpus/core/src/client/sse-event-processor.ts +50 -9
- package/corpus/templates/design/actions/get-design-snapshot.ts +41 -4
- package/corpus/templates/design/actions/present-design-variants.ts +21 -6
- 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-01-improved-variant-pick-follow-ups-so-selected-directions-cont.md +6 -0
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +6 -3
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +26 -11
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts +5 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +38 -10
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/observability/routes.d.ts +2 -2
- package/package.json +1 -1
package/corpus/README.md
CHANGED
package/corpus/core/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @agent-native/core
|
|
2
2
|
|
|
3
|
+
## 0.84.10
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 720b8b0: Make agent chat recovery surface completed-tool timeouts more reliably and keep Design variant follow-ups bounded to the selected screen.
|
|
8
|
+
|
|
9
|
+
## 0.84.9
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 8cfc0ee: Show a visible warning when an agent stops after its final completed tool action, even if it sent text before that tool finished.
|
|
14
|
+
|
|
3
15
|
## 0.84.8
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/corpus/core/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.84.
|
|
3
|
+
"version": "0.84.10",
|
|
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": {
|
|
@@ -328,7 +328,8 @@ iteration, or a human-in-the-loop choice among design directions.
|
|
|
328
328
|
full app per variant. Design saves every option as a normal screen on the
|
|
329
329
|
overview board and renders an inline chat choice with one button per screen
|
|
330
330
|
name. After the user picks, delete the unchosen variant screens and continue
|
|
331
|
-
from the kept screen
|
|
331
|
+
from the kept screen by first calling \`get-design-snapshot\` with that
|
|
332
|
+
screen's \`fileId\`, then making a bounded single-file pass.
|
|
332
333
|
- If the chat choice buttons are not available in the host, ask the user to
|
|
333
334
|
tell you the screen name they prefer. The variants are already real screens
|
|
334
335
|
on the board, so do not ask them to paste HTML or copy a generated handoff
|
|
@@ -351,8 +352,10 @@ iteration, or a human-in-the-loop choice among design directions.
|
|
|
351
352
|
and realistic controls over decorative mockups.
|
|
352
353
|
5. After \`present-design-variants\`, wait for the user's pick before
|
|
353
354
|
generating the next version. Keep the chosen screen, delete the other
|
|
354
|
-
variant screens,
|
|
355
|
-
|
|
355
|
+
variant screens, call \`get-design-snapshot\` with \`fileId\` for the kept
|
|
356
|
+
screen, then continue from that single file in a bounded pass. Prefer
|
|
357
|
+
\`edit-design\`; if \`generate-design\` is needed, update only the kept file
|
|
358
|
+
compactly and stop after the first successful save.
|
|
356
359
|
|
|
357
360
|
## Design Quality Bar
|
|
358
361
|
|
|
@@ -703,7 +703,26 @@ function hasContinuationProgress(content: ContentPart[]): boolean {
|
|
|
703
703
|
);
|
|
704
704
|
}
|
|
705
705
|
|
|
706
|
-
|
|
706
|
+
const COMPLETED_TOOL_TIMEOUT_NAME_RE =
|
|
707
|
+
/^(add|apply|archive|capture|create|delete|deploy|duplicate|edit|generate|grant|insert|migrate|move|present|publish|remove|rename|reorder|revoke|save|send|set|sync|trash|update|write)(-|$)/;
|
|
708
|
+
const COMPLETED_TOOL_TIMEOUT_NAME_ALLOWLIST = new Set([
|
|
709
|
+
"connect-assets-mcp",
|
|
710
|
+
"import-design-tokens",
|
|
711
|
+
]);
|
|
712
|
+
|
|
713
|
+
function isCompletedToolTimeoutCandidate(
|
|
714
|
+
part: Extract<ContentPart, { type: "tool-call" }>,
|
|
715
|
+
): boolean {
|
|
716
|
+
if (part.completedSideEffect === false) return false;
|
|
717
|
+
if (part.completedSideEffect === true) return true;
|
|
718
|
+
const toolName = part.toolName.toLowerCase();
|
|
719
|
+
return (
|
|
720
|
+
COMPLETED_TOOL_TIMEOUT_NAME_ALLOWLIST.has(toolName) ||
|
|
721
|
+
COMPLETED_TOOL_TIMEOUT_NAME_RE.test(toolName)
|
|
722
|
+
);
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
function lastCompletedTimeoutCandidateTool(
|
|
707
726
|
content: ContentPart[],
|
|
708
727
|
): Extract<ContentPart, { type: "tool-call" }> | undefined {
|
|
709
728
|
for (let i = content.length - 1; i >= 0; i--) {
|
|
@@ -713,7 +732,7 @@ function lastCompletedSideEffectTool(
|
|
|
713
732
|
part.activity !== true &&
|
|
714
733
|
part.result !== undefined &&
|
|
715
734
|
part.isError !== true &&
|
|
716
|
-
part
|
|
735
|
+
isCompletedToolTimeoutCandidate(part)
|
|
717
736
|
) {
|
|
718
737
|
return part;
|
|
719
738
|
}
|
|
@@ -1866,7 +1885,7 @@ export function createAgentChatAdapter(
|
|
|
1866
1885
|
// before tool_start; treating it as progress caused silent retry
|
|
1867
1886
|
// loops when the LLM timed out while assembling a large tool input.
|
|
1868
1887
|
const hasInFlightTool = hasInFlightToolCall(visibleContent);
|
|
1869
|
-
const
|
|
1888
|
+
const completedTool = lastCompletedTimeoutCandidateTool(content);
|
|
1870
1889
|
// Either real output or an actively-running tool counts as progress
|
|
1871
1890
|
// for the stalled/empty caps.
|
|
1872
1891
|
const madeProgress = madeContentProgress || hasInFlightTool;
|
|
@@ -1963,22 +1982,23 @@ export function createAgentChatAdapter(
|
|
|
1963
1982
|
emptyTransientContinuationAttempts = 0;
|
|
1964
1983
|
} else {
|
|
1965
1984
|
totalTransientContinuationAttempts += 1;
|
|
1966
|
-
// If a
|
|
1967
|
-
//
|
|
1968
|
-
//
|
|
1969
|
-
//
|
|
1970
|
-
//
|
|
1971
|
-
// out" message.
|
|
1985
|
+
// If a tool already completed, do not turn a missing closing
|
|
1986
|
+
// sentence into a scary connection failure. Give the model one
|
|
1987
|
+
// continuation opportunity (the completed tool itself counts as
|
|
1988
|
+
// progress on the first timeout); if the follow-up produces no new
|
|
1989
|
+
// content, stop locally with a clear completed-tool warning.
|
|
1972
1990
|
if (
|
|
1973
|
-
|
|
1991
|
+
signal.reason === "run_timeout" &&
|
|
1992
|
+
completedTool &&
|
|
1974
1993
|
!hasInFlightToolCall(content) &&
|
|
1994
|
+
!currentPreparingToolName &&
|
|
1975
1995
|
!madeContentProgress &&
|
|
1976
1996
|
!hasInFlightTool
|
|
1977
1997
|
) {
|
|
1978
1998
|
return {
|
|
1979
1999
|
ok: false,
|
|
1980
2000
|
resetVisibleContent: false,
|
|
1981
|
-
completedToolName:
|
|
2001
|
+
completedToolName: completedTool.toolName,
|
|
1982
2002
|
};
|
|
1983
2003
|
}
|
|
1984
2004
|
// Bail when the same write tool is stuck in-flight across too many
|
|
@@ -381,15 +381,21 @@ function interruptedToolMessage(pending: {
|
|
|
381
381
|
return `The agent stopped before starting ${actionLabel}. No tool result was returned, so the requested changes were not made.`;
|
|
382
382
|
}
|
|
383
383
|
|
|
384
|
-
function
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
384
|
+
function lastAssistantTextIndex(content: ContentPart[]): number {
|
|
385
|
+
for (let i = content.length - 1; i >= 0; i--) {
|
|
386
|
+
const part = content[i];
|
|
387
|
+
if (part.type === "text" && part.text.trim().length > 0) return i;
|
|
388
|
+
}
|
|
389
|
+
return -1;
|
|
388
390
|
}
|
|
389
391
|
|
|
390
|
-
function
|
|
392
|
+
function completedToolNamesAfterLastAssistantText(
|
|
393
|
+
content: ContentPart[],
|
|
394
|
+
): string[] {
|
|
395
|
+
const lastTextIndex = lastAssistantTextIndex(content);
|
|
391
396
|
const names = new Set<string>();
|
|
392
|
-
for (
|
|
397
|
+
for (let i = lastTextIndex + 1; i < content.length; i++) {
|
|
398
|
+
const part = content[i];
|
|
393
399
|
if (
|
|
394
400
|
part.type === "tool-call" &&
|
|
395
401
|
part.activity !== true &&
|
|
@@ -408,6 +414,25 @@ function completedToolOnlyMessage(toolNames: string[]): string | null {
|
|
|
408
414
|
return `The agent completed ${label}, but stopped before sending a final message. Review the completed tool card above or ask the agent to continue.`;
|
|
409
415
|
}
|
|
410
416
|
|
|
417
|
+
interface ProcessEventState {
|
|
418
|
+
completedToolsAfterLastAssistantText: Set<string>;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
function markAssistantText(state: ProcessEventState | undefined) {
|
|
422
|
+
state?.completedToolsAfterLastAssistantText.clear();
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
function markCompletedToolAfterAssistantText(
|
|
426
|
+
state: ProcessEventState | undefined,
|
|
427
|
+
toolName: string,
|
|
428
|
+
) {
|
|
429
|
+
state?.completedToolsAfterLastAssistantText.add(toolName);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
function resetProcessEventState(state: ProcessEventState | undefined) {
|
|
433
|
+
state?.completedToolsAfterLastAssistantText.clear();
|
|
434
|
+
}
|
|
435
|
+
|
|
411
436
|
/**
|
|
412
437
|
* Process a single SSE event and update the content accumulator.
|
|
413
438
|
* Returns: "continue" to keep going, "done" to stop, or a yield-ready result.
|
|
@@ -417,6 +442,7 @@ export function processEvent(
|
|
|
417
442
|
content: ContentPart[],
|
|
418
443
|
toolCallCounter: { value: number },
|
|
419
444
|
tabId: string | undefined,
|
|
445
|
+
state?: ProcessEventState,
|
|
420
446
|
): {
|
|
421
447
|
action:
|
|
422
448
|
| "continue"
|
|
@@ -435,6 +461,7 @@ export function processEvent(
|
|
|
435
461
|
if (ev.type === "clear") {
|
|
436
462
|
// Server is retrying — discard partial text/tool output from the failed attempt
|
|
437
463
|
content.length = 0;
|
|
464
|
+
resetProcessEventState(state);
|
|
438
465
|
dispatchActivityClear(tabId);
|
|
439
466
|
return { action: "continue" };
|
|
440
467
|
}
|
|
@@ -445,6 +472,7 @@ export function processEvent(
|
|
|
445
472
|
// image" doesn't linger beside streamed text. Idempotent (clears once, then
|
|
446
473
|
// no-ops) so per-token text deltas stay cheap.
|
|
447
474
|
if (ev.text) dispatchActivityClear(tabId);
|
|
475
|
+
if (ev.text?.trim()) markAssistantText(state);
|
|
448
476
|
const lastPart = content[content.length - 1];
|
|
449
477
|
if (lastPart && lastPart.type === "text") {
|
|
450
478
|
lastPart.text += ev.text ?? "";
|
|
@@ -602,6 +630,9 @@ export function processEvent(
|
|
|
602
630
|
}
|
|
603
631
|
if (ev.mcpApp) part.mcpApp = ev.mcpApp;
|
|
604
632
|
if (ev.chatUI) part.chatUI = ev.chatUI;
|
|
633
|
+
if (part.activity !== true && part.isError !== true) {
|
|
634
|
+
markCompletedToolAfterAssistantText(state, part.toolName);
|
|
635
|
+
}
|
|
605
636
|
}
|
|
606
637
|
}
|
|
607
638
|
return {
|
|
@@ -852,9 +883,11 @@ export function processEvent(
|
|
|
852
883
|
} as ChatModelRunResult,
|
|
853
884
|
};
|
|
854
885
|
}
|
|
855
|
-
const toolOnlyMessage =
|
|
856
|
-
|
|
857
|
-
|
|
886
|
+
const toolOnlyMessage = completedToolOnlyMessage(
|
|
887
|
+
state
|
|
888
|
+
? [...state.completedToolsAfterLastAssistantText]
|
|
889
|
+
: completedToolNamesAfterLastAssistantText(content),
|
|
890
|
+
);
|
|
858
891
|
if (toolOnlyMessage) {
|
|
859
892
|
content.push({
|
|
860
893
|
type: "text",
|
|
@@ -908,6 +941,9 @@ export async function* readSSEStream(
|
|
|
908
941
|
let buf = "";
|
|
909
942
|
let lastMeaningfulEventAt = Date.now();
|
|
910
943
|
const activityTrail: ActivityTrailEntry[] = [];
|
|
944
|
+
const processEventState: ProcessEventState = {
|
|
945
|
+
completedToolsAfterLastAssistantText: new Set(),
|
|
946
|
+
};
|
|
911
947
|
|
|
912
948
|
const withStreamMetadata = (r: ChatModelRunResult): ChatModelRunResult => {
|
|
913
949
|
if (!runId && activityTrail.length === 0) return r;
|
|
@@ -999,6 +1035,7 @@ export async function* readSSEStream(
|
|
|
999
1035
|
content,
|
|
1000
1036
|
toolCallCounter,
|
|
1001
1037
|
tabId,
|
|
1038
|
+
processEventState,
|
|
1002
1039
|
);
|
|
1003
1040
|
|
|
1004
1041
|
if (result) yield withStreamMetadata(result);
|
|
@@ -1062,6 +1099,9 @@ export async function readSSEStreamRaw(
|
|
|
1062
1099
|
const decoder = new TextDecoder();
|
|
1063
1100
|
let buf = "";
|
|
1064
1101
|
let lastMeaningfulEventAt = Date.now();
|
|
1102
|
+
const processEventState: ProcessEventState = {
|
|
1103
|
+
completedToolsAfterLastAssistantText: new Set(),
|
|
1104
|
+
};
|
|
1065
1105
|
// Tracks whether the most recent content state was already pushed via
|
|
1066
1106
|
// onUpdate inside the loop, so the post-loop flush below doesn't emit the
|
|
1067
1107
|
// identical content a second time when the stream closes without a terminal
|
|
@@ -1105,6 +1145,7 @@ export async function readSSEStreamRaw(
|
|
|
1105
1145
|
content,
|
|
1106
1146
|
toolCallCounter,
|
|
1107
1147
|
tabId,
|
|
1148
|
+
processEventState,
|
|
1108
1149
|
);
|
|
1109
1150
|
|
|
1110
1151
|
if (
|
|
@@ -23,9 +23,22 @@ export default defineAction({
|
|
|
23
23
|
"edited live, otherwise the stored content), the design's tweak " +
|
|
24
24
|
"definitions, the user's applied tweak selections, and the resolved CSS " +
|
|
25
25
|
"custom-property values so the agent sees the *tuned* design, not the " +
|
|
26
|
-
"original generated tokens.
|
|
26
|
+
"original generated tokens. Pass fileId or filename when continuing from " +
|
|
27
|
+
"one selected screen so large multi-file designs stay bounded. Read-only.",
|
|
27
28
|
schema: z.object({
|
|
28
29
|
designId: z.string().describe("Design project ID to snapshot"),
|
|
30
|
+
fileId: z
|
|
31
|
+
.string()
|
|
32
|
+
.optional()
|
|
33
|
+
.describe(
|
|
34
|
+
"Optional design file ID to return. Use this after a variant pick to snapshot only the kept screen.",
|
|
35
|
+
),
|
|
36
|
+
filename: z
|
|
37
|
+
.string()
|
|
38
|
+
.optional()
|
|
39
|
+
.describe(
|
|
40
|
+
"Optional design filename to return when fileId is unavailable.",
|
|
41
|
+
),
|
|
29
42
|
}),
|
|
30
43
|
readOnly: true,
|
|
31
44
|
http: { method: "GET" },
|
|
@@ -40,7 +53,7 @@ export default defineAction({
|
|
|
40
53
|
height: 680,
|
|
41
54
|
}),
|
|
42
55
|
},
|
|
43
|
-
run: async ({ designId }) => {
|
|
56
|
+
run: async ({ designId, fileId, filename }) => {
|
|
44
57
|
const access = await resolveAccess("design", designId);
|
|
45
58
|
if (!access) {
|
|
46
59
|
const err = new Error("Design not found") as Error & {
|
|
@@ -52,6 +65,28 @@ export default defineAction({
|
|
|
52
65
|
const design = access.resource as typeof schema.designs.$inferSelect;
|
|
53
66
|
|
|
54
67
|
const snapshot = await buildDesignSnapshot(designId, design.data);
|
|
68
|
+
const requestedFileId = fileId?.trim();
|
|
69
|
+
const requestedFilename = filename?.trim();
|
|
70
|
+
const files = requestedFileId
|
|
71
|
+
? snapshot.files.filter((file) => file.id === requestedFileId)
|
|
72
|
+
: requestedFilename
|
|
73
|
+
? snapshot.files.filter((file) => file.filename === requestedFilename)
|
|
74
|
+
: snapshot.files;
|
|
75
|
+
|
|
76
|
+
if ((requestedFileId || requestedFilename) && files.length === 0) {
|
|
77
|
+
const err = new Error("Design file not found") as Error & {
|
|
78
|
+
statusCode: number;
|
|
79
|
+
};
|
|
80
|
+
err.statusCode = 404;
|
|
81
|
+
throw err;
|
|
82
|
+
}
|
|
83
|
+
if (!requestedFileId && requestedFilename && files.length > 1) {
|
|
84
|
+
const err = new Error(
|
|
85
|
+
"Multiple design files match filename; pass fileId instead",
|
|
86
|
+
) as Error & { statusCode: number };
|
|
87
|
+
err.statusCode = 409;
|
|
88
|
+
throw err;
|
|
89
|
+
}
|
|
55
90
|
|
|
56
91
|
return {
|
|
57
92
|
designId,
|
|
@@ -60,13 +95,15 @@ export default defineAction({
|
|
|
60
95
|
projectType: design.projectType,
|
|
61
96
|
designSystemId: design.designSystemId ?? null,
|
|
62
97
|
updatedAt: design.updatedAt,
|
|
63
|
-
files:
|
|
98
|
+
files: files.map((f) => ({
|
|
99
|
+
id: f.id,
|
|
64
100
|
filename: f.filename,
|
|
65
101
|
fileType: f.fileType,
|
|
66
102
|
content: f.content,
|
|
67
103
|
source: f.source,
|
|
68
104
|
})),
|
|
69
|
-
fileCount:
|
|
105
|
+
fileCount: files.length,
|
|
106
|
+
totalFileCount: snapshot.files.length,
|
|
70
107
|
tweaks: snapshot.tweaks,
|
|
71
108
|
appliedTweaks: snapshot.appliedTweaks,
|
|
72
109
|
resolvedCssVars: snapshot.resolvedCssVars,
|
|
@@ -40,7 +40,17 @@ const FALLBACK_INSTRUCTIONS =
|
|
|
40
40
|
"The generated directions have been saved as normal screens on the Design " +
|
|
41
41
|
"overview board. The chat shows one button per screen. Ask the user to pick " +
|
|
42
42
|
"a screen by name if the inline buttons are not available; after they pick, " +
|
|
43
|
-
"delete the other variant screens
|
|
43
|
+
"delete the other variant screens, call get-design-snapshot with fileId for " +
|
|
44
|
+
"the kept screen, and continue from that one file in a bounded pass.";
|
|
45
|
+
|
|
46
|
+
const VARIANT_PICK_SUBMIT_MESSAGE =
|
|
47
|
+
"Use this design direction. Delete the other variant screens, call " +
|
|
48
|
+
"get-design-snapshot with the selected option's fileId (or filename if " +
|
|
49
|
+
"needed) for the kept file, then continue from that current HTML in a " +
|
|
50
|
+
"bounded single-file pass. Prefer edit-design for refinements; if " +
|
|
51
|
+
"generate-design is needed, update only the kept file compactly. Do not " +
|
|
52
|
+
"generate a full multi-screen rewrite or resend a huge payload. Stop after " +
|
|
53
|
+
"the first successful save.";
|
|
44
54
|
|
|
45
55
|
const variantSchema = z.object({
|
|
46
56
|
id: z.string().min(1).describe("Stable variant id, e.g. 'minimal-focus'"),
|
|
@@ -410,7 +420,11 @@ export default defineAction({
|
|
|
410
420
|
"Provide 2-5 variants (3 is the sweet spot). Use this for design " +
|
|
411
421
|
"exploration before follow-up refinement. After the user's choice, keep " +
|
|
412
422
|
"the chosen screen, delete the other generated variant screens, and " +
|
|
413
|
-
"
|
|
423
|
+
"call get-design-snapshot with fileId for the kept screen before " +
|
|
424
|
+
"continuing from that single file in a bounded pass. Prefer edit-design " +
|
|
425
|
+
"for refinements; if generate-design is needed, update only the kept file " +
|
|
426
|
+
"compactly and stop after the first successful save. For complex apps, " +
|
|
427
|
+
"make each variant a " +
|
|
414
428
|
"compact representative screen; pass concise labels/descriptions/features " +
|
|
415
429
|
"and omit content when full HTML would be too large. Design will render " +
|
|
416
430
|
"compact screens from the direction data. Expand the chosen direction " +
|
|
@@ -563,9 +577,9 @@ export default defineAction({
|
|
|
563
577
|
await writeAppStateForCurrentTab("guided-questions", {
|
|
564
578
|
title: prompt ?? "Pick a direction",
|
|
565
579
|
description:
|
|
566
|
-
"All options are on the board. Choose
|
|
580
|
+
"All options are on the board. Choose one to keep; I will delete the others, read only the kept screen, and continue from that single file in a bounded pass.",
|
|
567
581
|
submitLabel: "Use selected direction",
|
|
568
|
-
submitMessage:
|
|
582
|
+
submitMessage: VARIANT_PICK_SUBMIT_MESSAGE,
|
|
569
583
|
skipLabel: "Show another set",
|
|
570
584
|
skipMessage: "None of these directions are right.",
|
|
571
585
|
questions: [
|
|
@@ -590,7 +604,8 @@ export default defineAction({
|
|
|
590
604
|
label: screen.label || optionName(index),
|
|
591
605
|
value:
|
|
592
606
|
`Keep "${screen.label}" (${screen.filename}, file id ${screen.id}) ` +
|
|
593
|
-
`from variant set ${variantSetId}. Delete the other variant screens: ${otherScreens}
|
|
607
|
+
`from variant set ${variantSetId}. Delete the other variant screens: ${otherScreens}. ` +
|
|
608
|
+
`Then call get-design-snapshot with designId ${designId} and fileId ${screen.id} (filename ${screen.filename}) and continue from that current HTML in a bounded single-file pass. Prefer edit-design for refinements; if generate-design is needed, update only this kept file compactly. Do not generate a full multi-screen rewrite or resend a huge payload. Stop after the first successful save.`,
|
|
594
609
|
};
|
|
595
610
|
}),
|
|
596
611
|
},
|
|
@@ -608,7 +623,7 @@ export default defineAction({
|
|
|
608
623
|
embed: true,
|
|
609
624
|
fallbackInstructions: FALLBACK_INSTRUCTIONS,
|
|
610
625
|
nextRequiredAction:
|
|
611
|
-
"Wait for the user to pick a screen in chat. Then delete the unchosen variant screens with delete-file and continue from the
|
|
626
|
+
"Wait for the user to pick a screen in chat. Then delete the unchosen variant screens with delete-file, call get-design-snapshot with fileId for the chosen screen, and continue from that single file in a bounded pass. Prefer edit-design; if generate-design is needed, update only the kept file compactly and stop after the first successful save.",
|
|
612
627
|
};
|
|
613
628
|
},
|
|
614
629
|
link: ({ result }) => {
|
|
@@ -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 the unchosen variant screens, then continue from the kept
|
|
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 the unchosen variant screens, call get-design-snapshot with fileId for the kept screen, then continue from that single file in a bounded pass. Prefer edit-design; if generate-design is needed, update only the kept file compactly and stop after the first successful 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 the unchosen variant screens, then continue from the kept
|
|
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 the unchosen variant screens, call get-design-snapshot with fileId for the kept screen, then continue from that single file in a bounded pass. Prefer edit-design; if generate-design is needed, update only the kept file compactly and stop after the first successful 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)
|
|
@@ -1325,7 +1325,7 @@ function designVariantGenerationDirectives(
|
|
|
1325
1325
|
...designSystemGenerationDirectives(designSystemId),
|
|
1326
1326
|
"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.",
|
|
1327
1327
|
"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.",
|
|
1328
|
-
"Wait for the user's chat pick, delete the unchosen variant screens, then continue from the kept
|
|
1328
|
+
"Wait for the user's chat pick, delete the unchosen variant screens, call `get-design-snapshot` with `fileId` for the kept screen, then continue from that single file in a bounded pass. Prefer `edit-design`; if `generate-design` is needed, update only the kept file compactly and stop after the first successful save.",
|
|
1329
1329
|
];
|
|
1330
1330
|
}
|
|
1331
1331
|
|
|
@@ -1336,7 +1336,7 @@ function designGenerationDirectives(
|
|
|
1336
1336
|
return [
|
|
1337
1337
|
`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.`,
|
|
1338
1338
|
...designSystemGenerationDirectives(designSystemId),
|
|
1339
|
-
"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 the unchosen variant screens, then continue from the kept
|
|
1339
|
+
"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 the unchosen variant screens, call `get-design-snapshot` with `fileId` for the kept screen, then continue from that single file in a bounded pass. Prefer `edit-design`; if `generate-design` is needed, update only the kept file compactly and stop after the first successful save. Otherwise generate one polished first direction.",
|
|
1340
1340
|
"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.",
|
|
1341
1341
|
"After generate-design succeeds, stop and summarize what was created.",
|
|
1342
1342
|
];
|
package/dist/cli/skills.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/cli/skills.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,EAKL,KAAK,gBAAgB,EAEtB,MAAM,gBAAgB,CAAC;AAUxB,OAAO,EAAW,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAGjE,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/cli/skills.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/skills.js
CHANGED
|
@@ -308,7 +308,8 @@ iteration, or a human-in-the-loop choice among design directions.
|
|
|
308
308
|
full app per variant. Design saves every option as a normal screen on the
|
|
309
309
|
overview board and renders an inline chat choice with one button per screen
|
|
310
310
|
name. After the user picks, delete the unchosen variant screens and continue
|
|
311
|
-
from the kept screen
|
|
311
|
+
from the kept screen by first calling \`get-design-snapshot\` with that
|
|
312
|
+
screen's \`fileId\`, then making a bounded single-file pass.
|
|
312
313
|
- If the chat choice buttons are not available in the host, ask the user to
|
|
313
314
|
tell you the screen name they prefer. The variants are already real screens
|
|
314
315
|
on the board, so do not ask them to paste HTML or copy a generated handoff
|
|
@@ -331,8 +332,10 @@ iteration, or a human-in-the-loop choice among design directions.
|
|
|
331
332
|
and realistic controls over decorative mockups.
|
|
332
333
|
5. After \`present-design-variants\`, wait for the user's pick before
|
|
333
334
|
generating the next version. Keep the chosen screen, delete the other
|
|
334
|
-
variant screens,
|
|
335
|
-
|
|
335
|
+
variant screens, call \`get-design-snapshot\` with \`fileId\` for the kept
|
|
336
|
+
screen, then continue from that single file in a bounded pass. Prefer
|
|
337
|
+
\`edit-design\`; if \`generate-design\` is needed, update only the kept file
|
|
338
|
+
compactly and stop after the first successful save.
|
|
336
339
|
|
|
337
340
|
## Design Quality Bar
|
|
338
341
|
|