@agent-native/core 0.84.6 → 0.84.8
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/client/agent-chat-adapter.ts +74 -2
- package/corpus/core/src/client/sse-event-processor.ts +52 -0
- package/corpus/templates/design/AGENTS.md +9 -7
- package/corpus/templates/design/actions/present-design-variants.ts +202 -10
- package/corpus/templates/design/actions/show-design-questions.ts +6 -0
- package/corpus/templates/design/app/hooks/use-question-flow.ts +2 -2
- package/corpus/templates/design/app/pages/DesignEditor.tsx +47 -7
- package/corpus/templates/design/changelog/2026-07-01-design-prompts-that-ask-for-multiple-directions-now-start-generating-variants.md +6 -0
- package/corpus/templates/design/changelog/2026-07-01-design-variants-can-now-be-generated-from-compact-directions.md +6 -0
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +63 -2
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +46 -0
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/collab/routes.d.ts +2 -2
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +4 -4
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/package.json +1 -1
|
@@ -1302,6 +1302,33 @@ function designIntakeQuestionDirectives(
|
|
|
1302
1302
|
];
|
|
1303
1303
|
}
|
|
1304
1304
|
|
|
1305
|
+
function promptRequestsVariantExploration(prompt: string): boolean {
|
|
1306
|
+
const normalized = prompt.toLowerCase();
|
|
1307
|
+
const asksForVariants =
|
|
1308
|
+
/\b(variant|variants|variation|variations|direction|directions|option|options|concept|concepts|exploration|explorations)\b/.test(
|
|
1309
|
+
normalized,
|
|
1310
|
+
);
|
|
1311
|
+
if (!asksForVariants) return false;
|
|
1312
|
+
return (
|
|
1313
|
+
/\b(2|3|4|5|two|three|four|five|multiple|several|distinct|different|choose|compare|side[-\s]?by[-\s]?side)\b/.test(
|
|
1314
|
+
normalized,
|
|
1315
|
+
) || /\bto choose from\b/.test(normalized)
|
|
1316
|
+
);
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
function designVariantGenerationDirectives(
|
|
1320
|
+
designId: string,
|
|
1321
|
+
designSystemId?: string | null,
|
|
1322
|
+
): string[] {
|
|
1323
|
+
return [
|
|
1324
|
+
`Use the \`present-design-variants --designId="${designId}"\` action first. The design already exists - DO NOT call create-design.`,
|
|
1325
|
+
...designSystemGenerationDirectives(designSystemId),
|
|
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
|
+
"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 screen.",
|
|
1329
|
+
];
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1305
1332
|
function designGenerationDirectives(
|
|
1306
1333
|
designId: string,
|
|
1307
1334
|
designSystemId?: string | null,
|
|
@@ -1309,7 +1336,7 @@ function designGenerationDirectives(
|
|
|
1309
1336
|
return [
|
|
1310
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.`,
|
|
1311
1338
|
...designSystemGenerationDirectives(designSystemId),
|
|
1312
|
-
"If the user asked to explore variations, call `present-design-variants` with 2-5
|
|
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 screen. Otherwise generate one polished first direction.",
|
|
1313
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.",
|
|
1314
1341
|
"After generate-design succeeds, stop and summarize what was created.",
|
|
1315
1342
|
];
|
|
@@ -5955,7 +5982,9 @@ export default function DesignEditor() {
|
|
|
5955
5982
|
return;
|
|
5956
5983
|
}
|
|
5957
5984
|
|
|
5958
|
-
const
|
|
5985
|
+
const shouldExploreVariants = promptRequestsVariantExploration(prompt);
|
|
5986
|
+
const shouldSkipQuestions =
|
|
5987
|
+
pending.skipQuestions === true || shouldExploreVariants;
|
|
5959
5988
|
const context = [
|
|
5960
5989
|
sourceContext,
|
|
5961
5990
|
`Design id: "${id}"`,
|
|
@@ -5966,9 +5995,11 @@ export default function DesignEditor() {
|
|
|
5966
5995
|
: "",
|
|
5967
5996
|
fileContext,
|
|
5968
5997
|
"",
|
|
5969
|
-
...(
|
|
5970
|
-
?
|
|
5971
|
-
:
|
|
5998
|
+
...(shouldExploreVariants
|
|
5999
|
+
? designVariantGenerationDirectives(id, pendingDesignSystemId)
|
|
6000
|
+
: shouldSkipQuestions
|
|
6001
|
+
? designGenerationDirectives(id, pendingDesignSystemId)
|
|
6002
|
+
: designIntakeQuestionDirectives(id, pendingDesignSystemId)),
|
|
5972
6003
|
].join("\n");
|
|
5973
6004
|
|
|
5974
6005
|
clearGenerationCompleteTimer();
|
|
@@ -17082,13 +17113,20 @@ ${serializedHtml}
|
|
|
17082
17113
|
persistPromptDesignSystem(designSystemId);
|
|
17083
17114
|
const fileContext = formatUploadedFileContext(files);
|
|
17084
17115
|
const images = imageAttachmentsFromUploadedFiles(files);
|
|
17116
|
+
const shouldExploreVariants =
|
|
17117
|
+
promptRequestsVariantExploration(prompt);
|
|
17118
|
+
const shouldSkipQuestions = shouldExploreVariants;
|
|
17085
17119
|
const context = [
|
|
17086
17120
|
`The user has design "${id}" (title: "${design.title}") open and wants to fill it with design files.`,
|
|
17087
17121
|
`User request: "${prompt}"`,
|
|
17088
17122
|
designSystemId ? `Design system id: "${designSystemId}"` : "",
|
|
17089
17123
|
fileContext,
|
|
17090
17124
|
"",
|
|
17091
|
-
...
|
|
17125
|
+
...(shouldExploreVariants
|
|
17126
|
+
? designVariantGenerationDirectives(id, designSystemId)
|
|
17127
|
+
: shouldSkipQuestions
|
|
17128
|
+
? designGenerationDirectives(id, designSystemId)
|
|
17129
|
+
: designIntakeQuestionDirectives(id, designSystemId)),
|
|
17092
17130
|
].join("\n");
|
|
17093
17131
|
clearGenerationCompleteTimer();
|
|
17094
17132
|
setGenerationIssue(null);
|
|
@@ -17104,7 +17142,9 @@ ${serializedHtml}
|
|
|
17104
17142
|
});
|
|
17105
17143
|
setHasPendingGeneration(true);
|
|
17106
17144
|
const runTabId = agentSubmit(
|
|
17107
|
-
|
|
17145
|
+
shouldSkipQuestions
|
|
17146
|
+
? `Generate design for "${design.title}": ${prompt}`
|
|
17147
|
+
: `Prepare design questions for "${design.title}": ${prompt}`,
|
|
17108
17148
|
context,
|
|
17109
17149
|
{ ...options, newTab: true, images },
|
|
17110
17150
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-chat-adapter.d.ts","sourceRoot":"","sources":["../../src/client/agent-chat-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAsB,MAAM,qBAAqB,CAAC;AAMhF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAkBrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,MAAM,oBAAoB;AAC9B;;;;GAIG;AACD,KAAK;AACP,0EAA0E;GACxE,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-chat-adapter.d.ts","sourceRoot":"","sources":["../../src/client/agent-chat-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAsB,MAAM,qBAAqB,CAAC;AAMhF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAkBrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,MAAM,oBAAoB;AAC9B;;;;GAIG;AACD,KAAK;AACP,0EAA0E;GACxE,WAAW,CAAC;AAgqChB;;;;GAIG;AACH;;;GAGG;AACH,MAAM,WAAW,6BAA6B;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IAC3C,SAAS,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IAC5C,SAAS,CAAC,EAAE;QAAE,OAAO,EAAE,eAAe,GAAG,SAAS,CAAA;KAAE,CAAC;IACrD,WAAW,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IACxD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,CAAA;KAAE,CAAC;IAC3D,OAAO,CAAC,EAAE,oBAAoB,CAAC;CAChC;AAED,wBAAgB,sBAAsB,CACpC,OAAO,CAAC,EAAE,6BAA6B,GACtC,gBAAgB,CAo+ClB"}
|
|
@@ -41,6 +41,12 @@ const MAX_EMPTY_TRANSIENT_CONTINUATIONS = 3;
|
|
|
41
41
|
// round re-sending any large pasted payload) before bailing. Catching the
|
|
42
42
|
// repeat ends it in a few rounds with a clear, actionable message instead.
|
|
43
43
|
const MAX_REPEATED_TRANSIENT_CONTINUATIONS = 3;
|
|
44
|
+
// How many consecutive continuations that only reach the SAME "preparing
|
|
45
|
+
// action" activity card we tolerate before giving up. This catches runs that
|
|
46
|
+
// keep timing out while assembling a large tool payload: they are not empty,
|
|
47
|
+
// and the narration may vary enough to bypass the text-repeat guard, but the
|
|
48
|
+
// real tool never starts.
|
|
49
|
+
const MAX_REPEATED_ACTION_PREPARATION_CONTINUATIONS = 3;
|
|
44
50
|
const RETRY_BASE_DELAY_MS = 500;
|
|
45
51
|
const RETRY_MAX_DELAY_MS = 8_000;
|
|
46
52
|
const MAX_HISTORY_ATTACHMENT_CHARS = 60_000;
|
|
@@ -601,6 +607,17 @@ function lastActivityTool(trail) {
|
|
|
601
607
|
}
|
|
602
608
|
return undefined;
|
|
603
609
|
}
|
|
610
|
+
function lastUnresolvedToolActivity(content) {
|
|
611
|
+
for (let i = content.length - 1; i >= 0; i--) {
|
|
612
|
+
const part = content[i];
|
|
613
|
+
if (part.type === "tool-call" &&
|
|
614
|
+
part.activity === true &&
|
|
615
|
+
part.result === undefined) {
|
|
616
|
+
return part.toolName;
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
return undefined;
|
|
620
|
+
}
|
|
604
621
|
function snapshotContent(content) {
|
|
605
622
|
return content.map((part) => part.type === "text" ? { ...part } : { ...part, args: { ...part.args } });
|
|
606
623
|
}
|
|
@@ -688,7 +705,7 @@ function incrementalActionGuidance(tool) {
|
|
|
688
705
|
case "update-design":
|
|
689
706
|
return "persist a minimal first version (fewer files) with `generate-design`, then refine individual files with `edit-design` search/replace instead of resending everything";
|
|
690
707
|
case "present-design-variants":
|
|
691
|
-
return "
|
|
708
|
+
return "call `present-design-variants` with concise labels, descriptions, accent colors, and feature bullets; omit large `content` HTML when needed so the action can render compact representative screens, then refine the chosen direction with `generate-design` or `edit-design`";
|
|
692
709
|
case "create-visual-plan":
|
|
693
710
|
case "create-ui-plan":
|
|
694
711
|
case "create-plan-design":
|
|
@@ -1073,6 +1090,9 @@ export function createAgentChatAdapter(options) {
|
|
|
1073
1090
|
let repeatedInFlightToolCount = 0;
|
|
1074
1091
|
let recoveryGaveUpOnInFlightTool = false;
|
|
1075
1092
|
const MAX_REPEATED_INFLIGHT_TOOL_STALLS = 3;
|
|
1093
|
+
let lastPreparingToolName;
|
|
1094
|
+
let repeatedActionPreparationCount = 0;
|
|
1095
|
+
let recoveryGaveUpOnActionPreparation = false;
|
|
1076
1096
|
const continuationHistoryFragments = [];
|
|
1077
1097
|
const structuredContinuationFragments = [];
|
|
1078
1098
|
let visibleContinuationPrefix = [];
|
|
@@ -1101,6 +1121,10 @@ export function createAgentChatAdapter(options) {
|
|
|
1101
1121
|
lastInFlightToolName
|
|
1102
1122
|
? `last_inflight_tool: ${lastInFlightToolName}`
|
|
1103
1123
|
: "",
|
|
1124
|
+
`repeated_action_preparation_stalls: ${repeatedActionPreparationCount}`,
|
|
1125
|
+
lastPreparingToolName
|
|
1126
|
+
? `last_preparing_tool: ${lastPreparingToolName}`
|
|
1127
|
+
: "",
|
|
1104
1128
|
`total_transient_continuations: ${totalTransientContinuationAttempts}`,
|
|
1105
1129
|
attemptedRunIds.length > 0
|
|
1106
1130
|
? `attempted_runs: ${attemptedRunIds.join(", ")}`
|
|
@@ -1116,6 +1140,12 @@ export function createAgentChatAdapter(options) {
|
|
|
1116
1140
|
if (recoveryGaveUpOnRepetition) {
|
|
1117
1141
|
return "The agent got stuck repeating the same response without finishing, so I stopped the automatic retries. This often happens when it tries to re-type a large pasted file into one action — starting a new chat, or asking for a smaller first step, usually gets it unstuck.";
|
|
1118
1142
|
}
|
|
1143
|
+
if (recoveryGaveUpOnActionPreparation) {
|
|
1144
|
+
const tool = lastPreparingToolName
|
|
1145
|
+
? ` the ${humanizeActionName(lastPreparingToolName)} action`
|
|
1146
|
+
: " the same action";
|
|
1147
|
+
return `The agent got stuck preparing${tool} input and never started the tool, so I stopped the automatic retries. Try a smaller first step or a more compact version of the request.`;
|
|
1148
|
+
}
|
|
1119
1149
|
if (content.length === 0 &&
|
|
1120
1150
|
(reason === "run_timeout" ||
|
|
1121
1151
|
reason === "no_progress" ||
|
|
@@ -1180,6 +1210,8 @@ export function createAgentChatAdapter(options) {
|
|
|
1180
1210
|
repeatedTransientContinuationAttempts,
|
|
1181
1211
|
repeatedInFlightToolCount,
|
|
1182
1212
|
lastInFlightToolName,
|
|
1213
|
+
repeatedActionPreparationCount,
|
|
1214
|
+
lastPreparingToolName,
|
|
1183
1215
|
totalTransientContinuationAttempts,
|
|
1184
1216
|
...extra,
|
|
1185
1217
|
},
|
|
@@ -1197,6 +1229,8 @@ export function createAgentChatAdapter(options) {
|
|
|
1197
1229
|
repeatedTransientContinuationAttempts,
|
|
1198
1230
|
repeatedInFlightToolCount,
|
|
1199
1231
|
lastInFlightToolName,
|
|
1232
|
+
repeatedActionPreparationCount,
|
|
1233
|
+
lastPreparingToolName,
|
|
1200
1234
|
totalTransientContinuationAttempts,
|
|
1201
1235
|
},
|
|
1202
1236
|
},
|
|
@@ -1438,7 +1472,10 @@ export function createAgentChatAdapter(options) {
|
|
|
1438
1472
|
// Either real output or an actively-running tool counts as progress
|
|
1439
1473
|
// for the stalled/empty caps.
|
|
1440
1474
|
const madeProgress = madeContentProgress || hasInFlightTool;
|
|
1441
|
-
const madeDurableToolProgress = visibleContent.some((part) => part.type === "tool-call" &&
|
|
1475
|
+
const madeDurableToolProgress = visibleContent.some((part) => part.type === "tool-call" &&
|
|
1476
|
+
part.activity !== true &&
|
|
1477
|
+
part.result !== undefined);
|
|
1478
|
+
const currentPreparingToolName = lastUnresolvedToolActivity(visibleContent);
|
|
1442
1479
|
// In-flight tool stall guard. When the same write tool is stuck
|
|
1443
1480
|
// in-flight because the connection keeps dropping (stream_ended),
|
|
1444
1481
|
// hasInFlightTool=true keeps madeProgress=true and completely
|
|
@@ -1477,6 +1514,25 @@ export function createAgentChatAdapter(options) {
|
|
|
1477
1514
|
else if (!currentInFlightToolName) {
|
|
1478
1515
|
repeatedInFlightToolCount = 0;
|
|
1479
1516
|
}
|
|
1517
|
+
const isRepeatedActionPreparationCandidate = signal.reason !== "loop_limit" &&
|
|
1518
|
+
currentPreparingToolName !== undefined &&
|
|
1519
|
+
!hasInFlightTool &&
|
|
1520
|
+
!madeDurableToolProgress;
|
|
1521
|
+
if (isRepeatedActionPreparationCandidate) {
|
|
1522
|
+
if (currentPreparingToolName === lastPreparingToolName) {
|
|
1523
|
+
repeatedActionPreparationCount += 1;
|
|
1524
|
+
}
|
|
1525
|
+
else {
|
|
1526
|
+
repeatedActionPreparationCount = 0;
|
|
1527
|
+
lastPreparingToolName = currentPreparingToolName;
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
else if (!currentPreparingToolName ||
|
|
1531
|
+
hasInFlightTool ||
|
|
1532
|
+
madeDurableToolProgress) {
|
|
1533
|
+
repeatedActionPreparationCount = 0;
|
|
1534
|
+
lastPreparingToolName = undefined;
|
|
1535
|
+
}
|
|
1480
1536
|
// Degenerate repetition guard. When the model gets stuck re-streaming
|
|
1481
1537
|
// the SAME narration every continuation without ever starting or
|
|
1482
1538
|
// finishing a tool, each round is "new" text — so madeProgress stays
|
|
@@ -1520,6 +1576,11 @@ export function createAgentChatAdapter(options) {
|
|
|
1520
1576
|
recoveryGaveUpOnInFlightTool = true;
|
|
1521
1577
|
return { ok: false, resetVisibleContent: false };
|
|
1522
1578
|
}
|
|
1579
|
+
if (repeatedActionPreparationCount >
|
|
1580
|
+
MAX_REPEATED_ACTION_PREPARATION_CONTINUATIONS) {
|
|
1581
|
+
recoveryGaveUpOnActionPreparation = true;
|
|
1582
|
+
return { ok: false, resetVisibleContent: false };
|
|
1583
|
+
}
|
|
1523
1584
|
// Bail fast on a non-advancing repetition loop, well before the
|
|
1524
1585
|
// stalled/empty/total budgets would (each round otherwise re-sends
|
|
1525
1586
|
// the whole pasted payload). Tracked separately so it never trips
|