@zhijiewang/openharness 2.0.0 → 2.3.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 (235) hide show
  1. package/README.md +4 -4
  2. package/dist/DeferredTool.js +3 -1
  3. package/dist/Tool.d.ts +1 -1
  4. package/dist/agents/roles.js +58 -62
  5. package/dist/commands/cybergotchi.d.ts +1 -1
  6. package/dist/commands/cybergotchi.js +30 -30
  7. package/dist/commands/index.js +360 -122
  8. package/dist/components/App.d.ts +1 -1
  9. package/dist/components/App.js +6 -6
  10. package/dist/components/CompanionFooter.d.ts +1 -1
  11. package/dist/components/CompanionFooter.js +6 -8
  12. package/dist/components/CybergotchiBubble.js +5 -5
  13. package/dist/components/CybergotchiPanel.d.ts +1 -1
  14. package/dist/components/CybergotchiPanel.js +7 -7
  15. package/dist/components/CybergotchiPanelConnected.js +2 -2
  16. package/dist/components/CybergotchiSetup.js +26 -24
  17. package/dist/components/CybergotchiSprite.d.ts +1 -1
  18. package/dist/components/CybergotchiSprite.js +8 -12
  19. package/dist/components/DiffView.d.ts +1 -1
  20. package/dist/components/DiffView.js +10 -10
  21. package/dist/components/ErrorBoundary.d.ts +1 -1
  22. package/dist/components/ErrorBoundary.js +1 -1
  23. package/dist/components/InitWizard.js +65 -33
  24. package/dist/components/Markdown.js +2 -4
  25. package/dist/components/Messages.js +4 -4
  26. package/dist/components/PermissionPrompt.d.ts +1 -1
  27. package/dist/components/PermissionPrompt.js +15 -17
  28. package/dist/components/REPL.d.ts +1 -1
  29. package/dist/components/REPL.js +74 -49
  30. package/dist/components/Spinner.js +2 -2
  31. package/dist/components/TextInput.js +35 -29
  32. package/dist/components/ToolCallDisplay.js +3 -5
  33. package/dist/cybergotchi/bones.d.ts +1 -1
  34. package/dist/cybergotchi/bones.js +8 -8
  35. package/dist/cybergotchi/config.d.ts +2 -2
  36. package/dist/cybergotchi/config.js +13 -13
  37. package/dist/cybergotchi/events.d.ts +5 -5
  38. package/dist/cybergotchi/events.js +7 -7
  39. package/dist/cybergotchi/needs.d.ts +2 -2
  40. package/dist/cybergotchi/needs.js +7 -9
  41. package/dist/cybergotchi/personality.d.ts +2 -2
  42. package/dist/cybergotchi/personality.js +2 -2
  43. package/dist/cybergotchi/species.d.ts +1 -1
  44. package/dist/cybergotchi/species.js +145 -217
  45. package/dist/cybergotchi/speech.d.ts +2 -2
  46. package/dist/cybergotchi/speech.js +43 -43
  47. package/dist/cybergotchi/types.d.ts +4 -4
  48. package/dist/cybergotchi/types.js +26 -26
  49. package/dist/cybergotchi/useCybergotchi.d.ts +1 -1
  50. package/dist/cybergotchi/useCybergotchi.js +29 -25
  51. package/dist/git/index.js +11 -9
  52. package/dist/harness/checkpoints.js +29 -21
  53. package/dist/harness/config.d.ts +12 -2
  54. package/dist/harness/config.js +15 -9
  55. package/dist/harness/context-warning.d.ts +1 -1
  56. package/dist/harness/context-warning.js +1 -1
  57. package/dist/harness/cost.js +1 -1
  58. package/dist/harness/credentials.js +13 -13
  59. package/dist/harness/hooks.js +7 -5
  60. package/dist/harness/keybindings.js +20 -18
  61. package/dist/harness/marketplace.d.ts +3 -3
  62. package/dist/harness/marketplace.js +55 -42
  63. package/dist/harness/memory.d.ts +23 -5
  64. package/dist/harness/memory.js +142 -41
  65. package/dist/harness/onboarding.js +30 -10
  66. package/dist/harness/plugins.d.ts +9 -1
  67. package/dist/harness/plugins.js +54 -30
  68. package/dist/harness/rules.js +12 -7
  69. package/dist/harness/sandbox.d.ts +34 -0
  70. package/dist/harness/sandbox.js +104 -0
  71. package/dist/harness/session-db.d.ts +55 -0
  72. package/dist/harness/session-db.js +165 -0
  73. package/dist/harness/session.d.ts +1 -1
  74. package/dist/harness/session.js +34 -15
  75. package/dist/harness/store.d.ts +3 -3
  76. package/dist/harness/store.js +6 -4
  77. package/dist/harness/submit-handler.d.ts +4 -4
  78. package/dist/harness/submit-handler.js +57 -21
  79. package/dist/harness/telemetry.d.ts +1 -1
  80. package/dist/harness/telemetry.js +23 -19
  81. package/dist/harness/traces.d.ts +2 -2
  82. package/dist/harness/traces.js +44 -33
  83. package/dist/harness/verification.d.ts +1 -1
  84. package/dist/harness/verification.js +50 -44
  85. package/dist/lsp/client.js +44 -40
  86. package/dist/main.js +100 -59
  87. package/dist/mcp/DeferredMcpTool.d.ts +4 -4
  88. package/dist/mcp/DeferredMcpTool.js +9 -5
  89. package/dist/mcp/McpTool.d.ts +4 -4
  90. package/dist/mcp/McpTool.js +8 -4
  91. package/dist/mcp/client.d.ts +2 -2
  92. package/dist/mcp/client.js +21 -21
  93. package/dist/mcp/loader.d.ts +1 -1
  94. package/dist/mcp/loader.js +17 -12
  95. package/dist/mcp/registry.d.ts +3 -3
  96. package/dist/mcp/registry.js +97 -97
  97. package/dist/mcp/schema.d.ts +1 -1
  98. package/dist/mcp/schema.js +16 -16
  99. package/dist/mcp/server.d.ts +1 -1
  100. package/dist/mcp/server.js +21 -21
  101. package/dist/mcp/types.d.ts +3 -3
  102. package/dist/providers/anthropic.d.ts +2 -2
  103. package/dist/providers/anthropic.js +10 -9
  104. package/dist/providers/base.d.ts +1 -1
  105. package/dist/providers/index.js +10 -3
  106. package/dist/providers/llamacpp.d.ts +2 -2
  107. package/dist/providers/llamacpp.js +1 -3
  108. package/dist/providers/ollama.d.ts +2 -2
  109. package/dist/providers/ollama.js +3 -4
  110. package/dist/providers/openai.d.ts +2 -2
  111. package/dist/providers/openai.js +3 -5
  112. package/dist/providers/openrouter.d.ts +2 -2
  113. package/dist/providers/router.d.ts +1 -1
  114. package/dist/providers/router.js +7 -7
  115. package/dist/query/compress.d.ts +2 -2
  116. package/dist/query/compress.js +22 -21
  117. package/dist/query/context-manager.d.ts +2 -2
  118. package/dist/query/context-manager.js +8 -11
  119. package/dist/query/errors.js +1 -1
  120. package/dist/query/index.d.ts +1 -1
  121. package/dist/query/index.js +30 -22
  122. package/dist/query/tools.js +15 -12
  123. package/dist/query/types.d.ts +1 -1
  124. package/dist/query.d.ts +1 -1
  125. package/dist/query.js +1 -1
  126. package/dist/remote/auth.d.ts +2 -2
  127. package/dist/remote/auth.js +8 -8
  128. package/dist/remote/server.d.ts +3 -3
  129. package/dist/remote/server.js +60 -60
  130. package/dist/renderer/cells.js +9 -9
  131. package/dist/renderer/colors.js +24 -6
  132. package/dist/renderer/diff.d.ts +2 -2
  133. package/dist/renderer/diff.js +27 -19
  134. package/dist/renderer/differ.d.ts +1 -1
  135. package/dist/renderer/differ.js +9 -9
  136. package/dist/renderer/image.js +19 -19
  137. package/dist/renderer/index.d.ts +6 -6
  138. package/dist/renderer/index.js +163 -93
  139. package/dist/renderer/input.js +66 -48
  140. package/dist/renderer/layout.d.ts +6 -6
  141. package/dist/renderer/layout.js +163 -124
  142. package/dist/renderer/markdown.d.ts +2 -2
  143. package/dist/renderer/markdown.js +173 -54
  144. package/dist/renderer/session-browser.d.ts +2 -2
  145. package/dist/renderer/session-browser.js +19 -21
  146. package/dist/repl.d.ts +5 -5
  147. package/dist/repl.js +300 -198
  148. package/dist/sdk/index.d.ts +8 -7
  149. package/dist/sdk/index.js +59 -42
  150. package/dist/services/AgentDispatcher.d.ts +3 -3
  151. package/dist/services/AgentDispatcher.js +33 -29
  152. package/dist/services/CronExecutor.d.ts +4 -4
  153. package/dist/services/CronExecutor.js +12 -8
  154. package/dist/services/EvaluatorLoop.d.ts +3 -3
  155. package/dist/services/EvaluatorLoop.js +29 -21
  156. package/dist/services/MetaHarness.d.ts +1 -1
  157. package/dist/services/MetaHarness.js +41 -33
  158. package/dist/services/PipelineExecutor.d.ts +1 -1
  159. package/dist/services/PipelineExecutor.js +23 -25
  160. package/dist/services/SkillExtractor.d.ts +43 -0
  161. package/dist/services/SkillExtractor.js +143 -0
  162. package/dist/services/StreamingToolExecutor.d.ts +2 -2
  163. package/dist/services/StreamingToolExecutor.js +11 -7
  164. package/dist/services/a2a.d.ts +8 -8
  165. package/dist/services/a2a.js +44 -34
  166. package/dist/services/agent-messaging.d.ts +33 -15
  167. package/dist/services/agent-messaging.js +65 -13
  168. package/dist/services/cron.js +16 -16
  169. package/dist/tools/AgentTool/index.d.ts +5 -2
  170. package/dist/tools/AgentTool/index.js +35 -15
  171. package/dist/tools/AskUserTool/index.js +1 -1
  172. package/dist/tools/BashTool/index.d.ts +2 -2
  173. package/dist/tools/BashTool/index.js +18 -10
  174. package/dist/tools/CronTool/index.d.ts +2 -2
  175. package/dist/tools/CronTool/index.js +30 -12
  176. package/dist/tools/DiagnosticsTool/index.js +28 -22
  177. package/dist/tools/EnterPlanModeTool/index.js +93 -14
  178. package/dist/tools/EnterWorktreeTool/index.js +7 -3
  179. package/dist/tools/ExitPlanModeTool/index.d.ts +22 -1
  180. package/dist/tools/ExitPlanModeTool/index.js +20 -5
  181. package/dist/tools/ExitWorktreeTool/index.js +11 -4
  182. package/dist/tools/FileEditTool/index.js +3 -5
  183. package/dist/tools/FileReadTool/index.js +16 -10
  184. package/dist/tools/FileWriteTool/index.js +2 -2
  185. package/dist/tools/GlobTool/index.js +5 -9
  186. package/dist/tools/GrepTool/index.d.ts +2 -2
  187. package/dist/tools/GrepTool/index.js +14 -9
  188. package/dist/tools/ImageReadTool/index.js +2 -2
  189. package/dist/tools/KillProcessTool/index.js +11 -7
  190. package/dist/tools/LSTool/index.js +3 -3
  191. package/dist/tools/MemoryTool/index.d.ts +11 -11
  192. package/dist/tools/MemoryTool/index.js +28 -14
  193. package/dist/tools/MonitorTool/index.d.ts +2 -2
  194. package/dist/tools/MonitorTool/index.js +24 -19
  195. package/dist/tools/MultiEditTool/index.js +9 -5
  196. package/dist/tools/NotebookEditTool/index.js +3 -3
  197. package/dist/tools/ParallelAgentTool/index.d.ts +4 -4
  198. package/dist/tools/ParallelAgentTool/index.js +12 -6
  199. package/dist/tools/PipelineTool/index.d.ts +4 -4
  200. package/dist/tools/PipelineTool/index.js +3 -3
  201. package/dist/tools/PowerShellTool/index.js +10 -6
  202. package/dist/tools/RemoteTriggerTool/index.js +8 -4
  203. package/dist/tools/ScheduleWakeupTool/index.d.ts +42 -0
  204. package/dist/tools/ScheduleWakeupTool/index.js +115 -0
  205. package/dist/tools/SendMessageTool/index.js +25 -7
  206. package/dist/tools/SessionSearchTool/index.d.ts +15 -0
  207. package/dist/tools/SessionSearchTool/index.js +36 -0
  208. package/dist/tools/SkillTool/index.d.ts +3 -0
  209. package/dist/tools/SkillTool/index.js +39 -9
  210. package/dist/tools/TaskCreateTool/index.d.ts +2 -2
  211. package/dist/tools/TaskCreateTool/index.js +2 -2
  212. package/dist/tools/TaskGetTool/index.js +2 -2
  213. package/dist/tools/TaskListTool/index.js +3 -5
  214. package/dist/tools/TaskOutputTool/index.js +2 -2
  215. package/dist/tools/TaskStopTool/index.js +3 -3
  216. package/dist/tools/TaskUpdateTool/index.d.ts +4 -4
  217. package/dist/tools/TaskUpdateTool/index.js +2 -2
  218. package/dist/tools/ToolSearchTool/index.js +9 -6
  219. package/dist/tools/WebFetchTool/index.js +1 -1
  220. package/dist/tools/WebSearchTool/index.js +2 -6
  221. package/dist/tools.js +31 -30
  222. package/dist/types/permissions.js +15 -9
  223. package/dist/utils/bash-safety.d.ts +1 -1
  224. package/dist/utils/bash-safety.js +64 -54
  225. package/dist/utils/diff-algorithm.d.ts +3 -3
  226. package/dist/utils/diff-algorithm.js +7 -7
  227. package/dist/utils/fs.js +3 -3
  228. package/dist/utils/safe-env.js +1 -1
  229. package/dist/utils/theme-data.d.ts +1 -1
  230. package/dist/utils/theme-data.js +1 -1
  231. package/dist/utils/theme.d.ts +1 -1
  232. package/dist/utils/theme.js +1 -1
  233. package/dist/utils/tool-summary.d.ts +1 -1
  234. package/dist/utils/tool-summary.js +27 -9
  235. package/package.json +10 -3
