@zhijiewang/openharness 0.1.2 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/ISSUE_TEMPLATE/bug_report.md +27 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +17 -0
- package/.github/pull_request_template.md +24 -0
- package/CHANGELOG.md +1 -1
- package/CODE_OF_CONDUCT.md +43 -0
- package/README.md +109 -62
- package/SECURITY.md +21 -0
- package/dist/Tool.d.ts +1 -1
- package/dist/Tool.js +1 -1
- package/dist/commands/index.d.ts +37 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +189 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/components/App.d.ts.map +1 -1
- package/dist/components/App.js +3 -2
- package/dist/components/App.js.map +1 -1
- package/dist/components/ErrorBoundary.d.ts +17 -0
- package/dist/components/ErrorBoundary.d.ts.map +1 -0
- package/dist/components/ErrorBoundary.js +19 -0
- package/dist/components/ErrorBoundary.js.map +1 -0
- package/dist/components/Markdown.d.ts.map +1 -1
- package/dist/components/Markdown.js +70 -18
- package/dist/components/Markdown.js.map +1 -1
- package/dist/components/Messages.d.ts.map +1 -1
- package/dist/components/Messages.js +10 -4
- package/dist/components/Messages.js.map +1 -1
- package/dist/components/PermissionPrompt.d.ts.map +1 -1
- package/dist/components/PermissionPrompt.js +25 -7
- package/dist/components/PermissionPrompt.js.map +1 -1
- package/dist/components/REPL.d.ts.map +1 -1
- package/dist/components/REPL.js +60 -6
- package/dist/components/REPL.js.map +1 -1
- package/dist/components/Spinner.d.ts +3 -2
- package/dist/components/Spinner.d.ts.map +1 -1
- package/dist/components/Spinner.js +22 -4
- package/dist/components/Spinner.js.map +1 -1
- package/dist/components/TextInput.d.ts.map +1 -1
- package/dist/components/TextInput.js +4 -1
- package/dist/components/TextInput.js.map +1 -1
- package/dist/git/index.d.ts +47 -0
- package/dist/git/index.d.ts.map +1 -0
- package/dist/git/index.js +151 -0
- package/dist/git/index.js.map +1 -0
- package/dist/harness/session.d.ts.map +1 -1
- package/dist/harness/session.js +2 -1
- package/dist/harness/session.js.map +1 -1
- package/dist/main.js +89 -3
- package/dist/main.js.map +1 -1
- package/dist/providers/openai.js +11 -1
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/openrouter.js +11 -1
- package/dist/providers/openrouter.js.map +1 -1
- package/dist/query.d.ts +15 -11
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +196 -80
- package/dist/query.js.map +1 -1
- package/dist/services/StreamingToolExecutor.d.ts +25 -0
- package/dist/services/StreamingToolExecutor.d.ts.map +1 -0
- package/dist/services/StreamingToolExecutor.js +107 -0
- package/dist/services/StreamingToolExecutor.js.map +1 -0
- package/dist/tools/AgentTool/index.d.ts +15 -0
- package/dist/tools/AgentTool/index.d.ts.map +1 -0
- package/dist/tools/AgentTool/index.js +30 -0
- package/dist/tools/AgentTool/index.js.map +1 -0
- package/dist/tools/AskUserTool/index.d.ts +15 -0
- package/dist/tools/AskUserTool/index.d.ts.map +1 -0
- package/dist/tools/AskUserTool/index.js +30 -0
- package/dist/tools/AskUserTool/index.js.map +1 -0
- package/dist/tools/EnterPlanModeTool/index.d.ts +6 -0
- package/dist/tools/EnterPlanModeTool/index.d.ts.map +1 -0
- package/dist/tools/EnterPlanModeTool/index.js +37 -0
- package/dist/tools/EnterPlanModeTool/index.js.map +1 -0
- package/dist/tools/ExitPlanModeTool/index.d.ts +6 -0
- package/dist/tools/ExitPlanModeTool/index.d.ts.map +1 -0
- package/dist/tools/ExitPlanModeTool/index.js +21 -0
- package/dist/tools/ExitPlanModeTool/index.js.map +1 -0
- package/dist/tools/NotebookEditTool/index.d.ts +18 -0
- package/dist/tools/NotebookEditTool/index.d.ts.map +1 -0
- package/dist/tools/NotebookEditTool/index.js +61 -0
- package/dist/tools/NotebookEditTool/index.js.map +1 -0
- package/dist/tools/SkillTool/index.d.ts +15 -0
- package/dist/tools/SkillTool/index.d.ts.map +1 -0
- package/dist/tools/SkillTool/index.js +49 -0
- package/dist/tools/SkillTool/index.js.map +1 -0
- package/dist/tools/TaskCreateTool/index.d.ts +15 -0
- package/dist/tools/TaskCreateTool/index.d.ts.map +1 -0
- package/dist/tools/TaskCreateTool/index.js +54 -0
- package/dist/tools/TaskCreateTool/index.js.map +1 -0
- package/dist/tools/TaskListTool/index.d.ts +6 -0
- package/dist/tools/TaskListTool/index.d.ts.map +1 -0
- package/dist/tools/TaskListTool/index.js +40 -0
- package/dist/tools/TaskListTool/index.js.map +1 -0
- package/dist/tools/TaskUpdateTool/index.d.ts +18 -0
- package/dist/tools/TaskUpdateTool/index.d.ts.map +1 -0
- package/dist/tools/TaskUpdateTool/index.js +50 -0
- package/dist/tools/TaskUpdateTool/index.js.map +1 -0
- package/dist/tools/WebSearchTool/index.d.ts +15 -0
- package/dist/tools/WebSearchTool/index.d.ts.map +1 -0
- package/dist/tools/WebSearchTool/index.js +76 -0
- package/dist/tools/WebSearchTool/index.js.map +1 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +27 -0
- package/dist/tools.js.map +1 -1
- package/dist/types/message.d.ts +1 -1
- package/dist/types/message.js +1 -1
- package/dist/types/permissions.d.ts +2 -2
- package/dist/types/permissions.js +2 -2
- package/dist/utils/retry.d.ts +10 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +23 -0
- package/dist/utils/retry.js.map +1 -0
- package/dist/utils/theme.d.ts +27 -0
- package/dist/utils/theme.d.ts.map +1 -0
- package/dist/utils/theme.js +45 -0
- package/dist/utils/theme.js.map +1 -0
- package/dist/utils/tokens.d.ts +18 -0
- package/dist/utils/tokens.d.ts.map +1 -0
- package/dist/utils/tokens.js +57 -0
- package/dist/utils/tokens.js.map +1 -0
- package/package.json +61 -57
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Report a bug in OpenHarness
|
|
4
|
+
labels: bug
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
**Describe the bug**
|
|
8
|
+
A clear description of what the bug is.
|
|
9
|
+
|
|
10
|
+
**To reproduce**
|
|
11
|
+
Steps to reproduce the behavior:
|
|
12
|
+
1. Run `oh ...`
|
|
13
|
+
2. See error
|
|
14
|
+
|
|
15
|
+
**Expected behavior**
|
|
16
|
+
What you expected to happen.
|
|
17
|
+
|
|
18
|
+
**Environment**
|
|
19
|
+
- OS:
|
|
20
|
+
- Node version:
|
|
21
|
+
- OpenHarness version:
|
|
22
|
+
- LLM provider:
|
|
23
|
+
|
|
24
|
+
**Logs / error output**
|
|
25
|
+
```
|
|
26
|
+
paste any relevant output here
|
|
27
|
+
```
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature request
|
|
3
|
+
about: Suggest an idea for OpenHarness
|
|
4
|
+
labels: enhancement
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
**Problem / motivation**
|
|
8
|
+
What problem does this solve, or what use case does it enable?
|
|
9
|
+
|
|
10
|
+
**Proposed solution**
|
|
11
|
+
Describe the feature you'd like.
|
|
12
|
+
|
|
13
|
+
**Alternatives considered**
|
|
14
|
+
Any other approaches you've thought about?
|
|
15
|
+
|
|
16
|
+
**Additional context**
|
|
17
|
+
Screenshots, examples, or links if relevant.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
<!-- What does this PR do? -->
|
|
4
|
+
|
|
5
|
+
## Related issue
|
|
6
|
+
|
|
7
|
+
Closes #
|
|
8
|
+
|
|
9
|
+
## Type of change
|
|
10
|
+
|
|
11
|
+
- [ ] Bug fix
|
|
12
|
+
- [ ] New feature
|
|
13
|
+
- [ ] Breaking change
|
|
14
|
+
- [ ] Documentation
|
|
15
|
+
|
|
16
|
+
## Testing
|
|
17
|
+
|
|
18
|
+
<!-- How did you test this? -->
|
|
19
|
+
|
|
20
|
+
## Checklist
|
|
21
|
+
|
|
22
|
+
- [ ] Code builds without errors (`npm run build`)
|
|
23
|
+
- [ ] Types pass (`npm run typecheck`)
|
|
24
|
+
- [ ] Tests pass (`npm test`)
|
package/CHANGELOG.md
CHANGED
|
@@ -6,7 +6,7 @@ Initial alpha release. TypeScript rewrite.
|
|
|
6
6
|
|
|
7
7
|
### Features
|
|
8
8
|
- Single TypeScript process with React+Ink terminal UI
|
|
9
|
-
- Agent loop with async generator streaming
|
|
9
|
+
- Agent loop with async generator streaming
|
|
10
10
|
- 5 LLM providers: Ollama, OpenAI, Anthropic, OpenRouter, OpenAI-compatible
|
|
11
11
|
- 7 tools: Read, Edit, Write, Bash, Glob, Grep, WebFetch (all with Zod schemas)
|
|
12
12
|
- Permission gate with ask/trust/deny modes and risk-based tool approval
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.
|
|
6
|
+
|
|
7
|
+
We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
|
|
8
|
+
|
|
9
|
+
## Our Standards
|
|
10
|
+
|
|
11
|
+
Examples of behavior that contributes to a positive environment:
|
|
12
|
+
|
|
13
|
+
- Demonstrating empathy and kindness toward other people
|
|
14
|
+
- Being respectful of differing opinions, viewpoints, and experiences
|
|
15
|
+
- Giving and gracefully accepting constructive feedback
|
|
16
|
+
- Accepting responsibility and apologizing to those affected by our mistakes
|
|
17
|
+
- Focusing on what is best not just for us as individuals, but for the overall community
|
|
18
|
+
|
|
19
|
+
Examples of unacceptable behavior:
|
|
20
|
+
|
|
21
|
+
- The use of sexualized language or imagery, and sexual attention or advances of any kind
|
|
22
|
+
- Trolling, insulting or derogatory comments, and personal or political attacks
|
|
23
|
+
- Public or private harassment
|
|
24
|
+
- Publishing others' private information without explicit permission
|
|
25
|
+
- Other conduct which could reasonably be considered inappropriate in a professional setting
|
|
26
|
+
|
|
27
|
+
## Enforcement Responsibilities
|
|
28
|
+
|
|
29
|
+
Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
|
|
30
|
+
|
|
31
|
+
## Scope
|
|
32
|
+
|
|
33
|
+
This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces.
|
|
34
|
+
|
|
35
|
+
## Enforcement
|
|
36
|
+
|
|
37
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at the repository's issue tracker or by contacting the maintainer directly via GitHub.
|
|
38
|
+
|
|
39
|
+
All complaints will be reviewed and investigated promptly and fairly.
|
|
40
|
+
|
|
41
|
+
## Attribution
|
|
42
|
+
|
|
43
|
+
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.1.
|
package/README.md
CHANGED
|
@@ -11,12 +11,19 @@
|
|
|
11
11
|
`--`
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
AI coding agent in your terminal. Works with any LLM -- free local models or cloud APIs.
|
|
15
15
|
|
|
16
|
-

