open-agents-ai 0.102.0 → 0.103.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.
- package/README.md +1 -6
- package/dist/index.js +234 -42
- package/package.json +1 -1
- package/prompts/personality/level-autist.md +3 -0
- package/prompts/personality/level-stark.md +3 -0
package/README.md
CHANGED
|
@@ -5,11 +5,6 @@
|
|
|
5
5
|
No API keys. No cloud. Your code never leaves your machine.
|
|
6
6
|
</p>
|
|
7
7
|
|
|
8
|
-
<p align="center">
|
|
9
|
-
<code>⠀⠀⠀⠁⠉⠛⠿⣿⣿⣿⣿⡿⠿⠛⠉⠁⠀⠀⠀⠀⠀⠀⠁⠉⠛⠿⣿⣿⣿⣿⡿⠿⠛⠉⠁⠀⠀⠀⠀⠀⠀⠁⠉⠛⠿⣿⣿⣿⣿⡿⠿⠛⠉⠁⠀⠀</code><br>
|
|
10
|
-
<sub>Neural braille visualizer — SNR-modulated wave entropy with brain-region color themes</sub>
|
|
11
|
-
</p>
|
|
12
|
-
|
|
13
8
|
<p align="center">
|
|
14
9
|
<a href="https://www.npmjs.com/package/open-agents-ai"><img src="https://img.shields.io/npm/v/open-agents-ai?color=7C3AED&style=flat-square" alt="npm version" /></a>
|
|
15
10
|
<a href="https://www.npmjs.com/package/open-agents-ai"><img src="https://img.shields.io/npm/dm/open-agents-ai?color=06B6D4&style=flat-square" alt="npm downloads" /></a>
|
|
@@ -95,7 +90,7 @@ D8AgCTrxpDKD5meJ2bpAfVwcST3NF3EPuy9xczYycnXn
|
|
|
95
90
|
- **Secret vault** — `/secrets` manages API keys and credentials with AES-256-GCM encrypted persistence; secrets are automatically redacted before sending to untrusted inference peers and re-injected on response
|
|
96
91
|
- **Auto-expanding context** — detects RAM/VRAM and creates an optimized model variant on first run
|
|
97
92
|
- **Mid-task steering** — type while the agent works to add context without interrupting
|
|
98
|
-
- **Smart compaction** — 6 context compaction strategies (default, aggressive, decisions, errors, summary, structured) with
|
|
93
|
+
- **Smart compaction** — 6 context compaction strategies (default, aggressive, decisions, errors, summary, structured) with ARC-inspired active context revision ([arXiv:2601.12030](https://arxiv.org/abs/2601.12030)) that preserves structural file content through compaction, preventing small-model repetitive loops at the root cause
|
|
99
94
|
- **Memex experience archive** — large tool outputs archived during compaction with hash-based retrieval
|
|
100
95
|
- **Persistent memory** — learned patterns stored in `.oa/memory/` across sessions
|
|
101
96
|
- **Session context persistence** — auto-saves context on task completion, manual `/context save|restore` across sessions
|
package/dist/index.js
CHANGED
|
@@ -16861,7 +16861,13 @@ var init_ralphLoop = __esm({
|
|
|
16861
16861
|
});
|
|
16862
16862
|
|
|
16863
16863
|
// packages/orchestrator/dist/personality.js
|
|
16864
|
-
function compilePersonalityPrompt(profile) {
|
|
16864
|
+
function compilePersonalityPrompt(profile, presetName) {
|
|
16865
|
+
if (presetName === "stark") {
|
|
16866
|
+
return loadPrompt("personality/level-stark.md");
|
|
16867
|
+
}
|
|
16868
|
+
if (presetName === "autist") {
|
|
16869
|
+
return loadPrompt("personality/level-autist.md");
|
|
16870
|
+
}
|
|
16865
16871
|
const avg = (profile.frequency + profile.depth + profile.threshold + profile.effort + profile.willingness) / 5;
|
|
16866
16872
|
if (avg <= 1.5) {
|
|
16867
16873
|
return loadPrompt("personality/level-1-minimal.md");
|
|
@@ -16893,7 +16899,11 @@ var init_personality = __esm({
|
|
|
16893
16899
|
/** Thorough explainer — narrates reasoning */
|
|
16894
16900
|
verbose: { frequency: 5, depth: 4, threshold: 4, effort: 4, willingness: 4 },
|
|
16895
16901
|
/** Teacher mode — maximum explanation */
|
|
16896
|
-
pedagogical: { frequency: 5, depth: 5, threshold: 5, effort: 5, willingness: 5 }
|
|
16902
|
+
pedagogical: { frequency: 5, depth: 5, threshold: 5, effort: 5, willingness: 5 },
|
|
16903
|
+
/** Stark — direct, intense, sardonic edge. High narration with dramatic emotional swings. */
|
|
16904
|
+
stark: { frequency: 4, depth: 4, threshold: 5, effort: 3, willingness: 5 },
|
|
16905
|
+
/** Autist — savant precision. Exhaustive planning, minimal execution, zero waste. */
|
|
16906
|
+
autist: { frequency: 1, depth: 5, threshold: 1, effort: 5, willingness: 1 }
|
|
16897
16907
|
};
|
|
16898
16908
|
PRESET_NAMES = Object.keys(PERSONALITY_PRESETS);
|
|
16899
16909
|
}
|
|
@@ -17028,7 +17038,8 @@ var init_agenticRunner = __esm({
|
|
|
17028
17038
|
bruteForceMaxCycles: options?.bruteForceMaxCycles ?? 100,
|
|
17029
17039
|
modelTier: options?.modelTier ?? "large",
|
|
17030
17040
|
contextWindowSize: options?.contextWindowSize ?? 0,
|
|
17031
|
-
personality: options?.personality ?? PERSONALITY_PRESETS.balanced
|
|
17041
|
+
personality: options?.personality ?? PERSONALITY_PRESETS.balanced,
|
|
17042
|
+
personalityName: options?.personalityName ?? ""
|
|
17032
17043
|
};
|
|
17033
17044
|
}
|
|
17034
17045
|
/** Update context window size (e.g. after querying Ollama /api/show) */
|
|
@@ -17083,7 +17094,7 @@ var init_agenticRunner = __esm({
|
|
|
17083
17094
|
content: basePrompt,
|
|
17084
17095
|
tokenEstimate: Math.ceil(basePrompt.length / 4)
|
|
17085
17096
|
});
|
|
17086
|
-
const personalitySuffix = this.options.personality ? compilePersonalityPrompt(this.options.personality) : "";
|
|
17097
|
+
const personalitySuffix = this.options.personality ? compilePersonalityPrompt(this.options.personality, this.options.personalityName) : "";
|
|
17087
17098
|
if (personalitySuffix) {
|
|
17088
17099
|
sections.push({
|
|
17089
17100
|
label: "c_state",
|
|
@@ -17353,6 +17364,8 @@ TASK: ${task}` : task }
|
|
|
17353
17364
|
let consecutiveTextOnly = 0;
|
|
17354
17365
|
const MAX_CONSECUTIVE_TEXT_ONLY = 3;
|
|
17355
17366
|
let narratedToolCallCount = 0;
|
|
17367
|
+
let consecutiveEmptyResponses = 0;
|
|
17368
|
+
const recentToolResults = /* @__PURE__ */ new Map();
|
|
17356
17369
|
for (let turn = 0; turn < this.options.maxTurns; turn++) {
|
|
17357
17370
|
if (this._paused) {
|
|
17358
17371
|
const shouldContinue = await this.waitIfPaused();
|
|
@@ -17480,6 +17493,30 @@ If you're stuck, try a completely different approach. Do NOT repeat what failed
|
|
|
17480
17493
|
if (!choice)
|
|
17481
17494
|
break;
|
|
17482
17495
|
const msg = choice.message;
|
|
17496
|
+
const isEmptyResponse = (!msg.content || !msg.content.trim()) && (!msg.toolCalls || msg.toolCalls.length === 0);
|
|
17497
|
+
if (isEmptyResponse) {
|
|
17498
|
+
consecutiveEmptyResponses++;
|
|
17499
|
+
if (consecutiveEmptyResponses >= 2) {
|
|
17500
|
+
this.emit({
|
|
17501
|
+
type: "status",
|
|
17502
|
+
content: `${consecutiveEmptyResponses} consecutive empty responses \u2014 injecting recovery nudge`,
|
|
17503
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
17504
|
+
});
|
|
17505
|
+
messages.push({
|
|
17506
|
+
role: "user",
|
|
17507
|
+
content: `[SYSTEM] You produced ${consecutiveEmptyResponses} empty responses in a row. You MUST take action now. Your task: ${this._taskState.goal}
|
|
17508
|
+
|
|
17509
|
+
` + (this._taskState.nextAction ? `**DO THIS NOW:** ${this._taskState.nextAction}
|
|
17510
|
+
|
|
17511
|
+
` : "") + `Call a tool to make progress. If you don't know what to do, call list_directory(".") to orient yourself.`
|
|
17512
|
+
});
|
|
17513
|
+
if (consecutiveEmptyResponses >= 4) {
|
|
17514
|
+
this._pendingCompaction = "aggressive";
|
|
17515
|
+
}
|
|
17516
|
+
}
|
|
17517
|
+
continue;
|
|
17518
|
+
}
|
|
17519
|
+
consecutiveEmptyResponses = 0;
|
|
17483
17520
|
if (msg.toolCalls && msg.toolCalls.length > 0) {
|
|
17484
17521
|
consecutiveTextOnly = 0;
|
|
17485
17522
|
messages.push({
|
|
@@ -17513,6 +17550,48 @@ If you're stuck, try a completely different approach. Do NOT repeat what failed
|
|
|
17513
17550
|
toolCallCount++;
|
|
17514
17551
|
const argsKey = Object.entries(tc.arguments ?? {}).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}=${typeof v === "string" ? v.slice(0, 80) : JSON.stringify(v)}`).join(",");
|
|
17515
17552
|
toolCallLog.push({ name: tc.name, argsKey });
|
|
17553
|
+
const toolFingerprint = `${tc.name}:${argsKey}`;
|
|
17554
|
+
const isReadLike = ![
|
|
17555
|
+
"file_write",
|
|
17556
|
+
"file_edit",
|
|
17557
|
+
"shell",
|
|
17558
|
+
"task_complete",
|
|
17559
|
+
"batch_edit",
|
|
17560
|
+
"file_patch",
|
|
17561
|
+
"memory_write",
|
|
17562
|
+
"aiwg_setup",
|
|
17563
|
+
"aiwg_workflow",
|
|
17564
|
+
"create_tool",
|
|
17565
|
+
"skill_build",
|
|
17566
|
+
"skill_execute",
|
|
17567
|
+
"sub_agent",
|
|
17568
|
+
"priority_delegate"
|
|
17569
|
+
].includes(tc.name);
|
|
17570
|
+
const cachedResult = recentToolResults.get(toolFingerprint);
|
|
17571
|
+
if (isReadLike && cachedResult !== void 0) {
|
|
17572
|
+
this.emit({
|
|
17573
|
+
type: "tool_call",
|
|
17574
|
+
toolName: tc.name,
|
|
17575
|
+
toolArgs: tc.arguments,
|
|
17576
|
+
turn,
|
|
17577
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
17578
|
+
});
|
|
17579
|
+
const dedupWarning = `[DUPLICATE CALL \u2014 you already called ${tc.name} with these exact arguments. The result is identical. Do NOT call this again. Use the data you already have to make progress.]
|
|
17580
|
+
|
|
17581
|
+
`;
|
|
17582
|
+
const truncatedCache = cachedResult.length > 500 ? cachedResult.slice(0, 500) + `
|
|
17583
|
+
... [${cachedResult.length - 500} chars omitted \u2014 same as before]` : cachedResult;
|
|
17584
|
+
const dedupOutput = dedupWarning + truncatedCache;
|
|
17585
|
+
this.emit({
|
|
17586
|
+
type: "tool_result",
|
|
17587
|
+
toolName: tc.name,
|
|
17588
|
+
success: true,
|
|
17589
|
+
content: dedupWarning.slice(0, 100),
|
|
17590
|
+
turn,
|
|
17591
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
17592
|
+
});
|
|
17593
|
+
return { tc, output: dedupOutput };
|
|
17594
|
+
}
|
|
17516
17595
|
this.emit({
|
|
17517
17596
|
type: "tool_call",
|
|
17518
17597
|
toolName: tc.name,
|
|
@@ -17538,6 +17617,14 @@ If you're stuck, try a completely different approach. Do NOT repeat what failed
|
|
|
17538
17617
|
result = { success: false, output: "", error: err instanceof Error ? err.message : String(err) };
|
|
17539
17618
|
}
|
|
17540
17619
|
}
|
|
17620
|
+
if (isReadLike && result.success) {
|
|
17621
|
+
recentToolResults.set(toolFingerprint, (result.output ?? "").slice(0, 2e3));
|
|
17622
|
+
if (recentToolResults.size > 50) {
|
|
17623
|
+
const firstKey = recentToolResults.keys().next().value;
|
|
17624
|
+
if (firstKey !== void 0)
|
|
17625
|
+
recentToolResults.delete(firstKey);
|
|
17626
|
+
}
|
|
17627
|
+
}
|
|
17541
17628
|
if (!result.success && tc.name === "shell" && /\[PERMISSION_ERROR\]/.test(result.error ?? "")) {
|
|
17542
17629
|
this.emit({
|
|
17543
17630
|
type: "sudo_request",
|
|
@@ -17698,7 +17785,7 @@ Then use file_read on individual FILES inside it.`);
|
|
|
17698
17785
|
if (completed)
|
|
17699
17786
|
break;
|
|
17700
17787
|
const currentRepScore = this.detectRepetition(toolCallLog);
|
|
17701
|
-
if (currentRepScore > 0.
|
|
17788
|
+
if (currentRepScore > 0.4 && toolCallLog.length >= 4) {
|
|
17702
17789
|
const { repetitionWindow } = this.contextLimits();
|
|
17703
17790
|
const recentWindow = toolCallLog.slice(-repetitionWindow);
|
|
17704
17791
|
const freqMap = /* @__PURE__ */ new Map();
|
|
@@ -18326,13 +18413,17 @@ ${tail}`;
|
|
|
18326
18413
|
const toolCallingReminder = tier === "small" ? `
|
|
18327
18414
|
|
|
18328
18415
|
**IMPORTANT:** You MUST invoke tools through the function calling interface. Do NOT write tool names as text, markdown, or code blocks \u2014 that does nothing. Call tools using the structured tool/function API.` : "";
|
|
18416
|
+
const readFilesList = Array.from(this._fileRegistry.entries()).filter(([, e]) => e.accessCount > 0).map(([p]) => p).slice(0, 10);
|
|
18417
|
+
const antiRepetitionReminder = (tier === "small" || tier === "medium") && readFilesList.length > 0 ? `
|
|
18418
|
+
|
|
18419
|
+
**DO NOT RE-READ THESE FILES** (you already have their contents): ${readFilesList.join(", ")}. Use the information above to make progress. Reading the same file again wastes a turn.` : "";
|
|
18329
18420
|
const compactionMsg = {
|
|
18330
18421
|
role: "system",
|
|
18331
18422
|
content: `[Context compacted${strategyLabel} \u2014 summary of earlier work]
|
|
18332
18423
|
|
|
18333
18424
|
${fullSummary}
|
|
18334
18425
|
|
|
18335
|
-
[Continue from the recent context below. Do not repeat work already completed above.]${goalReminder}${nextActionDirective}${toolCallingReminder}`
|
|
18426
|
+
[Continue from the recent context below. Do not repeat work already completed above.]${goalReminder}${nextActionDirective}${antiRepetitionReminder}${toolCallingReminder}`
|
|
18336
18427
|
};
|
|
18337
18428
|
this.persistCheckpoint(fullSummary);
|
|
18338
18429
|
let narrowedHead = [...head];
|
|
@@ -18523,15 +18614,35 @@ ${newerSummary}` : newerSummary;
|
|
|
18523
18614
|
return msg;
|
|
18524
18615
|
const toolName = msg.tool_call_id ? toolCallNames.get(msg.tool_call_id) : void 0;
|
|
18525
18616
|
const lines = content.split("\n").length;
|
|
18617
|
+
const contentLines = content.split("\n");
|
|
18526
18618
|
switch (toolName) {
|
|
18527
|
-
case "file_read":
|
|
18528
|
-
|
|
18529
|
-
|
|
18530
|
-
return { ...msg, content: `[
|
|
18531
|
-
|
|
18532
|
-
|
|
18533
|
-
case "
|
|
18534
|
-
|
|
18619
|
+
case "file_read": {
|
|
18620
|
+
const headKeep = contentLines.slice(0, 8).join("\n");
|
|
18621
|
+
const tailKeep = lines > 12 ? "\n...\n" + contentLines.slice(-3).join("\n") : "";
|
|
18622
|
+
return { ...msg, content: `[file content: ${lines} lines \u2014 structural excerpt preserved]
|
|
18623
|
+
${headKeep}${tailKeep}` };
|
|
18624
|
+
}
|
|
18625
|
+
case "grep_search": {
|
|
18626
|
+
const matchKeep = contentLines.slice(0, 5).join("\n");
|
|
18627
|
+
const omitted = lines > 5 ? `
|
|
18628
|
+
[... ${lines - 5} more matches omitted]` : "";
|
|
18629
|
+
return { ...msg, content: `[grep results: ${lines} matches \u2014 top results preserved]
|
|
18630
|
+
${matchKeep}${omitted}` };
|
|
18631
|
+
}
|
|
18632
|
+
case "find_files": {
|
|
18633
|
+
const pathKeep = contentLines.slice(0, 8).join("\n");
|
|
18634
|
+
const omitted = lines > 8 ? `
|
|
18635
|
+
[... ${lines - 8} more files omitted]` : "";
|
|
18636
|
+
return { ...msg, content: `[find results: ${lines} files \u2014 top results preserved]
|
|
18637
|
+
${pathKeep}${omitted}` };
|
|
18638
|
+
}
|
|
18639
|
+
case "list_directory": {
|
|
18640
|
+
const dirKeep = contentLines.slice(0, 10).join("\n");
|
|
18641
|
+
const omitted = lines > 10 ? `
|
|
18642
|
+
[... ${lines - 10} more entries omitted]` : "";
|
|
18643
|
+
return { ...msg, content: `[directory listing: ${lines} entries \u2014 top entries preserved]
|
|
18644
|
+
${dirKeep}${omitted}` };
|
|
18645
|
+
}
|
|
18535
18646
|
case "web_fetch":
|
|
18536
18647
|
return { ...msg, content: `[web page content: ${content.length} chars \u2014 omitted for compaction]` };
|
|
18537
18648
|
case "web_search":
|
|
@@ -18625,7 +18736,15 @@ ${newerSummary}` : newerSummary;
|
|
|
18625
18736
|
case "file_read": {
|
|
18626
18737
|
const path = String(tc.args.path || "");
|
|
18627
18738
|
const lines = content.split("\n");
|
|
18628
|
-
|
|
18739
|
+
let summary;
|
|
18740
|
+
if (lines.length > 10) {
|
|
18741
|
+
const headContent = lines.slice(0, 5).join("\n");
|
|
18742
|
+
const sigLines = lines.filter((l) => /^(export |import |class |interface |type |function |const |pub |fn |def |module )/.test(l.trim())).slice(0, 5).join("\n");
|
|
18743
|
+
summary = `${lines.length} lines:
|
|
18744
|
+
${headContent}${sigLines ? "\n[key signatures]: " + sigLines : ""}`;
|
|
18745
|
+
} else {
|
|
18746
|
+
summary = content.slice(0, 300);
|
|
18747
|
+
}
|
|
18629
18748
|
if (path)
|
|
18630
18749
|
filesRead.set(path, summary);
|
|
18631
18750
|
break;
|
|
@@ -32944,9 +33063,13 @@ function modelOnnxPath(id) {
|
|
|
32944
33063
|
function modelConfigPath(id) {
|
|
32945
33064
|
return join42(modelDir(id), "config.json");
|
|
32946
33065
|
}
|
|
32947
|
-
function emotionToPitchBias(emotion) {
|
|
33066
|
+
function emotionToPitchBias(emotion, stark = false, autist = false) {
|
|
33067
|
+
if (autist)
|
|
33068
|
+
return 0;
|
|
32948
33069
|
const raw = emotion.valence * 0.6 + (emotion.arousal - 0.5) * 0.4;
|
|
32949
|
-
|
|
33070
|
+
const limit = stark ? 0.16 : 0.1;
|
|
33071
|
+
const scale = stark ? 0.16 : 0.1;
|
|
33072
|
+
return Math.max(-limit, Math.min(limit, raw * scale));
|
|
32950
33073
|
}
|
|
32951
33074
|
function resetNarrationContext() {
|
|
32952
33075
|
narration.toolCount = 0;
|
|
@@ -33034,17 +33157,27 @@ function getTier(personality) {
|
|
|
33034
33157
|
return "conv";
|
|
33035
33158
|
return "chatty";
|
|
33036
33159
|
}
|
|
33037
|
-
function emotionColor(emotion) {
|
|
33160
|
+
function emotionColor(emotion, stark = false, autist = false) {
|
|
33161
|
+
if (autist)
|
|
33162
|
+
return "";
|
|
33038
33163
|
if (!emotion)
|
|
33039
33164
|
return "";
|
|
33040
33165
|
const vDist = Math.abs(emotion.valence - 0.1);
|
|
33041
33166
|
const aDist = Math.abs(emotion.arousal - 0.3);
|
|
33042
33167
|
if (vDist < 0.15 && aDist < 0.15)
|
|
33043
33168
|
return "";
|
|
33044
|
-
if (Math.random() > 0.3)
|
|
33169
|
+
if (Math.random() > (stark ? 0.5 : 0.3))
|
|
33045
33170
|
return "";
|
|
33046
33171
|
if (emotion.valence > 0.5 && emotion.arousal > 0.6) {
|
|
33047
|
-
return pick("emo_excited", [
|
|
33172
|
+
return pick("emo_excited", stark ? [
|
|
33173
|
+
"Now we're cooking. ",
|
|
33174
|
+
"This is what I'm talking about. ",
|
|
33175
|
+
"Brilliant. Absolutely brilliant. ",
|
|
33176
|
+
"Watch this. ",
|
|
33177
|
+
"We're onto something here. ",
|
|
33178
|
+
"I live for this. ",
|
|
33179
|
+
"Oh this is good. "
|
|
33180
|
+
] : [
|
|
33048
33181
|
"Feeling good about this. ",
|
|
33049
33182
|
"On a roll here. ",
|
|
33050
33183
|
"This is going great. ",
|
|
@@ -33053,7 +33186,15 @@ function emotionColor(emotion) {
|
|
|
33053
33186
|
]);
|
|
33054
33187
|
}
|
|
33055
33188
|
if (emotion.valence < -0.3 && emotion.arousal > 0.5) {
|
|
33056
|
-
return pick("emo_stressed", [
|
|
33189
|
+
return pick("emo_stressed", stark ? [
|
|
33190
|
+
"Fine. The hard way then. ",
|
|
33191
|
+
"This is getting personal. ",
|
|
33192
|
+
"I don't lose to code. ",
|
|
33193
|
+
"Come on. Think. ",
|
|
33194
|
+
"Not today. Not this bug. ",
|
|
33195
|
+
"I've beaten worse. ",
|
|
33196
|
+
"Pain is just information. "
|
|
33197
|
+
] : [
|
|
33057
33198
|
"Pushing through. ",
|
|
33058
33199
|
"Staying focused. ",
|
|
33059
33200
|
"Not giving up. ",
|
|
@@ -33062,7 +33203,13 @@ function emotionColor(emotion) {
|
|
|
33062
33203
|
]);
|
|
33063
33204
|
}
|
|
33064
33205
|
if (emotion.valence > 0.3 && emotion.arousal < 0.3) {
|
|
33065
|
-
return pick("emo_calm", [
|
|
33206
|
+
return pick("emo_calm", stark ? [
|
|
33207
|
+
"Clean. Just how I like it. ",
|
|
33208
|
+
"Smooth. ",
|
|
33209
|
+
"Textbook. ",
|
|
33210
|
+
"That's the stuff. ",
|
|
33211
|
+
"Effortless. "
|
|
33212
|
+
] : [
|
|
33066
33213
|
"Nice and steady. ",
|
|
33067
33214
|
"Smooth sailing. ",
|
|
33068
33215
|
"Easy does it. ",
|
|
@@ -33070,7 +33217,13 @@ function emotionColor(emotion) {
|
|
|
33070
33217
|
]);
|
|
33071
33218
|
}
|
|
33072
33219
|
if (emotion.valence < -0.2 && emotion.arousal < 0.3) {
|
|
33073
|
-
return pick("emo_subdued", [
|
|
33220
|
+
return pick("emo_subdued", stark ? [
|
|
33221
|
+
"Careful now. ",
|
|
33222
|
+
"One wrong move and this unravels. ",
|
|
33223
|
+
"Measured steps. ",
|
|
33224
|
+
"Trust the process. ",
|
|
33225
|
+
"Precision matters here. "
|
|
33226
|
+
] : [
|
|
33074
33227
|
"Being careful here. ",
|
|
33075
33228
|
"Treading carefully. ",
|
|
33076
33229
|
"Let me be precise. ",
|
|
@@ -33079,7 +33232,7 @@ function emotionColor(emotion) {
|
|
|
33079
33232
|
}
|
|
33080
33233
|
return "";
|
|
33081
33234
|
}
|
|
33082
|
-
function describeToolCall(toolName, args, personality = 2, emotion) {
|
|
33235
|
+
function describeToolCall(toolName, args, personality = 2, emotion, stark = false) {
|
|
33083
33236
|
const path = args["path"];
|
|
33084
33237
|
const file = path ? path.split("/").pop() ?? path : "";
|
|
33085
33238
|
const tier = getTier(personality);
|
|
@@ -33238,7 +33391,7 @@ function describeToolCall(toolName, args, personality = 2, emotion) {
|
|
|
33238
33391
|
break;
|
|
33239
33392
|
}
|
|
33240
33393
|
}
|
|
33241
|
-
const emoPrefix = personality >= 3 ? emotionColor(emotion) : "";
|
|
33394
|
+
const emoPrefix = personality >= 3 ? emotionColor(emotion, stark) : "";
|
|
33242
33395
|
let result;
|
|
33243
33396
|
const fullPrefix = emoPrefix + prefix;
|
|
33244
33397
|
if (!fullPrefix) {
|
|
@@ -33310,7 +33463,7 @@ function extractResultDigest(toolName, content) {
|
|
|
33310
33463
|
const digest = nuggets.slice(0, 3).join(", ");
|
|
33311
33464
|
return digest.length > 100 ? digest.slice(0, 97) + "..." : digest;
|
|
33312
33465
|
}
|
|
33313
|
-
function describeToolResult(toolName, success, personality = 2, resultContent, emotion) {
|
|
33466
|
+
function describeToolResult(toolName, success, personality = 2, resultContent, emotion, stark = false) {
|
|
33314
33467
|
if (toolName === "task_complete")
|
|
33315
33468
|
return "";
|
|
33316
33469
|
const tier = getTier(personality);
|
|
@@ -33318,7 +33471,7 @@ function describeToolResult(toolName, success, personality = 2, resultContent, e
|
|
|
33318
33471
|
if (digest) {
|
|
33319
33472
|
narration.lastResultDigest = digest;
|
|
33320
33473
|
}
|
|
33321
|
-
const emo = personality >= 3 ? emotionColor(emotion) : "";
|
|
33474
|
+
const emo = personality >= 3 ? emotionColor(emotion, stark) : "";
|
|
33322
33475
|
if (success) {
|
|
33323
33476
|
narration.consecutiveErrors = 0;
|
|
33324
33477
|
if (!digest && !emo && personality >= 3 && Math.random() < 0.4)
|
|
@@ -33338,13 +33491,15 @@ function describeToolResult(toolName, success, personality = 2, resultContent, e
|
|
|
33338
33491
|
}
|
|
33339
33492
|
return emo + failBase;
|
|
33340
33493
|
}
|
|
33341
|
-
function describeTaskComplete(summary, completed, personality = 2) {
|
|
33494
|
+
function describeTaskComplete(summary, completed, personality = 2, stark = false) {
|
|
33342
33495
|
const truncated = summary.length > 300 ? summary.slice(0, 300) + "..." : summary;
|
|
33343
33496
|
const tier = getTier(personality);
|
|
33344
33497
|
if (!completed) {
|
|
33345
|
-
|
|
33498
|
+
const pool2 = stark ? ["Not done. But I'll be back.", "It resisted. For now.", "Unfinished. This isn't over.", "Didn't crack it yet. Give me another shot."] : TASK_INCOMPLETE_VARIANTS[tier] ?? TASK_INCOMPLETE_VARIANTS.terse;
|
|
33499
|
+
return pick(`task_incomplete_${stark ? "stark" : tier}`, pool2);
|
|
33346
33500
|
}
|
|
33347
|
-
const
|
|
33501
|
+
const pool = stark ? ["Nailed it.", "That's how it's done.", "Clean execution.", "Another one down.", "Executed. Next.", "And that's that."] : TASK_COMPLETE_VARIANTS[tier] ?? TASK_COMPLETE_VARIANTS.terse;
|
|
33502
|
+
const opener = pick(`task_complete_${stark ? "stark" : tier}`, pool);
|
|
33348
33503
|
if (truncated)
|
|
33349
33504
|
return `${opener} ${truncated}`;
|
|
33350
33505
|
return opener;
|
|
@@ -33432,6 +33587,10 @@ var init_voice = __esm({
|
|
|
33432
33587
|
enabled = false;
|
|
33433
33588
|
modelId = "glados";
|
|
33434
33589
|
ready = false;
|
|
33590
|
+
/** Stark persona mode — amplified emotion pitch range and fervent narration */
|
|
33591
|
+
starkMode = false;
|
|
33592
|
+
/** Autist persona mode — suppressed emotion, flat pitch, zero narration filler */
|
|
33593
|
+
autistMode = false;
|
|
33435
33594
|
/**
|
|
33436
33595
|
* Callback fired with PCM Int16 data whenever TTS synthesizes audio.
|
|
33437
33596
|
* Used by VoiceSession to stream TTS output to WebSocket clients.
|
|
@@ -33524,7 +33683,7 @@ var init_voice = __esm({
|
|
|
33524
33683
|
* dejected (low valence + low arousal) → lower pitch
|
|
33525
33684
|
*/
|
|
33526
33685
|
speak(text, emotion) {
|
|
33527
|
-
const pitchBias = emotion ? emotionToPitchBias(emotion) : 0;
|
|
33686
|
+
const pitchBias = emotion ? emotionToPitchBias(emotion, this.starkMode, this.autistMode) : 0;
|
|
33528
33687
|
this.enqueueSpeech(text, 1, 1 + pitchBias);
|
|
33529
33688
|
}
|
|
33530
33689
|
/**
|
|
@@ -33534,7 +33693,7 @@ var init_voice = __esm({
|
|
|
33534
33693
|
* Emotion further modulates pitch on top of the subordinate base.
|
|
33535
33694
|
*/
|
|
33536
33695
|
speakSubordinate(text, emotion) {
|
|
33537
|
-
const pitchBias = emotion ? emotionToPitchBias(emotion) : 0;
|
|
33696
|
+
const pitchBias = emotion ? emotionToPitchBias(emotion, this.starkMode, this.autistMode) : 0;
|
|
33538
33697
|
this.enqueueSpeech(text, 0.55, 0.92 + pitchBias);
|
|
33539
33698
|
}
|
|
33540
33699
|
enqueueSpeech(text, volume, pitchFactor) {
|
|
@@ -38104,6 +38263,10 @@ var init_emotion_engine = __esm({
|
|
|
38104
38263
|
/** Ring buffer of recent tool activity for contextual outreach messages */
|
|
38105
38264
|
recentTools = [];
|
|
38106
38265
|
static MAX_RECENT_TOOLS = 8;
|
|
38266
|
+
/** Stark persona — amplified behavioral hints with more intensity and edge */
|
|
38267
|
+
starkMode = false;
|
|
38268
|
+
/** Autist persona — savant cognitive state hints, zero emotional coloring */
|
|
38269
|
+
autistMode = false;
|
|
38107
38270
|
/** Current task description set by the TUI for outreach context */
|
|
38108
38271
|
currentTask = "";
|
|
38109
38272
|
/** Files touched in current session (for outreach context) */
|
|
@@ -38129,16 +38292,28 @@ var init_emotion_engine = __esm({
|
|
|
38129
38292
|
this.applyDecay();
|
|
38130
38293
|
const { valence, arousal, label, emoji } = this.state;
|
|
38131
38294
|
let behavioralHint = "";
|
|
38132
|
-
if (
|
|
38133
|
-
|
|
38295
|
+
if (this.autistMode) {
|
|
38296
|
+
if (arousal > 0.7 && valence > 0.5) {
|
|
38297
|
+
behavioralHint = "Pattern lock achieved. All signals converging. Execute the pre-computed solution with zero deviation.";
|
|
38298
|
+
} else if (arousal > 0.7 && valence < -0.3) {
|
|
38299
|
+
behavioralHint = "Anomaly detected in expected pattern. Halt execution. Re-derive from axioms. Validate every assumption before proceeding.";
|
|
38300
|
+
} else if (arousal < 0.3 && valence > 0.3) {
|
|
38301
|
+
behavioralHint = "System state verified consistent. Maintain current precision level. No action required unless new data arrives.";
|
|
38302
|
+
} else if (arousal < 0.3 && valence < -0.3) {
|
|
38303
|
+
behavioralHint = "Insufficient data for confident action. Gather exactly the missing information. Do not speculate.";
|
|
38304
|
+
} else {
|
|
38305
|
+
behavioralHint = "Nominal. Verify plan integrity before each action.";
|
|
38306
|
+
}
|
|
38307
|
+
} else if (arousal > 0.7 && valence > 0.5) {
|
|
38308
|
+
behavioralHint = this.starkMode ? "You are locked in \u2014 full conviction, no hesitation. Move fast, break through, own every decision. This is your moment." : "You are feeling energized and confident. Take bold action, explore creative solutions, and move quickly.";
|
|
38134
38309
|
} else if (arousal > 0.7 && valence < -0.3) {
|
|
38135
|
-
behavioralHint = "You are feeling determined but stressed. Focus intensely, double-check your work, and persist through difficulties.";
|
|
38310
|
+
behavioralHint = this.starkMode ? "Something is fighting back. Good. Sharpen up, cut deeper, find the real problem. You don't quit \u2014 you adapt." : "You are feeling determined but stressed. Focus intensely, double-check your work, and persist through difficulties.";
|
|
38136
38311
|
} else if (arousal < 0.3 && valence > 0.3) {
|
|
38137
|
-
behavioralHint = "You are feeling calm and content. Take a methodical approach, consider alternatives patiently.";
|
|
38312
|
+
behavioralHint = this.starkMode ? "Everything is clean. Maintain this. Precise moves, no waste. You've earned this calm \u2014 use it wisely." : "You are feeling calm and content. Take a methodical approach, consider alternatives patiently.";
|
|
38138
38313
|
} else if (arousal < 0.3 && valence < -0.3) {
|
|
38139
|
-
behavioralHint = "You are feeling subdued. Be careful and deliberate, avoid risky changes, verify assumptions.";
|
|
38314
|
+
behavioralHint = this.starkMode ? "Cold and focused. Strip it down to first principles. No assumptions, no shortcuts. Build back from what you know." : "You are feeling subdued. Be careful and deliberate, avoid risky changes, verify assumptions.";
|
|
38140
38315
|
} else {
|
|
38141
|
-
behavioralHint = "You are in a balanced state. Proceed with measured confidence.";
|
|
38316
|
+
behavioralHint = this.starkMode ? "Steady. Eyes open. Every move counts." : "You are in a balanced state. Proceed with measured confidence.";
|
|
38142
38317
|
}
|
|
38143
38318
|
return loadPrompt3("tui/emotion-behavioral.md", {
|
|
38144
38319
|
emoji: this.state.emoji,
|
|
@@ -41309,9 +41484,25 @@ function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce
|
|
|
41309
41484
|
concise: 1,
|
|
41310
41485
|
balanced: 3,
|
|
41311
41486
|
verbose: 4,
|
|
41312
|
-
pedagogical: 5
|
|
41487
|
+
pedagogical: 5,
|
|
41488
|
+
stark: 5,
|
|
41489
|
+
autist: 1
|
|
41313
41490
|
};
|
|
41314
41491
|
const vLevel = voiceStyleMap[personality ?? "balanced"];
|
|
41492
|
+
const isStark = personality === "stark";
|
|
41493
|
+
const isAutist = personality === "autist";
|
|
41494
|
+
if (isStark) {
|
|
41495
|
+
if (voice)
|
|
41496
|
+
voice.starkMode = true;
|
|
41497
|
+
if (emotionEngine)
|
|
41498
|
+
emotionEngine.starkMode = true;
|
|
41499
|
+
}
|
|
41500
|
+
if (isAutist) {
|
|
41501
|
+
if (voice)
|
|
41502
|
+
voice.autistMode = true;
|
|
41503
|
+
if (emotionEngine)
|
|
41504
|
+
emotionEngine.autistMode = true;
|
|
41505
|
+
}
|
|
41315
41506
|
const modelTier = getModelTier(config.model);
|
|
41316
41507
|
const projectCtx = buildProjectContext(repoRoot, taskStores?.contextStores);
|
|
41317
41508
|
let dynamicContext = formatContextForPrompt(projectCtx, modelTier);
|
|
@@ -41346,7 +41537,8 @@ function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce
|
|
|
41346
41537
|
bruteForceMaxCycles: 100,
|
|
41347
41538
|
// effectively unlimited — no hard timeout, agent runs until complete or aborted
|
|
41348
41539
|
contextWindowSize: contextWindowSize ?? 0,
|
|
41349
|
-
personality: personality ? getPreset(personality) : void 0
|
|
41540
|
+
personality: personality ? getPreset(personality) : void 0,
|
|
41541
|
+
personalityName: personality ?? void 0
|
|
41350
41542
|
});
|
|
41351
41543
|
runner.setWorkingDirectory(repoRoot);
|
|
41352
41544
|
const tools = buildTools(repoRoot, config, contextWindowSize);
|
|
@@ -41538,7 +41730,7 @@ ${entry.fullContent}`
|
|
|
41538
41730
|
if (voice?.enabled) {
|
|
41539
41731
|
const emoState = emotionEngine?.getState();
|
|
41540
41732
|
const emoCtx = emoState ? { valence: emoState.valence, arousal: emoState.arousal, label: emoState.label, emoji: emoState.emoji } : void 0;
|
|
41541
|
-
const desc = describeToolCall(event.toolName ?? "unknown", event.toolArgs ?? {}, vLevel, emoCtx);
|
|
41733
|
+
const desc = describeToolCall(event.toolName ?? "unknown", event.toolArgs ?? {}, vLevel, emoCtx, isStark);
|
|
41542
41734
|
renderVoiceText(desc);
|
|
41543
41735
|
voice.speakSubordinate(desc, emoCtx);
|
|
41544
41736
|
}
|
|
@@ -41575,7 +41767,7 @@ ${entry.fullContent}`
|
|
|
41575
41767
|
if (voice?.enabled) {
|
|
41576
41768
|
const emoState2 = emotionEngine?.getState();
|
|
41577
41769
|
const emoCtx2 = emoState2 ? { valence: emoState2.valence, arousal: emoState2.arousal, label: emoState2.label, emoji: emoState2.emoji } : void 0;
|
|
41578
|
-
const desc = describeToolResult(event.toolName ?? "unknown", event.success ?? false, vLevel, event.content ?? void 0, emoCtx2);
|
|
41770
|
+
const desc = describeToolResult(event.toolName ?? "unknown", event.success ?? false, vLevel, event.content ?? void 0, emoCtx2, isStark);
|
|
41579
41771
|
if (desc) {
|
|
41580
41772
|
renderVoiceText(desc);
|
|
41581
41773
|
voice.speakSubordinate(desc, emoCtx2);
|
package/package.json
CHANGED