@travisennis/acai 0.0.11 → 0.0.12

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 (110) hide show
  1. package/README.md +2 -3
  2. package/dist/commands/init-project/utils.d.ts.map +1 -1
  3. package/dist/commands/init-project/utils.js +0 -11
  4. package/dist/commands/manager.d.ts.map +1 -1
  5. package/dist/commands/manager.js +6 -1
  6. package/dist/commands/resources/index.d.ts.map +1 -1
  7. package/dist/commands/resources/index.js +4 -1
  8. package/dist/commands/session/index.d.ts.map +1 -1
  9. package/dist/commands/session/index.js +6 -0
  10. package/dist/commands/session/types.d.ts +1 -0
  11. package/dist/commands/session/types.d.ts.map +1 -1
  12. package/dist/commands/tools/index.d.ts +3 -0
  13. package/dist/commands/tools/index.d.ts.map +1 -0
  14. package/dist/commands/tools/index.js +190 -0
  15. package/dist/commands/tools/templates.d.ts +6 -0
  16. package/dist/commands/tools/templates.d.ts.map +1 -0
  17. package/dist/commands/tools/templates.js +97 -0
  18. package/dist/config/index.d.ts +5 -0
  19. package/dist/config/index.d.ts.map +1 -1
  20. package/dist/config/index.js +41 -1
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +15 -3
  23. package/dist/models/anthropic-provider.d.ts +1 -1
  24. package/dist/models/deepseek-provider.d.ts +3 -3
  25. package/dist/models/deepseek-provider.js +17 -17
  26. package/dist/models/google-provider.d.ts +2 -4
  27. package/dist/models/google-provider.d.ts.map +1 -1
  28. package/dist/models/google-provider.js +2 -17
  29. package/dist/models/groq-provider.d.ts +2 -4
  30. package/dist/models/groq-provider.d.ts.map +1 -1
  31. package/dist/models/groq-provider.js +3 -21
  32. package/dist/models/opencode-go-provider.d.ts +11 -1
  33. package/dist/models/opencode-go-provider.d.ts.map +1 -1
  34. package/dist/models/opencode-go-provider.js +136 -0
  35. package/dist/models/opencode-zen-provider.d.ts +3 -3
  36. package/dist/models/opencode-zen-provider.d.ts.map +1 -1
  37. package/dist/models/opencode-zen-provider.js +26 -32
  38. package/dist/models/openrouter-provider.d.ts +4 -15
  39. package/dist/models/openrouter-provider.d.ts.map +1 -1
  40. package/dist/models/openrouter-provider.js +26 -169
  41. package/dist/models/providers.d.ts +1 -1
  42. package/dist/models/providers.d.ts.map +1 -1
  43. package/dist/models/xai-provider.d.ts +1 -2
  44. package/dist/models/xai-provider.d.ts.map +1 -1
  45. package/dist/models/xai-provider.js +0 -13
  46. package/dist/prompts/manager.d.ts.map +1 -1
  47. package/dist/prompts/manager.js +5 -1
  48. package/dist/prompts/system-prompt.d.ts +1 -0
  49. package/dist/prompts/system-prompt.d.ts.map +1 -1
  50. package/dist/prompts/system-prompt.js +20 -5
  51. package/dist/repl/index.d.ts +1 -2
  52. package/dist/repl/index.d.ts.map +1 -1
  53. package/dist/repl/index.js +5 -52
  54. package/dist/skills/activated-tracker.d.ts +11 -0
  55. package/dist/skills/activated-tracker.d.ts.map +1 -0
  56. package/dist/skills/activated-tracker.js +16 -0
  57. package/dist/skills/index.d.ts +1 -1
  58. package/dist/skills/index.d.ts.map +1 -1
  59. package/dist/skills/index.js +7 -1
  60. package/dist/tools/bash.d.ts +4 -4
  61. package/dist/tools/bash.d.ts.map +1 -1
  62. package/dist/tools/bash.js +17 -6
  63. package/dist/tools/directory-tree.d.ts +4 -4
  64. package/dist/tools/directory-tree.d.ts.map +1 -1
  65. package/dist/tools/directory-tree.js +2 -0
  66. package/dist/tools/dynamic-tool-loader.d.ts +11 -2
  67. package/dist/tools/dynamic-tool-loader.d.ts.map +1 -1
  68. package/dist/tools/dynamic-tool-loader.js +299 -39
  69. package/dist/tools/edit-file.d.ts +2 -2
  70. package/dist/tools/glob.d.ts +16 -16
  71. package/dist/tools/glob.d.ts.map +1 -1
  72. package/dist/tools/glob.js +9 -1
  73. package/dist/tools/grep.d.ts +14 -14
  74. package/dist/tools/grep.d.ts.map +1 -1
  75. package/dist/tools/grep.js +7 -0
  76. package/dist/tools/index.d.ts +42 -36
  77. package/dist/tools/index.d.ts.map +1 -1
  78. package/dist/tools/index.js +16 -1
  79. package/dist/tools/ls.d.ts +2 -2
  80. package/dist/tools/ls.d.ts.map +1 -1
  81. package/dist/tools/ls.js +1 -0
  82. package/dist/tools/read-file.d.ts +8 -8
  83. package/dist/tools/save-file.d.ts +4 -4
  84. package/dist/tools/skill.d.ts +2 -1
  85. package/dist/tools/skill.d.ts.map +1 -1
  86. package/dist/tools/skill.js +55 -12
  87. package/dist/tools/types.d.ts +8 -2
  88. package/dist/tools/types.d.ts.map +1 -1
  89. package/dist/tools/web-fetch.d.ts +6 -6
  90. package/dist/tools/web-fetch.d.ts.map +1 -1
  91. package/dist/tools/web-fetch.js +27 -8
  92. package/dist/tools/web-search.d.ts +4 -4
  93. package/dist/tools/web-search.js +1 -1
  94. package/dist/tui/components/footer.d.ts +0 -2
  95. package/dist/tui/components/footer.d.ts.map +1 -1
  96. package/dist/tui/components/footer.js +1 -17
  97. package/dist/utils/binary-output.d.ts +32 -0
  98. package/dist/utils/binary-output.d.ts.map +1 -0
  99. package/dist/utils/binary-output.js +127 -0
  100. package/dist/utils/command-protection.d.ts.map +1 -1
  101. package/dist/utils/command-protection.js +92 -9
  102. package/dist/utils/parsing.d.ts +1 -1
  103. package/dist/utils/parsing.d.ts.map +1 -1
  104. package/package.json +27 -25
  105. package/dist/modes/manager.d.ts +0 -24
  106. package/dist/modes/manager.d.ts.map +0 -1
  107. package/dist/modes/manager.js +0 -77
  108. package/dist/modes/prompts.d.ts +0 -2
  109. package/dist/modes/prompts.d.ts.map +0 -1
  110. package/dist/modes/prompts.js +0 -142