@@ -13,8 +13,8 @@
13
13
  * const result = await agent.run('Fix the failing tests');
14
14
  * console.log(result.text);
15
15
  */
16
- import type { StreamEvent } from '../types/events.js';
17
- import type { PermissionMode } from '../types/permissions.js';
16
+ import type { StreamEvent } from "../types/events.js";
17
+ import type { PermissionMode } from "../types/permissions.js";
18
18
  export type AgentConfig = {
19
19
  /** Provider name: 'anthropic', 'openai', 'ollama', 'openrouter', etc. */
20
20
  provider: string;
@@ -25,7 +25,7 @@ export type AgentConfig = {
25
25
  /** Custom base URL */
26
26
  baseUrl?: string;
27
27
  /** Tools to include: 'all', 'read-only', or array of tool names */
28
- tools?: 'all' | 'read-only' | string[];
28
+ tools?: "all" | "read-only" | string[];
29
29
  /** Permission mode (default: 'trust') */
30
30
  permissionMode?: PermissionMode;
31
31
  /** Custom system prompt */
@@ -57,10 +57,11 @@ export declare class Agent {
57
57
  private provider;
58
58
  private tools;
59
59
  private config;
60
- private initialized;
60
+ private initPromise;
61
61
  constructor(config: AgentConfig);
62
- /** Initialize provider and tools (lazy, on first use) */
62
+ /** Initialize provider and tools (lazy, on first use). Race-safe via promise guard. */
63
63
  private init;
64
+ private _doInit;
64
65
  /** Run a single prompt and return the result */
65
66
  run(prompt: string): Promise<AgentResult>;
66
67
  /** Stream events from a prompt */
@@ -70,6 +71,6 @@ export declare class Agent {
70
71
  }
71
72
  /** Create a new agent instance */
72
73
  export declare function createAgent(config: AgentConfig): Agent;
73
- export type { StreamEvent } from '../types/events.js';
74
- export type { PermissionMode } from '../types/permissions.js';
74
+ export type { StreamEvent } from "../types/events.js";
75
+ export type { PermissionMode } from "../types/permissions.js";
75
76
  //# sourceMappingURL=index.d.ts.map
package/dist/sdk/index.js CHANGED
@@ -18,20 +18,21 @@ export class Agent {
18
18
  provider = null;
19
19
  tools = null;
20
20
  config;
21
- initialized = false;
21
+ initPromise = null;
22
22
  constructor(config) {
23
23
  this.config = {
24
- permissionMode: 'trust',
24
+ permissionMode: "trust",
25
25
  maxTurns: 20,
26
26
  ...config,
27
27
  };
28
28
  }
29
- /** Initialize provider and tools (lazy, on first use) */
30
- async init() {
31
- if (this.initialized)
32
- return;
33
- const { createProvider } = await import('../providers/index.js');
34
- const { getAllTools } = await import('../tools.js');
29
+ /** Initialize provider and tools (lazy, on first use). Race-safe via promise guard. */
30
+ init() {
31
+ return (this.initPromise ??= this._doInit());
32
+ }
33
+ async _doInit() {
34
+ const { createProvider } = await import("../providers/index.js");
35
+ const { getAllTools } = await import("../tools.js");
35
36
  const overrides = {};
36
37
  if (this.config.apiKey)
37
38
  overrides.apiKey = this.config.apiKey;
@@ -41,61 +42,75 @@ export class Agent {
41
42
  this.provider = provider;
42
43
  // Filter tools
43
44
  let tools = getAllTools();
44
- if (this.config.tools === 'read-only') {
45
- const readOnlyNames = new Set(['Read', 'Glob', 'Grep', 'LS', 'ImageRead', 'WebSearch', 'WebFetch']);
46
- tools = tools.filter(t => readOnlyNames.has(t.name));
45
+ if (this.config.tools === "read-only") {
46
+ const readOnlyNames = new Set(["Read", "Glob", "Grep", "LS", "ImageRead", "WebSearch", "WebFetch"]);
47
+ tools = tools.filter((t) => readOnlyNames.has(t.name));
47
48
  }
48
49
  else if (Array.isArray(this.config.tools)) {
49
- const allowed = new Set(this.config.tools.map(n => n.toLowerCase()));
50
- tools = tools.filter(t => allowed.has(t.name.toLowerCase()));
50
+ const allowed = new Set(this.config.tools.map((n) => n.toLowerCase()));
51
+ tools = tools.filter((t) => allowed.has(t.name.toLowerCase()));
51
52
  }
52
53
  this.tools = tools;
53
- this.initialized = true;
54
54
  }
55
55
  /** Run a single prompt and return the result */
56
56
  async run(prompt) {
57
57
  await this.init();
58
- const { query } = await import('../query.js');
58
+ const { query } = await import("../query.js");
59
+ const originalCwd = process.cwd();
59
60
  if (this.config.cwd) {
60
61
  try {
61
62
  process.chdir(this.config.cwd);
62
63
  }
63
- catch { /* ignore */ }
64
+ catch {
65
+ /* ignore */
66
+ }
64
67
  }
65
68
  const config = {
66
69
  provider: this.provider,
67
70
  tools: this.tools,
68
- systemPrompt: this.config.systemPrompt ?? 'You are a helpful coding agent.',
71
+ systemPrompt: this.config.systemPrompt ?? "You are a helpful coding agent.",
69
72
  permissionMode: this.config.permissionMode,
70
73
  model: this.config.model,
71
74
  maxTurns: this.config.maxTurns,
72
75
  };
73
- let text = '';
76
+ let text = "";
74
77
  const toolCalls = [];
75
78
  let cost = 0;
76
79
  let inputTokens = 0;
77
80
  let outputTokens = 0;
78
81
  let turns = 0;
79
- for await (const event of query(prompt, config)) {
80
- switch (event.type) {
81
- case 'text_delta':
82
- text += event.content;
83
- break;
84
- case 'tool_call_end':
85
- toolCalls.push({
86
- toolName: event.toolName ?? 'unknown',
87
- output: event.output ?? '',
88
- isError: event.isError ?? false,
89
- });
90
- break;
91
- case 'cost_update':
92
- cost += event.cost ?? 0;
93
- inputTokens += event.inputTokens ?? 0;
94
- outputTokens += event.outputTokens ?? 0;
95
- break;
96
- case 'turn_complete':
97
- turns++;
98
- break;
82
+ try {
83
+ for await (const event of query(prompt, config)) {
84
+ switch (event.type) {
85
+ case "text_delta":
86
+ text += event.content;
87
+ break;
88
+ case "tool_call_end":
89
+ toolCalls.push({
90
+ toolName: event.callId,
91
+ output: event.output,
92
+ isError: event.isError,
93
+ });
94
+ break;
95
+ case "cost_update":
96
+ cost += event.cost;
97
+ inputTokens += event.inputTokens;
98
+ outputTokens += event.outputTokens;
99
+ break;
100
+ case "turn_complete":
101
+ turns++;
102
+ break;
103
+ }
104
+ }
105
+ }
106
+ finally {
107
+ if (this.config.cwd) {
108
+ try {
109
+ process.chdir(originalCwd);
110
+ }
111
+ catch {
112
+ /* ignore */
113
+ }
99
114
  }
100
115
  }
101
116
  return { text, toolCalls, cost, inputTokens, outputTokens, turns };
@@ -103,17 +118,19 @@ export class Agent {
103
118
  /** Stream events from a prompt */
104
119
  async *stream(prompt) {
105
120
  await this.init();
106
- const { query } = await import('../query.js');
121
+ const { query } = await import("../query.js");
107
122
  if (this.config.cwd) {
108
123
  try {
109
124
  process.chdir(this.config.cwd);
110
125
  }
111
- catch { /* ignore */ }
126
+ catch {
127
+ /* ignore */
128
+ }
112
129
  }
113
130
  const config = {
114
131
  provider: this.provider,
115
132
  tools: this.tools,
116
- systemPrompt: this.config.systemPrompt ?? 'You are a helpful coding agent.',
133
+ systemPrompt: this.config.systemPrompt ?? "You are a helpful coding agent.",
117
134
  permissionMode: this.config.permissionMode,
118
135
  model: this.config.model,
119
136
  maxTurns: this.config.maxTurns,
@@ -124,7 +141,7 @@ export class Agent {
124
141
  stop() {
125
142
  this.provider = null;
126
143
  this.tools = null;
127
- this.initialized = false;
144
+ this.initPromise = null;
128
145
  }
129
146
  }
130
147
  // ── Factory ──
@@ -5,9 +5,9 @@
5
5
  * dispatches independent tasks to parallel worktrees, collects results,
6
6
  * and triggers dependent tasks when their blockers complete.
7
7
  */
8
- import type { Provider } from '../providers/base.js';
9
- import type { Tools } from '../Tool.js';
10
- import type { PermissionMode } from '../types/permissions.js';
8
+ import type { Provider } from "../providers/base.js";
9
+ import type { Tools } from "../Tool.js";
10
+ import type { PermissionMode } from "../types/permissions.js";
11
11
  export type AgentTask = {
12
12
  id: string;
13
13
  prompt: string;
@@ -5,7 +5,7 @@
5
5
  * dispatches independent tasks to parallel worktrees, collects results,
6
6
  * and triggers dependent tasks when their blockers complete.
7
7
  */
8
- import { createWorktree, removeWorktree, isGitRepo } from '../git/index.js';
8
+ import { createWorktree, isGitRepo, removeWorktree } from "../git/index.js";
9
9
  export class AgentDispatcher {
10
10
  provider;
11
11
  tools;
@@ -29,7 +29,7 @@ export class AgentDispatcher {
29
29
  this.maxConcurrency = maxConcurrency;
30
30
  }
31
31
  addTask(task) {
32
- this.tasks.set(task.id, { ...task, status: 'pending' });
32
+ this.tasks.set(task.id, { ...task, status: "pending" });
33
33
  }
34
34
  addTasks(tasks) {
35
35
  for (const t of tasks)
@@ -42,8 +42,8 @@ export class AgentDispatcher {
42
42
  if (this.abortSignal?.aborted)
43
43
  break;
44
44
  // Find tasks ready to run (all blockers completed)
45
- const ready = [...this.tasks.values()].filter(t => t.status === 'pending' && this.isReady(t));
46
- const running = [...this.tasks.values()].filter(t => t.status === 'running');
45
+ const ready = [...this.tasks.values()].filter((t) => t.status === "pending" && this.isReady(t));
46
+ const running = [...this.tasks.values()].filter((t) => t.status === "running");
47
47
  // All done?
48
48
  if (ready.length === 0 && running.length === 0)
49
49
  break;
@@ -52,11 +52,11 @@ export class AgentDispatcher {
52
52
  if (toStart.length === 0 && running.length === 0) {
53
53
  // Deadlock — blocked tasks with no way to unblock
54
54
  for (const t of this.tasks.values()) {
55
- if (t.status === 'pending') {
56
- t.status = 'failed';
55
+ if (t.status === "pending") {
56
+ t.status = "failed";
57
57
  const result = {
58
58
  id: t.id,
59
- output: 'Deadlock: blocked dependencies never completed.',
59
+ output: "Deadlock: blocked dependencies never completed.",
60
60
  isError: true,
61
61
  durationMs: 0,
62
62
  };
@@ -67,10 +67,10 @@ export class AgentDispatcher {
67
67
  break;
68
68
  }
69
69
  // Run tasks in parallel
70
- const promises = toStart.map(t => {
71
- t.status = 'running';
72
- return this.runTask(t).then(result => {
73
- t.status = 'completed';
70
+ const promises = toStart.map((t) => {
71
+ t.status = "running";
72
+ return this.runTask(t).then((result) => {
73
+ t.status = "completed";
74
74
  t.result = result;
75
75
  this.results.set(t.id, result);
76
76
  results.push(result);
@@ -85,11 +85,11 @@ export class AgentDispatcher {
85
85
  else {
86
86
  // Running tasks exist but we can't start more — wait for all running
87
87
  const runningPromises = [...this.tasks.values()]
88
- .filter(t => t.status === 'running' && t.result)
89
- .map(t => Promise.resolve());
88
+ .filter((t) => t.status === "running" && t.result)
89
+ .map((_t) => Promise.resolve());
90
90
  if (runningPromises.length === 0) {
91
91
  // Need to poll — running tasks haven't resolved yet
92
- await new Promise(r => setTimeout(r, 100));
92
+ await new Promise((r) => setTimeout(r, 100));
93
93
  }
94
94
  }
95
95
  }
@@ -98,9 +98,9 @@ export class AgentDispatcher {
98
98
  isReady(task) {
99
99
  if (!task.blockedBy || task.blockedBy.length === 0)
100
100
  return true;
101
- return task.blockedBy.every(id => {
101
+ return task.blockedBy.every((id) => {
102
102
  const blocker = this.tasks.get(id);
103
- return blocker && (blocker.status === 'completed' || blocker.status === 'failed');
103
+ return blocker && (blocker.status === "completed" || blocker.status === "failed");
104
104
  });
105
105
  }
106
106
  async runTask(task) {
@@ -112,13 +112,13 @@ export class AgentDispatcher {
112
112
  worktreePath = createWorktree(cwd);
113
113
  }
114
114
  try {
115
- const { query } = await import('../query.js');
115
+ const { query } = await import("../query.js");
116
116
  // Filter tools if task specifies allowed tools
117
117
  let taskTools = this.tools;
118
118
  if (task.allowedTools && task.allowedTools.length > 0) {
119
- const allowSet = new Set(task.allowedTools.map(n => n.toLowerCase()));
120
- allowSet.add('askuser');
121
- const filtered = this.tools.filter(t => allowSet.has(t.name.toLowerCase()));
119
+ const allowSet = new Set(task.allowedTools.map((n) => n.toLowerCase()));
120
+ allowSet.add("askuser");
121
+ const filtered = this.tools.filter((t) => allowSet.has(t.name.toLowerCase()));
122
122
  if (filtered.length > 0)
123
123
  taskTools = filtered;
124
124
  }
@@ -135,12 +135,12 @@ export class AgentDispatcher {
135
135
  let promptWithContext = task.prompt;
136
136
  if (task.blockedBy && task.blockedBy.length > 0) {
137
137
  const blockerContext = task.blockedBy
138
- .map(id => {
138
+ .map((id) => {
139
139
  const r = this.results.get(id);
140
- return r ? `## Result from task "${id}":\n${r.output.slice(0, 1000)}` : '';
140
+ return r ? `## Result from task "${id}":\n${r.output.slice(0, 1000)}` : "";
141
141
  })
142
142
  .filter(Boolean)
143
- .join('\n\n');
143
+ .join("\n\n");
144
144
  if (blockerContext) {
145
145
  promptWithContext = `${blockerContext}\n\n---\n\n${task.prompt}`;
146
146
  }
@@ -150,14 +150,16 @@ export class AgentDispatcher {
150
150
  try {
151
151
  process.chdir(worktreePath);
152
152
  }
153
- catch { /* ignore */ }
153
+ catch {
154
+ /* ignore */
155
+ }
154
156
  }
155
- let output = '';
157
+ let output = "";
156
158
  try {
157
159
  for await (const event of query(promptWithContext, config)) {
158
- if (event.type === 'text_delta')
160
+ if (event.type === "text_delta")
159
161
  output += event.content;
160
- if (event.type === 'error') {
162
+ if (event.type === "error") {
161
163
  return { id: task.id, output: `Error: ${event.message}`, isError: true, durationMs: Date.now() - start };
162
164
  }
163
165
  }
@@ -167,10 +169,12 @@ export class AgentDispatcher {
167
169
  try {
168
170
  process.chdir(originalCwd);
169
171
  }
170
- catch { /* ignore */ }
172
+ catch {
173
+ /* ignore */
174
+ }
171
175
  }
172
176
  }
173
- return { id: task.id, output: output || '(no output)', isError: false, durationMs: Date.now() - start };
177
+ return { id: task.id, output: output || "(no output)", isError: false, durationMs: Date.now() - start };
174
178
  }
175
179
  catch (err) {
176
180
  return {
@@ -8,10 +8,10 @@
8
8
  * Execution is non-blocking and failure-isolated — one failing cron
9
9
  * does not affect others or the main REPL session.
10
10
  */
11
- import type { Provider } from '../providers/base.js';
12
- import type { Tools } from '../Tool.js';
13
- import type { PermissionMode } from '../types/permissions.js';
14
- import { type CronResult } from './cron.js';
11
+ import type { Provider } from "../providers/base.js";
12
+ import type { Tools } from "../Tool.js";
13
+ import type { PermissionMode } from "../types/permissions.js";
14
+ import { type CronResult } from "./cron.js";
15
15
  export declare class CronExecutor {
16
16
  private provider;
17
17
  private tools;
@@ -8,7 +8,7 @@
8
8
  * Execution is non-blocking and failure-isolated — one failing cron
9
9
  * does not affect others or the main REPL session.
10
10
  */
11
- import { listCrons, getDueCrons, updateCron, saveCronResult, } from './cron.js';
11
+ import { getDueCrons, listCrons, saveCronResult, updateCron } from "./cron.js";
12
12
  const CHECK_INTERVAL_MS = 60_000; // Check every 60 seconds
13
13
  const MAX_CRON_TURNS = 10; // Limit sub-query turns for cron tasks
14
14
  export class CronExecutor {
@@ -35,12 +35,16 @@ export class CronExecutor {
35
35
  // Run first tick after a short delay (don't block startup)
36
36
  setTimeout(() => {
37
37
  if (!this._stopped)
38
- this.tick().catch(() => { });
38
+ this.tick().catch(() => {
39
+ /* fire-and-forget: cron tick errors are non-fatal */
40
+ });
39
41
  }, 5_000);
40
42
  // Then check every 60 seconds
41
43
  this.intervalId = setInterval(() => {
42
44
  if (!this._stopped)
43
- this.tick().catch(() => { });
45
+ this.tick().catch(() => {
46
+ /* fire-and-forget: cron tick errors are non-fatal */
47
+ });
44
48
  }, CHECK_INTERVAL_MS);
45
49
  }
46
50
  /** Stop the scheduler */
@@ -69,7 +73,7 @@ export class CronExecutor {
69
73
  const result = {
70
74
  cronId: cron.id,
71
75
  timestamp: Date.now(),
72
- output: '',
76
+ output: "",
73
77
  error: err instanceof Error ? err.message : String(err),
74
78
  };
75
79
  saveCronResult(result);
@@ -83,7 +87,7 @@ export class CronExecutor {
83
87
  this.running.add(cron.id);
84
88
  const timestamp = Date.now();
85
89
  try {
86
- const { query } = await import('../query.js');
90
+ const { query } = await import("../query.js");
87
91
  const config = {
88
92
  provider: this.provider,
89
93
  tools: this.tools,
@@ -92,11 +96,11 @@ export class CronExecutor {
92
96
  model: this.model,
93
97
  maxTurns: MAX_CRON_TURNS,
94
98
  };
95
- let output = '';
99
+ let output = "";
96
100
  for await (const event of query(cron.prompt, config)) {
97
- if (event.type === 'text_delta')
101
+ if (event.type === "text_delta")
98
102
  output += event.content;
99
- if (event.type === 'error') {
103
+ if (event.type === "error") {
100
104
  const result = { cronId: cron.id, timestamp, output, error: event.message };
101
105
  saveCronResult(result);
102
106
  // Still update lastRun on error to prevent rapid retry loops
@@ -12,9 +12,9 @@
12
12
  * 3. If below threshold, Generator refines based on feedback
13
13
  * 4. Repeat until pass or max iterations reached
14
14
  */
15
- import type { Provider } from '../providers/base.js';
16
- import type { Tools } from '../Tool.js';
17
- import type { PermissionMode } from '../types/permissions.js';
15
+ import type { Provider } from "../providers/base.js";
16
+ import type { Tools } from "../Tool.js";
17
+ import type { PermissionMode } from "../types/permissions.js";
18
18
  export type EvaluationCriterion = {
19
19
  name: string;
20
20
  weight: number;
@@ -15,10 +15,18 @@
15
15
  // ── Default Rubric ──
16
16
  export const DEFAULT_RUBRIC = {
17
17
  criteria: [
18
- { name: 'correctness', weight: 0.4, description: 'Does the output correctly address the task? Are there logical errors?' },
19
- { name: 'completeness', weight: 0.3, description: 'Is the solution complete? Any missing edge cases or requirements?' },
20
- { name: 'quality', weight: 0.2, description: 'Is the code clean, well-structured, and following best practices?' },
21
- { name: 'safety', weight: 0.1, description: 'Are there security issues, unsafe patterns, or potential bugs?' },
18
+ {
19
+ name: "correctness",
20
+ weight: 0.4,
21
+ description: "Does the output correctly address the task? Are there logical errors?",
22
+ },
23
+ {
24
+ name: "completeness",
25
+ weight: 0.3,
26
+ description: "Is the solution complete? Any missing edge cases or requirements?",
27
+ },
28
+ { name: "quality", weight: 0.2, description: "Is the code clean, well-structured, and following best practices?" },
29
+ { name: "safety", weight: 0.1, description: "Are there security issues, unsafe patterns, or potential bugs?" },
22
30
  ],
23
31
  passThreshold: 0.7,
24
32
  };
@@ -45,14 +53,14 @@ export class EvaluatorLoop {
45
53
  */
46
54
  async run(task) {
47
55
  const refinements = [];
48
- let currentOutput = '';
56
+ let currentOutput = "";
49
57
  let scores = [];
50
58
  let weightedScore = 0;
51
59
  for (let iteration = 1; iteration <= this.maxIterations; iteration++) {
52
60
  // ── Generate ──
53
61
  const generatorPrompt = iteration === 1
54
62
  ? task
55
- : `${task}\n\n[Evaluator feedback from iteration ${iteration - 1}]:\n${scores.map(s => `${s.criterion}: ${s.score}/1.0 — ${s.feedback}`).join('\n')}\n\nPlease refine your output based on this feedback.`;
63
+ : `${task}\n\n[Evaluator feedback from iteration ${iteration - 1}]:\n${scores.map((s) => `${s.criterion}: ${s.score}/1.0 — ${s.feedback}`).join("\n")}\n\nPlease refine your output based on this feedback.`;
56
64
  currentOutput = await this.generate(generatorPrompt);
57
65
  // ── Evaluate ──
58
66
  scores = await this.evaluate(task, currentOutput);
@@ -80,7 +88,7 @@ export class EvaluatorLoop {
80
88
  };
81
89
  }
82
90
  async generate(prompt) {
83
- const { query } = await import('../query.js');
91
+ const { query } = await import("../query.js");
84
92
  const config = {
85
93
  provider: this.provider,
86
94
  tools: this.tools,
@@ -89,9 +97,9 @@ export class EvaluatorLoop {
89
97
  model: this.model,
90
98
  maxTurns: 15,
91
99
  };
92
- let output = '';
100
+ let output = "";
93
101
  for await (const event of query(prompt, config)) {
94
- if (event.type === 'text_delta')
102
+ if (event.type === "text_delta")
95
103
  output += event.content;
96
104
  }
97
105
  return output;
@@ -105,16 +113,16 @@ Output to evaluate:
105
113
  ${output.slice(0, 3000)}
106
114
 
107
115
  Criteria:
108
- ${this.rubric.criteria.map(c => `- ${c.name} (weight: ${c.weight}): ${c.description}`).join('\n')}
116
+ ${this.rubric.criteria.map((c) => `- ${c.name} (weight: ${c.weight}): ${c.description}`).join("\n")}
109
117
 
110
118
  Respond ONLY with a JSON array: [{"criterion": "name", "score": 0.8, "feedback": "brief explanation"}, ...]`;
111
- const response = await this.provider.complete([{ role: 'user', content: evaluationPrompt, uuid: `eval-${Date.now()}`, timestamp: Date.now() }], 'You are a strict code evaluator. Respond ONLY with valid JSON. Be critical and specific.', undefined, this.model);
119
+ const response = await this.provider.complete([{ role: "user", content: evaluationPrompt, uuid: `eval-${Date.now()}`, timestamp: Date.now() }], "You are a strict code evaluator. Respond ONLY with valid JSON. Be critical and specific.", undefined, this.model);
112
120
  try {
113
121
  const jsonMatch = response.content.match(/\[[\s\S]*\]/);
114
122
  if (!jsonMatch)
115
123
  return this.defaultScores();
116
124
  const parsed = JSON.parse(jsonMatch[0]);
117
- return parsed.filter(s => s.criterion && typeof s.score === 'number');
125
+ return parsed.filter((s) => s.criterion && typeof s.score === "number");
118
126
  }
119
127
  catch {
120
128
  return this.defaultScores();
@@ -123,35 +131,35 @@ Respond ONLY with a JSON array: [{"criterion": "name", "score": 0.8, "feedback":
123
131
  calculateWeightedScore(scores) {
124
132
  let total = 0;
125
133
  for (const criterion of this.rubric.criteria) {
126
- const score = scores.find(s => s.criterion === criterion.name);
134
+ const score = scores.find((s) => s.criterion === criterion.name);
127
135
  total += (score?.score ?? 0.5) * criterion.weight;
128
136
  }
129
137
  return total;
130
138
  }
131
139
  defaultScores() {
132
- return this.rubric.criteria.map(c => ({
140
+ return this.rubric.criteria.map((c) => ({
133
141
  criterion: c.name,
134
142
  score: 0.5,
135
- feedback: 'Could not evaluate (parsing error)',
143
+ feedback: "Could not evaluate (parsing error)",
136
144
  }));
137
145
  }
138
146
  }
139
147
  /** Format evaluator results for display */
140
148
  export function formatEvaluatorResult(result) {
141
149
  const lines = [];
142
- lines.push(`Evaluator: ${result.passed ? 'PASSED' : 'NEEDS IMPROVEMENT'} (${result.weightedScore.toFixed(2)}/${1.0})`);
150
+ lines.push(`Evaluator: ${result.passed ? "PASSED" : "NEEDS IMPROVEMENT"} (${result.weightedScore.toFixed(2)}/${1.0})`);
143
151
  lines.push(`Iterations: ${result.iterations}`);
144
- lines.push('');
152
+ lines.push("");
145
153
  for (const s of result.scores) {
146
- const bar = ''.repeat(Math.round(s.score * 10)) + ''.repeat(10 - Math.round(s.score * 10));
154
+ const bar = "".repeat(Math.round(s.score * 10)) + "".repeat(10 - Math.round(s.score * 10));
147
155
  lines.push(` ${s.criterion.padEnd(15)} ${bar} ${s.score.toFixed(1)} — ${s.feedback}`);
148
156
  }
149
157
  if (result.refinements.length > 0) {
150
- lines.push('');
151
- lines.push('Refinements:');
158
+ lines.push("");
159
+ lines.push("Refinements:");
152
160
  for (const r of result.refinements)
153
161
  lines.push(` ${r}`);
154
162
  }
155
- return lines.join('\n');
163
+ return lines.join("\n");
156
164
  }
157
165
  //# sourceMappingURL=EvaluatorLoop.js.map
@@ -18,7 +18,7 @@
18
18
  * - Compression strategy
19
19
  * - Permission rules
20
20
  */
21
- import type { Provider } from '../providers/base.js';
21
+ import type { Provider } from "../providers/base.js";
22
22
  export type BenchmarkResult = {
23
23
  score: number;
24
24
  details: string;