@tea-agent/loop-agent 0.39.0-beta.0 → 0.39.0-beta.1

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "version": "0.39.0-beta.0",
4
- "gitSha": "cf0cf7e8e996da8d1c727ccc7cb8f4c52f8d5319",
5
- "builtAt": "2026-08-21T03:47:18.913Z"
3
+ "version": "0.39.0-beta.1",
4
+ "gitSha": "d4e9fcaf663c172451bc1dd0553fbf7132e97132",
5
+ "builtAt": "2026-08-21T06:38:45.518Z"
6
6
  }
@@ -41,9 +41,6 @@ export function serializeDeterministicJson(value) {
41
41
  export function deterministicSha256(value) {
42
42
  return sha256Hex(serializeDeterministicJson(value));
43
43
  }
44
- /** Provider-safe limits for the two planner outputs. Larger work must split. */
45
- export const FRONTEND_PLAN_RESPONSE_MAX_BYTES = 14 * 1024;
46
- export const FRONTEND_CANONICAL_CONTRACT_MAX_BYTES = 16 * 1024;
47
44
  /** A contract materialization failure carries its classification plus the
48
45
  * audit context collected up to the failure point, so the prewrite gate can
49
46
  * persist a complete frontend-prewrite-result-v1 even when the canonical
@@ -1796,9 +1793,6 @@ export async function validateFrontendPlanPatchNodeOutput(input) {
1796
1793
  });
1797
1794
  };
1798
1795
  try {
1799
- if (Buffer.byteLength(input.text, "utf8") > FRONTEND_PLAN_RESPONSE_MAX_BYTES) {
1800
- throw new Error(`frontend plan response exceeds the ${FRONTEND_PLAN_RESPONSE_MAX_BYTES}-byte limit`);
1801
- }
1802
1796
  if (!input.sourceBinding)
1803
1797
  throw new Error("frontend plan patch validator requires DAG sourceBinding");
1804
1798
  const skeleton = input.structuredContractOutput?.skeleton;
@@ -1826,10 +1820,6 @@ export async function validateFrontendPlanPatchNodeOutput(input) {
1826
1820
  rawContractText: serializeDeterministicJson(merged),
1827
1821
  sourceBinding: input.sourceBinding,
1828
1822
  });
1829
- if (Buffer.byteLength(serializeDeterministicJson(analysis.canonical), "utf8") >
1830
- FRONTEND_CANONICAL_CONTRACT_MAX_BYTES) {
1831
- throw new Error(`frontend canonical contract exceeds the ${FRONTEND_CANONICAL_CONTRACT_MAX_BYTES}-byte limit; split the task`);
1832
- }
1833
1823
  const normalizedArtifact = await writeDeterministicJsonArtifact(input.runDir, path.posix.join(candidateDir, `attempt-${attempt}.normalized.json`), analysis.canonical);
1834
1824
  await writeReport({
1835
1825
  classification: "accepted-normalized",
@@ -1924,12 +1914,6 @@ export async function validateFrontendRevisionPatchNodeOutput(input) {
1924
1914
  attempt,
1925
1915
  text: input.text,
1926
1916
  });
1927
- if (Buffer.byteLength(input.text, "utf8") > FRONTEND_PLAN_RESPONSE_MAX_BYTES) {
1928
- return {
1929
- ok: false,
1930
- reason: `frontend revision response exceeds the ${FRONTEND_PLAN_RESPONSE_MAX_BYTES}-byte limit`,
1931
- };
1932
- }
1933
1917
  let citationsBlock;
1934
1918
  let patch;
1935
1919
  try {
@@ -4,15 +4,13 @@ import { z } from "zod";
4
4
  import { isOpenspecSpecFilePath } from "../../shared/openspec-spec.js";
5
5
  import { writeTextArtifactFile } from "../../infrastructure/harness/artifact-store.js";
6
6
  import { countExcludedGovernanceSpecFiles, resolveOpenspecGovernanceRoot, } from "../../task/frontend-project-capability.js";
7
- import { analyzeFrontendImplementationContract, writeFrontendImplementationContractArtifact, writeDeterministicJsonArtifact, assertFrontendSourceBindingFresh, deterministicSha256, sha256Hex, serializeDeterministicJson, FRONTEND_CANONICAL_CONTRACT_MAX_BYTES, applyFrontendImplementationContractPatch, extractFrontendImplementationJson, FrontendContractFailure, frontendNormalizationActionSchema, } from "./frontend-implementation-contract.js";
7
+ import { analyzeFrontendImplementationContract, writeFrontendImplementationContractArtifact, writeDeterministicJsonArtifact, assertFrontendSourceBindingFresh, deterministicSha256, sha256Hex, serializeDeterministicJson, applyFrontendImplementationContractPatch, extractFrontendImplementationJson, FrontendContractFailure, frontendNormalizationActionSchema, } from "./frontend-implementation-contract.js";
8
8
  import { renderFrontendPlanMarkdown } from "./frontend-plan-render.js";
9
9
  import { captureFrontendWorktreeBaseline } from "./frontend-worktree-diff.js";
10
10
  import { pathMatchesPattern } from "../../shared/git-progress.js";
11
11
  import { normalizeVerdictCandidateLine } from "./dynamic-runtime/shared.js";
12
12
  export const FRONTEND_PREWRITE_RESULT_SCHEMA_ID = "frontend-prewrite-result-v1";
13
13
  export const FRONTEND_PREWRITE_RESULT_ARTIFACT_NAME = "frontend-prewrite-result.json";
14
- /** Canonical contract serialization must stay at or below this byte size. */
15
- export const FRONTEND_CONTRACT_MAX_BYTES = FRONTEND_CANONICAL_CONTRACT_MAX_BYTES;
16
14
  /**
17
15
  * Machine-readable failure classification for blocked/retryable-invalid
18
16
  * prewrite outcomes. Kept alongside the human-readable failureReason so
@@ -39,7 +37,6 @@ export const frontendPrewriteFailureCodeSchema = z.enum([
39
37
  "component-spec-reference-invalid",
40
38
  "component-spec-not-cited",
41
39
  "component-choices-missing",
42
- "contract-too-large",
43
40
  "revision-patch-unmergeable",
44
41
  ]);
45
42
  export const frontendPrewriteResultV1Schema = z
@@ -732,21 +729,6 @@ export async function runFrontendPrewriteGate(input) {
732
729
  }
733
730
  throw error;
734
731
  }
735
- // Size guard: a canonical contract above 64KB is a retryable-invalid defect
736
- // (compress the contract) rather than a writer authorization failure.
737
- const contractSizeBytes = Buffer.byteLength(serializeDeterministicJson(analysis.canonical), "utf8");
738
- if (contractSizeBytes > FRONTEND_CONTRACT_MAX_BYTES) {
739
- return finalizePrewrite(input, {
740
- ...basePending,
741
- verdict,
742
- candidateJsonSha256: analysis.candidateJsonSha256,
743
- normalizationActions: [],
744
- mockStrategy: analysis.canonical.mockApi.strategy,
745
- classification: "retryable-invalid",
746
- failureReason: `frontend prewrite gate: canonical contract serialization is ${contractSizeBytes} bytes, exceeding the ${FRONTEND_CONTRACT_MAX_BYTES}-byte limit. 压缩契约(移除冗余 prose、重复目标或过长描述)后重试。`,
747
- failureCode: "contract-too-large",
748
- });
749
- }
750
732
  const mockStrategy = analysis.canonical.mockApi.strategy;
751
733
  if (!input.config.allowedMockStrategies.includes(mockStrategy)) {
752
734
  const quotedAllowed = input.config.allowedMockStrategies
@@ -2536,19 +2536,9 @@ async function buildFrontendHybridDagFromTask(sources) {
2536
2536
  const requirementIds = frontendSourceBinding.requirementIds;
2537
2537
  const requirementCoverageInstruction = requirementIds.length > 0
2538
2538
  ? [
2539
- `## Requirement Coverage (per-AC echo with bad/good examples)`,
2540
- `For each requirement ID below, echo the ID verbatim and confirm: expectedOutcome (user-observable or logic-observable), implementation targets (files), and verification targets (commandLabel + file).`,
2541
- `Do not skip any ID. Use the bad/good patterns below as reference for each field.`,
2542
- ``,
2543
- `Bad example (empty expectedOutcome, empty targets -- REJECTED at contract materialization):`,
2544
- `- AC-001: expectedOutcome="" implementationTargets=[] verificationTargets=[]`,
2545
- ``,
2546
- `Good example (concrete expectedOutcome, real files, real verification targets):`,
2547
- `- AC-001: expectedOutcome="TypeScript compilation exits with code 0 and produces no errors in dist/" implementationTargets=["src/app.tsx"] verificationTargets=["vt-typecheck":"npm run typecheck","tsconfig.json"]`,
2548
- ``,
2549
- ...requirementIds.map((id) => `- ${id}: [expectedOutcome] [implementation files] [verification targets]`),
2550
- ``,
2551
- `Every requirement MUST have a non-empty expectedOutcome. Every interaction MUST have non-empty trigger and expectedBehavior. UI states with applicable=true MUST have non-empty expectedBehavior. Empty strings or omitted fields for these will cause contract rejection.`,
2539
+ "## Requirement Coverage",
2540
+ `Cover each frozen ID exactly once in requirements[]: ${requirementIds.join(", ")}. Each item needs a concrete expectedOutcome, implementationTargets, and verificationTargetIds.`,
2541
+ "Interactions need trigger + expectedBehavior; applicable uiStates need expectedBehavior + implementationTargets + verificationTargetIds. Do not use empty strings.",
2552
2542
  ].join("\n")
2553
2543
  : "";
2554
2544
  const verificationTargetFileInstruction = [
@@ -2562,6 +2552,11 @@ async function buildFrontendHybridDagFromTask(sources) {
2562
2552
  "Before producing this contract/plan, use the Pi read tool to read the FULL bound source files (需求.md, 执行约束.md, and every `references/*` Bound readPath listed above) — the inline copies above may be truncated excerpts, and requirement/acceptance references are authoritative only in their full form.",
2563
2553
  "Do not drop scope fields, acceptance criteria, non-goals, UI states, or column/field definitions that exist in the full sources but are absent from the inline excerpts; if a field appears in the full source, it belongs in the contract.",
2564
2554
  ].join("\n");
2555
+ const plannerSourceReadInstruction = [
2556
+ "## Source-read policy",
2557
+ "Use the injected task sources plus frontend-contract-pi and frontend-scout-pi as the primary evidence. Do not repeat reads that those facts already settle.",
2558
+ "Read a bound source only to resolve a missing or conflicting field; read every applicable OpenSpec candidate directly before citing it. Never infer omitted task fields from a preview.",
2559
+ ].join("\n");
2565
2560
  const strategy = resolveDagVerifyStrategy(taskConfig);
2566
2561
  const readOnlyPaths = taskConfig.allowedPaths.length > 0 ? taskConfig.allowedPaths : ["**"];
2567
2562
  const behaviorPaths = deriveFrontendBehaviorPaths(taskConfig);
@@ -2799,7 +2794,7 @@ async function buildFrontendHybridDagFromTask(sources) {
2799
2794
  allowedPaths: readOnlyPaths,
2800
2795
  forbiddenPaths,
2801
2796
  skills: [],
2802
- outputContract: "JSON-only patch output: one-line lead-in, then exactly ONE fenced json object (```json ... ```) containing only the editable RFC 7386 plan patch for the runtime contract skeleton. Omit protected fields: schemaVersion, sourceBinding, riskLevel, targets.files, and mockApi.productionDefaultOff. Immediately after it, append exactly one ```openspec-citations``` fenced citation block. The runtime applies the patch, validates it, and promotes canonical full-contract JSON for downstream review. Do NOT emit a full contract, Markdown plan explanation, raw JSON, or any other fenced block. No file writes.",
2797
+ outputContract: "JSON-only patch output: exactly ONE fenced json object (```json ... ```) containing only the editable RFC 7386 plan patch for the runtime contract skeleton, immediately followed by exactly one ```openspec-citations``` fenced citation block. Omit protected fields: schemaVersion, sourceBinding, riskLevel, targets.files, and mockApi.productionDefaultOff. The runtime applies the patch, validates it, and promotes canonical full-contract JSON for downstream review. Do NOT emit a full contract, Markdown plan explanation, raw JSON, or any other fenced block. No file writes.",
2803
2798
  subtask_prompt: [
2804
2799
  "Use frontend-contract-pi, frontend-scout-pi, task sources, and the generation-time Mock capability evidence to fill the runtime-owned frontend contract skeleton. Return JSON-only output containing only an editable RFC 7386 plan patch. The runtime already owns schemaVersion, sourceBinding, riskLevel, targets.files, and mockApi.productionDefaultOff; omit those protected paths even when their values look obvious.",
2805
2800
  "The patch fields become the complete implementation plan after deterministic merge. Do not produce a separate plan document, prose mirror, or full contract.",
@@ -2807,13 +2802,13 @@ async function buildFrontendHybridDagFromTask(sources) {
2807
2802
  "Encode ordered steps (implementationSteps), target files, UI state handling, styling/component strategy (stylingStrategy), interaction notes, Mock/API strategy, dependency policy (dependencyPolicy), deterministic verification entrypoints, Real Integration Gap (realIntegrationGap), and residual risks (residualRisks) into the contract JSON fields. Use only the fixed entrypoints below; implementation may add tests behind them but cannot replace them.",
2808
2803
  "Every target file and verification target must be selected from the current target workspace and task scope. Do not reuse paths or symbols from examples, prior tasks, or loop-agent itself; if the project uses app/, packages/, spec/, __tests__, or another layout, preserve that layout.",
2809
2804
  "Consume the Scout TARGET_SURFACE evidence before selecting files. Preserve the discovered existing entrypoint and data source. If implementationPaths or testPaths are outside task allowedPaths, record a blocking scope conflict; do not substitute a new page or silently broaden the writeSet.",
2810
- "Output in this exact order: (1) exactly one fenced json object containing the editable plan patch; (2) exactly one openspec-citations citation fenced block appended immediately after it. Do NOT emit protected skeleton fields, a full contract, Markdown plan explanation, raw JSON, or any other fenced block.",
2805
+ "Output exactly two adjacent blocks: (1) one fenced json object containing the editable plan patch; (2) one openspec-citations citation block. Do NOT emit protected skeleton fields, a full contract, Markdown plan explanation, raw JSON, or any other fenced block.",
2811
2806
  "Each requirement must state its user-observable or logic-observable expectedOutcome. Each interaction must state its trigger and expectedBehavior. IDs plus file paths are not sufficient behavior semantics.",
2812
2807
  requirementCoverageInstruction,
2813
2808
  "verificationTargets[].commandLabel MUST be one of the frozen command labels listed above. Any other value will be rejected at contract materialization.",
2814
2809
  verificationTargetFileInstruction,
2815
2810
  "Read-only: do not modify code, docs, artifacts, or repository files.",
2816
- mandatorySourceReadInstruction,
2811
+ plannerSourceReadInstruction,
2817
2812
  fixedVerificationContext,
2818
2813
  sourceContext,
2819
2814
  mockContextBlock,
@@ -2866,15 +2861,15 @@ async function buildFrontendHybridDagFromTask(sources) {
2866
2861
  allowedPaths: readOnlyPaths,
2867
2862
  forbiddenPaths,
2868
2863
  skills: [],
2869
- outputContract: "When the initial design review requests revision, return a one-line lead-in followed by exactly ONE fenced json object (```json ... ```) containing an RFC 7386 merge-patch delta against the original frontend-implementation-contract-v1 (only the fields you change; null deletes a key; arrays and scalars replace; plain objects merge recursively). Immediately after it, append exactly one ```openspec-citations``` fenced citation block. Do NOT emit a full contract, Markdown explanation, or prose — the output is JSON-only; the gate applies the patch on the original contract and renders plan.md deterministically. Apart from the patch JSON fenced block and the openspec-citations block, do not emit any other fenced block or raw JSON. No file writes.",
2864
+ outputContract: "When the initial design review requests revision, return exactly ONE fenced json object (```json ... ```) containing an RFC 7386 merge-patch delta against the original frontend-implementation-contract-v1 (only the fields you change; null deletes a key; arrays and scalars replace; plain objects merge recursively), immediately followed by exactly one ```openspec-citations``` fenced citation block. Do NOT emit a full contract, Markdown explanation, or prose — the output is JSON-only; the gate applies the patch on the original contract and renders plan.md deterministically. Apart from the patch JSON fenced block and the openspec-citations block, do not emit any other fenced block or raw JSON. No file writes.",
2870
2865
  subtask_prompt: [
2871
- "Consume frontend-plan-pi (original contract JSON) and frontend-design-review-pi (first design review findings).",
2866
+ "Consume the hash-bound frontend-plan-pi contract artifact and frontend-design-review-pi findings. Read the artifact only for fields affected by a Required Plan Correction.",
2872
2867
  "This node runs only when frontend-design-review-pi emitted VERDICT: request-revision. Produce an RFC 7386 merge-patch delta against the original contract JSON that addresses every Required Plan Correction from the design findings.",
2873
2868
  "The patch delta may update editable contract fields such as requirements, implementationSteps, targets.routes/publicApiChanges, uiStates, interactions, mockApi.strategy/activation/endpoints, dependencyPolicy, stylingStrategy, uiComponentChoices, verificationTargets, evidenceGaps, residualRisks, and realIntegrationGap. It must not modify protected schemaVersion, sourceBinding, riskLevel, targets.files, or mockApi.productionDefaultOff. Only include fields you change; omit unchanged fields (the gate applies the patch on the original contract). null deletes a key; arrays and scalars replace; plain objects merge recursively.",
2874
- requirementCoverageInstruction,
2869
+ "Only include changed fields. For a changed requirement, preserve its expectedOutcome, implementationTargets, and verificationTargetIds; do not resend unchanged requirements.",
2875
2870
  "Do not turn MOCK_STRATEGY: blocked into an implementable strategy without new repository or contract evidence that resolves every blocker.",
2876
2871
  "Read-only: do not modify code, docs, artifacts, or repository files. This node revises the plan only.",
2877
- "Output in this exact order: (1) exactly one fenced json object containing the merge-patch delta — this is the only plan output the prewrite gate applies on the original contract; (2) exactly one openspec-citations citation fenced block appended immediately after it. Do NOT emit a full contract, Markdown explanation, or prose — the output is JSON-only. Do not emit any raw JSON or JSON objects in prose. Apart from the patch JSON fenced block and the openspec-citations block, do not emit any other fenced block. Do not include secrets or unsafe paths.",
2872
+ "Output exactly two adjacent blocks: (1) one fenced json object containing the merge-patch delta; (2) one openspec-citations citation block. Do NOT emit a full contract, Markdown explanation, or prose. Do not emit raw JSON or JSON objects in prose, secrets, or unsafe paths.",
2878
2873
  "Preserve each requirement expectedOutcome and each interaction trigger/expectedBehavior in the effective (merged) contract; do not reduce behavior semantics to IDs and paths.",
2879
2874
  "verificationTargets[].commandLabel MUST be one of the frozen command labels listed above. Any other value will be rejected at contract materialization.",
2880
2875
  verificationTargetFileInstruction,
@@ -132,14 +132,14 @@ export function buildNodePrompt(spec, task, upstream, options) {
132
132
  function frontendStructuredArtifactRetryGuidance(schemaId) {
133
133
  if (schemaId === "frontend-implementation-contract-plan-patch-v1") {
134
134
  return [
135
- "Return exactly this artifact and nothing else: one short lead-in line, then exactly one fenced json block containing only the editable RFC 7386 plan patch, immediately followed by exactly one fenced openspec-citations block.",
135
+ "Return exactly two blocks and nothing else: one fenced json block containing only the editable RFC 7386 plan patch, immediately followed by one fenced openspec-citations block.",
136
136
  "The runtime applies your patch to its protected contract skeleton. Do not emit schemaVersion, sourceBinding, riskLevel, targets.files, or mockApi.productionDefaultOff; do not emit the full contract.",
137
137
  "Do not emit Markdown headings, bullets, plan prose, explanations, raw JSON, or any other fenced block.",
138
138
  ];
139
139
  }
140
140
  if (schemaId === "frontend-implementation-contract-revision-patch-v1") {
141
141
  return [
142
- "Return exactly this artifact and nothing else: one short lead-in line, then exactly one fenced json block containing the RFC 7386 merge-patch delta, immediately followed by exactly one fenced openspec-citations block.",
142
+ "Return exactly two blocks and nothing else: one fenced json block containing the RFC 7386 merge-patch delta, immediately followed by one fenced openspec-citations block.",
143
143
  "The delta contains only the fields you change; null deletes a key, arrays and scalars replace, and plain objects merge recursively. Do not emit a full contract or a schemaVersion/targets section.",
144
144
  "Do not emit Markdown headings, bullets, plan prose, explanations, raw JSON, or any other fenced block.",
145
145
  ];
@@ -149,6 +149,27 @@ function frontendStructuredArtifactRetryGuidance(schemaId) {
149
149
  "The contract JSON fields are the complete implementation plan. Do not emit a separate plan document, Markdown headings, bullets, plan prose, explanations, raw JSON, or any other fenced block.",
150
150
  ];
151
151
  }
152
+ function isFrontendPlanArtifactSchema(schemaId) {
153
+ return (schemaId === "frontend-implementation-contract-plan-patch-v1" ||
154
+ schemaId === "frontend-implementation-contract-revision-patch-v1");
155
+ }
156
+ function buildFrontendPlanArtifactRecoveryPrompt(options) {
157
+ const cause = options.failure === "truncated"
158
+ ? "Previous response was truncated by the provider (stopReason=length)."
159
+ : options.failure === "too-large"
160
+ ? "Previous response could not be retained by the provider."
161
+ : "Previous response failed structured validation.";
162
+ return [
163
+ "<retry_instruction>",
164
+ cause,
165
+ options.reason ? `Validation error: ${options.reason}` : "",
166
+ ...frontendStructuredArtifactRetryGuidance(options.schemaId),
167
+ "Use concise values and reference paths/IDs instead of copying source prose. Do not omit required semantics.",
168
+ "</retry_instruction>",
169
+ ]
170
+ .filter(Boolean)
171
+ .join("\n");
172
+ }
152
173
  function buildAttemptPrompt(task, basePrompt, attemptNumber, previousFailureCategory, previousProtocolReason, recoveryTargetPaths, recoveryDiagnostics) {
153
174
  if (attemptNumber <= 1)
154
175
  return basePrompt;
@@ -164,6 +185,13 @@ function buildAttemptPrompt(task, basePrompt, attemptNumber, previousFailureCate
164
185
  if (previousFailureCategory === "invalid-output" &&
165
186
  task.structuredContractOutput &&
166
187
  previousProtocolReason) {
188
+ if (isFrontendPlanArtifactSchema(task.structuredContractOutput.schemaId)) {
189
+ return buildFrontendPlanArtifactRecoveryPrompt({
190
+ failure: "invalid",
191
+ reason: previousProtocolReason,
192
+ schemaId: task.structuredContractOutput.schemaId,
193
+ });
194
+ }
167
195
  return [
168
196
  basePrompt,
169
197
  "",
@@ -178,22 +206,12 @@ function buildAttemptPrompt(task, basePrompt, attemptNumber, previousFailureCate
178
206
  if (previousFailureCategory === "structured-output-truncated" &&
179
207
  task.structuredContractOutput) {
180
208
  const schemaId = task.structuredContractOutput.schemaId;
181
- if (schemaId === "frontend-implementation-contract-plan-patch-v1" ||
182
- schemaId === "frontend-implementation-contract-revision-patch-v1") {
183
- const payloadKind = schemaId === "frontend-implementation-contract-plan-patch-v1"
184
- ? "editable plan patch"
185
- : "RFC 7386 revision patch";
186
- return [
187
- "<retry_instruction>",
188
- "Previous response was truncated (stopReason=length).",
189
- previousProtocolReason ? `Validation error: ${previousProtocolReason}` : "",
190
- `Return one short lead-in, one complete fenced json ${payloadKind}, then one fenced openspec-citations block.`,
191
- "Protected: schemaVersion, sourceBinding, riskLevel, targets.files, mockApi.productionDefaultOff. Required semantics: requirement expectedOutcome; interaction trigger + expectedBehavior; frozen verification command labels.",
192
- "No prose, examples, schema copy, Markdown headings, raw JSON, or other fences.",
193
- "</retry_instruction>",
194
- ]
195
- .filter(Boolean)
196
- .join("\n");
209
+ if (isFrontendPlanArtifactSchema(schemaId)) {
210
+ return buildFrontendPlanArtifactRecoveryPrompt({
211
+ failure: "truncated",
212
+ reason: previousProtocolReason,
213
+ schemaId,
214
+ });
197
215
  }
198
216
  return [
199
217
  basePrompt,
@@ -271,6 +289,12 @@ function buildAttemptPrompt(task, basePrompt, attemptNumber, previousFailureCate
271
289
  }
272
290
  if (task.outputMode === "structured-required") {
273
291
  if (task.structuredContractOutput) {
292
+ if (isFrontendPlanArtifactSchema(task.structuredContractOutput.schemaId)) {
293
+ return buildFrontendPlanArtifactRecoveryPrompt({
294
+ failure: "too-large",
295
+ schemaId: task.structuredContractOutput.schemaId,
296
+ });
297
+ }
274
298
  return [
275
299
  basePrompt,
276
300
  "",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tea-agent/loop-agent",
3
- "version": "0.39.0-beta.0",
3
+ "version": "0.39.0-beta.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "loop-agent": "bin/loop-agent.js",