@@ -1,9 +1,8 @@
1
1
  import { generateRulesFromSession } from "../commands/generate-rules/service.js";
2
2
  import { showModelSelector } from "../commands/model/model-panel.js";
3
3
  import { showReviewPanel } from "../commands/review/review-panel.js";
4
- import { ModeManager } from "../modes/manager.js";
4
+ import { parseSkillsPath } from "../config/index.js";
5
5
  import { processPrompt } from "../prompts/mentions.js";
6
- import { createUserMessage } from "../sessions/manager.js";
7
6
  import { loadSkills } from "../skills/index.js";
8
7
  import { alert, setTerminalTitle, startProgress, stopProgress, } from "../terminal/control.js";
9
8
  import style from "../terminal/style.js";
@@ -51,8 +50,6 @@ export class Repl {
51
50
  allToolExecutions = [];
52
51
  // verbose mode state
53
52
  verboseMode = false;
54
- // mode manager
55
- modeManager;
56
53
  // ProjectConfig - initialized in init()
57
54
  config;
58
55
  /** Creates a new Repl instance, initializing the TUI layout and components. */
@@ -90,7 +87,6 @@ export class Repl {
90
87
  this.isInitialized = false;
91
88
  this.pendingTools = new Map();
92
89
  this.tools = options.tools;
93
- this.modeManager = new ModeManager();
94
90
  this.notification = new NotificationComponent("", { r: 52, g: 53, b: 65 }, style.yellow, 1, () => this.tui.requestRender());
95
91
  }
96
92
  /**
@@ -103,7 +99,9 @@ export class Repl {
103
99
  return;
104
100
  }
105
101
  // Setup autocomplete for file paths, slash commands, and skills
106
- const skills = await loadSkills();
102
+ const appConfig = await this.options.configManager.getConfig();
103
+ const skillPaths = parseSkillsPath(appConfig.skills.path);
104
+ const skills = await loadSkills(skillPaths);
107
105
  const commandsList = await this.options.commands.getCompletions();
108
106
  const autocompleteProvider = new CombinedProvider([
109
107
  new CommandProvider(commandsList),
@@ -124,7 +122,6 @@ export class Repl {
124
122
  projectStatus: await getProjectStatus(),
125
123
  currentContextWindow: 0,
126
124
  contextWindow: modelConfig.contextWindow,
127
- currentMode: this.modeManager.getDisplayName(),
128
125
  });
129
126
  this.tui.onCtrlC = () => {
130
127
  this.handleCtrlC();
@@ -144,16 +141,6 @@ export class Repl {
144
141
  this.tui.onCtrlM = () => {
145
142
  void this.handleCtrlM();
146
143
  };
147
- this.tui.onShiftTab = () => {
148
- this.modeManager.cycleMode();
149
- this.footer.setState({
150
- projectStatus: this.footer.getProjectStatus(),
151
- currentContextWindow: this.options.sessionManager.getLastTurnContextWindow(),
152
- contextWindow: this.options.modelManager.getModelMetadata("repl").contextWindow,
153
- currentMode: this.modeManager.getDisplayName(),
154
- });
155
- this.tui.requestRender();
156
- };
157
144
  // Set callback for session reconstruction (used by /history command)
158
145
  this.tui.onReconstructSession = () => this.rerender();
159
146
  this.tui.addChild(this.welcome);
@@ -212,27 +199,7 @@ export class Repl {
212
199
  }
213
200
  const userPrompt = promptManager.get();
214
201
  const userMsg = promptManager.getUserMessage();
215
- if (!this.modeManager.isNormal()) {
216
- if (this.modeManager.isFirstMessage()) {
217
- const initialPrompt = this.modeManager.getInitialPrompt();
218
- if (initialPrompt) {
219
- const modeMessage = createUserMessage([], initialPrompt);
220
- sessionManager.appendUserMessage(modeMessage);
221
- }
222
- sessionManager.appendUserMessage(userMsg);
223
- this.modeManager.markFirstMessageSent();
224
- }
225
- else {
226
- sessionManager.appendUserMessage(userMsg);
227
- const reminderMessage = this.modeManager.getReminderMessage();
228
- if (reminderMessage) {
229
- sessionManager.setTransientMessages([reminderMessage]);
230
- }
231
- }
232
- }
233
- else {
234
- sessionManager.appendUserMessage(userMsg);
235
- }
202
+ sessionManager.appendUserMessage(userMsg);
236
203
  this.addMessageToChat({ role: "user", content: userPrompt });
237
204
  this.editor.setText("");
238
205
  this.tui.requestRender();
@@ -263,7 +230,6 @@ export class Repl {
263
230
  currentContextWindow: this.options.sessionManager.getLastTurnContextWindow(),
264
231
  contextWindow: this.options.modelManager.getModelMetadata("repl").contextWindow,
265
232
  agentState: state,
266
- currentMode: this.modeManager.getDisplayName(),
267
233
  });
268
234
  const eventType = event.type;
269
235
  switch (eventType) {
@@ -350,7 +316,6 @@ export class Repl {
350
316
  this.pendingTools.clear();
351
317
  this.editor.disableSubmit = false;
352
318
  this.options.sessionManager.clearTransientMessages();
353
- this.options.sessionManager.setMetadata("modeState", this.modeManager.toJson());
354
319
  if (!this.options.noSession) {
355
320
  await this.options.sessionManager.save();
356
321
  }
@@ -360,7 +325,6 @@ export class Repl {
360
325
  projectStatus: ps,
361
326
  currentContextWindow: this.options.sessionManager.getLastTurnContextWindow(),
362
327
  contextWindow: this.options.modelManager.getModelMetadata("repl").contextWindow,
363
- currentMode: this.modeManager.getDisplayName(),
364
328
  });
365
329
  this.tui.requestRender();
366
330
  });
@@ -369,7 +333,6 @@ export class Repl {
369
333
  case "agent-error":
370
334
  logger.error(event, "agent-error");
371
335
  this.options.sessionManager.clearTransientMessages();
372
- this.options.sessionManager.setMetadata("modeState", this.modeManager.toJson());
373
336
  if (!this.options.noSession) {
374
337
  await this.options.sessionManager.save();
375
338
  }
@@ -473,10 +436,6 @@ export class Repl {
473
436
  * display.
474
437
  */
475
438
  async rerender() {
476
- const modeState = this.options.sessionManager.getMetadata("modeState");
477
- if (modeState && typeof modeState === "object" && "mode" in modeState) {
478
- this.modeManager.fromJson(modeState);
479
- }
480
439
  // When resuming a session, populate tokenTracker with historical usage
481
440
  // so the footer displays the correct total session usage
482
441
  const totalUsage = this.options.sessionManager.getTotalTokenUsage();
@@ -500,7 +459,6 @@ export class Repl {
500
459
  projectStatus: await getProjectStatus(),
501
460
  currentContextWindow: this.options.sessionManager.getLastTurnContextWindow(),
502
461
  contextWindow: this.options.modelManager.getModelMetadata("repl").contextWindow,
503
- currentMode: this.modeManager.getDisplayName(),
504
462
  });
505
463
  // Reconstruct entire session display from messages
506
464
  this.reconstructSession();
@@ -725,14 +683,12 @@ export class Repl {
725
683
  // Auto-generate rules before starting new session if enabled
726
684
  // Run in background - don't block new session from starting
727
685
  this.maybeGenerateRules().catch((err) => logger.debug({ err }, "Background rule generation failed"));
728
- this.options.sessionManager.setMetadata("modeState", this.modeManager.toJson());
729
686
  if (!this.options.noSession) {
730
687
  await this.options.sessionManager.save();
731
688
  }
732
689
  this.options.sessionManager.create(this.options.modelManager.getModel("repl").modelId);
733
690
  }
734
691
  this.config = await this.options.configManager.getConfig();
735
- this.modeManager.reset();
736
692
  this.options.sessionManager.clearTransientMessages();
737
693
  this.options.tokenTracker.reset();
738
694
  setTerminalTitle(`acai: ${process.cwd()}`);
@@ -747,7 +703,6 @@ export class Repl {
747
703
  projectStatus: this.footer.getProjectStatus(),
748
704
  currentContextWindow: 0,
749
705
  contextWindow: this.options.modelManager.getModelMetadata("repl").contextWindow,
750
- currentMode: this.modeManager.getDisplayName(),
751
706
  });
