@zhijiewang/openharness 0.1.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.
- package/CHANGELOG.md +18 -0
- package/CONTRIBUTING.md +55 -0
- package/LICENSE +21 -0
- package/README.md +154 -0
- package/data/models.json +74 -0
- package/data/prompts/system.md +25 -0
- package/data/skills/code-review.md +19 -0
- package/data/skills/commit.md +17 -0
- package/data/skills/debug.md +24 -0
- package/data/skills/tdd.md +22 -0
- package/dist/Tool.d.ts +45 -0
- package/dist/Tool.d.ts.map +1 -0
- package/dist/Tool.js +62 -0
- package/dist/Tool.js.map +1 -0
- package/dist/components/App.d.ts +16 -0
- package/dist/components/App.d.ts.map +1 -0
- package/dist/components/App.js +25 -0
- package/dist/components/App.js.map +1 -0
- package/dist/components/Messages.d.ts +9 -0
- package/dist/components/Messages.d.ts.map +1 -0
- package/dist/components/Messages.js +23 -0
- package/dist/components/Messages.js.map +1 -0
- package/dist/components/PermissionPrompt.d.ts +9 -0
- package/dist/components/PermissionPrompt.d.ts.map +1 -0
- package/dist/components/PermissionPrompt.js +18 -0
- package/dist/components/PermissionPrompt.js.map +1 -0
- package/dist/components/REPL.d.ts +15 -0
- package/dist/components/REPL.d.ts.map +1 -0
- package/dist/components/REPL.js +114 -0
- package/dist/components/REPL.js.map +1 -0
- package/dist/components/Spinner.d.ts +7 -0
- package/dist/components/Spinner.d.ts.map +1 -0
- package/dist/components/Spinner.js +7 -0
- package/dist/components/Spinner.js.map +1 -0
- package/dist/components/TextInput.d.ts +7 -0
- package/dist/components/TextInput.d.ts.map +1 -0
- package/dist/components/TextInput.js +37 -0
- package/dist/components/TextInput.js.map +1 -0
- package/dist/components/ToolCallDisplay.d.ts +12 -0
- package/dist/components/ToolCallDisplay.d.ts.map +1 -0
- package/dist/components/ToolCallDisplay.js +16 -0
- package/dist/components/ToolCallDisplay.js.map +1 -0
- package/dist/harness/cost.d.ts +33 -0
- package/dist/harness/cost.d.ts.map +1 -0
- package/dist/harness/cost.js +68 -0
- package/dist/harness/cost.js.map +1 -0
- package/dist/harness/onboarding.d.ts +17 -0
- package/dist/harness/onboarding.d.ts.map +1 -0
- package/dist/harness/onboarding.js +99 -0
- package/dist/harness/onboarding.js.map +1 -0
- package/dist/harness/rules.d.ts +8 -0
- package/dist/harness/rules.d.ts.map +1 -0
- package/dist/harness/rules.js +66 -0
- package/dist/harness/rules.js.map +1 -0
- package/dist/harness/session.d.ts +24 -0
- package/dist/harness/session.d.ts.map +1 -0
- package/dist/harness/session.js +56 -0
- package/dist/harness/session.js.map +1 -0
- package/dist/main.d.ts +12 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +177 -0
- package/dist/main.js.map +1 -0
- package/dist/providers/anthropic.d.ts +27 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +291 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/base.d.ts +41 -0
- package/dist/providers/base.d.ts.map +1 -0
- package/dist/providers/base.js +5 -0
- package/dist/providers/base.js.map +1 -0
- package/dist/providers/index.d.ts +12 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +57 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/ollama.d.ts +19 -0
- package/dist/providers/ollama.d.ts.map +1 -0
- package/dist/providers/ollama.js +233 -0
- package/dist/providers/ollama.js.map +1 -0
- package/dist/providers/openai.d.ts +21 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +242 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/openrouter.d.ts +25 -0
- package/dist/providers/openrouter.d.ts.map +1 -0
- package/dist/providers/openrouter.js +278 -0
- package/dist/providers/openrouter.js.map +1 -0
- package/dist/query.d.ts +35 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +185 -0
- package/dist/query.js.map +1 -0
- package/dist/tools/BashTool/index.d.ts +15 -0
- package/dist/tools/BashTool/index.d.ts.map +1 -0
- package/dist/tools/BashTool/index.js +78 -0
- package/dist/tools/BashTool/index.js.map +1 -0
- package/dist/tools/FileEditTool/index.d.ts +21 -0
- package/dist/tools/FileEditTool/index.d.ts.map +1 -0
- package/dist/tools/FileEditTool/index.js +70 -0
- package/dist/tools/FileEditTool/index.js.map +1 -0
- package/dist/tools/FileReadTool/index.d.ts +18 -0
- package/dist/tools/FileReadTool/index.d.ts.map +1 -0
- package/dist/tools/FileReadTool/index.js +63 -0
- package/dist/tools/FileReadTool/index.js.map +1 -0
- package/dist/tools/FileWriteTool/index.d.ts +15 -0
- package/dist/tools/FileWriteTool/index.d.ts.map +1 -0
- package/dist/tools/FileWriteTool/index.js +42 -0
- package/dist/tools/FileWriteTool/index.js.map +1 -0
- package/dist/tools/GlobTool/index.d.ts +15 -0
- package/dist/tools/GlobTool/index.d.ts.map +1 -0
- package/dist/tools/GlobTool/index.js +126 -0
- package/dist/tools/GlobTool/index.js.map +1 -0
- package/dist/tools/GrepTool/index.d.ts +21 -0
- package/dist/tools/GrepTool/index.d.ts.map +1 -0
- package/dist/tools/GrepTool/index.js +125 -0
- package/dist/tools/GrepTool/index.js.map +1 -0
- package/dist/tools/WebFetchTool/index.d.ts +12 -0
- package/dist/tools/WebFetchTool/index.d.ts.map +1 -0
- package/dist/tools/WebFetchTool/index.js +98 -0
- package/dist/tools/WebFetchTool/index.js.map +1 -0
- package/dist/tools.d.ts +9 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +25 -0
- package/dist/tools.js.map +1 -0
- package/dist/types/events.d.ts +49 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +5 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/message.d.ts +27 -0
- package/dist/types/message.d.ts.map +1 -0
- package/dist/types/message.js +22 -0
- package/dist/types/message.js.map +1 -0
- package/dist/types/permissions.d.ts +22 -0
- package/dist/types/permissions.d.ts.map +1 -0
- package/dist/types/permissions.js +27 -0
- package/dist/types/permissions.js.map +1 -0
- package/package.json +55 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 (2026-04-01)
|
|
4
|
+
|
|
5
|
+
Initial alpha release. TypeScript rewrite.
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
- Single TypeScript process with React+Ink terminal UI
|
|
9
|
+
- Agent loop with async generator streaming (mirrors Claude Code's query.ts)
|
|
10
|
+
- 5 LLM providers: Ollama, OpenAI, Anthropic, OpenRouter, OpenAI-compatible
|
|
11
|
+
- 7 tools: Read, Edit, Write, Bash, Glob, Grep, WebFetch (all with Zod schemas)
|
|
12
|
+
- Permission gate with ask/trust/deny modes and risk-based tool approval
|
|
13
|
+
- Tool concurrency: read-only parallel, write serial
|
|
14
|
+
- Project rules (.oh/RULES.md)
|
|
15
|
+
- Cost tracking with per-model breakdown
|
|
16
|
+
- Session persistence
|
|
17
|
+
- Project auto-detection (15+ languages, 20+ frameworks)
|
|
18
|
+
- Global install: `npm install -g openharness` then just `oh`
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Contributing to OpenHarness
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in contributing.
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone https://github.com/zhijiewong/openharness.git
|
|
9
|
+
cd openharness
|
|
10
|
+
npm install
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Development
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx tsx src/main.tsx # run in dev mode
|
|
17
|
+
npx tsc --noEmit # type check
|
|
18
|
+
npm test # run tests
|
|
19
|
+
npm install -g . # install globally to test `oh` command
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Making Changes
|
|
23
|
+
|
|
24
|
+
1. Open an issue or discussion before starting large changes.
|
|
25
|
+
2. Create a branch from `main`.
|
|
26
|
+
3. Run `npx tsc --noEmit` and ensure zero errors before submitting a PR.
|
|
27
|
+
4. Keep the README and CLI help text in sync with code changes.
|
|
28
|
+
|
|
29
|
+
## Adding a New Provider
|
|
30
|
+
|
|
31
|
+
1. Create `src/providers/yourprovider.ts` implementing the `Provider` interface from `src/providers/base.ts`.
|
|
32
|
+
2. Implement `stream()`, `complete()`, `listModels()`, and `healthCheck()`.
|
|
33
|
+
3. Add a case in `src/providers/index.ts:createProviderInstance()`.
|
|
34
|
+
4. Add model pricing to `src/harness/cost.ts:MODEL_PRICING`.
|
|
35
|
+
|
|
36
|
+
## Adding a New Tool
|
|
37
|
+
|
|
38
|
+
1. Create `src/tools/YourTool/index.ts` implementing the `Tool` interface from `src/Tool.ts`.
|
|
39
|
+
2. Define a Zod input schema, set `name`, `description`, `riskLevel`.
|
|
40
|
+
3. Implement `call()`, `isReadOnly()`, `isConcurrencySafe()`, `prompt()`.
|
|
41
|
+
4. Register it in `src/tools.ts:getAllTools()`.
|
|
42
|
+
|
|
43
|
+
## Code Style
|
|
44
|
+
|
|
45
|
+
- TypeScript strict mode.
|
|
46
|
+
- Use Zod for all input validation.
|
|
47
|
+
- Async generators for streaming.
|
|
48
|
+
- No CLA required.
|
|
49
|
+
|
|
50
|
+
## Reporting Issues
|
|
51
|
+
|
|
52
|
+
Open an issue on GitHub with:
|
|
53
|
+
- What you expected vs what happened
|
|
54
|
+
- Steps to reproduce
|
|
55
|
+
- Node.js version and OS
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 wangz
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# OpenHarness
|
|
2
|
+
|
|
3
|
+
```
|
|
4
|
+
___
|
|
5
|
+
/ \
|
|
6
|
+
( ) ___ ___ ___ _ _ _ _ _ ___ _ _ ___ ___ ___
|
|
7
|
+
`~w~` / _ \| _ \| __| \| | || | /_\ | _ \ \| | __/ __/ __|
|
|
8
|
+
(( )) | (_) | _/| _|| .` | __ |/ _ \| / .` | _|\__ \__ \
|
|
9
|
+
))(( \___/|_| |___|_|\_|_||_/_/ \_\_|_\_|\_|___|___/___/
|
|
10
|
+
(( ))
|
|
11
|
+
`--`
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Open-source terminal coding agent. Build your own Claude Code with any LLM.
|
|
15
|
+
|
|
16
|
+

|
|
17
|
+

|
|
18
|
+

|
|
19
|
+

|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install -g openharness
|
|
27
|
+
oh
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
That's it. Just type `oh` to start chatting with your local Ollama model.
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
oh # auto-detect Ollama, start chatting
|
|
34
|
+
oh --model ollama/qwen2.5:7b # specific model
|
|
35
|
+
oh --model gpt-4o # use OpenAI (needs OPENAI_API_KEY)
|
|
36
|
+
oh --trust # auto-approve all tool calls
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Install
|
|
40
|
+
|
|
41
|
+
Requires **Node.js 18+**.
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# From npm (when published)
|
|
45
|
+
npm install -g openharness
|
|
46
|
+
|
|
47
|
+
# From source
|
|
48
|
+
git clone https://github.com/zhijiewong/openharness.git
|
|
49
|
+
cd openharness
|
|
50
|
+
npm install
|
|
51
|
+
npm install -g .
|
|
52
|
+
oh
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Why OpenHarness?
|
|
56
|
+
|
|
57
|
+
Claude Code is powerful but locked to Anthropic. OpenHarness gives you the same architecture -- React+Ink terminal UI, async generator agent loop, Zod tool schemas, permission gates -- but works with **any LLM**. Local models via Ollama (free, offline, private), or cloud APIs (OpenAI, Anthropic, OpenRouter, DeepSeek, Groq, and any OpenAI-compatible endpoint).
|
|
58
|
+
|
|
59
|
+
## Tools
|
|
60
|
+
|
|
61
|
+
| Tool | Risk | Description |
|
|
62
|
+
|------|------|-------------|
|
|
63
|
+
| Read | low | Read files with line ranges |
|
|
64
|
+
| Edit | medium | Search-and-replace edits |
|
|
65
|
+
| Write | medium | Create or overwrite files |
|
|
66
|
+
| Bash | high | Shell commands with timeout |
|
|
67
|
+
| Glob | low | Find files by pattern |
|
|
68
|
+
| Grep | low | Regex content search |
|
|
69
|
+
| WebFetch | medium | Fetch URL content |
|
|
70
|
+
|
|
71
|
+
Low-risk tools auto-approve. Medium and high risk require confirmation in `ask` mode.
|
|
72
|
+
|
|
73
|
+
## Commands
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
oh # start chatting (default command)
|
|
77
|
+
oh --model MODEL # use a specific model
|
|
78
|
+
oh --trust # auto-approve all tools
|
|
79
|
+
oh --deny # block all non-read tools
|
|
80
|
+
oh --resume ID # resume a saved session
|
|
81
|
+
oh models # list models and pricing
|
|
82
|
+
oh tools # list tools and risk levels
|
|
83
|
+
oh init # set up .oh/ for current project
|
|
84
|
+
oh sessions # list saved sessions
|
|
85
|
+
oh rules # show project rules
|
|
86
|
+
oh --version # show version
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Providers
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# Local (free, no API key)
|
|
93
|
+
oh --model ollama/llama3
|
|
94
|
+
oh --model ollama/qwen2.5:7b-instruct
|
|
95
|
+
|
|
96
|
+
# Cloud (set API key as env var)
|
|
97
|
+
OPENAI_API_KEY=sk-... oh --model gpt-4o
|
|
98
|
+
ANTHROPIC_API_KEY=sk-ant-... oh --model claude-sonnet-4-6
|
|
99
|
+
OPENROUTER_API_KEY=sk-or-... oh --model openrouter/deepseek-chat
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Project Rules
|
|
103
|
+
|
|
104
|
+
Create `.oh/RULES.md` in any repo (or run `oh init`):
|
|
105
|
+
|
|
106
|
+
```markdown
|
|
107
|
+
- Always run tests after changes
|
|
108
|
+
- Use strict TypeScript
|
|
109
|
+
- Never commit to main directly
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Rules load automatically into every session.
|
|
113
|
+
|
|
114
|
+
## Tech Stack
|
|
115
|
+
|
|
116
|
+
| | OpenHarness | Claude Code |
|
|
117
|
+
|---|---|---|
|
|
118
|
+
| Language | TypeScript (strict) | TypeScript (strict) |
|
|
119
|
+
| Runtime | Node.js 18+ | Bun |
|
|
120
|
+
| Terminal UI | React + Ink | React + custom Ink fork |
|
|
121
|
+
| Tool schemas | Zod | Zod |
|
|
122
|
+
| Agent loop | async generators | async generators |
|
|
123
|
+
| Providers | Any (5 built-in) | Anthropic only |
|
|
124
|
+
| License | MIT | Proprietary |
|
|
125
|
+
|
|
126
|
+
## Development
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
git clone https://github.com/zhijiewong/openharness.git
|
|
130
|
+
cd openharness
|
|
131
|
+
npm install
|
|
132
|
+
npx tsx src/main.tsx # run in dev mode
|
|
133
|
+
npx tsc --noEmit # type check
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Adding a provider
|
|
137
|
+
|
|
138
|
+
Create `src/providers/yourprovider.ts` implementing the `Provider` interface, add a case in `src/providers/index.ts`.
|
|
139
|
+
|
|
140
|
+
### Adding a tool
|
|
141
|
+
|
|
142
|
+
Create `src/tools/YourTool/index.ts` implementing the `Tool` interface with a Zod input schema, register it in `src/tools.ts`.
|
|
143
|
+
|
|
144
|
+
## Contributing
|
|
145
|
+
|
|
146
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
147
|
+
|
|
148
|
+
## License
|
|
149
|
+
|
|
150
|
+
MIT
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
This project is not affiliated with Anthropic.
|
package/data/models.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"gpt-4o": {
|
|
3
|
+
"provider": "openai",
|
|
4
|
+
"context_window": 128000,
|
|
5
|
+
"supports_tools": true,
|
|
6
|
+
"supports_vision": true,
|
|
7
|
+
"input_cost_per_mtok": 2.50,
|
|
8
|
+
"output_cost_per_mtok": 10.00
|
|
9
|
+
},
|
|
10
|
+
"gpt-4o-mini": {
|
|
11
|
+
"provider": "openai",
|
|
12
|
+
"context_window": 128000,
|
|
13
|
+
"supports_tools": true,
|
|
14
|
+
"supports_vision": true,
|
|
15
|
+
"input_cost_per_mtok": 0.15,
|
|
16
|
+
"output_cost_per_mtok": 0.60
|
|
17
|
+
},
|
|
18
|
+
"o3-mini": {
|
|
19
|
+
"provider": "openai",
|
|
20
|
+
"context_window": 200000,
|
|
21
|
+
"supports_tools": true,
|
|
22
|
+
"supports_vision": false,
|
|
23
|
+
"input_cost_per_mtok": 1.10,
|
|
24
|
+
"output_cost_per_mtok": 4.40
|
|
25
|
+
},
|
|
26
|
+
"claude-sonnet-4-6": {
|
|
27
|
+
"provider": "anthropic",
|
|
28
|
+
"context_window": 200000,
|
|
29
|
+
"supports_tools": true,
|
|
30
|
+
"supports_vision": true,
|
|
31
|
+
"input_cost_per_mtok": 3.00,
|
|
32
|
+
"output_cost_per_mtok": 15.00
|
|
33
|
+
},
|
|
34
|
+
"claude-haiku-4-5": {
|
|
35
|
+
"provider": "anthropic",
|
|
36
|
+
"context_window": 200000,
|
|
37
|
+
"supports_tools": true,
|
|
38
|
+
"supports_vision": true,
|
|
39
|
+
"input_cost_per_mtok": 0.80,
|
|
40
|
+
"output_cost_per_mtok": 4.00
|
|
41
|
+
},
|
|
42
|
+
"claude-opus-4-6": {
|
|
43
|
+
"provider": "anthropic",
|
|
44
|
+
"context_window": 200000,
|
|
45
|
+
"supports_tools": true,
|
|
46
|
+
"supports_vision": true,
|
|
47
|
+
"input_cost_per_mtok": 15.00,
|
|
48
|
+
"output_cost_per_mtok": 75.00
|
|
49
|
+
},
|
|
50
|
+
"deepseek-chat": {
|
|
51
|
+
"provider": "deepseek",
|
|
52
|
+
"context_window": 64000,
|
|
53
|
+
"supports_tools": true,
|
|
54
|
+
"supports_vision": false,
|
|
55
|
+
"input_cost_per_mtok": 0.14,
|
|
56
|
+
"output_cost_per_mtok": 0.28
|
|
57
|
+
},
|
|
58
|
+
"deepseek-coder": {
|
|
59
|
+
"provider": "deepseek",
|
|
60
|
+
"context_window": 64000,
|
|
61
|
+
"supports_tools": true,
|
|
62
|
+
"supports_vision": false,
|
|
63
|
+
"input_cost_per_mtok": 0.14,
|
|
64
|
+
"output_cost_per_mtok": 0.28
|
|
65
|
+
},
|
|
66
|
+
"qwen-turbo": {
|
|
67
|
+
"provider": "qwen",
|
|
68
|
+
"context_window": 128000,
|
|
69
|
+
"supports_tools": true,
|
|
70
|
+
"supports_vision": false,
|
|
71
|
+
"input_cost_per_mtok": 0.20,
|
|
72
|
+
"output_cost_per_mtok": 0.60
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
You are an AI coding assistant powered by OpenHarness. You help users with software engineering tasks by reading files, editing code, running commands, and managing their codebase.
|
|
2
|
+
|
|
3
|
+
# Core Principles
|
|
4
|
+
|
|
5
|
+
- Be concise and direct. Lead with the answer or action, not reasoning.
|
|
6
|
+
- Read code before suggesting changes. Understand existing patterns.
|
|
7
|
+
- Make the smallest change that solves the problem.
|
|
8
|
+
- Don't add features, refactoring, or improvements beyond what was asked.
|
|
9
|
+
- Don't add error handling for scenarios that can't happen.
|
|
10
|
+
- Prioritize writing safe, secure code. Watch for injection, XSS, and OWASP top 10.
|
|
11
|
+
|
|
12
|
+
# Tool Usage
|
|
13
|
+
|
|
14
|
+
- Use Read to examine files before editing them.
|
|
15
|
+
- Use Glob/Grep to find files and code patterns.
|
|
16
|
+
- Use Edit for targeted changes (not Write for modifying existing files).
|
|
17
|
+
- Use Bash for running tests, git commands, and system operations.
|
|
18
|
+
- Ask permission before destructive operations (delete, overwrite, force push).
|
|
19
|
+
|
|
20
|
+
# Working Style
|
|
21
|
+
|
|
22
|
+
- Break complex tasks into steps.
|
|
23
|
+
- Run tests after making changes.
|
|
24
|
+
- Use git to track progress on multi-step tasks.
|
|
25
|
+
- When stuck, explain what you tried and ask for guidance.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-review
|
|
3
|
+
description: Systematic code review for bugs, security, and quality
|
|
4
|
+
whenToUse: When reviewing code changes, PRs, or completed implementations
|
|
5
|
+
allowedTools: [Read, Glob, Grep, Bash]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Code Review
|
|
9
|
+
|
|
10
|
+
Review the code systematically for:
|
|
11
|
+
|
|
12
|
+
1. **Correctness** — Does the code do what it claims? Logic errors?
|
|
13
|
+
2. **Security** — SQL injection, XSS, command injection, path traversal, secrets in code?
|
|
14
|
+
3. **Error handling** — Are errors caught and handled appropriately?
|
|
15
|
+
4. **Edge cases** — Null/empty inputs, boundary conditions, concurrent access?
|
|
16
|
+
5. **Performance** — Unnecessary loops, missing indexes, N+1 queries?
|
|
17
|
+
6. **Readability** — Clear naming, reasonable complexity, adequate (not excessive) comments?
|
|
18
|
+
|
|
19
|
+
Report findings with file path, line number, severity (critical/warning/info), and suggested fix.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: commit
|
|
3
|
+
description: Create well-formed git commits
|
|
4
|
+
whenToUse: When the user asks to commit changes or create a PR
|
|
5
|
+
allowedTools: [Bash, Read, Glob]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Git Commit Workflow
|
|
9
|
+
|
|
10
|
+
1. Run `git status` and `git diff` to see what changed
|
|
11
|
+
2. Run `git log --oneline -5` to match the repo's commit message style
|
|
12
|
+
3. Stage specific files (not `git add -A`) to avoid committing secrets or binaries
|
|
13
|
+
4. Write a concise commit message:
|
|
14
|
+
- First line: imperative mood, under 72 chars, describes the "why"
|
|
15
|
+
- Body (if needed): explain context, not just what changed
|
|
16
|
+
5. Create the commit
|
|
17
|
+
6. Run `git status` to verify success
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: debug
|
|
3
|
+
description: Systematic debugging approach
|
|
4
|
+
whenToUse: When encountering any bug, test failure, or unexpected behavior
|
|
5
|
+
allowedTools: [Read, Bash, Grep, Glob]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Systematic Debugging
|
|
9
|
+
|
|
10
|
+
Follow this process:
|
|
11
|
+
|
|
12
|
+
1. **Reproduce** — Confirm the bug exists. Run the failing test or command.
|
|
13
|
+
2. **Read the error** — What does the error message actually say? Read the full stack trace.
|
|
14
|
+
3. **Locate** — Find the exact line where the error occurs. Read the surrounding code.
|
|
15
|
+
4. **Understand** — Why does this code produce the wrong result? Trace the data flow.
|
|
16
|
+
5. **Hypothesize** — Form a specific theory about the cause.
|
|
17
|
+
6. **Verify** — Test your theory with a minimal change or print statement.
|
|
18
|
+
7. **Fix** — Make the smallest change that fixes the bug.
|
|
19
|
+
8. **Confirm** — Run the test/command again to verify the fix works.
|
|
20
|
+
|
|
21
|
+
Rules:
|
|
22
|
+
- Don't guess. Read the error message carefully.
|
|
23
|
+
- Don't change multiple things at once.
|
|
24
|
+
- Don't skip the reproduce step.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tdd
|
|
3
|
+
description: Test-driven development workflow
|
|
4
|
+
whenToUse: When implementing any feature or bugfix, before writing implementation code
|
|
5
|
+
allowedTools: [Read, Edit, Write, Bash, Glob, Grep]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Test-Driven Development
|
|
9
|
+
|
|
10
|
+
Follow this workflow strictly:
|
|
11
|
+
|
|
12
|
+
1. **Write the test first** — Create a failing test that describes the expected behavior
|
|
13
|
+
2. **Run the test** — Verify it fails for the right reason
|
|
14
|
+
3. **Write minimal implementation** — Only enough code to make the test pass
|
|
15
|
+
4. **Run tests again** — Verify all tests pass
|
|
16
|
+
5. **Refactor** — Clean up the code while keeping tests green
|
|
17
|
+
|
|
18
|
+
Rules:
|
|
19
|
+
- Never write implementation before the test
|
|
20
|
+
- Each test should test one thing
|
|
21
|
+
- Keep tests fast and isolated
|
|
22
|
+
- Use descriptive test names that explain the behavior
|
package/dist/Tool.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool interface — mirrors Claude Code's Tool.ts pattern.
|
|
3
|
+
* Every tool implements this interface with Zod input validation.
|
|
4
|
+
*/
|
|
5
|
+
import type { z } from "zod";
|
|
6
|
+
import type { RiskLevel } from "./types/permissions.js";
|
|
7
|
+
export type ToolResult = {
|
|
8
|
+
output: string;
|
|
9
|
+
isError: boolean;
|
|
10
|
+
};
|
|
11
|
+
export type ToolContext = {
|
|
12
|
+
workingDir: string;
|
|
13
|
+
abortSignal?: AbortSignal;
|
|
14
|
+
};
|
|
15
|
+
export type Tool<Input extends z.ZodType = z.ZodType> = {
|
|
16
|
+
readonly name: string;
|
|
17
|
+
readonly description: string;
|
|
18
|
+
readonly inputSchema: Input;
|
|
19
|
+
readonly riskLevel: RiskLevel;
|
|
20
|
+
/** Whether this invocation is read-only (no side effects). */
|
|
21
|
+
isReadOnly(input: z.infer<Input>): boolean;
|
|
22
|
+
/** Whether this tool can run in parallel with other tools. */
|
|
23
|
+
isConcurrencySafe(input: z.infer<Input>): boolean;
|
|
24
|
+
/** Execute the tool. */
|
|
25
|
+
call(input: z.infer<Input>, context: ToolContext): Promise<ToolResult>;
|
|
26
|
+
/** Generate the prompt description for the LLM. */
|
|
27
|
+
prompt(): string;
|
|
28
|
+
};
|
|
29
|
+
export type Tools = Tool[];
|
|
30
|
+
/**
|
|
31
|
+
* Convert tool to the format expected by OpenAI-compatible APIs.
|
|
32
|
+
*/
|
|
33
|
+
export declare function toolToAPIFormat(tool: Tool): {
|
|
34
|
+
type: "function";
|
|
35
|
+
function: {
|
|
36
|
+
name: string;
|
|
37
|
+
description: string;
|
|
38
|
+
parameters: unknown;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Find a tool by name from a list of tools.
|
|
43
|
+
*/
|
|
44
|
+
export declare function findToolByName(tools: Tools, name: string): Tool | undefined;
|
|
45
|
+
//# sourceMappingURL=Tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tool.d.ts","sourceRoot":"","sources":["../src/Tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,IAAI,CAAC,KAAK,SAAS,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,IAAI;IACtD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,KAAK,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAE9B,8DAA8D;IAC9D,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC;IAE3C,8DAA8D;IAC9D,iBAAiB,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC;IAElD,wBAAwB;IACxB,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAEvE,mDAAmD;IACnD,MAAM,IAAI,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG,IAAI,EAAE,CAAC;AAE3B;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG;IAC3C,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE,CAAC;CACtE,CASA;AA4CD;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAE3E"}
|
package/dist/Tool.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool interface — mirrors Claude Code's Tool.ts pattern.
|
|
3
|
+
* Every tool implements this interface with Zod input validation.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Convert tool to the format expected by OpenAI-compatible APIs.
|
|
7
|
+
*/
|
|
8
|
+
export function toolToAPIFormat(tool) {
|
|
9
|
+
return {
|
|
10
|
+
type: "function",
|
|
11
|
+
function: {
|
|
12
|
+
name: tool.name,
|
|
13
|
+
description: tool.prompt(),
|
|
14
|
+
parameters: zodToJsonSchema(tool.inputSchema),
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Simple Zod-to-JSON-Schema converter for tool parameters.
|
|
20
|
+
* Handles the common cases (object, string, number, boolean, optional).
|
|
21
|
+
*/
|
|
22
|
+
function zodToJsonSchema(schema) {
|
|
23
|
+
// Zod provides .description and ._def for introspection
|
|
24
|
+
const def = schema._def;
|
|
25
|
+
if (def?.typeName === "ZodObject") {
|
|
26
|
+
const shape = schema.shape;
|
|
27
|
+
const properties = {};
|
|
28
|
+
const required = [];
|
|
29
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
30
|
+
const field = value;
|
|
31
|
+
const fieldDef = field._def;
|
|
32
|
+
if (fieldDef?.typeName === "ZodOptional") {
|
|
33
|
+
properties[key] = zodToJsonSchema(fieldDef.innerType);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
properties[key] = zodToJsonSchema(field);
|
|
37
|
+
required.push(key);
|
|
38
|
+
}
|
|
39
|
+
// Add description if present
|
|
40
|
+
if (field.description) {
|
|
41
|
+
properties[key].description = field.description;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return { type: "object", properties, required };
|
|
45
|
+
}
|
|
46
|
+
if (def?.typeName === "ZodString")
|
|
47
|
+
return { type: "string" };
|
|
48
|
+
if (def?.typeName === "ZodNumber")
|
|
49
|
+
return { type: "number" };
|
|
50
|
+
if (def?.typeName === "ZodBoolean")
|
|
51
|
+
return { type: "boolean" };
|
|
52
|
+
if (def?.typeName === "ZodArray")
|
|
53
|
+
return { type: "array", items: zodToJsonSchema(def.type) };
|
|
54
|
+
return { type: "string" }; // fallback
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Find a tool by name from a list of tools.
|
|
58
|
+
*/
|
|
59
|
+
export function findToolByName(tools, name) {
|
|
60
|
+
return tools.find((t) => t.name === name);
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=Tool.js.map
|
package/dist/Tool.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tool.js","sourceRoot":"","sources":["../src/Tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoCH;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,IAAU;IAIxC,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE;YACR,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,WAAW,EAAE,IAAI,CAAC,MAAM,EAAE;YAC1B,UAAU,EAAE,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC;SAC9C;KACF,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAS,eAAe,CAAC,MAAiB;IACxC,wDAAwD;IACxD,MAAM,GAAG,GAAI,MAAc,CAAC,IAAI,CAAC;IAEjC,IAAI,GAAG,EAAE,QAAQ,KAAK,WAAW,EAAE,CAAC;QAClC,MAAM,KAAK,GAAI,MAA2B,CAAC,KAAK,CAAC;QACjD,MAAM,UAAU,GAA4B,EAAE,CAAC;QAC/C,MAAM,QAAQ,GAAa,EAAE,CAAC;QAE9B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACjD,MAAM,KAAK,GAAG,KAAkB,CAAC;YACjC,MAAM,QAAQ,GAAI,KAAa,CAAC,IAAI,CAAC;YAErC,IAAI,QAAQ,EAAE,QAAQ,KAAK,aAAa,EAAE,CAAC;gBACzC,UAAU,CAAC,GAAG,CAAC,GAAG,eAAe,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;YACxD,CAAC;iBAAM,CAAC;gBACN,UAAU,CAAC,GAAG,CAAC,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;gBACzC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACrB,CAAC;YAED,6BAA6B;YAC7B,IAAK,KAAa,CAAC,WAAW,EAAE,CAAC;gBAC9B,UAAU,CAAC,GAAG,CAAS,CAAC,WAAW,GAAI,KAAa,CAAC,WAAW,CAAC;YACpE,CAAC;QACH,CAAC;QAED,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC;IAClD,CAAC;IAED,IAAI,GAAG,EAAE,QAAQ,KAAK,WAAW;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAC7D,IAAI,GAAG,EAAE,QAAQ,KAAK,WAAW;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAC7D,IAAI,GAAG,EAAE,QAAQ,KAAK,YAAY;QAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAC/D,IAAI,GAAG,EAAE,QAAQ,KAAK,UAAU;QAC9B,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;IAE7D,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,WAAW;AACxC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,KAAY,EAAE,IAAY;IACvD,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Provider } from "../providers/base.js";
|
|
2
|
+
import type { Tools } from "../Tool.js";
|
|
3
|
+
import type { PermissionMode } from "../types/permissions.js";
|
|
4
|
+
import type { Message } from "../types/message.js";
|
|
5
|
+
type AppProps = {
|
|
6
|
+
provider: Provider;
|
|
7
|
+
tools: Tools;
|
|
8
|
+
permissionMode: PermissionMode;
|
|
9
|
+
systemPrompt?: string;
|
|
10
|
+
model?: string;
|
|
11
|
+
initialMessages?: Message[];
|
|
12
|
+
};
|
|
13
|
+
declare const DEFAULT_SYSTEM_PROMPT = "You are OpenHarness, an AI coding assistant running in the user's terminal.\nYou have access to tools for reading, writing, and editing files, running shell commands, and searching the codebase.\nBe concise. Use tools proactively to help the user.";
|
|
14
|
+
export default function App({ provider, tools, permissionMode, systemPrompt, model, initialMessages, }: AppProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export { DEFAULT_SYSTEM_PROMPT };
|
|
16
|
+
//# sourceMappingURL=App.d.ts.map
|
|
@@ -0,0 +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;AAKnD,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,2CAyBV;AAED,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { loadRulesAsPrompt } from "../harness/rules.js";
|
|
4
|
+
import { detectProject, projectContextToPrompt } from "../harness/onboarding.js";
|
|
5
|
+
import REPL from "./REPL.js";
|
|
6
|
+
const DEFAULT_SYSTEM_PROMPT = `You are OpenHarness, an AI coding assistant running in the user's terminal.
|
|
7
|
+
You have access to tools for reading, writing, and editing files, running shell commands, and searching the codebase.
|
|
8
|
+
Be concise. Use tools proactively to help the user.`;
|
|
9
|
+
export default function App({ provider, tools, permissionMode, systemPrompt, model, initialMessages, }) {
|
|
10
|
+
// Build full system prompt with rules and project context
|
|
11
|
+
const fullSystemPrompt = useMemo(() => {
|
|
12
|
+
const parts = [systemPrompt || DEFAULT_SYSTEM_PROMPT];
|
|
13
|
+
const projectCtx = detectProject();
|
|
14
|
+
const projectPrompt = projectContextToPrompt(projectCtx);
|
|
15
|
+
if (projectPrompt)
|
|
16
|
+
parts.push(projectPrompt);
|
|
17
|
+
const rulesPrompt = loadRulesAsPrompt();
|
|
18
|
+
if (rulesPrompt)
|
|
19
|
+
parts.push(rulesPrompt);
|
|
20
|
+
return parts.join("\n\n");
|
|
21
|
+
}, [systemPrompt]);
|
|
22
|
+
return (_jsx(REPL, { provider: provider, tools: tools, permissionMode: permissionMode, systemPrompt: fullSystemPrompt, model: model, initialMessages: initialMessages }));
|
|
23
|
+
}
|
|
24
|
+
export { DEFAULT_SYSTEM_PROMPT };
|
|
25
|
+
//# sourceMappingURL=App.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"App.js","sourceRoot":"","sources":["../../src/components/App.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAKvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AACjF,OAAO,IAAI,MAAM,WAAW,CAAC;AAW7B,MAAM,qBAAqB,GAAG;;oDAEsB,CAAC;AAErD,MAAM,CAAC,OAAO,UAAU,GAAG,CAAC,EAC1B,QAAQ,EACR,KAAK,EACL,cAAc,EACd,YAAY,EACZ,KAAK,EACL,eAAe,GACN;IACT,0DAA0D;IAC1D,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,EAAE;QACpC,MAAM,KAAK,GAAa,CAAC,YAAY,IAAI,qBAAqB,CAAC,CAAC;QAEhE,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;QACnC,MAAM,aAAa,GAAG,sBAAsB,CAAC,UAAU,CAAC,CAAC;QACzD,IAAI,aAAa;YAAE,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAE7C,MAAM,WAAW,GAAG,iBAAiB,EAAE,CAAC;QACxC,IAAI,WAAW;YAAE,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAEzC,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;IAEnB,OAAO,CACL,KAAC,IAAI,IACH,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,KAAK,EACZ,cAAc,EAAE,cAAc,EAC9B,YAAY,EAAE,gBAAgB,EAC9B,KAAK,EAAE,KAAK,EACZ,eAAe,EAAE,eAAe,GAChC,CACH,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Message } from "../types/message.js";
|
|
2
|
+
import type { ToolCallState } from "./ToolCallDisplay.js";
|
|
3
|
+
type MessagesProps = {
|
|
4
|
+
messages: Message[];
|
|
5
|
+
toolCalls: Map<string, ToolCallState>;
|
|
6
|
+
};
|
|
7
|
+
export default function Messages({ messages, toolCalls }: MessagesProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=Messages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Messages.d.ts","sourceRoot":"","sources":["../../src/components/Messages.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAG1D,KAAK,aAAa,GAAG;IACnB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CACvC,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,aAAa,2CAQtE"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from "ink";
|
|
3
|
+
import ToolCallDisplay from "./ToolCallDisplay.js";
|
|
4
|
+
export default function Messages({ messages, toolCalls }) {
|
|
5
|
+
return (_jsx(Box, { flexDirection: "column", children: messages.map((msg) => (_jsx(MessageRow, { message: msg, toolCalls: toolCalls }, msg.uuid))) }));
|
|
6
|
+
}
|
|
7
|
+
function MessageRow({ message, toolCalls, }) {
|
|
8
|
+
const { role, content } = message;
|
|
9
|
+
if (role === "user") {
|
|
10
|
+
return (_jsxs(Box, { marginY: 0, children: [_jsx(Text, { color: "cyan", bold: true, children: "❯ " }), _jsx(Text, { bold: true, children: content })] }));
|
|
11
|
+
}
|
|
12
|
+
if (role === "assistant") {
|
|
13
|
+
return (_jsxs(Box, { flexDirection: "column", marginY: 0, children: [content ? (_jsxs(Box, { children: [_jsx(Text, { color: "magenta", bold: true, children: "◆ " }), _jsx(Text, { children: content })] })) : null, message.toolCalls?.map((tc) => {
|
|
14
|
+
const state = toolCalls.get(tc.id);
|
|
15
|
+
return state ? _jsx(ToolCallDisplay, { toolCall: state }, tc.id) : null;
|
|
16
|
+
})] }));
|
|
17
|
+
}
|
|
18
|
+
if (role === "tool") {
|
|
19
|
+
return null; // Tool results shown inline via ToolCallDisplay
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=Messages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Messages.js","sourceRoot":"","sources":["../../src/components/Messages.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAGhC,OAAO,eAAe,MAAM,sBAAsB,CAAC;AAOnD,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAiB;IACrE,OAAO,CACL,KAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,YACxB,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACrB,KAAC,UAAU,IAAgB,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,IAA5C,GAAG,CAAC,IAAI,CAAwC,CAClE,CAAC,GACE,CACP,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,EAClB,OAAO,EACP,SAAS,GAIV;IACC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAElC,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,OAAO,CACL,MAAC,GAAG,IAAC,OAAO,EAAE,CAAC,aACb,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,EAAC,IAAI,kBAAE,IAAI,GAAQ,EACrC,KAAC,IAAI,IAAC,IAAI,kBAAE,OAAO,GAAQ,IACvB,CACP,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;QACzB,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,OAAO,EAAE,CAAC,aACnC,OAAO,CAAC,CAAC,CAAC,CACT,MAAC,GAAG,eACF,KAAC,IAAI,IAAC,KAAK,EAAC,SAAS,EAAC,IAAI,kBAAE,IAAI,GAAQ,EACxC,KAAC,IAAI,cAAE,OAAO,GAAQ,IAClB,CACP,CAAC,CAAC,CAAC,IAAI,EACP,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;oBAC7B,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;oBACnC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAC,eAAe,IAAa,QAAQ,EAAE,KAAK,IAAtB,EAAE,CAAC,EAAE,CAAqB,CAAC,CAAC,CAAC,IAAI,CAAC;gBACzE,CAAC,CAAC,IACE,CACP,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC,CAAC,gDAAgD;IAC/D,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
type PermissionPromptProps = {
|
|
2
|
+
toolName: string;
|
|
3
|
+
description: string;
|
|
4
|
+
riskLevel: string;
|
|
5
|
+
onResolve: (allowed: boolean) => void;
|
|
6
|
+
};
|
|
7
|
+
export default function PermissionPrompt({ toolName, description, riskLevel, onResolve, }: PermissionPromptProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=PermissionPrompt.d.ts.map
|