zelari-code 1.6.0 → 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/hooks/historyCompaction.js +6 -5
- package/dist/cli/hooks/historyCompaction.js.map +1 -1
- package/dist/cli/hooks/useChatTurn.js +28 -22
- package/dist/cli/hooks/useChatTurn.js.map +1 -1
- package/dist/cli/main.bundled.js +502 -43
- 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/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
|
|
|
@@ -23438,6 +23805,17 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
23438
23805
|
const sessionId = config2.sessionId ?? crypto.randomUUID();
|
|
23439
23806
|
const runMode = config2.runMode ?? "implementation";
|
|
23440
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
|
+
}
|
|
23441
23819
|
yield createBrainEvent("council_mode", sessionId, {
|
|
23442
23820
|
tier: councilTierFromSize(config2.councilSize),
|
|
23443
23821
|
councilSize: config2.councilSize,
|
|
@@ -23561,7 +23939,8 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
23561
23939
|
effectiveModel,
|
|
23562
23940
|
onToolCall: () => {
|
|
23563
23941
|
toolCalls += 1;
|
|
23564
|
-
}
|
|
23942
|
+
},
|
|
23943
|
+
languageModule: councilLanguageModule
|
|
23565
23944
|
});
|
|
23566
23945
|
} else if (isDesignPhase) {
|
|
23567
23946
|
enforceDesignPhaseToolEmissions(agent.id, emittedToolNames);
|
|
@@ -23699,7 +24078,8 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
23699
24078
|
effectiveModel,
|
|
23700
24079
|
onToolCall: () => {
|
|
23701
24080
|
toolCalls += 1;
|
|
23702
|
-
}
|
|
24081
|
+
},
|
|
24082
|
+
languageModule: councilLanguageModule
|
|
23703
24083
|
});
|
|
23704
24084
|
} else if (isDesignPhase) {
|
|
23705
24085
|
enforceDesignPhaseToolEmissions(oracle.id, emittedToolNames);
|
|
@@ -23867,7 +24247,8 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
23867
24247
|
effectiveModel,
|
|
23868
24248
|
onToolCall: () => {
|
|
23869
24249
|
toolCalls += 1;
|
|
23870
|
-
}
|
|
24250
|
+
},
|
|
24251
|
+
languageModule: councilLanguageModule
|
|
23871
24252
|
});
|
|
23872
24253
|
} else if (isDesignPhase) {
|
|
23873
24254
|
enforceDesignPhaseToolEmissions(chairman.id, emittedToolNames);
|
|
@@ -23927,7 +24308,8 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
23927
24308
|
onSuccessfulWrite: () => {
|
|
23928
24309
|
successfulWriteCount += 1;
|
|
23929
24310
|
},
|
|
23930
|
-
onCouncilStatus: callbacks.onCouncilStatus
|
|
24311
|
+
onCouncilStatus: callbacks.onCouncilStatus,
|
|
24312
|
+
languageModule: councilLanguageModule
|
|
23931
24313
|
});
|
|
23932
24314
|
}
|
|
23933
24315
|
}
|
|
@@ -23946,7 +24328,8 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
23946
24328
|
effectiveModel,
|
|
23947
24329
|
onToolCall: () => {
|
|
23948
24330
|
toolCalls += 1;
|
|
23949
|
-
}
|
|
24331
|
+
},
|
|
24332
|
+
languageModule: councilLanguageModule
|
|
23950
24333
|
});
|
|
23951
24334
|
}
|
|
23952
24335
|
if (chairmanProjectRoot) {
|
|
@@ -23964,7 +24347,8 @@ async function* runCouncilPure(userMessage, config2, callbacks = {}) {
|
|
|
23964
24347
|
onToolCall: () => {
|
|
23965
24348
|
toolCalls += 1;
|
|
23966
24349
|
},
|
|
23967
|
-
onCouncilStatus: callbacks.onCouncilStatus
|
|
24350
|
+
onCouncilStatus: callbacks.onCouncilStatus,
|
|
24351
|
+
languageModule: councilLanguageModule
|
|
23968
24352
|
});
|
|
23969
24353
|
}
|
|
23970
24354
|
}
|
|
@@ -24030,7 +24414,8 @@ async function* applyCompletionRetry(args) {
|
|
|
24030
24414
|
toolRegistry: args.config.tools,
|
|
24031
24415
|
providerStream: args.config.providerStream,
|
|
24032
24416
|
runMode: args.config.runMode,
|
|
24033
|
-
retryPrompt: buildImplementationVerifyRetryPrompt(retryTool)
|
|
24417
|
+
retryPrompt: buildImplementationVerifyRetryPrompt(retryTool),
|
|
24418
|
+
languageModule: args.languageModule
|
|
24034
24419
|
});
|
|
24035
24420
|
for await (const event of retryGenerator) {
|
|
24036
24421
|
if (event.type === "tool_execution_start") {
|
|
@@ -24088,7 +24473,8 @@ async function* applyImplementationWriteRetry(args) {
|
|
|
24088
24473
|
toolRegistry: args.config.tools,
|
|
24089
24474
|
providerStream: args.config.providerStream,
|
|
24090
24475
|
runMode: "implementation",
|
|
24091
|
-
retryPrompt: buildImplementationWriteRetryPrompt(args.userMessage)
|
|
24476
|
+
retryPrompt: buildImplementationWriteRetryPrompt(args.userMessage),
|
|
24477
|
+
languageModule: args.languageModule
|
|
24092
24478
|
});
|
|
24093
24479
|
for await (const event of retryGenerator) {
|
|
24094
24480
|
if (event.type === "tool_execution_start")
|
|
@@ -24157,7 +24543,8 @@ async function* runChairmanDeliveryLoop(args) {
|
|
|
24157
24543
|
toolRegistry: args.config.tools,
|
|
24158
24544
|
providerStream: args.config.providerStream,
|
|
24159
24545
|
runMode: "implementation",
|
|
24160
|
-
retryPrompt: buildDeliveryFixPrompt(blocking, args.userMessage)
|
|
24546
|
+
retryPrompt: buildDeliveryFixPrompt(blocking, args.userMessage),
|
|
24547
|
+
languageModule: args.languageModule
|
|
24161
24548
|
});
|
|
24162
24549
|
for await (const event of fixGenerator) {
|
|
24163
24550
|
if (event.type === "tool_execution_start")
|
|
@@ -24255,7 +24642,8 @@ async function* runChairmanFixLoop(args) {
|
|
|
24255
24642
|
toolRegistry: args.config.tools,
|
|
24256
24643
|
providerStream: args.config.providerStream,
|
|
24257
24644
|
runMode: "implementation",
|
|
24258
|
-
retryPrompt: buildMotionFixPrompt(current)
|
|
24645
|
+
retryPrompt: buildMotionFixPrompt(current),
|
|
24646
|
+
languageModule: args.languageModule
|
|
24259
24647
|
});
|
|
24260
24648
|
for await (const event of fixGenerator) {
|
|
24261
24649
|
if (event.type === "tool_execution_start")
|
|
@@ -24400,7 +24788,8 @@ async function* applyRetryIfMissing(args) {
|
|
|
24400
24788
|
eventBus: args.config.eventBus,
|
|
24401
24789
|
toolRegistry: args.config.tools,
|
|
24402
24790
|
providerStream: args.config.providerStream,
|
|
24403
|
-
runMode: args.config.runMode
|
|
24791
|
+
runMode: args.config.runMode,
|
|
24792
|
+
languageModule: args.languageModule
|
|
24404
24793
|
});
|
|
24405
24794
|
for await (const event of retryGenerator) {
|
|
24406
24795
|
if (event.type === "tool_execution_start") {
|
|
@@ -24422,6 +24811,7 @@ var init_councilApi = __esm({
|
|
|
24422
24811
|
init_toolSchemas();
|
|
24423
24812
|
init_systemPromptBuilder();
|
|
24424
24813
|
init_tools();
|
|
24814
|
+
init_languagePolicy();
|
|
24425
24815
|
init_events();
|
|
24426
24816
|
init_AgentHarness();
|
|
24427
24817
|
init_modeBanners();
|
|
@@ -33163,12 +33553,32 @@ function finalizeStreamingAssistant(setMessages) {
|
|
|
33163
33553
|
});
|
|
33164
33554
|
}
|
|
33165
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
|
+
|
|
33166
33578
|
// src/cli/hooks/historyCompaction.ts
|
|
33167
33579
|
var COMPACT_MARKER = "[history] Earlier turns were compacted to stay within the context budget.";
|
|
33168
33580
|
function resolveMaxMessages(opts) {
|
|
33169
|
-
const
|
|
33170
|
-
const parsed = raw ? Number.parseInt(raw, 10) : 6;
|
|
33171
|
-
const envTurns = Number.isFinite(parsed) && parsed >= 0 ? parsed : 6;
|
|
33581
|
+
const envTurns = envNumber(process.env.ZELARI_HISTORY_TURNS, { default: 6, min: 0 });
|
|
33172
33582
|
const turns = opts?.maxMessages ? Math.ceil(opts.maxMessages / 4) : envTurns;
|
|
33173
33583
|
if (turns <= 0) return 0;
|
|
33174
33584
|
return turns * 4;
|
|
@@ -33379,21 +33789,24 @@ function useChatTurn(params) {
|
|
|
33379
33789
|
const workspaceContext = [workspaceSummary, zelariReadHint].filter(Boolean).join("\n\n");
|
|
33380
33790
|
let systemPrompt;
|
|
33381
33791
|
try {
|
|
33792
|
+
const languageModule = buildLanguagePolicyModuleFor(userText);
|
|
33382
33793
|
systemPrompt = buildSystemPrompt(singleAgentRole, {
|
|
33383
33794
|
tools: getAllTools(),
|
|
33384
33795
|
toolNames: toolListNames,
|
|
33385
33796
|
aiConfig: {
|
|
33386
33797
|
enabledSkills: [],
|
|
33387
33798
|
enabledTools: toolListNames,
|
|
33388
|
-
customPromptModules: [SINGLE_AGENT_IDENTITY_MODULE],
|
|
33799
|
+
customPromptModules: [SINGLE_AGENT_IDENTITY_MODULE, languageModule],
|
|
33389
33800
|
agentSkillConfigs: []
|
|
33390
33801
|
},
|
|
33391
33802
|
workspaceContext: workspaceContext || void 0,
|
|
33392
33803
|
ragContext: planSummary || void 0
|
|
33393
33804
|
});
|
|
33394
33805
|
} catch {
|
|
33806
|
+
const languageModule = buildLanguagePolicyModuleFor(userText);
|
|
33395
33807
|
systemPrompt = [
|
|
33396
33808
|
SINGLE_AGENT_IDENTITY_MODULE.content,
|
|
33809
|
+
languageModule.content,
|
|
33397
33810
|
shellContextBlock,
|
|
33398
33811
|
"# Available Tools",
|
|
33399
33812
|
"You can call these tools. Use them to take action and gather information autonomously:",
|
|
@@ -33402,16 +33815,14 @@ function useChatTurn(params) {
|
|
|
33402
33815
|
...planSummary ? ["", planSummary] : []
|
|
33403
33816
|
].join("\n");
|
|
33404
33817
|
}
|
|
33405
|
-
const maxToolCallsPerTurn = (
|
|
33406
|
-
|
|
33407
|
-
|
|
33408
|
-
|
|
33409
|
-
|
|
33410
|
-
|
|
33411
|
-
|
|
33412
|
-
|
|
33413
|
-
return Number.isFinite(n) && n > 0 ? n : 90;
|
|
33414
|
-
})();
|
|
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
|
+
});
|
|
33415
33826
|
const harness2 = new AgentHarness({
|
|
33416
33827
|
model: envConfig.model,
|
|
33417
33828
|
provider: "openai-compatible",
|
|
@@ -33748,11 +34159,10 @@ async function dispatchCouncilPromptImpl(text, deps, overrides = {}) {
|
|
|
33748
34159
|
const councilFeedbackStore = new FeedbackStore2();
|
|
33749
34160
|
let streamContent = "";
|
|
33750
34161
|
let streamMemberId = null;
|
|
33751
|
-
const councilMaxToolCalls = (
|
|
33752
|
-
|
|
33753
|
-
|
|
33754
|
-
|
|
33755
|
-
})();
|
|
34162
|
+
const councilMaxToolCalls = envNumber(process.env.ZELARI_MAX_TOOL_CALLS, {
|
|
34163
|
+
default: 15,
|
|
34164
|
+
min: 1
|
|
34165
|
+
});
|
|
33756
34166
|
let membersCompleted = 0;
|
|
33757
34167
|
let chairmanProducedOutput = false;
|
|
33758
34168
|
let chairmanSynthesisText = "";
|
|
@@ -34129,11 +34539,10 @@ async function runZelariMissionInTui(userMessage, deps, emit) {
|
|
|
34129
34539
|
hasPlan: hasWorkspacePlan2(projectRoot)
|
|
34130
34540
|
});
|
|
34131
34541
|
const memory = await getMemoryBackend2(projectRoot);
|
|
34132
|
-
const chairmanBudget = (
|
|
34133
|
-
|
|
34134
|
-
|
|
34135
|
-
|
|
34136
|
-
})();
|
|
34542
|
+
const chairmanBudget = envNumber(process.env.ZELARI_MODE_MAX_TOOLS_LUCIFER, {
|
|
34543
|
+
default: 30,
|
|
34544
|
+
min: 1
|
|
34545
|
+
});
|
|
34137
34546
|
try {
|
|
34138
34547
|
await runZelariMission2(userMessage, brief, {
|
|
34139
34548
|
projectRoot,
|
|
@@ -37295,6 +37704,7 @@ function emitEvent(event) {
|
|
|
37295
37704
|
// src/cli/runHeadless.ts
|
|
37296
37705
|
init_harness();
|
|
37297
37706
|
init_toolRegistry();
|
|
37707
|
+
init_skills2();
|
|
37298
37708
|
async function runHeadless(opts) {
|
|
37299
37709
|
const { provider, model } = resolveHeadlessProvider(opts);
|
|
37300
37710
|
const key = await resolveHeadlessKey(provider);
|
|
@@ -37322,11 +37732,61 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
|
37322
37732
|
description: t.function.description,
|
|
37323
37733
|
parameters: t.function.parameters
|
|
37324
37734
|
}));
|
|
37325
|
-
const
|
|
37326
|
-
|
|
37327
|
-
|
|
37328
|
-
|
|
37329
|
-
|
|
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
|
+
}
|
|
37330
37790
|
const harness = new AgentHarness({
|
|
37331
37791
|
model,
|
|
37332
37792
|
provider,
|
|
@@ -37339,9 +37799,8 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
|
|
|
37339
37799
|
toolRegistry,
|
|
37340
37800
|
providerStream,
|
|
37341
37801
|
maxToolLoopIterations: (() => {
|
|
37342
|
-
const
|
|
37343
|
-
|
|
37344
|
-
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;
|
|
37345
37804
|
})()
|
|
37346
37805
|
});
|
|
37347
37806
|
let finalReason = "completed";
|