|
|
17
17
|

|
|
18
18
|

|
|
19
19
|

|
|
20
|
+

|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
<video src="https://github.com/user-attachments/assets/ed19a2cc-14d3-4db3-aa5b-3dc07c444498" controls width="100%"></video>
|
|
25
|
+
|
|
26
|
+
*OpenHarness reading files, running commands, and editing code — powered by a local Ollama model.*
|
|
20
27
|
|
|
21
28
|
---
|
|
22
29
|
|
|
@@ -27,78 +34,120 @@ npm install -g @zhijiewang/openharness
|
|
|
27
34
|
oh
|
|
28
35
|
```
|
|
29
36
|
|
|
30
|
-
That's it.
|
|
37
|
+
That's it. OpenHarness auto-detects Ollama and starts chatting. No API key needed.
|
|
31
38
|
|
|
32
39
|
```bash
|
|
33
|
-
oh # auto-detect
|
|
40
|
+
oh # auto-detect local model
|
|
34
41
|
oh --model ollama/qwen2.5:7b # specific model
|
|
35
|
-
oh --model gpt-4o #
|
|
42
|
+
oh --model gpt-4o # cloud model (needs OPENAI_API_KEY)
|
|
36
43
|
oh --trust # auto-approve all tool calls
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
<!--  -->
|
|
40
|
-
|
|
41
|
-
## Install
|
|
42
|
-
|
|
43
|
-
Requires **Node.js 18+**.
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
# From npm
|
|
47
|
-
npm install -g @zhijiewang/openharness
|
|
48
|
-
|
|
49
|
-
# From source
|
|
50
|
-
git clone https://github.com/zhijiewong/openharness.git
|
|
51
|
-
cd openharness
|
|
52
|
-
npm install
|
|
53
|
-
npm install -g .
|
|
54
|
-
oh
|
|
44
|
+
oh run "fix the tests" --json # headless mode for CI/CD
|
|
55
45
|
```
|
|
56
46
|
|
|
57
47
|
## Why OpenHarness?
|
|
58
48
|
|
|
59
|
-
|
|
49
|
+
Most AI coding agents are locked to one provider or cost $20+/month. OpenHarness works with any LLM -- run it free with Ollama on your own machine, or connect to any cloud API. Every AI edit is git-committed and reversible with `/undo`.
|
|
50
|
+
|
|
51
|
+
| | OpenHarness | Claude Code | Aider | OpenCode |
|
|
52
|
+
|---|---|---|---|---|
|
|
53
|
+
| Any LLM | Yes (Ollama, OpenAI, Anthropic, OpenRouter, any OpenAI-compatible) | Anthropic only | Yes | Yes |
|
|
54
|
+
| Free local models | Ollama native | No | Yes | Yes |
|
|
55
|
+
| Tools | 17 with permission gates | 40+ | File-focused | 20+ |
|
|
56
|
+
| Git integration | Auto-commit + /undo | Yes | Deep git | Basic |
|
|
57
|
+
| Slash commands | 16 built-in | 80+ | Some | Some |
|
|
58
|
+
| Headless/CI mode | `oh run --json` | Yes | Yes | Yes |
|
|
59
|
+
| Terminal UI | React + Ink | React + Ink | Basic | BubbleTea |
|
|
60
|
+
| Language | TypeScript | TypeScript | Python | Go |
|
|
61
|
+
| License | MIT | Proprietary | Apache 2.0 | MIT |
|
|
62
|
+
| Price | Free (BYOK) | $20+/month | Free (BYOK) | Free (BYOK) |
|
|
60
63
|
|
|
61
|
-
## Tools
|
|
64
|
+
## Tools (17)
|
|
62
65
|
|
|
63
66
|
| Tool | Risk | Description |
|
|
64
67
|
|------|------|-------------|
|
|
68
|
+
| Bash | high | Execute shell commands with timeout |
|
|
65
69
|
| Read | low | Read files with line ranges |
|
|
66
|
-
| Edit | medium | Search-and-replace edits |
|
|
67
70
|
| Write | medium | Create or overwrite files |
|
|
68
|
-
|
|
|
71
|
+
| Edit | medium | Search-and-replace edits |
|
|
69
72
|
| Glob | low | Find files by pattern |
|
|
70
73
|
| Grep | low | Regex content search |
|
|
71
|
-
| WebFetch | medium | Fetch URL content |
|
|
74
|
+
| WebFetch | medium | Fetch URL content (SSRF-protected) |
|
|
75
|
+
| WebSearch | medium | Search the web |
|
|
76
|
+
| TaskCreate | low | Create structured tasks |
|
|
77
|
+
| TaskUpdate | low | Update task status |
|
|
78
|
+
| TaskList | low | List all tasks |
|
|
79
|
+
| AskUser | low | Ask user a question with options |
|
|
80
|
+
| Skill | low | Invoke a skill from .oh/skills/ |
|
|
81
|
+
| Agent | medium | Spawn a sub-agent for delegation |
|
|
82
|
+
| EnterPlanMode | low | Enter structured planning mode |
|
|
83
|
+
| ExitPlanMode | low | Exit planning mode |
|
|
84
|
+
| NotebookEdit | medium | Edit Jupyter notebooks |
|
|
85
|
+
|
|
86
|
+
Low-risk read-only tools auto-approve. Medium and high risk tools require confirmation in `ask` mode. Use `--trust` to skip all prompts.
|
|
87
|
+
|
|
88
|
+
## Slash Commands (16)
|
|
89
|
+
|
|
90
|
+
Type these during a chat session:
|
|
91
|
+
|
|
92
|
+
| Command | Description |
|
|
93
|
+
|---------|-------------|
|
|
94
|
+
| `/help` | Show all available commands |
|
|
95
|
+
| `/clear` | Clear conversation history |
|
|
96
|
+
| `/cost` | Show session cost and token usage |
|
|
97
|
+
| `/status` | Show model, mode, git branch, session info |
|
|
98
|
+
| `/diff` | Show uncommitted git changes |
|
|
99
|
+
| `/undo` | Undo last AI commit |
|
|
100
|
+
| `/commit [msg]` | Create a git commit |
|
|
101
|
+
| `/log` | Show recent git commits |
|
|
102
|
+
| `/files` | List files in context |
|
|
103
|
+
| `/model <name>` | Switch model mid-session |
|
|
104
|
+
| `/compact` | Compress conversation to free context |
|
|
105
|
+
| `/export` | Export conversation to markdown |
|
|
106
|
+
| `/plan` | Enter plan mode |
|
|
107
|
+
| `/review` | Review recent code changes |
|
|
108
|
+
| `/config` | Show configuration |
|
|
109
|
+
| `/memory` | View memories |
|
|
110
|
+
|
|
111
|
+
## Git Integration
|
|
112
|
+
|
|
113
|
+
OpenHarness auto-commits AI edits in git repos:
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
oh: Edit src/app.ts # auto-committed with "oh:" prefix
|
|
117
|
+
oh: Write tests/app.test.ts
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
- Every AI file change is committed automatically
|
|
121
|
+
- `/undo` reverts the last AI commit (only OH commits, never yours)
|
|
122
|
+
- `/diff` shows what changed
|
|
123
|
+
- Your dirty files are safe — committed separately before AI edits
|
|
72
124
|
|
|
73
|
-
|
|
125
|
+
## Headless Mode
|
|
74
126
|
|
|
75
|
-
|
|
127
|
+
Run a single prompt without interactive UI — perfect for CI/CD:
|
|
76
128
|
|
|
77
129
|
```bash
|
|
78
|
-
oh
|
|
79
|
-
oh
|
|
80
|
-
oh --
|
|
81
|
-
oh --deny # block all non-read tools
|
|
82
|
-
oh --resume ID # resume a saved session
|
|
83
|
-
oh models # list models and pricing
|
|
84
|
-
oh tools # list tools and risk levels
|
|
85
|
-
oh init # set up .oh/ for current project
|
|
86
|
-
oh sessions # list saved sessions
|
|
87
|
-
oh rules # show project rules
|
|
88
|
-
oh --version # show version
|
|
130
|
+
oh run "fix the failing tests" --model ollama/llama3 --trust
|
|
131
|
+
oh run "add error handling to api.ts" --json # JSON output
|
|
132
|
+
oh run "explain this codebase" --model gpt-4o
|
|
89
133
|
```
|
|
90
134
|
|
|
135
|
+
Exit code 0 on success, 1 on failure.
|
|
136
|
+
|
|
91
137
|
## Providers
|
|
92
138
|
|
|
93
139
|
```bash
|
|
94
|
-
# Local (free, no API key)
|
|
140
|
+
# Local (free, no API key needed)
|
|
95
141
|
oh --model ollama/llama3
|
|
96
142
|
oh --model ollama/qwen2.5:7b-instruct
|
|
97
143
|
|
|
98
|
-
# Cloud
|
|
144
|
+
# Cloud
|
|
99
145
|
OPENAI_API_KEY=sk-... oh --model gpt-4o
|
|
100
146
|
ANTHROPIC_API_KEY=sk-ant-... oh --model claude-sonnet-4-6
|
|
101
147
|
OPENROUTER_API_KEY=sk-or-... oh --model openrouter/deepseek-chat
|
|
148
|
+
|
|
149
|
+
# Any OpenAI-compatible endpoint
|
|
150
|
+
oh --model deepseek/deepseek-chat
|
|
102
151
|
```
|
|
103
152
|
|
|
104
153
|
## Project Rules
|
|
@@ -113,36 +162,37 @@ Create `.oh/RULES.md` in any repo (or run `oh init`):
|
|
|
113
162
|
|
|
114
163
|
Rules load automatically into every session.
|
|
115
164
|
|
|
116
|
-
##
|
|
117
|
-
|
|
118
|
-
| | OpenHarness | Claude Code |
|
|
119
|
-
|---|---|---|
|
|
120
|
-
| Language | TypeScript (strict) | TypeScript (strict) |
|
|
121
|
-
| Runtime | Node.js 18+ | Bun |
|
|
122
|
-
| Terminal UI | React + Ink | React + custom Ink fork |
|
|
123
|
-
| Tool schemas | Zod | Zod |
|
|
124
|
-
| Agent loop | async generators | async generators |
|
|
125
|
-
| Providers | Any (5 built-in) | Anthropic only |
|
|
126
|
-
| License | MIT | Proprietary |
|
|
165
|
+
## Install
|
|
127
166
|
|
|
128
|
-
|
|
167
|
+
Requires **Node.js 18+**.
|
|
129
168
|
|
|
130
169
|
```bash
|
|
170
|
+
# From npm
|
|
171
|
+
npm install -g @zhijiewang/openharness
|
|
172
|
+
|
|
173
|
+
# From source
|
|
131
174
|
git clone https://github.com/zhijiewong/openharness.git
|
|
132
175
|
cd openharness
|
|
176
|
+
npm install && npm install -g .
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Development
|
|
180
|
+
|
|
181
|
+
```bash
|
|
133
182
|
npm install
|
|
134
183
|
npx tsx src/main.tsx # run in dev mode
|
|
135
184
|
npx tsc --noEmit # type check
|
|
185
|
+
npm test # run tests
|
|
136
186
|
```
|
|
137
187
|
|
|
138
|
-
### Adding a provider
|
|
139
|
-
|
|
140
|
-
Create `src/providers/yourprovider.ts` implementing the `Provider` interface, add a case in `src/providers/index.ts`.
|
|
141
|
-
|
|
142
188
|
### Adding a tool
|
|
143
189
|
|
|
144
190
|
Create `src/tools/YourTool/index.ts` implementing the `Tool` interface with a Zod input schema, register it in `src/tools.ts`.
|
|
145
191
|
|
|
192
|
+
### Adding a provider
|
|
193
|
+
|
|
194
|
+
Create `src/providers/yourprovider.ts` implementing the `Provider` interface, add a case in `src/providers/index.ts`.
|
|
195
|
+
|
|
146
196
|
## Contributing
|
|
147
197
|
|
|
148
198
|
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
@@ -151,6 +201,3 @@ See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
|
151
201
|
|
|
152
202
|
MIT
|
|
153
203
|
|
|
154
|
-
---
|
|
155
|
-
|
|
156
|
-
This project is not affiliated with Anthropic.
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
| Version | Supported |
|
|
6
|
+
|---------|-----------|
|
|
7
|
+
| 0.1.x | ✅ |
|
|
8
|
+
|
|
9
|
+
## Reporting a Vulnerability
|
|
10
|
+
|
|
11
|
+
Please **do not** report security vulnerabilities via public GitHub issues.
|
|
12
|
+
|
|
13
|
+
Instead, open a [GitHub Security Advisory](https://github.com/zhijiewong/openharness/security/advisories/new) or contact the maintainer directly via the profile on GitHub.
|
|
14
|
+
|
|
15
|
+
Please include:
|
|
16
|
+
- Description of the vulnerability
|
|
17
|
+
- Steps to reproduce
|
|
18
|
+
- Potential impact
|
|
19
|
+
- Suggested fix (if any)
|
|
20
|
+
|
|
21
|
+
You can expect a response within 48 hours. If confirmed, a patch will be prioritized and released as soon as possible.
|
package/dist/Tool.d.ts
CHANGED
package/dist/Tool.js
CHANGED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slash command system — /help, /clear, /diff, /undo, /cost, etc.
|
|
3
|
+
*
|
|
4
|
+
* Commands are processed in the REPL before being sent to the LLM.
|
|
5
|
+
* If input starts with /, it's treated as a command.
|
|
6
|
+
*/
|
|
7
|
+
import type { Message } from "../types/message.js";
|
|
8
|
+
export type CommandResult = {
|
|
9
|
+
/** Text output to display */
|
|
10
|
+
output: string;
|
|
11
|
+
/** If true, don't send to LLM */
|
|
12
|
+
handled: boolean;
|
|
13
|
+
/** If set, clear messages */
|
|
14
|
+
clearMessages?: boolean;
|
|
15
|
+
/** If set, update model */
|
|
16
|
+
newModel?: string;
|
|
17
|
+
/** If set, replace messages with compacted version */
|
|
18
|
+
compactedMessages?: Message[];
|
|
19
|
+
};
|
|
20
|
+
export type CommandContext = {
|
|
21
|
+
messages: Message[];
|
|
22
|
+
model: string;
|
|
23
|
+
permissionMode: string;
|
|
24
|
+
totalCost: number;
|
|
25
|
+
totalInputTokens: number;
|
|
26
|
+
totalOutputTokens: number;
|
|
27
|
+
sessionId: string;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Check if input is a slash command. If so, execute it.
|
|
31
|
+
*/
|
|
32
|
+
export declare function processSlashCommand(input: string, context: CommandContext): CommandResult | null;
|
|
33
|
+
/**
|
|
34
|
+
* Get all registered command names (for autocomplete/display).
|
|
35
|
+
*/
|
|
36
|
+
export declare function getCommandNames(): string[];
|
|
37
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,MAAM,aAAa,GAAG;IAC1B,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,6BAA6B;IAC7B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,iBAAiB,CAAC,EAAE,OAAO,EAAE,CAAC;CAC/B,CAAC;AAIF,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AA4KF;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,aAAa,GAAG,IAAI,CAiBhG;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAE1C"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slash command system — /help, /clear, /diff, /undo, /cost, etc.
|
|
3
|
+
*
|
|
4
|
+
* Commands are processed in the REPL before being sent to the LLM.
|
|
5
|
+
* If input starts with /, it's treated as a command.
|
|
6
|
+
*/
|
|
7
|
+
import { writeFileSync, mkdirSync } from "node:fs";
|
|
8
|
+
import { dirname } from "node:path";
|
|
9
|
+
import { isGitRepo, gitDiff, gitUndo, gitCommit, gitLog, gitBranch } from "../git/index.js";
|
|
10
|
+
const commands = new Map();
|
|
11
|
+
function register(name, description, handler) {
|
|
12
|
+
commands.set(name, { description, handler });
|
|
13
|
+
}
|
|
14
|
+
// ── Register all commands ──
|
|
15
|
+
register("help", "Show available commands", () => {
|
|
16
|
+
const lines = ["Available commands:\n"];
|
|
17
|
+
for (const [name, { description }] of commands) {
|
|
18
|
+
lines.push(` /${name.padEnd(12)} ${description}`);
|
|
19
|
+
}
|
|
20
|
+
return { output: lines.join("\n"), handled: true };
|
|
21
|
+
});
|
|
22
|
+
register("clear", "Clear conversation history", () => {
|
|
23
|
+
return { output: "Conversation cleared.", handled: true, clearMessages: true };
|
|
24
|
+
});
|
|
25
|
+
register("cost", "Show session cost and token usage", (_args, ctx) => {
|
|
26
|
+
const lines = [
|
|
27
|
+
`Cost: $${ctx.totalCost.toFixed(4)}`,
|
|
28
|
+
`Tokens: ${ctx.totalInputTokens.toLocaleString()} input, ${ctx.totalOutputTokens.toLocaleString()} output`,
|
|
29
|
+
`Model: ${ctx.model}`,
|
|
30
|
+
`Session: ${ctx.sessionId}`,
|
|
31
|
+
];
|
|
32
|
+
return { output: lines.join("\n"), handled: true };
|
|
33
|
+
});
|
|
34
|
+
register("status", "Show session status", (_args, ctx) => {
|
|
35
|
+
const lines = [
|
|
36
|
+
`Model: ${ctx.model}`,
|
|
37
|
+
`Mode: ${ctx.permissionMode}`,
|
|
38
|
+
`Messages: ${ctx.messages.length}`,
|
|
39
|
+
`Cost: $${ctx.totalCost.toFixed(4)}`,
|
|
40
|
+
`Session: ${ctx.sessionId}`,
|
|
41
|
+
];
|
|
42
|
+
if (isGitRepo()) {
|
|
43
|
+
lines.push(`Git branch: ${gitBranch()}`);
|
|
44
|
+
}
|
|
45
|
+
return { output: lines.join("\n"), handled: true };
|
|
46
|
+
});
|
|
47
|
+
register("diff", "Show uncommitted git changes", () => {
|
|
48
|
+
if (!isGitRepo()) {
|
|
49
|
+
return { output: "Not a git repository.", handled: true };
|
|
50
|
+
}
|
|
51
|
+
const diff = gitDiff();
|
|
52
|
+
return { output: diff || "No uncommitted changes.", handled: true };
|
|
53
|
+
});
|
|
54
|
+
register("undo", "Undo last AI commit", () => {
|
|
55
|
+
if (!isGitRepo()) {
|
|
56
|
+
return { output: "Not a git repository.", handled: true };
|
|
57
|
+
}
|
|
58
|
+
const success = gitUndo();
|
|
59
|
+
return {
|
|
60
|
+
output: success ? "Undone. Last AI commit reverted." : "Nothing to undo (last commit wasn't from OpenHarness).",
|
|
61
|
+
handled: true,
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
register("commit", "Create a git commit", (args) => {
|
|
65
|
+
if (!isGitRepo()) {
|
|
66
|
+
return { output: "Not a git repository.", handled: true };
|
|
67
|
+
}
|
|
68
|
+
const message = args.trim() || "manual commit";
|
|
69
|
+
const success = gitCommit(message);
|
|
70
|
+
return { output: success ? `Committed: ${message}` : "Nothing to commit.", handled: true };
|
|
71
|
+
});
|
|
72
|
+
register("log", "Show recent git commits", () => {
|
|
73
|
+
if (!isGitRepo()) {
|
|
74
|
+
return { output: "Not a git repository.", handled: true };
|
|
75
|
+
}
|
|
76
|
+
return { output: gitLog(10) || "No commits yet.", handled: true };
|
|
77
|
+
});
|
|
78
|
+
register("files", "List files in context", (_args, ctx) => {
|
|
79
|
+
const files = new Set();
|
|
80
|
+
for (const msg of ctx.messages) {
|
|
81
|
+
// Extract file paths from tool calls
|
|
82
|
+
if (msg.toolCalls) {
|
|
83
|
+
for (const tc of msg.toolCalls) {
|
|
84
|
+
const path = tc.arguments?.file_path ?? tc.arguments?.path;
|
|
85
|
+
if (path)
|
|
86
|
+
files.add(String(path));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (files.size === 0)
|
|
91
|
+
return { output: "No files in context yet.", handled: true };
|
|
92
|
+
return { output: `Files in context:\n${[...files].map(f => ` ${f}`).join("\n")}`, handled: true };
|
|
93
|
+
});
|
|
94
|
+
register("model", "Switch model (e.g., /model gpt-4o)", (args) => {
|
|
95
|
+
const model = args.trim();
|
|
96
|
+
if (!model)
|
|
97
|
+
return { output: "Usage: /model <model-name>", handled: true };
|
|
98
|
+
return { output: `Switched to ${model}.`, handled: true, newModel: model };
|
|
99
|
+
});
|
|
100
|
+
register("compact", "Compress conversation history", (_args, ctx) => {
|
|
101
|
+
const before = ctx.messages.length;
|
|
102
|
+
// Keep system messages + last 10 messages, truncate old tool results
|
|
103
|
+
const compacted = [];
|
|
104
|
+
const keepLast = 10;
|
|
105
|
+
const messages = ctx.messages;
|
|
106
|
+
for (let i = 0; i < messages.length; i++) {
|
|
107
|
+
const msg = messages[i];
|
|
108
|
+
const isRecent = i >= messages.length - keepLast;
|
|
109
|
+
if (msg.role === "system") {
|
|
110
|
+
compacted.push(msg);
|
|
111
|
+
}
|
|
112
|
+
else if (isRecent) {
|
|
113
|
+
compacted.push(msg);
|
|
114
|
+
}
|
|
115
|
+
else if (msg.role === "tool") {
|
|
116
|
+
// Truncate old tool results
|
|
117
|
+
compacted.push({ ...msg, content: "[compacted]" });
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
compacted.push(msg);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
output: `Compacted: ${before} → ${compacted.length} messages. Old tool results truncated.`,
|
|
125
|
+
handled: true,
|
|
126
|
+
compactedMessages: compacted,
|
|
127
|
+
};
|
|
128
|
+
});
|
|
129
|
+
register("export", "Export conversation to file", (_args, ctx) => {
|
|
130
|
+
const lines = ctx.messages
|
|
131
|
+
.filter(m => m.role === "user" || m.role === "assistant")
|
|
132
|
+
.map(m => `${m.role === "user" ? "User" : "Assistant"}: ${m.content}`)
|
|
133
|
+
.join("\n\n");
|
|
134
|
+
const filename = `.oh/export-${ctx.sessionId}.md`;
|
|
135
|
+
try {
|
|
136
|
+
mkdirSync(dirname(filename), { recursive: true });
|
|
137
|
+
writeFileSync(filename, lines);
|
|
138
|
+
return { output: `Exported to ${filename}`, handled: true };
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return { output: `Export failed. Content:\n\n${lines.slice(0, 500)}`, handled: true };
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
register("config", "Show current configuration", () => {
|
|
145
|
+
return { output: "Use: oh config show (in a new terminal)", handled: true };
|
|
146
|
+
});
|
|
147
|
+
register("memory", "View memories", () => {
|
|
148
|
+
return { output: "Use: oh memory (in a new terminal)", handled: true };
|
|
149
|
+
});
|
|
150
|
+
register("plan", "Enter plan mode", () => {
|
|
151
|
+
return { output: "Plan mode: describe what you want to build. I'll create a plan before implementing.", handled: false };
|
|
152
|
+
});
|
|
153
|
+
register("review", "Review recent code changes", () => {
|
|
154
|
+
if (!isGitRepo()) {
|
|
155
|
+
return { output: "Not a git repository.", handled: true };
|
|
156
|
+
}
|
|
157
|
+
const diff = gitDiff();
|
|
158
|
+
if (!diff)
|
|
159
|
+
return { output: "No changes to review.", handled: true };
|
|
160
|
+
// Pass to LLM for review
|
|
161
|
+
return { output: "", handled: false };
|
|
162
|
+
});
|
|
163
|
+
// ── Command Parser ──
|
|
164
|
+
/**
|
|
165
|
+
* Check if input is a slash command. If so, execute it.
|
|
166
|
+
*/
|
|
167
|
+
export function processSlashCommand(input, context) {
|
|
168
|
+
const trimmed = input.trim();
|
|
169
|
+
if (!trimmed.startsWith("/"))
|
|
170
|
+
return null;
|
|
171
|
+
const spaceIdx = trimmed.indexOf(" ");
|
|
172
|
+
const name = (spaceIdx === -1 ? trimmed.slice(1) : trimmed.slice(1, spaceIdx)).toLowerCase();
|
|
173
|
+
const args = spaceIdx === -1 ? "" : trimmed.slice(spaceIdx + 1);
|
|
174
|
+
const cmd = commands.get(name);
|
|
175
|
+
if (!cmd) {
|
|
176
|
+
return {
|
|
177
|
+
output: `Unknown command: /${name}. Type /help for available commands.`,
|
|
178
|
+
handled: true,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
return cmd.handler(args, context);
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Get all registered command names (for autocomplete/display).
|
|
185
|
+
*/
|
|
186
|
+
export function getCommandNames() {
|
|
187
|
+
return [...commands.keys()];
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/components/App.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/components/App.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAOnD,KAAK,QAAQ,GAAG;IACd,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC;IACb,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC;CAC7B,CAAC;AAEF,QAAA,MAAM,qBAAqB,4PAEyB,CAAC;AAErD,MAAM,CAAC,OAAO,UAAU,GAAG,CAAC,EAC1B,QAAQ,EACR,KAAK,EACL,cAAc,EACd,YAAY,EACZ,KAAK,EACL,eAAe,GAChB,EAAE,QAAQ,2CA4BV;AAED,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
|