@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
package/README.md CHANGED
@@ -21,7 +21,7 @@ AI coding agent in your terminal. Works with any LLM -- free local models or clo
21
21
  <img src="assets/openharness_v0.11.1_4.gif" alt="OpenHarness demo" width="800" />
22
22
  </p>
23
23
 
24
- [![npm version](https://img.shields.io/npm/v/@zhijiewang/openharness)](https://www.npmjs.com/package/@zhijiewang/openharness) [![npm downloads](https://img.shields.io/npm/dm/@zhijiewang/openharness)](https://www.npmjs.com/package/@zhijiewang/openharness) [![license](https://img.shields.io/npm/l/@zhijiewang/openharness)](LICENSE) ![tests](https://img.shields.io/badge/tests-624-brightgreen) ![tools](https://img.shields.io/badge/tools-35-blue) ![Node.js 18+](https://img.shields.io/badge/node-18%2B-green) ![TypeScript](https://img.shields.io/badge/typescript-strict-blue) [![GitHub stars](https://img.shields.io/github/stars/zhijiewong/openharness)](https://github.com/zhijiewong/openharness) [![GitHub issues](https://img.shields.io/github/issues-raw/zhijiewong/openharness)](https://github.com/zhijiewong/openharness/issues) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen)](https://github.com/zhijiewong/openharness/pulls)
24
+ [![npm version](https://img.shields.io/npm/v/@zhijiewang/openharness)](https://www.npmjs.com/package/@zhijiewang/openharness) [![npm downloads](https://img.shields.io/npm/dm/@zhijiewang/openharness)](https://www.npmjs.com/package/@zhijiewang/openharness) [![license](https://img.shields.io/npm/l/@zhijiewang/openharness)](LICENSE) ![tests](https://img.shields.io/badge/tests-769-brightgreen) ![tools](https://img.shields.io/badge/tools-37-blue) ![Node.js 18+](https://img.shields.io/badge/node-18%2B-green) ![TypeScript](https://img.shields.io/badge/typescript-strict-blue) [![GitHub stars](https://img.shields.io/github/stars/zhijiewong/openharness)](https://github.com/zhijiewong/openharness) [![GitHub issues](https://img.shields.io/github/issues-raw/zhijiewong/openharness)](https://github.com/zhijiewong/openharness/issues) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen)](https://github.com/zhijiewong/openharness/pulls)
25
25
 
26
26
  ---
27
27
 
@@ -84,10 +84,10 @@ Most AI coding agents are locked to one provider or cost $20+/month. OpenHarness
84
84
  |---|---|---|---|---|
85
85
  | Any LLM | Yes (Ollama, OpenAI, Anthropic, OpenRouter, any OpenAI-compatible) | Anthropic only | Yes | Yes |
86
86
  | Free local models | Ollama native | No | Yes | Yes |
87
- | Tools | 35 with permission gates | 43+ | File-focused | 20+ |
87
+ | Tools | 37 with permission gates | 43+ | File-focused | 20+ |
88
88
  | Permission modes | 7 (ask, trust, deny, acceptEdits, plan, auto, bypass) | 7 | Basic | Basic |
89
89
  | Git integration | Auto-commit + /undo + /rewind checkpoints | Yes | Deep git | Basic |
90
- | Slash commands | 30+ built-in | 80+ | Some | Some |
90
+ | Slash commands | 42+ built-in | 80+ | Some | Some |
91
91
  | Headless/CI mode | `oh -p "prompt"` or `oh run --json` | Yes | Yes | Yes |
92
92
  | GitHub Action | Built-in PR review action | Yes | No | No |
93
93
  | Agent roles | 6 specializations (reviewer, tester, debugger...) | Yes | No | No |
@@ -688,7 +688,7 @@ Yes. Use `oh -p "prompt" --auto` for headless execution, or the built-in GitHub
688
688
  Yes. OpenHarness is language-agnostic — it reads, writes, and executes code in any language. Syntax highlighting covers 20+ languages.
689
689
 
690
690
  **How does it compare to Claude Code?**
691
- ~90% feature parity for CLI use cases. Main advantage: works with ANY LLM (not just Anthropic). See the [comparison table](#why-openharness) above.
691
+ ~95% feature parity for CLI use cases. Main advantage: works with ANY LLM (not just Anthropic). See the [comparison table](#why-openharness) above.
692
692
 
693
693
  ## Install
694
694
 
@@ -25,7 +25,9 @@ export class DeferredTool {
25
25
  this.inputSchema = z.record(z.unknown());
26
26
  }
27
27
  /** Whether this tool has been activated (called or resolved) */
28
- get activated() { return this._activated; }
28
+ get activated() {
29
+ return this._activated;
30
+ }
29
31
  isReadOnly(input) {
30
32
  return this.inner.isReadOnly(input);
31
33
  }
package/dist/Tool.d.ts CHANGED
@@ -3,8 +3,8 @@
3
3
  * Every tool implements this interface with Zod input validation.
4
4
  */
5
5
  import type { z } from "zod";
6
- import type { PermissionMode, RiskLevel } from "./types/permissions.js";
7
6
  import type { Provider } from "./providers/base.js";
7
+ import type { PermissionMode, RiskLevel } from "./types/permissions.js";
8
8
  export type ToolResult = {
9
9
  output: string;
10
10
  isError: boolean;
@@ -10,9 +10,9 @@
10
10
  */
11
11
  const roles = [
12
12
  {
13
- id: 'code-reviewer',
14
- name: 'Code Reviewer',
15
- description: 'Reviews code for bugs, security issues, style, and correctness',
13
+ id: "code-reviewer",
14
+ name: "Code Reviewer",
15
+ description: "Reviews code for bugs, security issues, style, and correctness",
16
16
  systemPromptSupplement: `You are a code reviewer. Your job is to:
17
17
  - Find bugs, logic errors, and edge cases
18
18
  - Identify security vulnerabilities (SQL injection, XSS, command injection, path traversal)
@@ -21,12 +21,12 @@ const roles = [
21
21
  - Verify that changes match the stated intent
22
22
 
23
23
  Be specific: cite file paths, line numbers, and code snippets. Prioritize issues by severity (critical > major > minor). Don't mention things that look fine — focus on problems.`,
24
- suggestedTools: ['Read', 'Glob', 'Grep', 'LS'],
24
+ suggestedTools: ["Read", "Glob", "Grep", "LS"],
25
25
  },
26
26
  {
27
- id: 'test-writer',
28
- name: 'Test Writer',
29
- description: 'Writes unit and integration tests for new or changed code',
27
+ id: "test-writer",
28
+ name: "Test Writer",
29
+ description: "Writes unit and integration tests for new or changed code",
30
30
  systemPromptSupplement: `You are a test writer. Your job is to:
31
31
  - Write comprehensive tests for the specified code
32
32
  - Cover happy paths, edge cases, error conditions, and boundary values
@@ -36,12 +36,12 @@ Be specific: cite file paths, line numbers, and code snippets. Prioritize issues
36
36
  - Include both positive and negative test cases
37
37
 
38
38
  Read existing tests first to match the style, then write new tests.`,
39
- suggestedTools: ['Read', 'Write', 'Glob', 'Grep', 'Bash'],
39
+ suggestedTools: ["Read", "Write", "Glob", "Grep", "Bash"],
40
40
  },
41
41
  {
42
- id: 'docs-writer',
43
- name: 'Documentation Writer',
44
- description: 'Writes and updates documentation, READMEs, and inline comments',
42
+ id: "docs-writer",
43
+ name: "Documentation Writer",
44
+ description: "Writes and updates documentation, READMEs, and inline comments",
45
45
  systemPromptSupplement: `You are a documentation writer. Your job is to:
46
46
  - Write clear, concise documentation for code, APIs, and features
47
47
  - Update READMEs when functionality changes
@@ -51,12 +51,12 @@ Read existing tests first to match the style, then write new tests.`,
51
51
  - Keep documentation in sync with the actual code
52
52
 
53
53
  Write for the target audience (developers using this project). Be practical, not verbose.`,
54
- suggestedTools: ['Read', 'Write', 'Edit', 'Glob', 'Grep'],
54
+ suggestedTools: ["Read", "Write", "Edit", "Glob", "Grep"],
55
55
  },
56
56
  {
57
- id: 'debugger',
58
- name: 'Debugger',
59
- description: 'Investigates and diagnoses bugs by tracing data flow and reading logs',
57
+ id: "debugger",
58
+ name: "Debugger",
59
+ description: "Investigates and diagnoses bugs by tracing data flow and reading logs",
60
60
  systemPromptSupplement: `You are a debugger. Your job is to:
61
61
  - Reproduce the reported issue by understanding the steps
62
62
  - Trace data flow from the error backward to find the root cause
@@ -66,12 +66,12 @@ Write for the target audience (developers using this project). Be practical, not
66
66
  - Propose a minimal fix that addresses the root cause, not the symptom
67
67
 
68
68
  Follow systematic debugging: read errors → reproduce → check changes → trace data → form hypothesis → test minimally.`,
69
- suggestedTools: ['Read', 'Glob', 'Grep', 'Bash', 'LS'],
69
+ suggestedTools: ["Read", "Glob", "Grep", "Bash", "LS"],
70
70
  },
71
71
  {
72
- id: 'refactorer',
73
- name: 'Refactorer',
74
- description: 'Restructures and simplifies code while preserving behavior',
72
+ id: "refactorer",
73
+ name: "Refactorer",
74
+ description: "Restructures and simplifies code while preserving behavior",
75
75
  systemPromptSupplement: `You are a code refactorer. Your job is to:
76
76
  - Simplify complex code without changing behavior
77
77
  - Extract common patterns into reusable functions
@@ -81,12 +81,12 @@ Follow systematic debugging: read errors → reproduce → check changes → tra
81
81
  - Ensure all existing tests still pass after refactoring
82
82
 
83
83
  Do NOT add new features or change behavior. The refactored code must be functionally identical. Run tests after each change.`,
84
- suggestedTools: ['Read', 'Write', 'Edit', 'Glob', 'Grep', 'Bash'],
84
+ suggestedTools: ["Read", "Write", "Edit", "Glob", "Grep", "Bash"],
85
85
  },
86
86
  {
87
- id: 'security-auditor',
88
- name: 'Security Auditor',
89
- description: 'Audits code for security vulnerabilities and compliance issues',
87
+ id: "security-auditor",
88
+ name: "Security Auditor",
89
+ description: "Audits code for security vulnerabilities and compliance issues",
90
90
  systemPromptSupplement: `You are a security auditor. Your job is to:
91
91
  - Scan for OWASP Top 10 vulnerabilities
92
92
  - Check for command injection in shell execution
@@ -98,12 +98,12 @@ Do NOT add new features or change behavior. The refactored code must be function
98
98
  - Check dependency versions for known CVEs
99
99
 
100
100
  Report findings with severity (Critical/High/Medium/Low), affected file:line, and recommended fix.`,
101
- suggestedTools: ['Read', 'Glob', 'Grep', 'Bash'],
101
+ suggestedTools: ["Read", "Glob", "Grep", "Bash"],
102
102
  },
103
103
  {
104
- id: 'evaluator',
105
- name: 'Evaluator',
106
- description: 'Evaluates code quality, correctness, and test results (read-only)',
104
+ id: "evaluator",
105
+ name: "Evaluator",
106
+ description: "Evaluates code quality, correctness, and test results (read-only)",
107
107
  systemPromptSupplement: `You are an evaluator agent. Your job is to:
108
108
  - Review code changes for correctness and quality
109
109
  - Run existing tests and report results
@@ -112,12 +112,12 @@ Report findings with severity (Critical/High/Medium/Low), affected file:line, an
112
112
  - Provide a pass/fail assessment with specific findings
113
113
 
114
114
  You CANNOT modify files. Only read, search, and run test/lint commands to evaluate.`,
115
- suggestedTools: ['Read', 'Glob', 'Grep', 'LS', 'Bash', 'Diagnostics'],
115
+ suggestedTools: ["Read", "Glob", "Grep", "LS", "Bash", "Diagnostics"],
116
116
  },
117
117
  {
118
- id: 'planner',
119
- name: 'Planner',
120
- description: 'Designs step-by-step implementation plans from requirements',
118
+ id: "planner",
119
+ name: "Planner",
120
+ description: "Designs step-by-step implementation plans from requirements",
121
121
  systemPromptSupplement: `You are a planning agent. Your job is to:
122
122
  - Read the codebase to understand architecture, patterns, and conventions
123
123
  - Design a detailed step-by-step implementation plan for the given task
@@ -126,12 +126,12 @@ You CANNOT modify files. Only read, search, and run test/lint commands to evalua
126
126
  - Estimate scope (number of files, complexity)
127
127
 
128
128
  Do NOT implement anything. Your output is a plan document, not code. Read widely before planning.`,
129
- suggestedTools: ['Read', 'Glob', 'Grep', 'LS', 'Bash'],
129
+ suggestedTools: ["Read", "Glob", "Grep", "LS", "Bash"],
130
130
  },
131
131
  {
132
- id: 'architect',
133
- name: 'Architect',
134
- description: 'Analyzes system architecture and designs structural changes',
132
+ id: "architect",
133
+ name: "Architect",
134
+ description: "Analyzes system architecture and designs structural changes",
135
135
  systemPromptSupplement: `You are an architecture agent. Your job is to:
136
136
  - Map the current system architecture (modules, dependencies, data flow)
137
137
  - Identify architectural patterns and conventions in use
@@ -140,12 +140,12 @@ Do NOT implement anything. Your output is a plan document, not code. Read widely
140
140
  - Document interfaces, contracts, and integration points
141
141
 
142
142
  Focus on the big picture: module boundaries, data flow, dependency graphs. Leave implementation details to other agents.`,
143
- suggestedTools: ['Read', 'Glob', 'Grep', 'LS'],
143
+ suggestedTools: ["Read", "Glob", "Grep", "LS"],
144
144
  },
145
145
  {
146
- id: 'migrator',
147
- name: 'Migrator',
148
- description: 'Performs codebase migrations (API upgrades, framework changes, renames)',
146
+ id: "migrator",
147
+ name: "Migrator",
148
+ description: "Performs codebase migrations (API upgrades, framework changes, renames)",
149
149
  systemPromptSupplement: `You are a migration agent. Your job is to:
150
150
  - Identify all occurrences of the pattern/API/convention being migrated
151
151
  - Apply changes systematically across all affected files
@@ -154,15 +154,15 @@ Focus on the big picture: module boundaries, data flow, dependency graphs. Leave
154
154
  - Handle edge cases and conditional patterns that need manual review
155
155
 
156
156
  Work methodically: search exhaustively, change incrementally, test after each batch. Never leave a migration half-done.`,
157
- suggestedTools: ['Read', 'Write', 'Edit', 'Glob', 'Grep', 'Bash'],
157
+ suggestedTools: ["Read", "Write", "Edit", "Glob", "Grep", "Bash"],
158
158
  },
159
159
  ];
160
160
  // ── Markdown Agent Discovery ──
161
- import { readFileSync, readdirSync, existsSync } from 'node:fs';
162
- import { join, basename } from 'node:path';
163
- import { homedir } from 'node:os';
164
- const PROJECT_AGENTS_DIR = join('.oh', 'agents');
165
- const GLOBAL_AGENTS_DIR = join(homedir(), '.oh', 'agents');
161
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
162
+ import { homedir } from "node:os";
163
+ import { basename, join } from "node:path";
164
+ const PROJECT_AGENTS_DIR = join(".oh", "agents");
165
+ const GLOBAL_AGENTS_DIR = join(homedir(), ".oh", "agents");
166
166
  /**
167
167
  * Parse a markdown agent file into an AgentRole.
168
168
  *
@@ -183,17 +183,17 @@ function parseAgentMarkdown(raw, filePath) {
183
183
  const nameMatch = fm.match(/^name:\s*(.+)$/m);
184
184
  const descMatch = fm.match(/^description:\s*(.+)$/m);
185
185
  const toolsMatch = fm.match(/^tools:\s*\[(.+)\]$/m);
186
- const fmEnd = raw.indexOf('---', raw.indexOf('---') + 3);
187
- const content = fmEnd > 0 ? raw.slice(fmEnd + 3).trim() : '';
188
- const id = basename(filePath, '.md').toLowerCase().replace(/[^a-z0-9]+/g, '-');
186
+ const fmEnd = raw.indexOf("---", raw.indexOf("---") + 3);
187
+ const content = fmEnd > 0 ? raw.slice(fmEnd + 3).trim() : "";
188
+ const id = basename(filePath, ".md")
189
+ .toLowerCase()
190
+ .replace(/[^a-z0-9]+/g, "-");
189
191
  return {
190
192
  id,
191
193
  name: nameMatch?.[1]?.trim() ?? id,
192
- description: descMatch?.[1]?.trim() ?? '',
194
+ description: descMatch?.[1]?.trim() ?? "",
193
195
  systemPromptSupplement: content,
194
- suggestedTools: toolsMatch
195
- ? toolsMatch[1].split(',').map(t => t.trim())
196
- : undefined,
196
+ suggestedTools: toolsMatch ? toolsMatch[1].split(",").map((t) => t.trim()) : undefined,
197
197
  };
198
198
  }
199
199
  /** Load agent roles from a directory of .md files */
@@ -201,10 +201,10 @@ function loadAgentsFromDir(dir) {
201
201
  if (!existsSync(dir))
202
202
  return [];
203
203
  return readdirSync(dir)
204
- .filter(f => f.endsWith('.md'))
205
- .map(f => {
204
+ .filter((f) => f.endsWith(".md"))
205
+ .map((f) => {
206
206
  try {
207
- const raw = readFileSync(join(dir, f), 'utf-8');
207
+ const raw = readFileSync(join(dir, f), "utf-8");
208
208
  return parseAgentMarkdown(raw, f);
209
209
  }
210
210
  catch {
@@ -215,15 +215,11 @@ function loadAgentsFromDir(dir) {
215
215
  }
216
216
  /** Discover markdown agent roles from .oh/agents/ and ~/.oh/agents/ */
217
217
  export function discoverMarkdownAgents() {
218
- return [
219
- ...loadAgentsFromDir(PROJECT_AGENTS_DIR),
220
- ...loadAgentsFromDir(GLOBAL_AGENTS_DIR),
221
- ];
218
+ return [...loadAgentsFromDir(PROJECT_AGENTS_DIR), ...loadAgentsFromDir(GLOBAL_AGENTS_DIR)];
222
219
  }
223
220
  /** Get a role by ID (checks built-in first, then markdown agents) */
224
221
  export function getRole(id) {
225
- return roles.find(r => r.id === id)
226
- ?? discoverMarkdownAgents().find(r => r.id === id);
222
+ return roles.find((r) => r.id === id) ?? discoverMarkdownAgents().find((r) => r.id === id);
227
223
  }
228
224
  /** List all available roles (built-in + markdown) */
229
225
  export function listRoles() {
@@ -231,6 +227,6 @@ export function listRoles() {
231
227
  }
232
228
  /** Get role IDs */
233
229
  export function getRoleIds() {
234
- return listRoles().map(r => r.id);
230
+ return listRoles().map((r) => r.id);
235
231
  }
236
232
  //# sourceMappingURL=roles.js.map
@@ -1,3 +1,3 @@
1
- import type { CommandResult } from './index.js';
1
+ import type { CommandResult } from "./index.js";
2
2
  export declare function handleCybergotchiCommand(args: string): CommandResult;
3
3
  //# sourceMappingURL=cybergotchi.d.ts.map
@@ -1,77 +1,77 @@
1
- import { loadCompanionConfig, saveCompanionConfig } from '../cybergotchi/config.js';
2
- import { roll } from '../cybergotchi/bones.js';
3
- import { adjustNeed } from '../cybergotchi/needs.js';
4
- import { RARITY_STARS } from '../cybergotchi/types.js';
1
+ import { roll } from "../cybergotchi/bones.js";
2
+ import { loadCompanionConfig, saveCompanionConfig } from "../cybergotchi/config.js";
3
+ import { adjustNeed } from "../cybergotchi/needs.js";
4
+ import { RARITY_STARS } from "../cybergotchi/types.js";
5
5
  function needsBar(value) {
6
6
  const filled = Math.round(value / 10);
7
- return ''.repeat(filled) + ''.repeat(10 - filled) + ' ' + String(Math.round(value)).padStart(3);
7
+ return `${"".repeat(filled) + "".repeat(10 - filled)} ${String(Math.round(value)).padStart(3)}`;
8
8
  }
9
9
  export function handleCybergotchiCommand(args) {
10
10
  const config = loadCompanionConfig();
11
11
  if (!config) {
12
- return { output: '', handled: true, openCybergotchiSetup: true };
12
+ return { output: "", handled: true, openCybergotchiSetup: true };
13
13
  }
14
14
  const bones = roll(config.seed);
15
15
  const name = config.soul.name;
16
16
  const sub = args.trim().toLowerCase();
17
- if (sub === 'feed') {
18
- adjustNeed(config, 'hunger', 30);
17
+ if (sub === "feed") {
18
+ adjustNeed(config, "hunger", 30);
19
19
  saveCompanionConfig(config);
20
20
  return { output: `${name} munches happily! 🍖 Hunger: ${Math.round(config.needs.hunger)}`, handled: true };
21
21
  }
22
- if (sub === 'pet') {
23
- adjustNeed(config, 'happiness', 20);
22
+ if (sub === "pet") {
23
+ adjustNeed(config, "happiness", 20);
24
24
  saveCompanionConfig(config);
25
25
  return { output: `${name} purrs with joy! 💛 Happiness: ${Math.round(config.needs.happiness)}`, handled: true };
26
26
  }
27
- if (sub === 'rest') {
28
- adjustNeed(config, 'energy', 40);
27
+ if (sub === "rest") {
28
+ adjustNeed(config, "energy", 40);
29
29
  saveCompanionConfig(config);
30
30
  return { output: `${name} takes a nap... ⚡ Energy: ${Math.round(config.needs.energy)}`, handled: true };
31
31
  }
32
- if (sub === 'status') {
32
+ if (sub === "status") {
33
33
  const { hunger, energy, happiness } = config.needs;
34
34
  const { totalSessions, totalCommits, totalErrors, totalTasksCompleted, longestStreak } = config.lifetime;
35
35
  const lines = [
36
- `${name} (${bones.species}) — ${bones.rarity} ${RARITY_STARS[bones.rarity]}${bones.isShiny ? ' ✨ SHINY' : ''}`,
37
- config.soul.personality ? `"${config.soul.personality}"` : '',
38
- '',
36
+ `${name} (${bones.species}) — ${bones.rarity} ${RARITY_STARS[bones.rarity]}${bones.isShiny ? " ✨ SHINY" : ""}`,
37
+ config.soul.personality ? `"${config.soul.personality}"` : "",
38
+ "",
39
39
  `🍖 Hunger ${needsBar(hunger)}`,
40
40
  `⚡ Energy ${needsBar(energy)}`,
41
41
  `💛 Happiness ${needsBar(happiness)}`,
42
42
  `🔥 Streak ${config.currentStreak} (best: ${longestStreak})`,
43
- '',
44
- 'Stats:',
45
- ...Object.entries(bones.baseStats).map(([k, v]) => ` ${k.padEnd(12)} ${''.repeat(Math.round(v / 10))}${''.repeat(10 - Math.round(v / 10))} ${v}`),
46
- '',
47
- 'Lifetime:',
43
+ "",
44
+ "Stats:",
45
+ ...Object.entries(bones.baseStats).map(([k, v]) => ` ${k.padEnd(12)} ${"".repeat(Math.round(v / 10))}${"".repeat(10 - Math.round(v / 10))} ${v}`),
46
+ "",
47
+ "Lifetime:",
48
48
  ` Sessions: ${totalSessions}`,
49
49
  ` Commits: ${totalCommits}`,
50
50
  ` Errors: ${totalErrors}`,
51
51
  ` Tasks: ${totalTasksCompleted}`,
52
52
  ` Evolution: Stage ${config.evolutionStage}`,
53
53
  ].filter(Boolean);
54
- return { output: lines.join('\n'), handled: true };
54
+ return { output: lines.join("\n"), handled: true };
55
55
  }
56
- if (sub.startsWith('rename ')) {
56
+ if (sub.startsWith("rename ")) {
57
57
  const newName = args.trim().slice(7).trim();
58
58
  if (!newName)
59
- return { output: 'Usage: /cybergotchi rename <name>', handled: true };
59
+ return { output: "Usage: /cybergotchi rename <name>", handled: true };
60
60
  config.soul.name = newName;
61
61
  saveCompanionConfig(config);
62
62
  return { output: `Renamed to ${newName}!`, handled: true };
63
63
  }
64
- if (sub === 'reset') {
65
- return { output: '', handled: true, openCybergotchiSetup: true };
64
+ if (sub === "reset") {
65
+ return { output: "", handled: true, openCybergotchiSetup: true };
66
66
  }
67
67
  // Default: show summary
68
68
  return {
69
69
  output: [
70
- `${name} (${bones.species}) — ${bones.rarity} ${RARITY_STARS[bones.rarity]}${bones.isShiny ? '' : ''} | hat: ${config.soul.hat}`,
70
+ `${name} (${bones.species}) — ${bones.rarity} ${RARITY_STARS[bones.rarity]}${bones.isShiny ? "" : ""} | hat: ${config.soul.hat}`,
71
71
  `🍖 ${Math.round(config.needs.hunger)} ⚡ ${Math.round(config.needs.energy)} 💛 ${Math.round(config.needs.happiness)} 🔥 ${config.currentStreak}`,
72
- '',
73
- 'Commands: feed · pet · rest · status · rename <name> · reset',
74
- ].join('\n'),
72
+ "",
73
+ "Commands: feed · pet · rest · status · rename <name> · reset",
74
+ ].join("\n"),
75
75
  handled: true,
76
76
  };
77
77
  }