@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.
@@ -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 compact, complete HTML directions: one representative screen per direction, not a full app per variant. Wait for their chat pick, delete the unchosen variant screens, then continue from the kept screen. Otherwise generate one polished first direction.",
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 shouldSkipQuestions = pending.skipQuestions === true;
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
- ...(shouldSkipQuestions
5970
- ? designGenerationDirectives(id, pendingDesignSystemId)
5971
- : designIntakeQuestionDirectives(id, pendingDesignSystemId)),
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
- ...designIntakeQuestionDirectives(id, designSystemId),
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
- `Prepare design questions for "${design.title}": ${prompt}`,
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
  );
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-01
4
+ ---
5
+
6
+ Design prompts that already ask for multiple directions now start generating variants instead of stopping at intake questions.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-01
4
+ ---
5
+
6
+ Design variants can now be generated from compact directions, reducing long-running agent stalls.
@@ -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;AA0oChB;;;;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,CAk7ClB"}
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 "save compact but complete variant screens with `present-design-variants` first, keeping each HTML direction focused enough to finish, then refine the chosen direction with `generate-design` or `edit-design`";
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" && part.result !== undefined);
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