752
707
  this.tui.requestRender();
753
708
  }
@@ -769,7 +724,6 @@ export class Repl {
769
724
  }
770
725
  this.notification.setMessage("");
771
726
  this.tui.requestRender();
772
- this.options.sessionManager.setMetadata("modeState", this.modeManager.toJson());
773
727
  if (!this.options.noSession) {
774
728
  void this.options.sessionManager.save();
775
729
  }
@@ -795,7 +749,6 @@ export class Repl {
795
749
  }
796
750
  this.notification.setMessage("");
797
751
  this.tui.requestRender();
798
- this.options.sessionManager.setMetadata("modeState", this.modeManager.toJson());
799
752
  if (!this.options.noSession) {
800
753
  void this.options.sessionManager.save();
801
754
  }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Tracks which skills have been activated in the current session.
3
+ * Used to avoid re-injecting the same skill instructions multiple times.
4
+ */
5
+ export declare class ActivatedSkillsTracker {
6
+ private activatedSkills;
7
+ has(skillName: string): boolean;
8
+ add(skillName: string): void;
9
+ reset(): void;
10
+ }
11
+ //# sourceMappingURL=activated-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activated-tracker.d.ts","sourceRoot":"","sources":["../../source/skills/activated-tracker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,sBAAsB;IACjC,OAAO,CAAC,eAAe,CAA0B;IAEjD,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAI/B,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAI5B,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Tracks which skills have been activated in the current session.
3
+ * Used to avoid re-injecting the same skill instructions multiple times.
4
+ */
5
+ export class ActivatedSkillsTracker {
6
+ activatedSkills = new Set();
7
+ has(skillName) {
8
+ return this.activatedSkills.has(skillName);
9
+ }
10
+ add(skillName) {
11
+ this.activatedSkills.add(skillName);
12
+ }
13
+ reset() {
14
+ this.activatedSkills.clear();
15
+ }
16
+ }
@@ -23,7 +23,7 @@ export declare class Skills {
23
23
  getUserInvocable(): Skill[];
24
24
  getModelInvocable(): Skill[];
25
25
  }
