@kognai/orchestrator-core 0.2.6 → 0.2.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.
|
@@ -68,6 +68,16 @@ class CodingAgent {
|
|
|
68
68
|
delete task._escalateNext;
|
|
69
69
|
(0, orchestrate_engine_1.log)(orchestrate_engine_1.c.magenta, ` ⤴ [ESCALATE] ${task.id}: prior ${escalation} → upgrading to ${model}`);
|
|
70
70
|
}
|
|
71
|
+
// TICKET-349 (trigger fix): when the previous attempt was rejected for
|
|
72
|
+
// truncation by the supervisor (authoritative), force the multi-pass
|
|
73
|
+
// continuation loop on this attempt's generated file(s) — even if the coder's
|
|
74
|
+
// detectTruncation() heuristic thinks the file looks complete. The supervisor
|
|
75
|
+
// already determined it isn't. Consumed once here.
|
|
76
|
+
const forceContinuation = task._forceContinuation === true;
|
|
77
|
+
if (forceContinuation) {
|
|
78
|
+
delete task._forceContinuation;
|
|
79
|
+
(0, orchestrate_engine_1.log)(orchestrate_engine_1.c.magenta, ` ⤴ [ASSEMBLE] ${task.id}: prior TRUNCATION reject → forcing multi-pass continuation on this attempt`);
|
|
80
|
+
}
|
|
71
81
|
(0, orchestrate_engine_1.log)(orchestrate_engine_1.c.gray, ` -> Using ${model} [${routingReason}]`);
|
|
72
82
|
// B.12: Compress context before cloud calls to reduce token spend 70-80%
|
|
73
83
|
if (provider === 'clawrouter' || provider === 'anthropic') {
|
|
@@ -320,36 +330,58 @@ Write ONLY the content for "${filepath}". Rules:
|
|
|
320
330
|
fileContent = await this.fixJsonWithOllama(fileContent, filepath);
|
|
321
331
|
}
|
|
322
332
|
}
|
|
323
|
-
//
|
|
324
|
-
//
|
|
325
|
-
//
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
333
|
+
// TICKET-349: multi-pass chunked generation. The OpenClaw gateway clamps
|
|
334
|
+
// output to ~4096 tokens regardless of the requested max_tokens, so a file
|
|
335
|
+
// larger than one chunk gets cut mid-statement → [TRUNCATION] reject, no
|
|
336
|
+
// matter how capable the model is (deepseek AND sonnet truncate at the
|
|
337
|
+
// same length). Decompose the GENERATION: keep issuing continuation passes
|
|
338
|
+
// and appending until the file is complete (no truncation) or we hit the
|
|
339
|
+
// chunk cap. Works for ALL providers (previously clawrouter/ollama-only).
|
|
340
|
+
// Bounded by KOGNAI_MAX_CONTINUATION_CHUNKS (default 5 → ~5×4k≈20k output)
|
|
341
|
+
// and a no-progress guard so it can never loop forever.
|
|
342
|
+
const MAX_CONTINUATION_CHUNKS = parseInt(process.env.KOGNAI_MAX_CONTINUATION_CHUNKS ?? '5', 10);
|
|
343
|
+
let chunk = 0;
|
|
344
|
+
// TICKET-349 (trigger fix): fire on detectTruncation OR a forced first
|
|
345
|
+
// pass (set when the supervisor truncation-rejected the prior attempt).
|
|
346
|
+
// The forced pass only applies to chunk 0; after that the loop continues
|
|
347
|
+
// purely on detectTruncation, and the no-progress guard stops it if the
|
|
348
|
+
// file is actually complete (a continuation that adds nothing → break).
|
|
349
|
+
while ((this.detectTruncation(fileContent) || (forceContinuation && chunk === 0)) && chunk < MAX_CONTINUATION_CHUNKS) {
|
|
350
|
+
chunk++;
|
|
351
|
+
(0, orchestrate_engine_1.log)(orchestrate_engine_1.c.yellow, ` ! TRUNCATION in ${filepath} — continuation pass ${chunk}/${MAX_CONTINUATION_CHUNKS} (gateway ~4k output cap)...`);
|
|
352
|
+
const continuationPrompt = `The previous response for "${filepath}" was TRUNCATED — it ended mid-function or with an incomplete block. Here is the tail of what exists so far:
|
|
330
353
|
|
|
331
354
|
\`\`\`typescript
|
|
332
355
|
${fileContent.substring(fileContent.length - 1500)}
|
|
333
356
|
\`\`\`
|
|
334
357
|
|
|
335
|
-
Continue from where it left off and output ONLY the remaining code (no duplicated content
|
|
358
|
+
Continue EXACTLY from where it left off and output ONLY the remaining code (no duplicated content, no preamble, no markdown fences). End the file with its final closing brace.`;
|
|
359
|
+
let grew = false;
|
|
336
360
|
try {
|
|
337
|
-
const contResponse = await (0, orchestrate_engine_1.callLLM)(provider, model, this.systemPrompt, continuationPrompt, 120000, this.name, `${task.id}
|
|
361
|
+
const contResponse = await (0, orchestrate_engine_1.callLLM)(provider, model, this.systemPrompt, continuationPrompt, 120000, this.name, `${task.id}_continuation_${chunk}`);
|
|
338
362
|
let contContent = contResponse.choices?.[0]?.message?.content || '';
|
|
339
363
|
contContent = contContent.replace(/<think>[\s\S]*?<\/think>/g, '').trim();
|
|
340
364
|
const contBlocks = this.extractCodeBlocks(contContent);
|
|
341
365
|
const continuation = contBlocks.length > 0 ? contBlocks[0] : this.stripResidualFences(contContent);
|
|
342
366
|
if (continuation.length > 50) {
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
(0, orchestrate_engine_1.log)(orchestrate_engine_1.c.green, ` ✓ Continuation merged for ${filepath} (+${continuation.length} chars)`);
|
|
367
|
+
fileContent = this.stripResidualFences(fileContent + '\n' + continuation);
|
|
368
|
+
grew = true;
|
|
369
|
+
(0, orchestrate_engine_1.log)(orchestrate_engine_1.c.green, ` ✓ Pass ${chunk} merged for ${filepath} (+${continuation.length} chars, total ${fileContent.length})`);
|
|
347
370
|
}
|
|
348
371
|
}
|
|
349
372
|
catch (contErr) {
|
|
350
|
-
(0, orchestrate_engine_1.log)(orchestrate_engine_1.c.yellow, ` ! Continuation failed: ${contErr.message}`);
|
|
373
|
+
(0, orchestrate_engine_1.log)(orchestrate_engine_1.c.yellow, ` ! Continuation pass ${chunk} failed: ${contErr.message}`);
|
|
374
|
+
}
|
|
375
|
+
// No-progress guard: if a pass added nothing usable, stop — further
|
|
376
|
+
// passes won't help and would just burn budget.
|
|
377
|
+
if (!grew) {
|
|
378
|
+
(0, orchestrate_engine_1.log)(orchestrate_engine_1.c.yellow, ` ! Continuation made no progress — stopping at pass ${chunk}`);
|
|
379
|
+
break;
|
|
351
380
|
}
|
|
352
381
|
}
|
|
382
|
+
if (chunk > 0 && !this.detectTruncation(fileContent)) {
|
|
383
|
+
(0, orchestrate_engine_1.log)(orchestrate_engine_1.c.green, ` ✓ ${filepath} assembled complete over ${chunk + 1} pass(es)`);
|
|
384
|
+
}
|
|
353
385
|
createdFiles.push({ path: filepath, content: fileContent });
|
|
354
386
|
}
|
|
355
387
|
catch (error) {
|
|
@@ -915,6 +915,15 @@ ONLY output the JSON array. No markdown, no explanation.`;
|
|
|
915
915
|
// escalation at typical token volumes — well under the daily wallet.
|
|
916
916
|
// Cleared in CodingAgent.execute after consumption.
|
|
917
917
|
task._escalateNext = 'TRUNCATION';
|
|
918
|
+
// TICKET-349 (trigger fix): the supervisor's truncation verdict is the
|
|
919
|
+
// AUTHORITATIVE "this file is incomplete" signal — stronger than the
|
|
920
|
+
// coder's detectTruncation() brace-heuristic, which lets balanced-but-
|
|
921
|
+
// incomplete files through (verified 2026-06-13: 0 continuation passes
|
|
922
|
+
// fired despite repeated truncation rejects). Force the coder's
|
|
923
|
+
// multi-pass continuation loop on the next attempt so it ASSEMBLES the
|
|
924
|
+
// file across passes instead of one-shot-regenerating (which re-truncates
|
|
925
|
+
// even on Sonnet). Consumed + cleared in CodingAgent.execute.
|
|
926
|
+
task._forceContinuation = true;
|
|
918
927
|
}
|
|
919
928
|
else if (task._integrityFailed) {
|
|
920
929
|
(0, engine_primitives_1.log)(engine_primitives_1.c.yellow, `\n↻ Task ${task.id} REJECTED on attempt ${attempt} (${review.score}/100) [INTEGRITY-FAILED]`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kognai/orchestrator-core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"description": "Kognai sovereign orchestrator — core engine (template-agnostic). Shared by all products (Kognai/coding, Voxight/market-intel, Invoica/fin-compliance); each supplies only its template. Replaces per-repo forks of orchestrate-agents-v2 / sprint-runner / lib.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "SkinGem",
|