open-agents-ai 0.59.0 → 0.60.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.
Files changed (2) hide show
  1. package/dist/index.js +616 -232
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -26671,265 +26671,286 @@ function modelOnnxPath(id) {
26671
26671
  function modelConfigPath(id) {
26672
26672
  return join34(modelDir(id), "config.json");
26673
26673
  }
26674
- function describeToolCall(toolName, args, personality = 2) {
26675
- const path = args["path"];
26676
- const file = path ? path.split("/").pop() ?? path : "";
26677
- if (personality <= 2) {
26678
- return describeToolCallTerse(toolName, args, file);
26679
- }
26680
- if (personality <= 3) {
26681
- return describeToolCallConversational(toolName, args, file);
26674
+ function resetNarrationContext() {
26675
+ narration.toolCount = 0;
26676
+ narration.toolCounts = {};
26677
+ narration.consecutiveErrors = 0;
26678
+ narration.totalErrors = 0;
26679
+ narration.lastTool = "";
26680
+ narration.lastFile = "";
26681
+ narration.filesSeen.clear();
26682
+ narration.lastVariantIdx = {};
26683
+ }
26684
+ function pick(key, variants) {
26685
+ if (variants.length === 1)
26686
+ return variants[0];
26687
+ const last = narration.lastVariantIdx[key] ?? -1;
26688
+ let idx;
26689
+ do {
26690
+ idx = Math.floor(Math.random() * variants.length);
26691
+ } while (idx === last && variants.length > 1);
26692
+ narration.lastVariantIdx[key] = idx;
26693
+ return variants[idx];
26694
+ }
26695
+ function getShellCategory(cmd) {
26696
+ if (/npm\s+test|vitest|jest|mocha/.test(cmd))
26697
+ return "test";
26698
+ if (/npm\s+run\s+build|tsc|esbuild/.test(cmd))
26699
+ return "build";
26700
+ if (/npm\s+install|pnpm\s+install/.test(cmd))
26701
+ return "install";
26702
+ if (/git\s+/.test(cmd))
26703
+ return "git";
26704
+ if (/npm\s+run\s+lint|eslint|biome/.test(cmd))
26705
+ return "lint";
26706
+ if (/node\s+/.test(cmd))
26707
+ return "node";
26708
+ if (/python|pip/.test(cmd))
26709
+ return "python";
26710
+ if (/curl|wget|fetch/.test(cmd))
26711
+ return "network";
26712
+ if (/docker|podman/.test(cmd))
26713
+ return "container";
26714
+ return "generic";
26715
+ }
26716
+ function contextPrefix(toolName, file) {
26717
+ const count = narration.toolCounts[toolName] ?? 0;
26718
+ const isSameFile = file && file === narration.lastFile;
26719
+ const isRevisit = file && narration.filesSeen.has(file);
26720
+ if (narration.toolCount === 0)
26721
+ return "";
26722
+ if (narration.consecutiveErrors === 1) {
26723
+ const afterError = ["Okay, ", "Right, ", "Alright, "];
26724
+ return pick("ctx_aftererr", afterError);
26725
+ }
26726
+ if (narration.consecutiveErrors === 2) {
26727
+ const afterMultiErr = ["Let me try something different. ", "New approach. ", "Switching tactics. "];
26728
+ return pick("ctx_multierr", afterMultiErr);
26729
+ }
26730
+ if (narration.consecutiveErrors >= 3) {
26731
+ const persistent = ["Third time's the charm. ", "One more try. ", "Okay, different angle entirely. "];
26732
+ return pick("ctx_persistent", persistent);
26733
+ }
26734
+ if (isSameFile && count > 0) {
26735
+ const sameFile = ["Back to ", "Still working on ", ""];
26736
+ const chosen = pick("ctx_samefile", sameFile);
26737
+ if (chosen)
26738
+ return chosen;
26739
+ }
26740
+ if (isRevisit && !isSameFile) {
26741
+ const revisit = ["Coming back to ", "Revisiting ", ""];
26742
+ const chosen = pick("ctx_revisit", revisit);
26743
+ if (chosen)
26744
+ return chosen;
26745
+ }
26746
+ if (narration.toolCount > 0 && narration.toolCount % 8 === 0) {
26747
+ const beats = ["Making good progress. ", "Moving along. ", ""];
26748
+ return pick("ctx_beat", beats);
26682
26749
  }
26683
- return describeToolCallChatty(toolName, args, file);
26750
+ return "";
26684
26751
  }
26685
- function describeToolCallTerse(toolName, args, file) {
26686
- switch (toolName) {
26687
- case "file_read":
26688
- return `Reading ${file}`;
26689
- case "file_write":
26690
- return `Writing ${file}`;
26691
- case "file_edit":
26692
- return `Editing ${file}`;
26693
- case "file_patch":
26694
- return `Patching ${file}`;
26695
- case "shell":
26696
- return describeShellTerse(String(args["command"] ?? ""));
26697
- case "grep_search":
26698
- return `Searching for ${args["pattern"] ?? "pattern"}`;
26699
- case "find_files":
26700
- return `Finding files matching ${args["pattern"] ?? "pattern"}`;
26701
- case "list_directory":
26702
- return `Listing directory ${file || "contents"}`;
26703
- case "web_search":
26704
- return `Searching the web`;
26705
- case "web_fetch":
26706
- return `Fetching web page`;
26707
- case "memory_read":
26708
- return `Reading from memory`;
26709
- case "memory_write":
26710
- return `Saving to memory`;
26711
- case "task_complete":
26712
- return String(args["summary"] ?? "Task complete");
26713
- case "batch_edit":
26714
- return `Editing multiple files`;
26715
- case "codebase_map":
26716
- return `Mapping project structure`;
26717
- case "diagnostic":
26718
- return `Running diagnostics`;
26719
- case "git_info":
26720
- return `Checking git status`;
26721
- case "aiwg_setup":
26722
- return `Setting up development framework`;
26723
- case "aiwg_health":
26724
- return `Analyzing project health`;
26725
- case "aiwg_workflow":
26726
- return `Running workflow command`;
26727
- case "background_run":
26728
- return `Starting background task`;
26729
- case "task_status":
26730
- return `Checking task status`;
26731
- case "task_output":
26732
- return `Reading task output`;
26733
- case "task_stop":
26734
- return `Stopping background task`;
26735
- case "sub_agent":
26736
- return `Delegating to sub agent`;
26737
- case "image_read":
26738
- return `Reading image`;
26739
- case "screenshot":
26740
- return `Taking screenshot`;
26741
- case "ocr":
26742
- return `Extracting text from image`;
26743
- case "create_tool":
26744
- return `Creating custom tool`;
26745
- case "manage_tools":
26746
- return `Managing custom tools`;
26747
- case "browser_action":
26748
- return `Browser ${args["action"] ?? "action"}`;
26749
- case "scheduler":
26750
- return `${args["action"] === "create" ? "Scheduling task" : "Checking scheduler"}`;
26751
- case "reminder":
26752
- return `${args["action"] === "set" ? "Setting reminder" : "Checking reminders"}`;
26753
- case "agenda":
26754
- return `Checking agenda`;
26755
- default:
26756
- return `Using ${toolName}`;
26757
- }
26752
+ function getTier(personality) {
26753
+ if (personality <= 2)
26754
+ return "terse";
26755
+ if (personality <= 3)
26756
+ return "conv";
26757
+ return "chatty";
26758
26758
  }
26759
- function describeToolCallConversational(toolName, args, file) {
26759
+ function describeToolCall(toolName, args, personality = 2) {
26760
+ const path = args["path"];
26761
+ const file = path ? path.split("/").pop() ?? path : "";
26762
+ const tier = getTier(personality);
26763
+ const prefix = personality >= 3 ? contextPrefix(toolName, file) : "";
26764
+ narration.toolCount++;
26765
+ narration.toolCounts[toolName] = (narration.toolCounts[toolName] ?? 0) + 1;
26766
+ narration.lastTool = toolName;
26767
+ if (file) {
26768
+ narration.filesSeen.add(file);
26769
+ narration.lastFile = file;
26770
+ }
26771
+ let base;
26772
+ const poolKey = `${toolName}_${tier}`;
26760
26773
  switch (toolName) {
26761
26774
  case "file_read":
26762
- return `Let me take a look at ${file}`;
26775
+ base = pick(poolKey, (FILE_READ_VARIANTS[tier] ?? FILE_READ_VARIANTS.terse)(file, args));
26776
+ break;
26763
26777
  case "file_write":
26764
- return `Writing changes to ${file}`;
26778
+ base = pick(poolKey, (FILE_WRITE_VARIANTS[tier] ?? FILE_WRITE_VARIANTS.terse)(file, args));
26779
+ break;
26765
26780
  case "file_edit":
26766
- return `Making some edits to ${file}`;
26767
26781
  case "file_patch":
26768
- return `Patching up ${file}`;
26769
- case "shell":
26770
- return describeShellConversational(String(args["command"] ?? ""));
26782
+ base = pick(poolKey, (FILE_EDIT_VARIANTS[tier] ?? FILE_EDIT_VARIANTS.terse)(file, args));
26783
+ break;
26784
+ case "shell": {
26785
+ const cat = getShellCategory(String(args["command"] ?? ""));
26786
+ const pool = SHELL_VARIANTS[cat] ?? SHELL_VARIANTS.generic;
26787
+ base = pick(`shell_${cat}_${tier}`, pool[tier] ?? pool.terse);
26788
+ break;
26789
+ }
26771
26790
  case "grep_search":
26772
- return `Searching the code for ${args["pattern"] ?? "that pattern"}`;
26773
- case "find_files":
26774
- return `Looking for files matching ${args["pattern"] ?? "that pattern"}`;
26775
- case "list_directory":
26776
- return `Checking what's in ${file || "the directory"}`;
26791
+ base = pick(poolKey, (GREP_VARIANTS[tier] ?? GREP_VARIANTS.terse)(file, args));
26792
+ break;
26793
+ case "find_files": {
26794
+ const pat = args["pattern"] ?? "pattern";
26795
+ const findVariants = {
26796
+ terse: [`Finding ${pat}`, `Searching for ${pat}`],
26797
+ conv: [`Looking for files matching ${pat}`, `Finding files that match ${pat}`],
26798
+ chatty: [`Scouring the project for ${pat}`, `Searching far and wide for ${pat}`, `Let me find everything matching ${pat}`]
26799
+ };
26800
+ base = pick(poolKey, findVariants[tier] ?? findVariants.terse);
26801
+ break;
26802
+ }
26803
+ case "list_directory": {
26804
+ const dir = file || "the directory";
26805
+ const listVariants = {
26806
+ terse: [`Listing ${dir}`, `Checking ${dir}`],
26807
+ conv: [`Checking what's in ${dir}`, `Looking at ${dir} contents`],
26808
+ chatty: [`Let's see what we've got in ${dir}`, `Browsing through ${dir}`]
26809
+ };
26810
+ base = pick(poolKey, listVariants[tier] ?? listVariants.terse);
26811
+ break;
26812
+ }
26777
26813
  case "web_search":
26778
- return `Let me search the web for that`;
26814
+ base = pick(poolKey, (WEB_SEARCH_VARIANTS[tier] ?? WEB_SEARCH_VARIANTS.terse)(file, args));
26815
+ break;
26779
26816
  case "web_fetch":
26780
- return `Pulling up that web page`;
26817
+ base = pick(poolKey, (WEB_FETCH_VARIANTS[tier] ?? WEB_FETCH_VARIANTS.terse)(file, args));
26818
+ break;
26781
26819
  case "memory_read":
26782
- return `Checking my notes`;
26820
+ base = pick(poolKey, (MEMORY_READ_VARIANTS[tier] ?? MEMORY_READ_VARIANTS.terse)(file, args));
26821
+ break;
26783
26822
  case "memory_write":
26784
- return `Making a note of that`;
26823
+ base = pick(poolKey, (MEMORY_WRITE_VARIANTS[tier] ?? MEMORY_WRITE_VARIANTS.terse)(file, args));
26824
+ break;
26785
26825
  case "task_complete":
26786
- return String(args["summary"] ?? "All done");
26787
- case "batch_edit":
26788
- return `Editing several files at once`;
26789
- case "codebase_map":
26790
- return `Mapping out the project structure`;
26791
- case "diagnostic":
26792
- return `Running some diagnostics`;
26793
- case "git_info":
26794
- return `Checking the git status`;
26826
+ base = String(args["summary"] ?? (tier === "chatty" ? "And that's a wrap" : tier === "conv" ? "All done" : "Task complete"));
26827
+ break;
26795
26828
  case "sub_agent":
26796
- return `Handing this off to a sub agent`;
26797
- case "image_read":
26798
- return `Taking a look at that image`;
26799
- case "screenshot":
26800
- return `Grabbing a screenshot`;
26801
- case "browser_action":
26802
- return `Let me ${args["action"] === "navigate" ? "open that page" : args["action"] === "screenshot" ? "grab a screenshot of the browser" : `do a browser ${args["action"] ?? "action"}`}`;
26803
- case "scheduler":
26804
- return `${args["action"] === "create" ? "Setting up a scheduled task" : "Checking the schedule"}`;
26805
- case "reminder":
26806
- return `${args["action"] === "set" ? "Making a note for next time" : "Looking at reminders"}`;
26807
- case "agenda":
26808
- return `Let me check what's on the agenda`;
26809
- default:
26810
- return `Working with ${toolName}`;
26829
+ base = pick(poolKey, (SUB_AGENT_VARIANTS[tier] ?? SUB_AGENT_VARIANTS.terse)(file, args));
26830
+ break;
26831
+ case "batch_edit": {
26832
+ const batchV = {
26833
+ terse: ["Editing multiple files", "Batch editing"],
26834
+ conv: ["Editing several files at once", "Making changes across multiple files"],
26835
+ chatty: ["Okay, editing a bunch of files here, bear with me", "Touching several files at once, lot of ground to cover"]
26836
+ };
26837
+ base = pick(poolKey, batchV[tier] ?? batchV.terse);
26838
+ break;
26839
+ }
26840
+ case "codebase_map": {
26841
+ const mapV = {
26842
+ terse: ["Mapping project", "Scanning structure"],
26843
+ conv: ["Mapping out the project structure", "Getting the project layout"],
26844
+ chatty: ["Let me get the lay of the land on this project", "Mapping the whole codebase out"]
26845
+ };
26846
+ base = pick(poolKey, mapV[tier] ?? mapV.terse);
26847
+ break;
26848
+ }
26849
+ case "diagnostic": {
26850
+ const diagV = {
26851
+ terse: ["Running diagnostics", "Diagnostic check"],
26852
+ conv: ["Running some diagnostics", "Let me run a diagnostic"],
26853
+ chatty: ["Running diagnostics, let's see if anything looks off", "Time for a health check"]
26854
+ };
26855
+ base = pick(poolKey, diagV[tier] ?? diagV.terse);
26856
+ break;
26857
+ }
26858
+ case "git_info": {
26859
+ const gitV = {
26860
+ terse: ["Checking git", "Git status"],
26861
+ conv: ["Checking the git status", "Looking at git info"],
26862
+ chatty: ["Checking in with git to see where things stand", "Let me see what git has to say"]
26863
+ };
26864
+ base = pick(poolKey, gitV[tier] ?? gitV.terse);
26865
+ break;
26866
+ }
26867
+ case "image_read": {
26868
+ const imgV = {
26869
+ terse: ["Reading image", "Loading image"],
26870
+ conv: ["Taking a look at that image", "Opening the image"],
26871
+ chatty: ["Let me get a good look at that image", "Opening up the image to see what's there"]
26872
+ };
26873
+ base = pick(poolKey, imgV[tier] ?? imgV.terse);
26874
+ break;
26875
+ }
26876
+ case "screenshot": {
26877
+ const ssV = {
26878
+ terse: ["Taking screenshot", "Capturing screen"],
26879
+ conv: ["Grabbing a screenshot", "Capturing what's on screen"],
26880
+ chatty: ["Snapping a screenshot to see what's happening", "Let me grab a visual"]
26881
+ };
26882
+ base = pick(poolKey, ssV[tier] ?? ssV.terse);
26883
+ break;
26884
+ }
26885
+ case "ocr": {
26886
+ const ocrV = {
26887
+ terse: ["Extracting text", "Running OCR"],
26888
+ conv: ["Extracting text from the image", "Running OCR on this"],
26889
+ chatty: ["Let me pull the text out of this image", "Running optical character recognition"]
26890
+ };
26891
+ base = pick(poolKey, ocrV[tier] ?? ocrV.terse);
26892
+ break;
26893
+ }
26894
+ case "browser_action": {
26895
+ const action = args["action"] ?? "action";
26896
+ const browserV = {
26897
+ terse: [`Browser ${action}`],
26898
+ conv: [
26899
+ action === "navigate" ? "Opening that page" : action === "screenshot" ? "Grabbing a screenshot of the browser" : `Browser ${action}`
26900
+ ],
26901
+ chatty: [
26902
+ action === "navigate" ? "Firing up the browser, let's see what's on that page" : action === "screenshot" ? "Getting a visual from the browser" : `Doing a browser ${action}`
26903
+ ]
26904
+ };
26905
+ base = pick(poolKey, browserV[tier] ?? browserV.terse);
26906
+ break;
26907
+ }
26908
+ default: {
26909
+ const defaultV = {
26910
+ terse: [`Using ${toolName}`],
26911
+ conv: [`Working with ${toolName}`, `Using ${toolName}`],
26912
+ chatty: [`Pulling in ${toolName}, hang tight`, `Using ${toolName} for this`, `Working with ${toolName} here`]
26913
+ };
26914
+ base = pick(poolKey, defaultV[tier] ?? defaultV.terse);
26915
+ break;
26916
+ }
26811
26917
  }
26812
- }
26813
- function describeToolCallChatty(toolName, args, file) {
26814
- switch (toolName) {
26815
- case "file_read":
26816
- return `Alright, let's crack open ${file} and see what we're working with`;
26817
- case "file_write":
26818
- return `Time to write this out to ${file}`;
26819
- case "file_edit":
26820
- return `Let me tweak ${file}, I think I see what needs to change`;
26821
- case "file_patch":
26822
- return `Patching up ${file}, this should do the trick`;
26823
- case "shell":
26824
- return describeShellChatty(String(args["command"] ?? ""));
26825
- case "grep_search":
26826
- return `Hunting through the code for ${args["pattern"] ?? "what we need"}`;
26827
- case "find_files":
26828
- return `Scouring the project for files matching ${args["pattern"] ?? "our target"}`;
26829
- case "list_directory":
26830
- return `Let's see what we've got in ${file || "this directory"}`;
26831
- case "web_search":
26832
- return `Off to the web to track this down`;
26833
- case "web_fetch":
26834
- return `Grabbing that page, one moment`;
26835
- case "memory_read":
26836
- return `Let me dig through my notes on this`;
26837
- case "memory_write":
26838
- return `Stashing this away for later`;
26839
- case "task_complete":
26840
- return String(args["summary"] ?? "And that's a wrap");
26841
- case "batch_edit":
26842
- return `Okay, editing a bunch of files here, bear with me`;
26843
- case "codebase_map":
26844
- return `Let me get the lay of the land on this project`;
26845
- case "diagnostic":
26846
- return `Running diagnostics, let's see if anything looks off`;
26847
- case "git_info":
26848
- return `Checking in with git to see where things stand`;
26849
- case "sub_agent":
26850
- return `Bringing in reinforcements for this one`;
26851
- case "image_read":
26852
- return `Let me get a good look at that image`;
26853
- case "screenshot":
26854
- return `Snapping a screenshot to see what's happening`;
26855
- case "browser_action":
26856
- return `Firing up the browser, let's ${args["action"] === "navigate" ? "see what's on that page" : args["action"] === "screenshot" ? "get a visual" : `${args["action"] ?? "do this"}`}`;
26857
- case "scheduler":
26858
- return `${args["action"] === "create" ? "Alright, let me set up a recurring task for you" : "Let me pull up the schedule and see what's coming up"}`;
26859
- case "reminder":
26860
- return `${args["action"] === "set" ? "Leaving myself a note for future me, don't let me forget" : "Let me check if past me left any reminders"}`;
26861
- case "agenda":
26862
- return `Let me see the full picture of what needs doing`;
26863
- default:
26864
- return `Pulling in ${toolName}, hang tight`;
26918
+ if (!prefix)
26919
+ return base;
26920
+ if (prefix.endsWith(". ") || prefix.endsWith("! "))
26921
+ return prefix + base;
26922
+ if (prefix && base.length > 0) {
26923
+ return prefix + base.charAt(0).toLowerCase() + base.slice(1);
26865
26924
  }
26866
- }
26867
- function describeShellTerse(cmd) {
26868
- if (/npm\s+test|vitest|jest|mocha/.test(cmd))
26869
- return "Running tests";
26870
- if (/npm\s+run\s+build|tsc|esbuild/.test(cmd))
26871
- return "Building project";
26872
- if (/npm\s+install|pnpm\s+install/.test(cmd))
26873
- return "Installing dependencies";
26874
- if (/git\s+/.test(cmd))
26875
- return "Running git command";
26876
- if (/npm\s+run\s+lint|eslint|biome/.test(cmd))
26877
- return "Running linter";
26878
- if (cmd.length > 40)
26879
- return "Running shell command";
26880
- return `Running ${cmd.slice(0, 30)}`;
26881
- }
26882
- function describeShellConversational(cmd) {
26883
- if (/npm\s+test|vitest|jest|mocha/.test(cmd))
26884
- return "Let's run the tests and see how we're doing";
26885
- if (/npm\s+run\s+build|tsc|esbuild/.test(cmd))
26886
- return "Building the project now";
26887
- if (/npm\s+install|pnpm\s+install/.test(cmd))
26888
- return "Installing the dependencies";
26889
- if (/git\s+/.test(cmd))
26890
- return "Running a git command";
26891
- if (/npm\s+run\s+lint|eslint|biome/.test(cmd))
26892
- return "Checking the code with the linter";
26893
- return "Running a command";
26894
- }
26895
- function describeShellChatty(cmd) {
26896
- if (/npm\s+test|vitest|jest|mocha/.test(cmd))
26897
- return "Alright, moment of truth, let's see if the tests pass";
26898
- if (/npm\s+run\s+build|tsc|esbuild/.test(cmd))
26899
- return "Kicking off a build, fingers crossed";
26900
- if (/npm\s+install|pnpm\s+install/.test(cmd))
26901
- return "Pulling in dependencies, this might take a sec";
26902
- if (/git\s+/.test(cmd))
26903
- return "Checking in with git";
26904
- if (/npm\s+run\s+lint|eslint|biome/.test(cmd))
26905
- return "Running the linter, let's keep things tidy";
26906
- return "Firing off a shell command";
26925
+ return base;
26907
26926
  }
26908
26927
  function describeToolResult(toolName, success, personality = 2) {
26909
26928
  if (toolName === "task_complete")
26910
26929
  return "";
26911
- if (personality <= 2) {
26912
- return success ? "Done" : "That failed, trying to fix it";
26930
+ const tier = getTier(personality);
26931
+ if (success) {
26932
+ narration.consecutiveErrors = 0;
26933
+ if (personality >= 3 && Math.random() < 0.4)
26934
+ return "";
26935
+ return pick(`result_ok_${tier}`, RESULT_SUCCESS_VARIANTS[tier] ?? RESULT_SUCCESS_VARIANTS.terse);
26913
26936
  }
26914
- if (personality <= 3) {
26915
- return success ? "Got it" : "That didn't work, let me try another approach";
26937
+ narration.consecutiveErrors++;
26938
+ narration.totalErrors++;
26939
+ if (narration.consecutiveErrors >= 3) {
26940
+ return pick(`result_multifail_${tier}`, RESULT_MULTI_FAIL_VARIANTS[tier] ?? RESULT_MULTI_FAIL_VARIANTS.terse);
26916
26941
  }
26917
- return success ? "Looking good, moving on" : "Hmm, that didn't go as planned. Let me take a different angle";
26942
+ return pick(`result_fail_${tier}`, RESULT_FAIL_VARIANTS[tier] ?? RESULT_FAIL_VARIANTS.terse);
26918
26943
  }
26919
26944
  function describeTaskComplete(summary, completed, personality = 2) {
26920
26945
  const truncated = summary.length > 300 ? summary.slice(0, 300) + "..." : summary;
26946
+ const tier = getTier(personality);
26921
26947
  if (!completed) {
26922
- if (personality <= 2)
26923
- return "Task did not complete.";
26924
- if (personality <= 3)
26925
- return "I wasn't able to finish that one.";
26926
- return "Well, that didn't quite get there. You might want to take a look at what's left.";
26948
+ return pick(`task_incomplete_${tier}`, TASK_INCOMPLETE_VARIANTS[tier] ?? TASK_INCOMPLETE_VARIANTS.terse);
26927
26949
  }
26928
- if (personality <= 2)
26929
- return `Task complete. ${truncated}`;
26930
- if (personality <= 3)
26931
- return `All done. ${truncated}`;
26932
- return `And we're done! ${truncated}`;
26950
+ const opener = pick(`task_complete_${tier}`, TASK_COMPLETE_VARIANTS[tier] ?? TASK_COMPLETE_VARIANTS.terse);
26951
+ if (truncated)
26952
+ return `${opener} ${truncated}`;
26953
+ return opener;
26933
26954
  }
26934
26955
  function formatBytes2(bytes) {
26935
26956
  if (bytes < 1024)
@@ -26938,7 +26959,7 @@ function formatBytes2(bytes) {
26938
26959
  return `${(bytes / 1024).toFixed(0)}KB`;
26939
26960
  return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
26940
26961
  }
26941
- var VOICE_MODELS, VoiceEngine;
26962
+ var VOICE_MODELS, VoiceEngine, narration, FILE_READ_VARIANTS, FILE_WRITE_VARIANTS, FILE_EDIT_VARIANTS, GREP_VARIANTS, WEB_SEARCH_VARIANTS, WEB_FETCH_VARIANTS, MEMORY_READ_VARIANTS, MEMORY_WRITE_VARIANTS, SUB_AGENT_VARIANTS, SHELL_VARIANTS, RESULT_SUCCESS_VARIANTS, RESULT_FAIL_VARIANTS, RESULT_MULTI_FAIL_VARIANTS, TASK_COMPLETE_VARIANTS, TASK_INCOMPLETE_VARIANTS;
26942
26963
  var init_voice = __esm({
26943
26964
  "packages/cli/dist/tui/voice.js"() {
26944
26965
  "use strict";
@@ -27500,6 +27521,368 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
27500
27521
  renderInfo("Voice model loaded.");
27501
27522
  }
27502
27523
  };
27524
+ narration = {
27525
+ toolCount: 0,
27526
+ toolCounts: {},
27527
+ consecutiveErrors: 0,
27528
+ totalErrors: 0,
27529
+ lastTool: "",
27530
+ lastFile: "",
27531
+ filesSeen: /* @__PURE__ */ new Set(),
27532
+ lastVariantIdx: {}
27533
+ };
27534
+ FILE_READ_VARIANTS = {
27535
+ terse: (f) => [`Reading ${f}`, `Opening ${f}`, `Loading ${f}`],
27536
+ conv: (f) => [
27537
+ `Let me take a look at ${f}`,
27538
+ `Opening up ${f}`,
27539
+ `Pulling up ${f}`,
27540
+ `Checking ${f}`,
27541
+ `Let me see what's in ${f}`
27542
+ ],
27543
+ chatty: (f) => [
27544
+ `Alright, let's crack open ${f} and see what we're working with`,
27545
+ `Diving into ${f}`,
27546
+ `Let me pull up ${f} and see what's going on`,
27547
+ `Time to see what ${f} has for us`,
27548
+ `Opening ${f}, let's see what we've got`,
27549
+ `Taking a look inside ${f}`
27550
+ ]
27551
+ };
27552
+ FILE_WRITE_VARIANTS = {
27553
+ terse: (f) => [`Writing ${f}`, `Saving ${f}`, `Creating ${f}`],
27554
+ conv: (f) => [
27555
+ `Writing changes to ${f}`,
27556
+ `Saving the updates to ${f}`,
27557
+ `Putting this into ${f}`,
27558
+ `Writing this out to ${f}`
27559
+ ],
27560
+ chatty: (f) => [
27561
+ `Time to write this out to ${f}`,
27562
+ `Laying down the changes in ${f}`,
27563
+ `Writing the new version of ${f}`,
27564
+ `Let me save this to ${f} before I forget`,
27565
+ `Committing these changes to ${f}`
27566
+ ]
27567
+ };
27568
+ FILE_EDIT_VARIANTS = {
27569
+ terse: (f) => [`Editing ${f}`, `Modifying ${f}`, `Updating ${f}`],
27570
+ conv: (f) => [
27571
+ `Making some edits to ${f}`,
27572
+ `Adjusting ${f}`,
27573
+ `Tweaking ${f}`,
27574
+ `Updating ${f} with the fix`,
27575
+ `Applying changes to ${f}`
27576
+ ],
27577
+ chatty: (f) => [
27578
+ `Let me tweak ${f}, I think I see what needs to change`,
27579
+ `Making some surgical edits to ${f}`,
27580
+ `Alright, adjusting ${f} now`,
27581
+ `Got it, let me fix that up in ${f}`,
27582
+ `Reshaping ${f} a bit here`,
27583
+ `Modifying ${f}, this should get us closer`
27584
+ ]
27585
+ };
27586
+ GREP_VARIANTS = {
27587
+ terse: (_f, a) => [`Searching for ${a["pattern"] ?? "pattern"}`, `Grepping ${a["pattern"] ?? "code"}`],
27588
+ conv: (_f, a) => [
27589
+ `Searching the code for ${a["pattern"] ?? "that pattern"}`,
27590
+ `Looking for ${a["pattern"] ?? "matches"} in the codebase`,
27591
+ `Scanning for ${a["pattern"] ?? "that"} across the files`
27592
+ ],
27593
+ chatty: (_f, a) => [
27594
+ `Hunting through the code for ${a["pattern"] ?? "what we need"}`,
27595
+ `Let me track down ${a["pattern"] ?? "that"} in the source`,
27596
+ `Scouring the codebase for ${a["pattern"] ?? "our target"}`,
27597
+ `Searching high and low for ${a["pattern"] ?? "this pattern"}`
27598
+ ]
27599
+ };
27600
+ WEB_SEARCH_VARIANTS = {
27601
+ terse: () => [`Searching the web`, `Web search`, `Looking it up online`],
27602
+ conv: () => [
27603
+ `Let me search the web for that`,
27604
+ `Checking online for that`,
27605
+ `Let me look that up`,
27606
+ `Searching the web real quick`
27607
+ ],
27608
+ chatty: () => [
27609
+ `Off to the web to track this down`,
27610
+ `Let me see what the internet has to say about this`,
27611
+ `Heading online to dig up some answers`,
27612
+ `Time for a quick web search`,
27613
+ `Let me consult the wider world on this one`
27614
+ ]
27615
+ };
27616
+ WEB_FETCH_VARIANTS = {
27617
+ terse: () => [`Fetching page`, `Loading page`, `Downloading page`],
27618
+ conv: () => [
27619
+ `Pulling up that web page`,
27620
+ `Fetching the page now`,
27621
+ `Loading that page`,
27622
+ `Grabbing the content from that URL`
27623
+ ],
27624
+ chatty: () => [
27625
+ `Grabbing that page, one moment`,
27626
+ `Let me pull that page up and see what's there`,
27627
+ `Fetching the goods from that URL`,
27628
+ `Loading up that page now`
27629
+ ]
27630
+ };
27631
+ MEMORY_READ_VARIANTS = {
27632
+ terse: () => [`Reading memory`, `Checking notes`, `Recalling`],
27633
+ conv: () => [
27634
+ `Checking my notes`,
27635
+ `Let me see what I remember`,
27636
+ `Pulling up my notes on this`,
27637
+ `Looking through memory`
27638
+ ],
27639
+ chatty: () => [
27640
+ `Let me dig through my notes on this`,
27641
+ `Checking what I've got stored away`,
27642
+ `Searching my memory for something relevant`,
27643
+ `Let me recall what I know about this`
27644
+ ]
27645
+ };
27646
+ MEMORY_WRITE_VARIANTS = {
27647
+ terse: () => [`Saving to memory`, `Noting that`, `Remembering`],
27648
+ conv: () => [
27649
+ `Making a note of that`,
27650
+ `Saving this for later`,
27651
+ `Jotting that down`,
27652
+ `Storing that away`
27653
+ ],
27654
+ chatty: () => [
27655
+ `Stashing this away for later`,
27656
+ `Making a mental note of this one`,
27657
+ `Saving this to memory so I don't forget`,
27658
+ `Filing this away for next time`
27659
+ ]
27660
+ };
27661
+ SUB_AGENT_VARIANTS = {
27662
+ terse: () => [`Delegating to sub agent`, `Spawning sub agent`, `Handing off`],
27663
+ conv: () => [
27664
+ `Handing this off to a sub agent`,
27665
+ `Bringing in some help for this`,
27666
+ `Delegating this part of the work`
27667
+ ],
27668
+ chatty: () => [
27669
+ `Bringing in reinforcements for this one`,
27670
+ `Let me hand this off to a specialist`,
27671
+ `Calling in backup on this`,
27672
+ `This needs a dedicated agent, passing it along`
27673
+ ]
27674
+ };
27675
+ SHELL_VARIANTS = {
27676
+ test: {
27677
+ terse: ["Running tests", "Testing", "Executing tests"],
27678
+ conv: [
27679
+ "Let's run the tests and see how we're doing",
27680
+ "Running the test suite",
27681
+ "Time to check if the tests pass",
27682
+ "Let me run those tests"
27683
+ ],
27684
+ chatty: [
27685
+ "Alright, moment of truth, let's see if the tests pass",
27686
+ "Running the tests, fingers crossed",
27687
+ "Test time, let's see where we stand",
27688
+ "Kicking off the test suite, here goes nothing",
27689
+ "Let's put this to the test, literally"
27690
+ ]
27691
+ },
27692
+ build: {
27693
+ terse: ["Building project", "Compiling", "Building"],
27694
+ conv: [
27695
+ "Building the project now",
27696
+ "Compiling everything",
27697
+ "Starting the build",
27698
+ "Let me build this"
27699
+ ],
27700
+ chatty: [
27701
+ "Kicking off a build, fingers crossed",
27702
+ "Time to compile and see if everything holds together",
27703
+ "Building the project, let's see how it goes",
27704
+ "Alright, build time",
27705
+ "Compiling the whole thing, one moment"
27706
+ ]
27707
+ },
27708
+ install: {
27709
+ terse: ["Installing dependencies", "Installing packages", "Running install"],
27710
+ conv: [
27711
+ "Installing the dependencies",
27712
+ "Pulling in the packages",
27713
+ "Getting the dependencies set up"
27714
+ ],
27715
+ chatty: [
27716
+ "Pulling in dependencies, this might take a sec",
27717
+ "Installing packages, grab a coffee",
27718
+ "Setting up the dependencies now"
27719
+ ]
27720
+ },
27721
+ git: {
27722
+ terse: ["Running git command", "Git operation", "Checking git"],
27723
+ conv: [
27724
+ "Running a git command",
27725
+ "Checking with git",
27726
+ "Let me do a git operation"
27727
+ ],
27728
+ chatty: [
27729
+ "Checking in with git to see where things stand",
27730
+ "Let me consult git on this",
27731
+ "Running a quick git operation",
27732
+ "Talking to git for a second"
27733
+ ]
27734
+ },
27735
+ lint: {
27736
+ terse: ["Running linter", "Linting", "Checking style"],
27737
+ conv: [
27738
+ "Checking the code with the linter",
27739
+ "Running the linter",
27740
+ "Let me check the code style"
27741
+ ],
27742
+ chatty: [
27743
+ "Running the linter, let's keep things tidy",
27744
+ "Lint check time, making sure everything's clean",
27745
+ "Let's see if the linter is happy with this"
27746
+ ]
27747
+ },
27748
+ node: {
27749
+ terse: ["Running Node script", "Executing script"],
27750
+ conv: [
27751
+ "Running a Node script",
27752
+ "Executing this script",
27753
+ "Let me run this"
27754
+ ],
27755
+ chatty: [
27756
+ "Firing up this Node script, let's see what happens",
27757
+ "Running the script now",
27758
+ "Executing this one, stand by"
27759
+ ]
27760
+ },
27761
+ python: {
27762
+ terse: ["Running Python", "Executing Python script"],
27763
+ conv: ["Running a Python script", "Executing the Python code"],
27764
+ chatty: [
27765
+ "Running the Python script, one moment",
27766
+ "Firing up Python for this one"
27767
+ ]
27768
+ },
27769
+ network: {
27770
+ terse: ["Making network request", "Fetching data"],
27771
+ conv: ["Making a network request", "Fetching some data"],
27772
+ chatty: ["Reaching out to the network", "Making a request, let's see what comes back"]
27773
+ },
27774
+ container: {
27775
+ terse: ["Running container command", "Docker operation"],
27776
+ conv: ["Running a container command", "Working with containers"],
27777
+ chatty: ["Spinning up containers, one moment", "Doing some container work"]
27778
+ },
27779
+ generic: {
27780
+ terse: ["Running command", "Executing command", "Shell command"],
27781
+ conv: [
27782
+ "Running a command",
27783
+ "Executing a shell command",
27784
+ "Let me run this command",
27785
+ "Firing off a command"
27786
+ ],
27787
+ chatty: [
27788
+ "Running a command, one moment",
27789
+ "Let me execute this and see what we get",
27790
+ "Firing off a shell command, stand by",
27791
+ "Executing this, let's see the output",
27792
+ "Running something in the shell real quick"
27793
+ ]
27794
+ }
27795
+ };
27796
+ RESULT_SUCCESS_VARIANTS = {
27797
+ terse: ["Done", "OK", "Complete", "Got it"],
27798
+ conv: [
27799
+ "Got it",
27800
+ "That worked",
27801
+ "Good to go",
27802
+ "Looking good",
27803
+ "All set",
27804
+ "Done"
27805
+ ],
27806
+ chatty: [
27807
+ "Looking good, moving on",
27808
+ "That went well, next step",
27809
+ "Nice, onward",
27810
+ "Perfect, let's keep going",
27811
+ "Got what I needed, moving on",
27812
+ "That came through, great",
27813
+ "Worked like a charm"
27814
+ ]
27815
+ };
27816
+ RESULT_FAIL_VARIANTS = {
27817
+ terse: [
27818
+ "Failed, retrying",
27819
+ "Error, adjusting",
27820
+ "That failed, fixing"
27821
+ ],
27822
+ conv: [
27823
+ "That didn't work, let me try another approach",
27824
+ "Hit a snag, adjusting course",
27825
+ "Ran into an issue, trying again",
27826
+ "Didn't go as expected, let me rethink this",
27827
+ "Not quite, let me try something else"
27828
+ ],
27829
+ chatty: [
27830
+ "Hmm, that didn't go as planned, let me try a different angle",
27831
+ "Well that didn't work, but I've got another idea",
27832
+ "Okay, that approach didn't pan out, pivoting",
27833
+ "Hit a wall there, but I think I see another way",
27834
+ "Not the result I was hoping for, let me regroup",
27835
+ "That blew up, but no worries, I'll come at it differently",
27836
+ "Alright, that wasn't it, but I'm not giving up"
27837
+ ]
27838
+ };
27839
+ RESULT_MULTI_FAIL_VARIANTS = {
27840
+ terse: ["Still failing, changing approach", "Error again, different method"],
27841
+ conv: [
27842
+ "Another miss, time to rethink this fundamentally",
27843
+ "Still not working, let me step back and reconsider",
27844
+ "Okay, clearly this approach isn't it"
27845
+ ],
27846
+ chatty: [
27847
+ "That's a few misses now, time to really change things up",
27848
+ "Alright, clearly I need a completely different strategy here",
27849
+ "This keeps failing, let me take a step back and think about this differently",
27850
+ "Okay, I've been going about this wrong, new plan"
27851
+ ]
27852
+ };
27853
+ TASK_COMPLETE_VARIANTS = {
27854
+ terse: ["Task complete.", "Done.", "Finished."],
27855
+ conv: [
27856
+ "All done.",
27857
+ "That's everything.",
27858
+ "Finished up.",
27859
+ "All taken care of.",
27860
+ "Wrapped that up."
27861
+ ],
27862
+ chatty: [
27863
+ "And we're done!",
27864
+ "That's a wrap!",
27865
+ "All finished, good stuff.",
27866
+ "Mission accomplished.",
27867
+ "Everything's taken care of.",
27868
+ "Done and dusted."
27869
+ ]
27870
+ };
27871
+ TASK_INCOMPLETE_VARIANTS = {
27872
+ terse: ["Task did not complete.", "Incomplete.", "Could not finish."],
27873
+ conv: [
27874
+ "I wasn't able to finish that one.",
27875
+ "Didn't quite get there.",
27876
+ "Ran out of steam on that one.",
27877
+ "Couldn't quite wrap that up."
27878
+ ],
27879
+ chatty: [
27880
+ "Well, that didn't quite get there. You might want to take a look at what's left.",
27881
+ "I gave it my best shot, but couldn't finish everything.",
27882
+ "Got partway there, but some things still need attention.",
27883
+ "Not fully done, but I made progress on it."
27884
+ ]
27885
+ };
27503
27886
  }
27504
27887
  });
27505
27888
 
@@ -33922,6 +34305,7 @@ ${entry.fullContent}`
33922
34305
  const systemContext = emotionContext ? `Working directory: ${repoRoot}
33923
34306
 
33924
34307
  ${emotionContext}` : `Working directory: ${repoRoot}`;
34308
+ resetNarrationContext();
33925
34309
  const promise = runner.run(task, systemContext).then((result) => {
33926
34310
  const tokens = { total: result.totalTokens, estimated: result.estimatedTokens };
33927
34311
  contentWrite(() => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.59.0",
3
+ "version": "0.60.0",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",