26
- export declare function loadSkills(): Promise<Skills>;
26
+ export declare function loadSkills(additionalSkillPaths?: string[]): Promise<Skills>;
27
27
  export declare function formatSkillsForPrompt(skills: Skill[]): string;
28
28
  export {};
29
29
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/skills/index.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,OAAO,CAAC;IACvB,sBAAsB,EAAE,OAAO,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,UAAU,wBAAwB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAqRD,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,wBAAwB,EACjC,MAAM,SAAK,GACV,OAAO,CAAC,KAAK,EAAE,CAAC,CASlB;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAU;gBAEZ,MAAM,EAAE,KAAK,EAAE;IAI3B,MAAM,IAAI,KAAK,EAAE;IAIjB,gBAAgB,IAAI,KAAK,EAAE;IAI3B,iBAAiB,IAAI,KAAK,EAAE;CAG7B;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CAsFlD;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAgC7D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/skills/index.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,OAAO,CAAC;IACvB,sBAAsB,EAAE,OAAO,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,UAAU,wBAAwB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAqRD,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,wBAAwB,EACjC,MAAM,SAAK,GACV,OAAO,CAAC,KAAK,EAAE,CAAC,CASlB;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAU;gBAEZ,MAAM,EAAE,KAAK,EAAE;IAI3B,MAAM,IAAI,KAAK,EAAE;IAIjB,gBAAgB,IAAI,KAAK,EAAE;IAI3B,iBAAiB,IAAI,KAAK,EAAE;CAG7B;AAED,wBAAsB,UAAU,CAC9B,oBAAoB,GAAE,MAAM,EAAO,GAClC,OAAO,CAAC,MAAM,CAAC,CAkGjB;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAgC7D"}
@@ -216,7 +216,7 @@ export class Skills {
216
216
  return this.skills.filter((s) => !s.disableModelInvocation);
217
217
  }
