@tea-agent/loop-agent 0.26.5-beta.0 → 0.26.5-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.
|
@@ -346,12 +346,61 @@ function secretIssues(value, at = "$", issues = []) {
|
|
|
346
346
|
}
|
|
347
347
|
export function extractFrontendImplementationJson(text) {
|
|
348
348
|
const trimmed = text.trim();
|
|
349
|
+
const parse = (source) => {
|
|
350
|
+
try {
|
|
351
|
+
return JSON.parse(source);
|
|
352
|
+
}
|
|
353
|
+
catch (error) {
|
|
354
|
+
// Models sometimes put ordinary ASCII quotes inside a JSON string
|
|
355
|
+
// (for example: `reason: "支持..."`). Repair only quotes that are
|
|
356
|
+
// clearly not structural: a closing quote is followed by JSON
|
|
357
|
+
// punctuation, while an embedded quote is followed by content.
|
|
358
|
+
let repaired = "";
|
|
359
|
+
let inString = false;
|
|
360
|
+
let escaped = false;
|
|
361
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
362
|
+
const character = source[index];
|
|
363
|
+
if (character !== '"') {
|
|
364
|
+
repaired += character;
|
|
365
|
+
if (inString && character === "\\" && !escaped)
|
|
366
|
+
escaped = true;
|
|
367
|
+
else
|
|
368
|
+
escaped = false;
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
if (escaped) {
|
|
372
|
+
repaired += character;
|
|
373
|
+
escaped = false;
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
376
|
+
if (!inString) {
|
|
377
|
+
inString = true;
|
|
378
|
+
repaired += character;
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
381
|
+
const next = source.slice(index + 1).trimStart()[0];
|
|
382
|
+
if ([",", "}", "]", ":"].includes(next ?? "") || source.slice(index + 1).trim() === "") {
|
|
383
|
+
inString = false;
|
|
384
|
+
repaired += character;
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
repaired += "\\\"";
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
try {
|
|
391
|
+
return JSON.parse(repaired);
|
|
392
|
+
}
|
|
393
|
+
catch {
|
|
394
|
+
throw error;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
};
|
|
349
398
|
if (trimmed.startsWith("{") && trimmed.endsWith("}"))
|
|
350
|
-
return
|
|
399
|
+
return parse(trimmed);
|
|
351
400
|
const blocks = [...trimmed.matchAll(/```json\s*\n([\s\S]*?)\n```/gi)];
|
|
352
401
|
if (blocks.length !== 1)
|
|
353
402
|
throw new Error("output must contain exactly one fenced json object");
|
|
354
|
-
return
|
|
403
|
+
return parse(blocks[0][1]);
|
|
355
404
|
}
|
|
356
405
|
/**
|
|
357
406
|
* Build the authoritative frontend-implementation-contract sourceBinding from
|
|
@@ -2455,9 +2455,38 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
2455
2455
|
sourceContext,
|
|
2456
2456
|
].join("\n\n"),
|
|
2457
2457
|
},
|
|
2458
|
+
{
|
|
2459
|
+
id: "frontend-contract-json-pi",
|
|
2460
|
+
depends_on: [
|
|
2461
|
+
"frontend-plan-revision-pi",
|
|
2462
|
+
"frontend-plan-pi",
|
|
2463
|
+
"frontend-final-design-review-pi",
|
|
2464
|
+
"frontend-design-review-pi",
|
|
2465
|
+
],
|
|
2466
|
+
dependsPolicy: "all-or-condition-skip",
|
|
2467
|
+
role: "planner",
|
|
2468
|
+
executor: "pi",
|
|
2469
|
+
complexity: "MED",
|
|
2470
|
+
writePolicy: "read-only",
|
|
2471
|
+
outputMode: "structured-required",
|
|
2472
|
+
retryPolicy: STRUCTURED_REQUIRED_PI_RETRY_POLICY,
|
|
2473
|
+
allowedPaths: readOnlyPaths,
|
|
2474
|
+
forbiddenPaths,
|
|
2475
|
+
skills: FRONTEND_IMPLEMENTATION_SKILLS,
|
|
2476
|
+
outputContract: "Return exactly one JSON object conforming to frontend-implementation-contract-v1. No Markdown, prose, comments, or code fences.",
|
|
2477
|
+
subtask_prompt: [
|
|
2478
|
+
"Convert the effective reviewed frontend plan into the canonical frontend-implementation-contract-v1 JSON.",
|
|
2479
|
+
"Use frontend-plan-revision-pi when it is FINISHED; otherwise use frontend-plan-pi. Confirm the effective design review passed before producing the contract.",
|
|
2480
|
+
"Return only the JSON object. Do not wrap it in Markdown or a code fence. Do not add explanatory text.",
|
|
2481
|
+
"Preserve all requirement expectedOutcome, interaction trigger/expectedBehavior, target files, verification targets, Mock/API decisions, and Real Integration Gap from the effective plan.",
|
|
2482
|
+
frontendContractSchemaBlock,
|
|
2483
|
+
sourceContext,
|
|
2484
|
+
].join("\n\n"),
|
|
2485
|
+
},
|
|
2458
2486
|
{
|
|
2459
2487
|
id: "frontend-prewrite-gate-shell",
|
|
2460
2488
|
depends_on: [
|
|
2489
|
+
"frontend-contract-json-pi",
|
|
2461
2490
|
"frontend-final-design-review-pi",
|
|
2462
2491
|
"frontend-design-review-pi",
|
|
2463
2492
|
"frontend-plan-revision-pi",
|
|
@@ -2476,8 +2505,8 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
2476
2505
|
commands: [],
|
|
2477
2506
|
frontendPrewriteGate: {
|
|
2478
2507
|
schemaVersion: 1,
|
|
2479
|
-
planFromNodeId: "frontend-
|
|
2480
|
-
planFallbackFromNodeIds: ["frontend-plan-pi"],
|
|
2508
|
+
planFromNodeId: "frontend-contract-json-pi",
|
|
2509
|
+
planFallbackFromNodeIds: ["frontend-plan-revision-pi", "frontend-plan-pi"],
|
|
2481
2510
|
reviewFromNodeId: "frontend-final-design-review-pi",
|
|
2482
2511
|
reviewFallbackFromNodeIds: ["frontend-design-review-pi"],
|
|
2483
2512
|
requiredRequirementIds: requirementIds,
|
|
@@ -5287,7 +5316,7 @@ async function buildHybridDagForTemplate(sources, template) {
|
|
|
5287
5316
|
else if (template === "review-gated-dag")
|
|
5288
5317
|
spec = buildReviewGatedHybridDag(standard, sources);
|
|
5289
5318
|
else
|
|
5290
|
-
spec = buildSupervisedHybridDag(standard, sources);
|
|
5319
|
+
spec = await buildSupervisedHybridDag(standard, sources);
|
|
5291
5320
|
}
|
|
5292
5321
|
applyProjectGovernanceReview(spec, template, sources);
|
|
5293
5322
|
// New generate path always emits DagSpec v4 + bindings.
|
|
@@ -5721,10 +5750,12 @@ function buildWriteSetGateNode(sources) {
|
|
|
5721
5750
|
},
|
|
5722
5751
|
};
|
|
5723
5752
|
}
|
|
5724
|
-
function buildSoftVerifyNode(sources) {
|
|
5753
|
+
async function buildSoftVerifyNode(sources) {
|
|
5725
5754
|
const implementId = implementationNodeId();
|
|
5726
5755
|
const strategy = resolveDagVerifyStrategy(sources.taskConfig, "1");
|
|
5727
|
-
const fallbackCommands =
|
|
5756
|
+
const fallbackCommands = sources.repoRoot
|
|
5757
|
+
? (await discoverFrontendFallbackVerifyCommands(sources.repoRoot)).staticCommands
|
|
5758
|
+
: ["npm run typecheck"];
|
|
5728
5759
|
const focusedIntermediate = sources.verifyCommands?.intermediate.filter((command) => !isFullSuiteVerifyCommand(command));
|
|
5729
5760
|
const plannedIntermediate = applyMavenVerificationPlanning({
|
|
5730
5761
|
repoRoot: sources.repoRoot,
|
|
@@ -5966,7 +5997,7 @@ function resolveSupervisedConvergence(taskConfig) {
|
|
|
5966
5997
|
chainNodeIds: [...SUPERVISED_CONVERGENCE_CHAIN_NODE_IDS],
|
|
5967
5998
|
};
|
|
5968
5999
|
}
|
|
5969
|
-
function buildSupervisedHybridDag(standard, sources) {
|
|
6000
|
+
async function buildSupervisedHybridDag(standard, sources) {
|
|
5970
6001
|
const contract = getTaskOrThrow(standard, "contract-pi");
|
|
5971
6002
|
const scoutSrc = getTaskOrThrow(standard, "scout-src");
|
|
5972
6003
|
const scoutTests = getTaskOrThrow(standard, "scout-tests");
|
|
@@ -6018,7 +6049,7 @@ function buildSupervisedHybridDag(standard, sources) {
|
|
|
6018
6049
|
"final-write-set-audit-format-repair-pi",
|
|
6019
6050
|
],
|
|
6020
6051
|
}),
|
|
6021
|
-
buildSoftVerifyNode(sources),
|
|
6052
|
+
await buildSoftVerifyNode(sources),
|
|
6022
6053
|
buildProcessSupervisorNode(sources),
|
|
6023
6054
|
buildProcessGateNode(sources),
|
|
6024
6055
|
buildRepairNode(sources),
|
package/harness.json
CHANGED
|
@@ -58,9 +58,9 @@
|
|
|
58
58
|
"executors": {
|
|
59
59
|
"pi": {
|
|
60
60
|
"description": "Pi planning, review, diagnosis, and bounded writing when DAG toolProfile=write",
|
|
61
|
-
"LOW": "
|
|
62
|
-
"MED": "
|
|
63
|
-
"HIGH": "
|
|
61
|
+
"LOW": {"model": "deepseek/deepseek-v4-flash", "thinking": "high"},
|
|
62
|
+
"MED": {"model": "deepseek/deepseek-v4-flash", "thinking": "max"},
|
|
63
|
+
"HIGH": {"model": "deepseek/deepseek-v4-flash", "thinking": "max"}
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
}
|