@agent-native/core 0.84.5 → 0.84.7
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/agent/production-agent.ts +97 -38
- package/corpus/core/src/agent/run-store.ts +17 -0
- package/corpus/core/src/client/agent-chat-adapter.ts +74 -2
- package/corpus/core/src/server/agent-chat-plugin.ts +57 -12
- package/corpus/templates/design/AGENTS.md +9 -7
- package/corpus/templates/design/actions/present-design-variants.ts +202 -10
- package/corpus/templates/design/app/hooks/use-question-flow.ts +2 -2
- package/corpus/templates/design/app/pages/DesignEditor.tsx +1 -1
- package/corpus/templates/design/changelog/2026-07-01-design-variants-can-now-be-generated-from-compact-directions.md +6 -0
- package/dist/agent/production-agent.d.ts +20 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +65 -32
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-store.d.ts +14 -0
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +14 -0
- package/dist/agent/run-store.js.map +1 -1
- 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/collab/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/progress/routes.d.ts +1 -1
- package/dist/server/agent-chat-plugin.d.ts +9 -0
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +20 -8
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/package.json +1 -1
|
@@ -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
|