zelari-code 1.5.5 → 1.7.0
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/dist/cli/app.js +13 -2
- package/dist/cli/app.js.map +1 -1
- package/dist/cli/hooks/historyCompaction.js +125 -0
- package/dist/cli/hooks/historyCompaction.js.map +1 -0
- package/dist/cli/hooks/useChatTurn.js +121 -23
- package/dist/cli/hooks/useChatTurn.js.map +1 -1
- package/dist/cli/main.bundled.js +647 -44
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/runHeadless.js +79 -8
- package/dist/cli/runHeadless.js.map +1 -1
- package/dist/cli/slashHandlers/provider.js.map +1 -1
- package/dist/cli/utils/envNumber.js +62 -0
- package/dist/cli/utils/envNumber.js.map +1 -0
- package/package.json +1 -1
package/dist/cli/main.bundled.js
CHANGED
|
@@ -18401,6 +18401,366 @@ var init_systemPromptBuilder = __esm({
|
|
|
18401
18401
|
}
|
|
18402
18402
|
});
|
|
18403
18403
|
|
|
18404
|
+
// packages/core/dist/agents/languagePolicy.js
|
|
18405
|
+
function isLetter(cp) {
|
|
18406
|
+
return cp >= 65 && cp <= 90 || // A-Z
|
|
18407
|
+
cp >= 97 && cp <= 122 || // a-z
|
|
18408
|
+
cp >= 192 && cp <= 591 || // Latin-1 supplement + Extended A/B
|
|
18409
|
+
cp >= 7680 && cp <= 7935 || // Latin Extended Additional
|
|
18410
|
+
cp >= 880 && cp <= 1023 || // Greek
|
|
18411
|
+
cp >= 1024 && cp <= 1279 || // Cyrillic
|
|
18412
|
+
cp >= 1424 && cp <= 1535 || // Hebrew
|
|
18413
|
+
cp >= 1536 && cp <= 1791 || // Arabic
|
|
18414
|
+
cp >= 2304 && cp <= 2431 || // Devanagari
|
|
18415
|
+
cp >= 12352 && cp <= 12543 || // Hiragana + Katakana
|
|
18416
|
+
cp >= 19968 && cp <= 40959 || // CJK Unified
|
|
18417
|
+
cp >= 44032 && cp <= 55215;
|
|
18418
|
+
}
|
|
18419
|
+
function isLatinChar(cp) {
|
|
18420
|
+
return cp >= 65 && cp <= 90 || // A-Z
|
|
18421
|
+
cp >= 97 && cp <= 122 || // a-z
|
|
18422
|
+
cp >= 192 && cp <= 591 || // Latin-1 supplement + Extended A/B
|
|
18423
|
+
cp >= 7680 && cp <= 7935;
|
|
18424
|
+
}
|
|
18425
|
+
function detectResponseLanguage(text) {
|
|
18426
|
+
if (!text || text.trim().length === 0)
|
|
18427
|
+
return "it";
|
|
18428
|
+
const stripped = text.replace(/```[\s\S]*?```/g, " ").replace(/`[^`]*`/g, " ").toLowerCase();
|
|
18429
|
+
if (stripped.trim().length === 0)
|
|
18430
|
+
return "it";
|
|
18431
|
+
let totalLetters = 0;
|
|
18432
|
+
let nonLatinLetters = 0;
|
|
18433
|
+
for (let i = 0; i < stripped.length; i++) {
|
|
18434
|
+
const cp = stripped.codePointAt(i);
|
|
18435
|
+
if (cp === void 0)
|
|
18436
|
+
continue;
|
|
18437
|
+
if (!isLetter(cp))
|
|
18438
|
+
continue;
|
|
18439
|
+
totalLetters += 1;
|
|
18440
|
+
if (!isLatinChar(cp))
|
|
18441
|
+
nonLatinLetters += 1;
|
|
18442
|
+
}
|
|
18443
|
+
const nonLatinRatio = totalLetters > 0 ? nonLatinLetters / totalLetters : 0;
|
|
18444
|
+
const SCRIPT_DOMINANCE_THRESHOLD = 0.3;
|
|
18445
|
+
if (nonLatinRatio >= SCRIPT_DOMINANCE_THRESHOLD) {
|
|
18446
|
+
for (const { lang, ranges } of SCRIPT_RANGES) {
|
|
18447
|
+
for (const [lo, hi] of ranges) {
|
|
18448
|
+
for (let i = 0; i < stripped.length; i++) {
|
|
18449
|
+
const cp = stripped.codePointAt(i);
|
|
18450
|
+
if (cp !== void 0 && cp >= lo && cp <= hi)
|
|
18451
|
+
return lang;
|
|
18452
|
+
}
|
|
18453
|
+
}
|
|
18454
|
+
}
|
|
18455
|
+
}
|
|
18456
|
+
const ACCENT_VOTES = [
|
|
18457
|
+
// Italian-specific
|
|
18458
|
+
{ lang: "it", weight: 2, chars: "\xE0\xE8\xE9\xEC\xF2\xF3\xF9" },
|
|
18459
|
+
// French-only accents
|
|
18460
|
+
{ lang: "fr", weight: 2, chars: "\xE2\xE7\xEA\xEB\xEE\xEF\xF4\xFB\u0153\xE6" },
|
|
18461
|
+
// German-only
|
|
18462
|
+
{ lang: "de", weight: 3, chars: "\xE4\xF6\xFC\xDF" },
|
|
18463
|
+
// Spanish-only (ñ is the discriminator)
|
|
18464
|
+
{ lang: "es", weight: 3, chars: "\xF1\xE1\xED\xF3\xFA\xBF\xA1" },
|
|
18465
|
+
// Portuguese-only (ã/õ are the discriminator)
|
|
18466
|
+
{ lang: "pt", weight: 3, chars: "\xE3\xF5\xE1\xE9\xED\xF3\xFA\xE2\xEA\xF4" },
|
|
18467
|
+
// Dutch-only
|
|
18468
|
+
{ lang: "nl", weight: 2, chars: "\xE1\xE8\xE9\xEB\xED\xF3\xF6\xFA\xFC" }
|
|
18469
|
+
];
|
|
18470
|
+
const accentScores = {};
|
|
18471
|
+
for (const { lang, weight, chars } of ACCENT_VOTES) {
|
|
18472
|
+
let hits = 0;
|
|
18473
|
+
for (const c of chars)
|
|
18474
|
+
if (stripped.includes(c))
|
|
18475
|
+
hits += 1;
|
|
18476
|
+
if (hits > 0)
|
|
18477
|
+
accentScores[lang] = (accentScores[lang] ?? 0) + weight * hits;
|
|
18478
|
+
}
|
|
18479
|
+
const accentOrdered = Object.entries(accentScores).sort((a, b) => b[1] - a[1]).map(([l]) => l);
|
|
18480
|
+
if (accentOrdered.length > 0 && accentOrdered.length === 1) {
|
|
18481
|
+
return accentOrdered[0];
|
|
18482
|
+
}
|
|
18483
|
+
if (accentOrdered.length > 1) {
|
|
18484
|
+
return accentOrdered[0];
|
|
18485
|
+
}
|
|
18486
|
+
const tokens = stripped.split(/[\s,;.!?()\[\]{}<>:'"\\/]+/).filter((t) => t.length > 1);
|
|
18487
|
+
if (tokens.length === 0)
|
|
18488
|
+
return "it";
|
|
18489
|
+
const scores = {};
|
|
18490
|
+
for (const [lang, words] of Object.entries(FUNCTION_WORDS)) {
|
|
18491
|
+
let hits = 0;
|
|
18492
|
+
const tokenSet = new Set(tokens);
|
|
18493
|
+
for (const w of words) {
|
|
18494
|
+
if (tokenSet.has(w))
|
|
18495
|
+
hits += 1;
|
|
18496
|
+
}
|
|
18497
|
+
if (hits > 0)
|
|
18498
|
+
scores[lang] = hits;
|
|
18499
|
+
}
|
|
18500
|
+
const ordered = Object.entries(scores).sort((a, b) => b[1] - a[1] || (a[0] === "it" ? -1 : b[0] === "it" ? 1 : 0)).map(([l]) => l);
|
|
18501
|
+
if (ordered.length > 0)
|
|
18502
|
+
return ordered[0];
|
|
18503
|
+
return "it";
|
|
18504
|
+
}
|
|
18505
|
+
function resolveResponseLanguage(text, env = process.env) {
|
|
18506
|
+
const raw = env.ZELARI_RESPONSE_LANG?.trim().toLowerCase();
|
|
18507
|
+
if (raw && raw !== "auto") {
|
|
18508
|
+
if (raw in LANGUAGE_LABELS)
|
|
18509
|
+
return raw;
|
|
18510
|
+
const sink = globalThis.__zelariLangWarnSink ?? ((msg) => console.warn(`[zelari-code] ${msg}`));
|
|
18511
|
+
sink(`ZELARI_RESPONSE_LANG='${env.ZELARI_RESPONSE_LANG}' is not a supported language (known: ${Object.keys(LANGUAGE_LABELS).join(", ")}, or 'auto'). Falling back to detection.`);
|
|
18512
|
+
}
|
|
18513
|
+
return detectResponseLanguage(text);
|
|
18514
|
+
}
|
|
18515
|
+
function buildLanguageDirective(lang) {
|
|
18516
|
+
const label = LANGUAGE_LABELS[lang];
|
|
18517
|
+
return `# Response Language \u2014 ${label}
|
|
18518
|
+
|
|
18519
|
+
Reply in **${label}** for the entirety of your response, including any final synthesis, clarifying questions, and tool-call descriptions. This directive applies in all modes (single agent, council members, zelari slices):
|
|
18520
|
+
|
|
18521
|
+
- Read the user's last message in context and mirror its language. If the user's prompt is in ${label}, reply in ${label}. If it mixes languages, default to ${label}.
|
|
18522
|
+
- Do not switch to English (or any other language) for code, error messages, tool names, file paths, or technical terms \u2014 code is language-neutral and stays as-is.
|
|
18523
|
+
- If the user explicitly asks for a different language in the same turn (e.g. "reply in English"), honor that request for the rest of this turn only.
|
|
18524
|
+
- For clarifying questions (---QUESTION--- blocks), write the \`question\` and \`choices\` fields in ${label} so the picker UI matches the user's language.
|
|
18525
|
+
- For council synthesis (Lucifero) and any final-answer turn, the user-visible text is in ${label}; intermediate specialist notes that the user never sees directly can stay in their working language.`;
|
|
18526
|
+
}
|
|
18527
|
+
function buildLanguagePolicyModule(lang) {
|
|
18528
|
+
return {
|
|
18529
|
+
type: LANGUAGE_POLICY_MODULE_TYPE,
|
|
18530
|
+
title: `Response Language (${LANGUAGE_LABELS[lang]})`,
|
|
18531
|
+
priority: 5,
|
|
18532
|
+
content: buildLanguageDirective(lang)
|
|
18533
|
+
};
|
|
18534
|
+
}
|
|
18535
|
+
function buildLanguagePolicyModuleFor(userText, env = process.env) {
|
|
18536
|
+
return buildLanguagePolicyModule(resolveResponseLanguage(userText, env));
|
|
18537
|
+
}
|
|
18538
|
+
var LANGUAGE_LABELS, SCRIPT_RANGES, FUNCTION_WORDS, LANGUAGE_POLICY_MODULE_TYPE;
|
|
18539
|
+
var init_languagePolicy = __esm({
|
|
18540
|
+
"packages/core/dist/agents/languagePolicy.js"() {
|
|
18541
|
+
"use strict";
|
|
18542
|
+
LANGUAGE_LABELS = {
|
|
18543
|
+
it: "Italian",
|
|
18544
|
+
en: "English",
|
|
18545
|
+
fr: "French",
|
|
18546
|
+
es: "Spanish",
|
|
18547
|
+
de: "German",
|
|
18548
|
+
pt: "Portuguese",
|
|
18549
|
+
nl: "Dutch",
|
|
18550
|
+
zh: "Chinese (Simplified)",
|
|
18551
|
+
ja: "Japanese",
|
|
18552
|
+
ko: "Korean",
|
|
18553
|
+
ru: "Russian",
|
|
18554
|
+
ar: "Arabic"
|
|
18555
|
+
};
|
|
18556
|
+
SCRIPT_RANGES = [
|
|
18557
|
+
// v1.7.0 fix: ja/kr MUST come before zh — kanji (CJK Unified) and hangul
|
|
18558
|
+
// glyphs can fall in either's range when both languages are present, but
|
|
18559
|
+
// hiragana/katakana (ja) and hangul jamo (kr) are unique owners. A mixed
|
|
18560
|
+
// string like "こんにちは、関数の作り方を…" had kanji that triggered the
|
|
18561
|
+
// zh range first, returning 'zh' for a clearly-Japanese message.
|
|
18562
|
+
{ lang: "ja", ranges: [[12352, 12447], [12448, 12543]] },
|
|
18563
|
+
{ lang: "ko", ranges: [[44032, 55215], [4352, 4607]] },
|
|
18564
|
+
{ lang: "zh", ranges: [[19968, 40959]] },
|
|
18565
|
+
{ lang: "ar", ranges: [[1536, 1791]] },
|
|
18566
|
+
{ lang: "ru", ranges: [[1024, 1279]] }
|
|
18567
|
+
];
|
|
18568
|
+
FUNCTION_WORDS = {
|
|
18569
|
+
it: [
|
|
18570
|
+
"il",
|
|
18571
|
+
"lo",
|
|
18572
|
+
"la",
|
|
18573
|
+
"gli",
|
|
18574
|
+
"le",
|
|
18575
|
+
"un",
|
|
18576
|
+
"uno",
|
|
18577
|
+
"una",
|
|
18578
|
+
"di",
|
|
18579
|
+
"del",
|
|
18580
|
+
"della",
|
|
18581
|
+
"dei",
|
|
18582
|
+
"e",
|
|
18583
|
+
"che",
|
|
18584
|
+
"chi",
|
|
18585
|
+
"come",
|
|
18586
|
+
"con",
|
|
18587
|
+
"per",
|
|
18588
|
+
"non",
|
|
18589
|
+
"sono",
|
|
18590
|
+
"questo",
|
|
18591
|
+
"questa",
|
|
18592
|
+
"quello",
|
|
18593
|
+
"quella",
|
|
18594
|
+
"fare",
|
|
18595
|
+
"fai",
|
|
18596
|
+
"crea",
|
|
18597
|
+
"creare",
|
|
18598
|
+
"mostra",
|
|
18599
|
+
"ciao",
|
|
18600
|
+
"grazie",
|
|
18601
|
+
"bene",
|
|
18602
|
+
"male",
|
|
18603
|
+
"puoi",
|
|
18604
|
+
"come",
|
|
18605
|
+
"cosa",
|
|
18606
|
+
"questo"
|
|
18607
|
+
],
|
|
18608
|
+
en: [
|
|
18609
|
+
"the",
|
|
18610
|
+
"a",
|
|
18611
|
+
"an",
|
|
18612
|
+
"of",
|
|
18613
|
+
"and",
|
|
18614
|
+
"is",
|
|
18615
|
+
"are",
|
|
18616
|
+
"was",
|
|
18617
|
+
"were",
|
|
18618
|
+
"to",
|
|
18619
|
+
"for",
|
|
18620
|
+
"with",
|
|
18621
|
+
"that",
|
|
18622
|
+
"this",
|
|
18623
|
+
"these",
|
|
18624
|
+
"those",
|
|
18625
|
+
"do",
|
|
18626
|
+
"does",
|
|
18627
|
+
"make",
|
|
18628
|
+
"create",
|
|
18629
|
+
"show",
|
|
18630
|
+
"hello",
|
|
18631
|
+
"help",
|
|
18632
|
+
"please",
|
|
18633
|
+
"thanks",
|
|
18634
|
+
"how",
|
|
18635
|
+
"what",
|
|
18636
|
+
"where",
|
|
18637
|
+
"why"
|
|
18638
|
+
],
|
|
18639
|
+
fr: [
|
|
18640
|
+
"le",
|
|
18641
|
+
"la",
|
|
18642
|
+
"les",
|
|
18643
|
+
"un",
|
|
18644
|
+
"une",
|
|
18645
|
+
"des",
|
|
18646
|
+
"de",
|
|
18647
|
+
"du",
|
|
18648
|
+
"et",
|
|
18649
|
+
"est",
|
|
18650
|
+
"sont",
|
|
18651
|
+
"que",
|
|
18652
|
+
"qui",
|
|
18653
|
+
"avec",
|
|
18654
|
+
"pour",
|
|
18655
|
+
"dans",
|
|
18656
|
+
"pas",
|
|
18657
|
+
"oui",
|
|
18658
|
+
"non",
|
|
18659
|
+
"faire",
|
|
18660
|
+
"cr\xE9er",
|
|
18661
|
+
"bonjour",
|
|
18662
|
+
"merci",
|
|
18663
|
+
"bien"
|
|
18664
|
+
],
|
|
18665
|
+
es: [
|
|
18666
|
+
"el",
|
|
18667
|
+
"la",
|
|
18668
|
+
"los",
|
|
18669
|
+
"las",
|
|
18670
|
+
"un",
|
|
18671
|
+
"una",
|
|
18672
|
+
"de",
|
|
18673
|
+
"del",
|
|
18674
|
+
"y",
|
|
18675
|
+
"es",
|
|
18676
|
+
"son",
|
|
18677
|
+
"que",
|
|
18678
|
+
"con",
|
|
18679
|
+
"por",
|
|
18680
|
+
"para",
|
|
18681
|
+
"no",
|
|
18682
|
+
"s\xED",
|
|
18683
|
+
"hacer",
|
|
18684
|
+
"crear",
|
|
18685
|
+
"mostrar",
|
|
18686
|
+
"hola",
|
|
18687
|
+
"gracias",
|
|
18688
|
+
"bueno"
|
|
18689
|
+
],
|
|
18690
|
+
de: [
|
|
18691
|
+
"der",
|
|
18692
|
+
"die",
|
|
18693
|
+
"das",
|
|
18694
|
+
"den",
|
|
18695
|
+
"dem",
|
|
18696
|
+
"des",
|
|
18697
|
+
"und",
|
|
18698
|
+
"ist",
|
|
18699
|
+
"sind",
|
|
18700
|
+
"nicht",
|
|
18701
|
+
"mit",
|
|
18702
|
+
"f\xFCr",
|
|
18703
|
+
"auf",
|
|
18704
|
+
"zu",
|
|
18705
|
+
"ja",
|
|
18706
|
+
"nein",
|
|
18707
|
+
"machen",
|
|
18708
|
+
"erstellen",
|
|
18709
|
+
"zeigen",
|
|
18710
|
+
"hallo",
|
|
18711
|
+
"danke",
|
|
18712
|
+
"gut"
|
|
18713
|
+
],
|
|
18714
|
+
pt: [
|
|
18715
|
+
"o",
|
|
18716
|
+
"a",
|
|
18717
|
+
"os",
|
|
18718
|
+
"as",
|
|
18719
|
+
"um",
|
|
18720
|
+
"uma",
|
|
18721
|
+
"de",
|
|
18722
|
+
"do",
|
|
18723
|
+
"da",
|
|
18724
|
+
"e",
|
|
18725
|
+
"\xE9",
|
|
18726
|
+
"s\xE3o",
|
|
18727
|
+
"que",
|
|
18728
|
+
"com",
|
|
18729
|
+
"para",
|
|
18730
|
+
"n\xE3o",
|
|
18731
|
+
"sim",
|
|
18732
|
+
"fazer",
|
|
18733
|
+
"criar",
|
|
18734
|
+
"mostrar",
|
|
18735
|
+
"ol\xE1",
|
|
18736
|
+
"obrigado",
|
|
18737
|
+
"bom"
|
|
18738
|
+
],
|
|
18739
|
+
nl: [
|
|
18740
|
+
"de",
|
|
18741
|
+
"het",
|
|
18742
|
+
"een",
|
|
18743
|
+
"van",
|
|
18744
|
+
"en",
|
|
18745
|
+
"is",
|
|
18746
|
+
"zijn",
|
|
18747
|
+
"niet",
|
|
18748
|
+
"met",
|
|
18749
|
+
"voor",
|
|
18750
|
+
"ja",
|
|
18751
|
+
"nee",
|
|
18752
|
+
"doen",
|
|
18753
|
+
"maken",
|
|
18754
|
+
"tonen",
|
|
18755
|
+
"hallo",
|
|
18756
|
+
"dank",
|
|
18757
|
+
"goed"
|
|
18758
|
+
]
|
|
18759
|
+
};
|
|
18760
|
+
LANGUAGE_POLICY_MODULE_TYPE = "language-policy";
|
|
18761
|
+
}
|
|
18762
|
+
});
|
|
18763
|
+
|
|
18404
18764
|
// packages/core/dist/skills/index.js
|
|
18405
18765
|
var skills_exports = {};
|
|
18406
18766
|
__export(skills_exports, {
|
|
@@ -18408,14 +18768,19 @@ __export(skills_exports, {
|
|
|
18408
18768
|
ALL_TOOLS: () => ALL_TOOLS,
|
|
18409
18769
|
CODING_CATEGORY: () => CODING_CATEGORY,
|
|
18410
18770
|
CODING_SKILL_CATALOG: () => CODING_SKILL_CATALOG,
|
|
18771
|
+
LANGUAGE_POLICY_MODULE_TYPE: () => LANGUAGE_POLICY_MODULE_TYPE,
|
|
18411
18772
|
SINGLE_AGENT_IDENTITY_MODULE: () => SINGLE_AGENT_IDENTITY_MODULE,
|
|
18412
18773
|
SKILL_CATALOG: () => SKILL_CATALOG,
|
|
18413
18774
|
TOOL_DEFINITIONS: () => TOOL_DEFINITIONS,
|
|
18414
18775
|
VAULT_TOOL_DEFINITIONS: () => VAULT_TOOL_DEFINITIONS,
|
|
18415
18776
|
buildCustomParameters: () => buildCustomParameters,
|
|
18777
|
+
buildLanguageDirective: () => buildLanguageDirective,
|
|
18778
|
+
buildLanguagePolicyModule: () => buildLanguagePolicyModule,
|
|
18779
|
+
buildLanguagePolicyModuleFor: () => buildLanguagePolicyModuleFor,
|
|
18416
18780
|
buildSystemPrompt: () => buildSystemPrompt,
|
|
18417
18781
|
clearCustomTools: () => clearCustomTools,
|
|
18418
18782
|
cliToolToEnhanced: () => cliToolToEnhanced,
|
|
18783
|
+
detectResponseLanguage: () => detectResponseLanguage,
|
|
18419
18784
|
executeTool: () => executeTool,
|
|
18420
18785
|
findCodingSkillsByCategory: () => findCodingSkillsByCategory,
|
|
18421
18786
|
findCodingSkillsByTag: () => findCodingSkillsByTag,
|
|
@@ -18436,6 +18801,7 @@ __export(skills_exports, {
|
|
|
18436
18801
|
registerCustomTool: () => registerCustomTool,
|
|
18437
18802
|
registerSkill: () => registerSkill,
|
|
18438
18803
|
resolveAgentSkills: () => resolveAgentSkills,
|
|
18804
|
+
resolveResponseLanguage: () => resolveResponseLanguage,
|
|
18439
18805
|
resolveSkillDependencies: () => resolveSkillDependencies,
|
|
18440
18806
|
setWorkspaceStubs: () => setWorkspaceStubs,
|
|
18441
18807
|
unregisterCustomTool: () => unregisterCustomTool,
|
|
@@ -18453,6 +18819,7 @@ var init_skills2 = __esm({
|
|
|
18453
18819
|
init_harnessToolBridge();
|
|
18454
18820
|
init_promptModules();
|
|
18455
18821
|
init_systemPromptBuilder();
|
|
18822
|
+
init_languagePolicy();
|
|
18456
18823
|
}
|
|
18457
18824
|
});
|
|
18458
18825
|
|
|
@@ -18592,13 +18959,33 @@ var init_AgentHarness = __esm({
|
|
|
18592
18959
|
this.maxQueuedIterations = config2.maxQueuedIterations ?? 3;
|
|
18593
18960
|
this.maxToolLoopIterations = config2.maxToolLoopIterations ?? 30;
|
|
18594
18961
|
}
|
|
18962
|
+
/**
|
|
18963
|
+
* Snapshot of the live transcript (`this.config.messages`) as mutated
|
|
18964
|
+
* across `run()` iterations — the seed passed at construction plus any
|
|
18965
|
+
* assistant turns (with `toolCalls`) and tool results the loop appended.
|
|
18966
|
+
*
|
|
18967
|
+
* Used by the single-agent chat loop to carry rolling history across
|
|
18968
|
+
* turns: after a run completes, the caller reads the tail of this array
|
|
18969
|
+
* (the assistant/tool messages produced this turn) and feeds it back as
|
|
18970
|
+
* the seed for the next turn, so the model sees its own prior question
|
|
18971
|
+
* when the user answers with a short reply.
|
|
18972
|
+
*
|
|
18973
|
+
* The returned reference is the live array — callers MUST treat it as
|
|
18974
|
+
* read-only (do not mutate). Copy (`[...harness.getMessages()]`) before
|
|
18975
|
+
* retaining across runs.
|
|
18976
|
+
*
|
|
18977
|
+
* @since v1.6.0
|
|
18978
|
+
*/
|
|
18979
|
+
getMessages() {
|
|
18980
|
+
return this.config.messages;
|
|
18981
|
+
}
|
|
18595
18982
|
/**
|
|
18596
18983
|
* Member identity fields (memberId + memberName) to merge into every
|
|
18597
18984
|
* event payload. Returns an empty object when the run is a direct
|
|
18598
18985
|
* user prompt (no member context), so call sites can spread it
|
|
18599
18986
|
* unconditionally.
|
|
18600
18987
|
*
|
|
18601
|
-
* @since
|
|
18988
|
+
* @since v0.5.0
|
|
18602
18989
|
*/
|
|
18603
18990
|
memberFields() {
|
|
18604
18991
|
return {
|
|
@@ -23418,6 +23805,17 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
23418
23805
|
const sessionId = config2.sessionId ?? crypto.randomUUID();
|
|
23419
23806
|
const runMode = config2.runMode ?? "implementation";
|
|
23420
23807
|
const isDesignPhase = runMode === "design-phase";
|
|
23808
|
+
let councilLanguageModule;
|
|
23809
|
+
try {
|
|
23810
|
+
councilLanguageModule = buildLanguagePolicyModuleFor(userMessage);
|
|
23811
|
+
} catch {
|
|
23812
|
+
councilLanguageModule = {
|
|
23813
|
+
type: "language-policy",
|
|
23814
|
+
title: "Response Language",
|
|
23815
|
+
priority: 5,
|
|
23816
|
+
content: "# Response Language\nReply in the user's language when possible, otherwise Italian."
|
|
23817
|
+
};
|
|
23818
|
+
}
|
|
23421
23819
|
yield createBrainEvent("council_mode", sessionId, {
|
|
23422
23820
|
tier: councilTierFromSize(config2.councilSize),
|
|
23423
23821
|
councilSize: config2.councilSize,
|
|
@@ -23541,7 +23939,8 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
23541
23939
|
effectiveModel,
|
|
23542
23940
|
onToolCall: () => {
|
|
23543
23941
|
toolCalls += 1;
|
|
23544
|
-
}
|
|
23942
|
+
},
|
|
23943
|
+
languageModule: councilLanguageModule
|
|
23545
23944
|
});
|
|
23546
23945
|
} else if (isDesignPhase) {
|
|
23547
23946
|
enforceDesignPhaseToolEmissions(agent.id, emittedToolNames);
|
|
@@ -23679,7 +24078,8 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
23679
24078
|
effectiveModel,
|
|
23680
24079
|
onToolCall: () => {
|
|
23681
24080
|
toolCalls += 1;
|
|
23682
|
-
}
|
|
24081
|
+
},
|
|
24082
|
+
languageModule: councilLanguageModule
|
|
23683
24083
|
});
|
|
23684
24084
|
} else if (isDesignPhase) {
|
|
23685
24085
|
enforceDesignPhaseToolEmissions(oracle.id, emittedToolNames);
|
|
@@ -23847,7 +24247,8 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
23847
24247
|
effectiveModel,
|
|
23848
24248
|
onToolCall: () => {
|
|
23849
24249
|
toolCalls += 1;
|
|
23850
|
-
}
|
|
24250
|
+
},
|
|
24251
|
+
languageModule: councilLanguageModule
|
|
23851
24252
|
});
|
|
23852
24253
|
} else if (isDesignPhase) {
|
|
23853
24254
|
enforceDesignPhaseToolEmissions(chairman.id, emittedToolNames);
|
|
@@ -23907,7 +24308,8 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
23907
24308
|
onSuccessfulWrite: () => {
|
|
23908
24309
|
successfulWriteCount += 1;
|
|
23909
24310
|
},
|
|
23910
|
-
onCouncilStatus: callbacks.onCouncilStatus
|
|
24311
|
+
onCouncilStatus: callbacks.onCouncilStatus,
|
|
24312
|
+
languageModule: councilLanguageModule
|
|
23911
24313
|
});
|
|
23912
24314
|
}
|
|
23913
24315
|
}
|
|
@@ -23926,7 +24328,8 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
23926
24328
|
effectiveModel,
|
|
23927
24329
|
onToolCall: () => {
|
|
23928
24330
|
toolCalls += 1;
|
|
23929
|
-
}
|
|
24331
|
+
},
|
|
24332
|
+
languageModule: councilLanguageModule
|
|
23930
24333
|
});
|
|
23931
24334
|
}
|
|
23932
24335
|
if (chairmanProjectRoot) {
|
|
@@ -23944,7 +24347,8 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
23944
24347
|
onToolCall: () => {
|
|
23945
24348
|
toolCalls += 1;
|
|
23946
24349
|
},
|
|
23947
|
-
onCouncilStatus: callbacks.onCouncilStatus
|
|
24350
|
+
onCouncilStatus: callbacks.onCouncilStatus,
|
|
24351
|
+
languageModule: councilLanguageModule
|
|
23948
24352
|
});
|
|
23949
24353
|
}
|
|
23950
24354
|
}
|
|
@@ -24010,7 +24414,8 @@ async function* applyCompletionRetry(args) {
|
|
|
24010
24414
|
toolRegistry: args.config.tools,
|
|
24011
24415
|
providerStream: args.config.providerStream,
|
|
24012
24416
|
runMode: args.config.runMode,
|
|
24013
|
-
retryPrompt: buildImplementationVerifyRetryPrompt(retryTool)
|
|
24417
|
+
retryPrompt: buildImplementationVerifyRetryPrompt(retryTool),
|
|
24418
|
+
languageModule: args.languageModule
|
|
24014
24419
|
});
|
|
24015
24420
|
for await (const event of retryGenerator) {
|
|
24016
24421
|
if (event.type === "tool_execution_start") {
|
|
@@ -24068,7 +24473,8 @@ async function* applyImplementationWriteRetry(args) {
|
|
|
24068
24473
|
toolRegistry: args.config.tools,
|
|
24069
24474
|
providerStream: args.config.providerStream,
|
|
24070
24475
|
runMode: "implementation",
|
|
24071
|
-
retryPrompt: buildImplementationWriteRetryPrompt(args.userMessage)
|
|
24476
|
+
retryPrompt: buildImplementationWriteRetryPrompt(args.userMessage),
|
|
24477
|
+
languageModule: args.languageModule
|
|
24072
24478
|
});
|
|
24073
24479
|
for await (const event of retryGenerator) {
|
|
24074
24480
|
if (event.type === "tool_execution_start")
|
|
@@ -24137,7 +24543,8 @@ async function* runChairmanDeliveryLoop(args) {
|
|
|
24137
24543
|
toolRegistry: args.config.tools,
|
|
24138
24544
|
providerStream: args.config.providerStream,
|
|
24139
24545
|
runMode: "implementation",
|
|
24140
|
-
retryPrompt: buildDeliveryFixPrompt(blocking, args.userMessage)
|
|
24546
|
+
retryPrompt: buildDeliveryFixPrompt(blocking, args.userMessage),
|
|
24547
|
+
languageModule: args.languageModule
|
|
24141
24548
|
});
|
|
24142
24549
|
for await (const event of fixGenerator) {
|
|
24143
24550
|
if (event.type === "tool_execution_start")
|
|
@@ -24235,7 +24642,8 @@ async function* runChairmanFixLoop(args) {
|
|
|
24235
24642
|
toolRegistry: args.config.tools,
|
|
24236
24643
|
providerStream: args.config.providerStream,
|
|
24237
24644
|
runMode: "implementation",
|
|
24238
|
-
retryPrompt: buildMotionFixPrompt(current)
|
|
24645
|
+
retryPrompt: buildMotionFixPrompt(current),
|
|
24646
|
+
languageModule: args.languageModule
|
|
24239
24647
|
});
|
|
24240
24648
|
for await (const event of fixGenerator) {
|
|
24241
24649
|
if (event.type === "tool_execution_start")
|
|
@@ -24380,7 +24788,8 @@ async function* applyRetryIfMissing(args) {
|
|
|
24380
24788
|
eventBus: args.config.eventBus,
|
|
24381
24789
|
toolRegistry: args.config.tools,
|
|
24382
24790
|
providerStream: args.config.providerStream,
|
|
24383
|
-
runMode: args.config.runMode
|
|
24791
|
+
runMode: args.config.runMode,
|
|
24792
|
+
languageModule: args.languageModule
|
|
24384
24793
|
});
|
|
24385
24794
|
for await (const event of retryGenerator) {
|
|
24386
24795
|
if (event.type === "tool_execution_start") {
|
|
@@ -24402,6 +24811,7 @@ var init_councilApi = __esm({
|
|
|
24402
24811
|
init_toolSchemas();
|
|
24403
24812
|
init_systemPromptBuilder();
|
|
24404
24813
|
init_tools();
|
|
24814
|
+
init_languagePolicy();
|
|
24405
24815
|
init_events();
|
|
24406
24816
|
init_AgentHarness();
|
|
24407
24817
|
init_modeBanners();
|
|
@@ -33050,6 +33460,14 @@ init_keyStore();
|
|
|
33050
33460
|
init_toolRegistry();
|
|
33051
33461
|
init_skills2();
|
|
33052
33462
|
|
|
33463
|
+
// packages/core/dist/events/index.js
|
|
33464
|
+
init_events();
|
|
33465
|
+
|
|
33466
|
+
// packages/core/dist/index.js
|
|
33467
|
+
init_harness();
|
|
33468
|
+
init_council();
|
|
33469
|
+
init_skills2();
|
|
33470
|
+
|
|
33053
33471
|
// src/cli/hooks/messageHelpers.ts
|
|
33054
33472
|
function appendSystem(setMessages, content, ts = Date.now()) {
|
|
33055
33473
|
setMessages((prev2) => [
|
|
@@ -33135,6 +33553,81 @@ function finalizeStreamingAssistant(setMessages) {
|
|
|
33135
33553
|
});
|
|
33136
33554
|
}
|
|
33137
33555
|
|
|
33556
|
+
// src/cli/utils/envNumber.ts
|
|
33557
|
+
function envNumber(raw, opts) {
|
|
33558
|
+
const { default: def, min, max } = opts;
|
|
33559
|
+
if (raw === void 0 || raw === null) return def;
|
|
33560
|
+
const trimmed = raw.trim();
|
|
33561
|
+
if (trimmed.length === 0) return def;
|
|
33562
|
+
if (trimmed.toLowerCase() === "undefined" || trimmed.toLowerCase() === "null") return def;
|
|
33563
|
+
const parsed = Number.parseInt(trimmed, 10);
|
|
33564
|
+
if (!Number.isFinite(parsed)) return def;
|
|
33565
|
+
const absStr = `${Math.abs(parsed)}`;
|
|
33566
|
+
const body = trimmed.replace(/^[-+]/, "").replace(/^0+(?=\d)/, "");
|
|
33567
|
+
if (body !== absStr) return def;
|
|
33568
|
+
const firstChar = trimmed[0];
|
|
33569
|
+
const expectedSign = parsed < 0 ? "-" : /[0-9+]/.test(firstChar ?? "");
|
|
33570
|
+
const actualSign = parsed < 0 ? firstChar === "-" : firstChar !== "-";
|
|
33571
|
+
if (!expectedSign || !actualSign) return def;
|
|
33572
|
+
let clamped = parsed;
|
|
33573
|
+
if (min !== void 0 && clamped < min) clamped = min;
|
|
33574
|
+
if (max !== void 0 && clamped > max) clamped = max;
|
|
33575
|
+
return clamped;
|
|
33576
|
+
}
|
|
33577
|
+
|
|
33578
|
+
// src/cli/hooks/historyCompaction.ts
|
|
33579
|
+
var COMPACT_MARKER = "[history] Earlier turns were compacted to stay within the context budget.";
|
|
33580
|
+
function resolveMaxMessages(opts) {
|
|
33581
|
+
const envTurns = envNumber(process.env.ZELARI_HISTORY_TURNS, { default: 6, min: 0 });
|
|
33582
|
+
const turns = opts?.maxMessages ? Math.ceil(opts.maxMessages / 4) : envTurns;
|
|
33583
|
+
if (turns <= 0) return 0;
|
|
33584
|
+
return turns * 4;
|
|
33585
|
+
}
|
|
33586
|
+
function findValidCutIndex(messages, naiveCut) {
|
|
33587
|
+
let cut = naiveCut;
|
|
33588
|
+
while (cut < messages.length) {
|
|
33589
|
+
const kept = messages.slice(cut);
|
|
33590
|
+
const declared = /* @__PURE__ */ new Set();
|
|
33591
|
+
for (const m of kept) {
|
|
33592
|
+
if (m.role === "assistant" && m.toolCalls) {
|
|
33593
|
+
for (const tc of m.toolCalls) declared.add(tc.id);
|
|
33594
|
+
}
|
|
33595
|
+
}
|
|
33596
|
+
let moved = false;
|
|
33597
|
+
for (let k = 0; k < kept.length; k++) {
|
|
33598
|
+
const m = kept[k];
|
|
33599
|
+
if (m.role === "tool" && m.toolCallId && !declared.has(m.toolCallId)) {
|
|
33600
|
+
for (let j = cut - 1; j >= 0; j--) {
|
|
33601
|
+
const prev2 = messages[j];
|
|
33602
|
+
if (prev2.role === "assistant" && prev2.toolCalls && prev2.toolCalls.some((tc) => tc.id === m.toolCallId)) {
|
|
33603
|
+
cut = j;
|
|
33604
|
+
moved = true;
|
|
33605
|
+
break;
|
|
33606
|
+
}
|
|
33607
|
+
}
|
|
33608
|
+
break;
|
|
33609
|
+
}
|
|
33610
|
+
}
|
|
33611
|
+
if (!moved) break;
|
|
33612
|
+
}
|
|
33613
|
+
return cut;
|
|
33614
|
+
}
|
|
33615
|
+
function compactHistory(messages, opts) {
|
|
33616
|
+
const maxMessages = resolveMaxMessages(opts);
|
|
33617
|
+
if (maxMessages === 0) return [];
|
|
33618
|
+
if (messages.length <= maxMessages * 2) return messages;
|
|
33619
|
+
const naiveCut = messages.length - maxMessages;
|
|
33620
|
+
const cut = findValidCutIndex(messages, naiveCut);
|
|
33621
|
+
const dropped = cut;
|
|
33622
|
+
if (dropped === 0) return messages;
|
|
33623
|
+
const kept = messages.slice(cut);
|
|
33624
|
+
const summary = {
|
|
33625
|
+
role: "system",
|
|
33626
|
+
content: `${COMPACT_MARKER} ${dropped} earlier message(s) dropped.`
|
|
33627
|
+
};
|
|
33628
|
+
return [summary, ...kept];
|
|
33629
|
+
}
|
|
33630
|
+
|
|
33138
33631
|
// src/cli/hooks/chatStats.ts
|
|
33139
33632
|
function computeSessionStatsDelta(realUsage, userText, assistantContent, model, prev2) {
|
|
33140
33633
|
const promptTokens = realUsage ? realUsage.promptTokens : Math.ceil(userText.length / 4);
|
|
@@ -33160,16 +33653,22 @@ function useChatTurn(params) {
|
|
|
33160
33653
|
setSessionActive,
|
|
33161
33654
|
setSessionStats,
|
|
33162
33655
|
setLive,
|
|
33163
|
-
liveRef
|
|
33656
|
+
liveRef,
|
|
33657
|
+
setPicker
|
|
33164
33658
|
} = params;
|
|
33165
33659
|
const harnessRef = useRef4(null);
|
|
33166
33660
|
const [queueCount, setQueueCount] = useState6(0);
|
|
33661
|
+
const historyRef = useRef4([]);
|
|
33167
33662
|
const useLiveModel = !!(setLive && liveRef);
|
|
33168
33663
|
const dispatchPrompt = useCallback2(
|
|
33169
33664
|
async (userText, opts) => {
|
|
33170
33665
|
let envConfig;
|
|
33171
33666
|
let harness;
|
|
33667
|
+
let historySeedLen = 0;
|
|
33668
|
+
let turnSucceeded = false;
|
|
33172
33669
|
try {
|
|
33670
|
+
historyRef.current = compactHistory(historyRef.current);
|
|
33671
|
+
historySeedLen = historyRef.current.length;
|
|
33173
33672
|
envConfig = await providerFromEnv();
|
|
33174
33673
|
if (!envConfig) {
|
|
33175
33674
|
const active = resolveActiveProvider();
|
|
@@ -33290,21 +33789,24 @@ function useChatTurn(params) {
|
|
|
33290
33789
|
const workspaceContext = [workspaceSummary, zelariReadHint].filter(Boolean).join("\n\n");
|
|
33291
33790
|
let systemPrompt;
|
|
33292
33791
|
try {
|
|
33792
|
+
const languageModule = buildLanguagePolicyModuleFor(userText);
|
|
33293
33793
|
systemPrompt = buildSystemPrompt(singleAgentRole, {
|
|
33294
33794
|
tools: getAllTools(),
|
|
33295
33795
|
toolNames: toolListNames,
|
|
33296
33796
|
aiConfig: {
|
|
33297
33797
|
enabledSkills: [],
|
|
33298
33798
|
enabledTools: toolListNames,
|
|
33299
|
-
customPromptModules: [SINGLE_AGENT_IDENTITY_MODULE],
|
|
33799
|
+
customPromptModules: [SINGLE_AGENT_IDENTITY_MODULE, languageModule],
|
|
33300
33800
|
agentSkillConfigs: []
|
|
33301
33801
|
},
|
|
33302
33802
|
workspaceContext: workspaceContext || void 0,
|
|
33303
33803
|
ragContext: planSummary || void 0
|
|
33304
33804
|
});
|
|
33305
33805
|
} catch {
|
|
33806
|
+
const languageModule = buildLanguagePolicyModuleFor(userText);
|
|
33306
33807
|
systemPrompt = [
|
|
33307
33808
|
SINGLE_AGENT_IDENTITY_MODULE.content,
|
|
33809
|
+
languageModule.content,
|
|
33308
33810
|
shellContextBlock,
|
|
33309
33811
|
"# Available Tools",
|
|
33310
33812
|
"You can call these tools. Use them to take action and gather information autonomously:",
|
|
@@ -33313,21 +33815,23 @@ function useChatTurn(params) {
|
|
|
33313
33815
|
...planSummary ? ["", planSummary] : []
|
|
33314
33816
|
].join("\n");
|
|
33315
33817
|
}
|
|
33316
|
-
const maxToolCallsPerTurn = (
|
|
33317
|
-
|
|
33318
|
-
|
|
33319
|
-
|
|
33320
|
-
|
|
33321
|
-
|
|
33322
|
-
|
|
33323
|
-
|
|
33324
|
-
return Number.isFinite(n) && n > 0 ? n : 90;
|
|
33325
|
-
})();
|
|
33818
|
+
const maxToolCallsPerTurn = envNumber(process.env.ZELARI_MAX_TOOL_CALLS, {
|
|
33819
|
+
default: 25,
|
|
33820
|
+
min: 1
|
|
33821
|
+
});
|
|
33822
|
+
const maxToolLoopIterations = envNumber(process.env.ZELARI_MAX_TOOL_LOOP_ITERATIONS, {
|
|
33823
|
+
default: 90,
|
|
33824
|
+
min: 1
|
|
33825
|
+
});
|
|
33326
33826
|
const harness2 = new AgentHarness({
|
|
33327
33827
|
model: envConfig.model,
|
|
33328
33828
|
provider: "openai-compatible",
|
|
33329
33829
|
messages: [
|
|
33330
33830
|
{ role: "system", content: systemPrompt },
|
|
33831
|
+
// v1.6.0: seed prior turns so the model sees its own last
|
|
33832
|
+
// question when the user answers briefly. historyRef.current
|
|
33833
|
+
// is compacted above (possibly empty if ZELARI_HISTORY_TURNS=0).
|
|
33834
|
+
...historyRef.current,
|
|
33331
33835
|
{ role: "user", content: userText }
|
|
33332
33836
|
],
|
|
33333
33837
|
tools: toolRegistry.toOpenAITools().map((t) => ({
|
|
@@ -33458,10 +33962,53 @@ function useChatTurn(params) {
|
|
|
33458
33962
|
}
|
|
33459
33963
|
}
|
|
33460
33964
|
}
|
|
33965
|
+
turnSucceeded = true;
|
|
33461
33966
|
} finally {
|
|
33462
33967
|
flushStreaming();
|
|
33463
33968
|
if (useLiveModel) finalizeStreaming(setMessages, setLive);
|
|
33464
33969
|
else finalizeStreamingAssistant(setMessages);
|
|
33970
|
+
try {
|
|
33971
|
+
const h = harnessRef.current;
|
|
33972
|
+
if (h && turnSucceeded) {
|
|
33973
|
+
const all = h.getMessages();
|
|
33974
|
+
const seedLen = 1 + historySeedLen + 1;
|
|
33975
|
+
if (all.length > seedLen) {
|
|
33976
|
+
historyRef.current = historyRef.current.concat(
|
|
33977
|
+
all.slice(seedLen)
|
|
33978
|
+
);
|
|
33979
|
+
}
|
|
33980
|
+
}
|
|
33981
|
+
} catch {
|
|
33982
|
+
}
|
|
33983
|
+
if (turnSucceeded && setPicker && assistantContent) {
|
|
33984
|
+
try {
|
|
33985
|
+
const clar = parseClarificationRequest(assistantContent);
|
|
33986
|
+
if (clar && clar.choices && clar.choices.length >= 2) {
|
|
33987
|
+
const cleaned = cleanAgentContent(assistantContent);
|
|
33988
|
+
if (cleaned !== assistantContent) {
|
|
33989
|
+
setMessages((prev2) => {
|
|
33990
|
+
const next = [...prev2];
|
|
33991
|
+
for (let i = next.length - 1; i >= 0; i--) {
|
|
33992
|
+
if (next[i].role === "assistant") {
|
|
33993
|
+
next[i] = { ...next[i], content: cleaned };
|
|
33994
|
+
break;
|
|
33995
|
+
}
|
|
33996
|
+
}
|
|
33997
|
+
return next;
|
|
33998
|
+
});
|
|
33999
|
+
}
|
|
34000
|
+
setPicker({
|
|
34001
|
+
kind: "clarification",
|
|
34002
|
+
title: clar.question,
|
|
34003
|
+
items: clar.choices.map((c) => ({ value: c, label: c })),
|
|
34004
|
+
onAnswer: (value) => {
|
|
34005
|
+
void dispatchPrompt(value);
|
|
34006
|
+
}
|
|
34007
|
+
});
|
|
34008
|
+
}
|
|
34009
|
+
} catch {
|
|
34010
|
+
}
|
|
34011
|
+
}
|
|
33465
34012
|
harnessRef.current = null;
|
|
33466
34013
|
setQueueCount(0);
|
|
33467
34014
|
setBusy(false);
|
|
@@ -33612,11 +34159,10 @@ async function dispatchCouncilPromptImpl(text, deps, overrides = {}) {
|
|
|
33612
34159
|
const councilFeedbackStore = new FeedbackStore2();
|
|
33613
34160
|
let streamContent = "";
|
|
33614
34161
|
let streamMemberId = null;
|
|
33615
|
-
const councilMaxToolCalls = (
|
|
33616
|
-
|
|
33617
|
-
|
|
33618
|
-
|
|
33619
|
-
})();
|
|
34162
|
+
const councilMaxToolCalls = envNumber(process.env.ZELARI_MAX_TOOL_CALLS, {
|
|
34163
|
+
default: 15,
|
|
34164
|
+
min: 1
|
|
34165
|
+
});
|
|
33620
34166
|
let membersCompleted = 0;
|
|
33621
34167
|
let chairmanProducedOutput = false;
|
|
33622
34168
|
let chairmanSynthesisText = "";
|
|
@@ -33993,11 +34539,10 @@ async function runZelariMissionInTui(userMessage, deps, emit) {
|
|
|
33993
34539
|
hasPlan: hasWorkspacePlan2(projectRoot)
|
|
33994
34540
|
});
|
|
33995
34541
|
const memory = await getMemoryBackend2(projectRoot);
|
|
33996
|
-
const chairmanBudget = (
|
|
33997
|
-
|
|
33998
|
-
|
|
33999
|
-
|
|
34000
|
-
})();
|
|
34542
|
+
const chairmanBudget = envNumber(process.env.ZELARI_MODE_MAX_TOOLS_LUCIFER, {
|
|
34543
|
+
default: 30,
|
|
34544
|
+
min: 1
|
|
34545
|
+
});
|
|
34001
34546
|
try {
|
|
34002
34547
|
await runZelariMission2(userMessage, brief, {
|
|
34003
34548
|
projectRoot,
|
|
@@ -36404,7 +36949,11 @@ function App() {
|
|
|
36404
36949
|
setSessionActive: session.setSessionActive,
|
|
36405
36950
|
setSessionStats,
|
|
36406
36951
|
setLive: session.setLive,
|
|
36407
|
-
liveRef: session.liveRef
|
|
36952
|
+
liveRef: session.liveRef,
|
|
36953
|
+
// v1.6.0: lets dispatchPrompt open a SelectList when the agent poses a
|
|
36954
|
+
// ---QUESTION--- clarifying block, so the user picks from the offered
|
|
36955
|
+
// choices instead of typing (and the answer binds via rolling history).
|
|
36956
|
+
setPicker
|
|
36408
36957
|
});
|
|
36409
36958
|
const onNewSession = useCallback5((id) => {
|
|
36410
36959
|
void session.writerRef.current?.close();
|
|
@@ -36445,8 +36994,12 @@ function App() {
|
|
|
36445
36994
|
});
|
|
36446
36995
|
const onPickerSelect = useCallback5((value) => {
|
|
36447
36996
|
if (!picker) return;
|
|
36448
|
-
const cmd = `${picker.commandPrefix} ${value}`;
|
|
36449
36997
|
setPicker(null);
|
|
36998
|
+
if (picker.kind === "clarification") {
|
|
36999
|
+
picker.onAnswer?.(value);
|
|
37000
|
+
return;
|
|
37001
|
+
}
|
|
37002
|
+
const cmd = `${picker.commandPrefix} ${value}`;
|
|
36450
37003
|
void handleSubmit(cmd);
|
|
36451
37004
|
}, [picker, handleSubmit]);
|
|
36452
37005
|
const onPickerCancel = useCallback5(() => setPicker(null), []);
|
|
@@ -37151,6 +37704,7 @@ function emitEvent(event) {
|
|
|
37151
37704
|
// src/cli/runHeadless.ts
|
|
37152
37705
|
init_harness();
|
|
37153
37706
|
init_toolRegistry();
|
|
37707
|
+
init_skills2();
|
|
37154
37708
|
async function runHeadless(opts) {
|
|
37155
37709
|
const { provider, model } = resolveHeadlessProvider(opts);
|
|
37156
37710
|
const key = await resolveHeadlessKey(provider);
|
|
@@ -37178,11 +37732,61 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
|
37178
37732
|
description: t.function.description,
|
|
37179
37733
|
parameters: t.function.parameters
|
|
37180
37734
|
}));
|
|
37181
|
-
const
|
|
37182
|
-
|
|
37183
|
-
|
|
37184
|
-
|
|
37185
|
-
|
|
37735
|
+
const toolNames = tools.map((t) => t.name);
|
|
37736
|
+
let systemPrompt;
|
|
37737
|
+
let languageDirectiveContent;
|
|
37738
|
+
try {
|
|
37739
|
+
languageDirectiveContent = buildLanguagePolicyModuleFor(opts.task).content;
|
|
37740
|
+
} catch {
|
|
37741
|
+
languageDirectiveContent = "# Response Language\nReply in the user's language when possible, otherwise Italian.";
|
|
37742
|
+
}
|
|
37743
|
+
try {
|
|
37744
|
+
const headlessRole = {
|
|
37745
|
+
id: "single",
|
|
37746
|
+
name: "Zelari Code",
|
|
37747
|
+
codename: "zelari",
|
|
37748
|
+
role: "headless coding agent",
|
|
37749
|
+
color: "#00d9a3",
|
|
37750
|
+
avatar: "\u25C6",
|
|
37751
|
+
tools: toolNames,
|
|
37752
|
+
// v1.7.0 fix (agy audit): include platform/shell context in the role
|
|
37753
|
+
// prompt so the agent knows its cwd and shell — previously this was
|
|
37754
|
+
// empty (systemPrompt: '') and the agent lacked the platform block
|
|
37755
|
+
// the TUI single-agent path gets.
|
|
37756
|
+
systemPrompt: [
|
|
37757
|
+
"# Platform",
|
|
37758
|
+
`platform: ${process.platform}`,
|
|
37759
|
+
`shell: ${process.platform === "win32" ? "cmd.exe / Git Bash (auto-detected)" : "/bin/sh"}`,
|
|
37760
|
+
"",
|
|
37761
|
+
"# Working Directory",
|
|
37762
|
+
`You are running in: ${process.cwd()}`,
|
|
37763
|
+
"All relative file paths are resolved against this directory.",
|
|
37764
|
+
"The shell is NON-INTERACTIVE (stdin closed): pass non-interactive flags (--yes, --force, --template)."
|
|
37765
|
+
].join("\n")
|
|
37766
|
+
};
|
|
37767
|
+
systemPrompt = buildSystemPrompt(headlessRole, {
|
|
37768
|
+
tools: getAllTools(),
|
|
37769
|
+
toolNames,
|
|
37770
|
+
aiConfig: {
|
|
37771
|
+
enabledSkills: [],
|
|
37772
|
+
enabledTools: toolNames,
|
|
37773
|
+
customPromptModules: [SINGLE_AGENT_IDENTITY_MODULE, {
|
|
37774
|
+
type: "language-policy",
|
|
37775
|
+
title: "Response Language",
|
|
37776
|
+
priority: 5,
|
|
37777
|
+
content: languageDirectiveContent
|
|
37778
|
+
}],
|
|
37779
|
+
agentSkillConfigs: []
|
|
37780
|
+
}
|
|
37781
|
+
});
|
|
37782
|
+
} catch {
|
|
37783
|
+
systemPrompt = [
|
|
37784
|
+
"You are zelari-code, a CLI coding agent. Be concise and direct.",
|
|
37785
|
+
"When the user asks you to write code, debug, or explore, be proactive: list files and read key files to understand the project.",
|
|
37786
|
+
"When you finish a task, briefly summarize what you did.",
|
|
37787
|
+
languageDirectiveContent
|
|
37788
|
+
].join("\n");
|
|
37789
|
+
}
|
|
37186
37790
|
const harness = new AgentHarness({
|
|
37187
37791
|
model,
|
|
37188
37792
|
provider,
|
|
@@ -37195,9 +37799,8 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
|
37195
37799
|
toolRegistry,
|
|
37196
37800
|
providerStream,
|
|
37197
37801
|
maxToolLoopIterations: (() => {
|
|
37198
|
-
const
|
|
37199
|
-
|
|
37200
|
-
return Number.isFinite(n) && n > 0 ? n : 30;
|
|
37802
|
+
const n = envNumber(process.env.ZELARI_MAX_TOOL_LOOP_ITERATIONS, { default: 30, min: 1 });
|
|
37803
|
+
return n;
|
|
37201
37804
|
})()
|
|
37202
37805
|
});
|
|
37203
37806
|
let finalReason = "completed";
|