218
218
  }
219
- export async function loadSkills() {
219
+ export async function loadSkills(additionalSkillPaths = []) {
220
220
  const skillMap = new Map();
221
221
  // Codex: recursive, simple directory name
222
222
  const codexUserDir = join(homedir(), ".codex", "skills");
@@ -262,6 +262,12 @@ export async function loadSkills() {
262
262
  for (const skill of await loadSkillsFromDirInternal(agentsProjectSkillsDir, "project", "recursive", true)) {
263
263
  skillMap.set(skill.name, skill);
264
264
  }
265
+ // Additional skill paths from config (skills.path)
266
+ for (const skillPath of additionalSkillPaths) {
267
+ for (const skill of await loadSkillsFromDirInternal(skillPath, "config", "recursive", true)) {
268
+ skillMap.set(skill.name, skill);
269
+ }
270
+ }
265
271
  return new Skills(Array.from(skillMap.values()));
266
272
  }
267
273
  export function formatSkillsForPrompt(skills) {
@@ -6,8 +6,8 @@ export declare const BashTool: {
6
6
  };
7
7
  declare const inputSchema: z.ZodObject<{
8
8
  command: z.ZodString;
9
- cwd: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNullable<z.ZodString>>;
10
- timeout: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
9
+ cwd: z.ZodPreprocess<z.ZodNullable<z.ZodString>>;
10
+ timeout: z.ZodPreprocess<z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
11
11
  background: z.ZodOptional<z.ZodBoolean>;
12
12
  }, z.core.$strip>;
13
13
  type BashInputSchema = z.infer<typeof inputSchema>;
@@ -19,8 +19,8 @@ export declare const createBashTool: (options: {
19
19
  description: string;
20
20
  inputSchema: z.ZodObject<{
21
21
  command: z.ZodString;
22
- cwd: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNullable<z.ZodString>>;
23
- timeout: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
22
+ cwd: z.ZodPreprocess<z.ZodNullable<z.ZodString>>;
23
+ timeout: z.ZodPreprocess<z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
24
24
  background: z.ZodOptional<z.ZodBoolean>;
25
25
  }, z.core.$strip>;
26
26
  };
@@ -1 +1 @@
1
- {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../source/tools/bash.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAUpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AA0CvD,eAAO,MAAM,QAAQ;;CAEpB,CAAC;AA4MF,QAAA,MAAM,WAAW;;;;;iBAkBf,CAAC;AAEH,KAAK,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEnD,eAAO,MAAM,cAAc,GAAU,SAAS;IAC5C,SAAS,EAAE,gBAAgB,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;;;;;;;;;;yBA2FwB,eAAe;mDAIK,eAAe,mBACrC,oBAAoB,GACpC,OAAO,CAAC,MAAM,CAAC;EA6BrB,CAAC"}
1
+ {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../source/tools/bash.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAepD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AA0CvD,eAAO,MAAM,QAAQ;;CAEpB,CAAC;AA6MF,QAAA,MAAM,WAAW;;;;;iBAkBf,CAAC;AAEH,KAAK,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEnD,eAAO,MAAM,cAAc,GAAU,SAAS;IAC5C,SAAS,EAAE,gBAAgB,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;;;;;;;;;;yBAyGwB,eAAe;mDAIK,eAAe,mBACrC,oBAAoB,GACpC,OAAO,CAAC,MAAM,CAAC;EA6BrB,CAAC"}
@@ -1,4 +1,3 @@
1
- // import { execSync } from "node:child_process";
2
1
  import { randomBytes } from "node:crypto";
3
2
  import { mkdirSync, writeFileSync } from "node:fs";
4
3
  import { dirname } from "node:path";
@@ -6,6 +5,7 @@ import { z } from "zod";
6
5
  import { initExecutionEnvironment } from "../execution/index.js";
7
6
  import style from "../terminal/style.js";
8
7
  import { resolveCwd, validatePaths } from "../utils/bash.js";
8
+ import { formatBinaryMessage, isBinaryOutput, saveBinaryOutput, } from "../utils/binary-output.js";
9
9
  import { detectDestructiveCommand, formatBlockedCommandMessage, } from "../utils/command-protection.js";
10
10
  import { expandEnvVars } from "../utils/env-expand.js";
11
11
  import { logger } from "../utils/logger.js";
@@ -214,15 +214,16 @@ const MAX_OUTPUT_SIZE = 50 * 1024;
214
214
  /**
215
215
  * Truncates output if it exceeds MAX_OUTPUT_SIZE and adds a clear message.
216
216
  * This prevents extremely large outputs from exhausting the context window.
217
+ * The footer is always appended at the end, even when output is truncated.
217
218
  */
218
- function truncateOutput(output) {
219
+ function truncateOutput(output, footer) {
219
220
  if (output.length <= MAX_OUTPUT_SIZE) {
220
- return output;
221
+ return `${output}\n${footer}`;
221
222
  }
222
223
  const truncatedLength = MAX_OUTPUT_SIZE;
223
224
  const originalLength = output.length;
224
225
  const truncated = output.slice(0, truncatedLength);
225
- return `${truncated}\n\n[OUTPUT TRUNCATED: ${originalLength.toLocaleString()} characters total, showing first ${truncatedLength.toLocaleString()} characters. The output was too large and was truncated to prevent context window exhaustion. Consider using commands that produce smaller output (e.g., head, tail with line limits, or redirecting to a file).]`;
226
+ return `${truncated}\n\n[OUTPUT TRUNCATED: ${originalLength.toLocaleString()} characters total, showing first ${truncatedLength.toLocaleString()} characters. The output was too large and was truncated to prevent context window exhaustion. Consider using commands that produce smaller output (e.g., head, tail with line limits, or redirecting to a file).]\n${footer}`;
226
227
  }
227
228
  const inputSchema = z.object({
228
229
  command: z.string().describe("Full CLI command to execute."),
@@ -283,6 +284,7 @@ export const createBashTool = async (options) => {
283
284
  return `Background process started with PID: ${proc.pid}`;
284
285
  }
285
286
  async function executeSync(cmd, cwd, timeout, signal) {
287
+ const startTime = Date.now();
286
288
  const { output, exitCode, error } = await execEnv.executeCommand(cmd, {
287
289
  cwd,
288
290
  timeout,
@@ -291,6 +293,9 @@ export const createBashTool = async (options) => {
291
293
  captureStderr: true,
292
294
  throwOnError: false,
293
295
  });
296
+ const elapsedMs = Date.now() - startTime;
297
+ const timeStr = elapsedMs < 1000 ? `${elapsedMs}ms` : `${(elapsedMs / 1000).toFixed(1)}s`;
298
+ const metadataFooter = `[exit:${exitCode} | ${timeStr}]`;
294
299
  if (exitCode !== 0) {
295
300
  const errorMessage = error
296
301
  ? error.message
@@ -298,9 +303,15 @@ export const createBashTool = async (options) => {
298
303
  const combinedOutput = output
299
304
  ? `${errorMessage}\n${output}`
300
305
  : errorMessage;
301
- throw new Error(truncateOutput(combinedOutput));
306
+ throw new Error(truncateOutput(combinedOutput, metadataFooter));
302
307
  }
303
- return truncateOutput(output);
308
+ // Check for binary output and handle specially
309
+ if (isBinaryOutput(output)) {
310
+ const saveResult = saveBinaryOutput(output);
311
+ const binaryMessage = formatBinaryMessage(saveResult);
312
+ return `${binaryMessage}\n${metadataFooter}`;
313
+ }
314
+ return truncateOutput(output, metadataFooter);
304
315
  }
305
316
  return {
306
317
  toolDef: {
@@ -6,8 +6,8 @@ export declare const DirectoryTreeTool: {
6
6
  };
7
7
  declare const inputSchema: z.ZodObject<{
8
8
  path: z.ZodString;
9
- maxResults: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
10
- maxDepth: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
9
+ maxResults: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedNumber<unknown>>>>;
10
+ maxDepth: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedNumber<unknown>>>>;
11
11
  }, z.core.$strip>;
12
12
  type DirectoryTreeInputSchema = z.infer<typeof inputSchema>;
13
13
  export declare const createDirectoryTreeTool: (options: {
@@ -17,8 +17,8 @@ export declare const createDirectoryTreeTool: (options: {
17
17
  description: string;
18
18
  inputSchema: z.ZodObject<{
19
19
  path: z.ZodString;
20
- maxResults: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
21
- maxDepth: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
20
+ maxResults: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedNumber<unknown>>>>;
21
+ maxDepth: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedNumber<unknown>>>>;
22
22
  }, z.core.$strip>;
23
23
  };
24
24
  display({ path, maxDepth, maxResults }: DirectoryTreeInputSchema): string;
@@ -1 +1 @@
1
- {"version":3,"file":"directory-tree.d.ts","sourceRoot":"","sources":["../../source/tools/directory-tree.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAMpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAKvD,eAAO,MAAM,iBAAiB;;CAE7B,CAAC;AAEF,QAAA,MAAM,WAAW;;;;iBAYf,CAAC;AAEH,KAAK,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAE5D,eAAO,MAAM,uBAAuB,GAAU,SAAS;IACrD,SAAS,EAAE,gBAAgB,CAAC;CAC7B;;;;;;;;;4CAS2C,wBAAwB;4CAY9B,wBAAwB,mBACvC,oBAAoB,GACpC,OAAO,CAAC,MAAM,CAAC;EAyBrB,CAAC"}
1
+ {"version":3,"file":"directory-tree.d.ts","sourceRoot":"","sources":["../../source/tools/directory-tree.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAMpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAKvD,eAAO,MAAM,iBAAiB;;CAE7B,CAAC;AAEF,QAAA,MAAM,WAAW;;;;iBAcf,CAAC;AAEH,KAAK,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAE5D,eAAO,MAAM,uBAAuB,GAAU,SAAS;IACrD,SAAS,EAAE,gBAAgB,CAAC;CAC7B;;;;;;;;;4CAS2C,wBAAwB;4CAY9B,wBAAwB,mBACvC,oBAAoB,GACpC,OAAO,CAAC,MAAM,CAAC;EAyBrB,CAAC"}
@@ -15,9 +15,11 @@ const inputSchema = z.object({
15
15
  path: z.string().describe("The path"),
16
16
  maxResults: z
17
17
  .preprocess((val) => convertNullString(val), z.coerce.number().nullable())
18
+ .default(null)
18
19
  .describe(`Maximum number of items (files + directories) to return. Set to 0 for no limit. (default: ${DEFAULT_ITEM_LIMIT})`),
19
20
  maxDepth: z
20
21
  .preprocess((val) => convertNullString(val), z.coerce.number().nullable())
22
+ .default(null)
21
23
  .describe(`Maximum recursion depth. Set to 0 for no limit. (default: ${DEFAULT_DEPTH_LIMIT})`),
22
24
  });
23
25
  export const createDirectoryTreeTool = async (options) => {
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import type { ToolExecutionOptions } from "./types.ts";
2
+ import type { SessionContext, ToolExecutionOptions } from "./types.ts";
3
3
  declare const toolMetadataSchema: z.ZodObject<{
4
4
  name: z.ZodString;
5
5
  description: z.ZodString;
@@ -17,6 +17,14 @@ declare const toolMetadataSchema: z.ZodObject<{
17
17
  needsApproval: z.ZodDefault<z.ZodBoolean>;
18
18
  }, z.core.$strip>;
19
19
  type ToolMetadata = z.infer<typeof toolMetadataSchema>;
20
+ interface InterpreterResult {
21
+ command: string;
22
+ args: string[];
23
+ }
24
+ export declare function getShebang(scriptPath: string): string | null;
25
+ export declare function parseShebang(shebang: string, scriptPath: string): InterpreterResult;
26
+ export declare function resolveToolInterpreter(scriptPath: string): InterpreterResult | null;
27
+ export declare function parseTextSchema(content: string): ToolMetadata | null;
20
28
  export declare function parseToolMetadata(output: string): ToolMetadata;
21
29
  interface DynamicToolObject {
22
30
  toolDef: {
@@ -25,9 +33,10 @@ interface DynamicToolObject {
25
33
  };
26
34
  execute: (input: Record<string, unknown>, options: ToolExecutionOptions) => Promise<string>;
27
35
  }
28
- export declare function loadDynamicTools({ baseDir, existingToolNames, }: {
36
+ export declare function loadDynamicTools({ baseDir, existingToolNames, sessionContext, }: {
29
37
  baseDir: string;
30
38
  existingToolNames?: string[];
39
+ sessionContext?: SessionContext;
31
40
  }): Promise<Record<string, DynamicToolObject>>;
32
41
  export {};
33
42
  //# sourceMappingURL=dynamic-tool-loader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-tool-loader.d.ts","sourceRoot":"","sources":["../../source/tools/dynamic-tool-loader.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAGvD,QAAA,MAAM,kBAAkB;;;;;;;;;;;;;;;iBAatB,CAAC;AAEH,KAAK,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEvD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAS9D;AA2LD,UAAU,iBAAiB;IACzB,OAAO,EAAE;QACP,WAAW,EAAE,MAAM,CAAC;QAEpB,WAAW,EAAE,GAAG,CAAC;KAClB,CAAC;IACF,OAAO,EAAE,CACP,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,EAAE,oBAAoB,KAC1B,OAAO,CAAC,MAAM,CAAC,CAAC;CACtB;AAwCD,wBAAsB,gBAAgB,CAAC,EACrC,OAAO,EACP,iBAAsB,GACvB,EAAE;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B,8CA2FA"}
1
+ {"version":3,"file":"dynamic-tool-loader.d.ts","sourceRoot":"","sources":["../../source/tools/dynamic-tool-loader.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAGvE,QAAA,MAAM,kBAAkB;;;;;;;;;;;;;;;iBAatB,CAAC;AAEH,KAAK,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAMvD,UAAU,iBAAiB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAyBD,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAc5D;AAED,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,iBAAiB,CAUnB;AAED,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,GACjB,iBAAiB,GAAG,IAAI,CA0B1B;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAwFpE;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAS9D;AAsOD,UAAU,iBAAiB;IACzB,OAAO,EAAE;QACP,WAAW,EAAE,MAAM,CAAC;QAEpB,WAAW,EAAE,GAAG,CAAC;KAClB,CAAC;IACF,OAAO,EAAE,CACP,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,EAAE,oBAAoB,KAC1B,OAAO,CAAC,MAAM,CAAC,CAAC;CACtB;AAwED,wBAAsB,gBAAgB,CAAC,EACrC,OAAO,EACP,iBAAsB,EACtB,cAAc,GACf,EAAE;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC,8CAuJA"}