@charzhu/openjaw-agent 0.2.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 charzhu
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,546 @@
1
+ <div align="center">
2
+ <h1>🤖 OpenJaw Agent</h1>
3
+ <p><b>Autonomous Desktop AI Assistant — multi-provider, multi-channel, config-driven.</b></p>
4
+ <p>Runs independently in your terminal. No MCP server, no Claude Code, no Copilot CLI required.</p>
5
+ </div>
6
+
7
+ ---
8
+
9
+ ## What is OpenJaw Agent?
10
+
11
+ OpenJaw Agent is a **standalone AI assistant** that runs in your Windows terminal and can automate your entire desktop:
12
+
13
+ - 📧 **Email** — Read, compose, reply, forward, search (Outlook via COM)
14
+ - 💬 **Teams** — Send messages, read chats, monitor conversations (UIA automation)
15
+ - 💬 **WeChat** — Send messages, read chats via official iLink Bot API
16
+ - 🌐 **Browser** — Navigate, click, type, screenshot, extract content (Chrome CDP)
17
+ - 📄 **Office** — Word, Excel, PowerPoint automation (COM)
18
+ - 📁 **Files** — Read, write, edit, search, list, delete
19
+ - 🖥️ **System** — Run commands, clipboard, notifications, web search
20
+ - 🧠 **Memory** — Persistent hybrid-search memory, shared with MCP mode
21
+ - 🔌 **MCP** — Auto-discovers and connects to external MCP servers
22
+ - 🗣️ **Voice** — Text-to-speech (edge-tts) and speech-to-text input
23
+ - 🎓 **Skills** — 19 bundled skills for email drafting, research, document creation, and more
24
+
25
+ It connects to **Claude** or **GPT** via your proxy or API key, reasons about your request, picks the right tools, and executes them autonomously.
26
+
27
+ ### Multi-Channel Access
28
+
29
+ Beyond the terminal, the agent can be accessed through messaging bridges — all running the same agent loop with full tool access:
30
+
31
+ | Channel | Flag | How It Works |
32
+ |---------|------|-------------|
33
+ | **Terminal** | _(default)_ | New TUI built on React + vendored `@openjaw/ink`, with streaming, status bars, tool progress, and model/session controls |
34
+ | **Telegram** | `--telegram` | Long-polling bot — text, voice, photos. No public IP needed |
35
+ | **Telegram headless** | `--telegram --headless` | Telegram-only, no terminal UI |
36
+ | **Teams** | `--teams` | Self-chat bridge via Graph API. No bot registration needed |
37
+ | **Feishu (Lark)** | `--feishu` | WebSocket events via official SDK |
38
+ | **WeChat** | `--wechat` | iLink Bot API — QR login from iOS WeChat |
39
+ | **Legacy Ink UI** | `--legacy-ui` | Previous Ink UI (pre-rewrite) for A/B comparison |
40
+ | **Legacy REPL** | `--legacy` | Simple readline REPL |
41
+
42
+ Bridges run alongside the terminal UI (hybrid mode) or standalone (headless).
43
+
44
+ ### Terminal UI Architecture
45
+
46
+ The default terminal experience is the new TUI rewrite. `src/bootstrap.ts` initializes the in-process `AgentLoop`, tools, MCP, memory, voice, and bridge services; `src/eventBridge.ts` translates agent chunks into typed `GatewayEvent` objects; and `src/agentBus.ts` exposes a hermes-compatible `GatewayClient` event/RPC bus. `src/rpcHandlers.ts` serves the ported hermes hooks (`useMainApp`, `useSessionLifecycle`, `useSubmission`, and related hooks), while nanostores under `src/app/*` hold UI state for turns, overlays, selections, and delegation. React components in `src/components/*` render through the vendored `@openjaw/ink` renderer, a fork of hermes ink; see `packages/openjaw-ink/VENDOR.md` for provenance.
47
+
48
+ Use the default command for the new TUI, `--legacy-ui` to A/B test against the previous Ink UI, or `--legacy` for the readline REPL. See [`docs/TUI.md`](docs/TUI.md) for a concise map of the UI rewrite.
49
+
50
+ ## Quick Start
51
+
52
+ ### Prerequisites
53
+
54
+ - **Node.js 18+** — [Download](https://nodejs.org)
55
+ - **Windows 10/11** recommended (some automation tools require Windows; cross-platform basics work elsewhere)
56
+ - **LLM access** — Maestro proxy, Anthropic/OpenAI API keys, or GitHub Copilot via `/connect`
57
+
58
+ ### Install from npm (recommended)
59
+
60
+ ```bash
61
+ # Global install — exposes the `openjaw-agent` command on PATH
62
+ npm install -g @charzhu/openjaw-agent
63
+ openjaw-agent
64
+
65
+ # Or run on demand without installing
66
+ npx @charzhu/openjaw-agent
67
+ ```
68
+
69
+ The package ships a single bundled `dist/main.js` (no postinstall build step). After install, run `/connect` to pick a provider, then `/model` to pick a model.
70
+
71
+ ### Install from source (for contributors)
72
+
73
+ ```bash
74
+ git clone https://github.com/charzhu/openjaw.git
75
+ cd openjaw/openjaw-agent
76
+
77
+ # One-click install (builds openjaw core + agent, configures proxy)
78
+ install.bat
79
+
80
+ # Or manually:
81
+ cd ../openjaw-mcp && npm install && npm run build # build core first
82
+ cd ../openjaw-agent && npm install && npm run build
83
+ ```
84
+
85
+ ### Configure
86
+
87
+ For normal interactive use, you do not need to edit provider keys in YAML. Launch OpenJaw Agent, run `/connect` to pick Maestro, Anthropic, OpenAI, or GitHub Copilot, then run `/model` to choose from connected providers. `/connect` stores direct provider credentials in `~/.openjaw-agent/auth.json` and each provider context starts with a sensible default model.
88
+
89
+ `config.yaml` in the package directory, or `~/.openjaw-agent/config.yaml` after first run, is mainly for advanced defaults and non-interactive deployments:
90
+
91
+ ```yaml
92
+ llm:
93
+ provider: anthropic # updated by /connect
94
+ model: claude-sonnet-4-20250514 # updated by /model
95
+ api_key: proxy-token # placeholder; direct keys are stored by /connect
96
+ base_url: http://localhost:23333/api/anthropic # default Maestro proxy URL
97
+ max_tokens: 16384
98
+ temperature: 0.7
99
+ ```
100
+
101
+ Advanced OpenAI-compatible proxy tuning is still available with `openai_tool_mode: auto | compact | full` and `openai_max_tools`, but it is not part of the normal setup flow.
102
+
103
+ <details>
104
+ <summary>OpenAI configuration example</summary>
105
+
106
+ ```yaml
107
+ llm:
108
+ provider: openai
109
+ model: gpt-5.4
110
+ api_key: proxy-token # actual key is read from ~/.openjaw-agent/auth.json
111
+ max_tokens: 16384
112
+ temperature: 0.7
113
+ ```
114
+ </details>
115
+
116
+ For local proxy mode through Agent Maestro (`http://localhost:23333/api/anthropic` or `http://localhost:23333/api/openai`), use `/connect maestro`, then `/model` to choose a Maestro model. Maestro model selections use the local proxy and do not use Anthropic/OpenAI API keys stored by `/connect`. For OpenAI-compatible proxy requests, the default `openai_tool_mode: auto` sends a compact subset of tools instead of the full registry. All tools remain executable locally; the model can request additional tools with `openjaw_load_tools`. Use `openai_tool_mode: full` only for endpoints that reliably handle the full tool inventory.
117
+
118
+ <details>
119
+ <summary>Anthropic direct (no proxy) example</summary>
120
+
121
+ ```yaml
122
+ llm:
123
+ provider: anthropic
124
+ model: claude-sonnet-4-20250514
125
+ api_key: proxy-token # actual key is read from ~/.openjaw-agent/auth.json
126
+ max_tokens: 16384
127
+ temperature: 0.7
128
+ ```
129
+ </details>
130
+
131
+ <details>
132
+ <summary>Telegram bridge configuration</summary>
133
+
134
+ ```yaml
135
+ telegram:
136
+ token: "YOUR_BOT_TOKEN" # Get from @BotFather
137
+ allowed_users: [YOUR_USER_ID] # Get from @userinfobot
138
+ ```
139
+ </details>
140
+
141
+ <details>
142
+ <summary>Feishu (Lark) bridge configuration</summary>
143
+
144
+ ```yaml
145
+ feishu:
146
+ app_id: "YOUR_APP_ID"
147
+ app_secret: "YOUR_APP_SECRET"
148
+ allowed_users: ["open_id_1"] # Optional allowlist
149
+ ```
150
+ </details>
151
+
152
+ ### Run
153
+
154
+ ```bash
155
+ # Launch with the new TUI (default — React + @openjaw/ink)
156
+ openjawagent.bat
157
+ node dist/main.js
158
+
159
+ # A/B test against the previous Ink UI (pre-rewrite)
160
+ node dist/main.js --legacy-ui
161
+
162
+ # Launch with messaging bridges
163
+ node dist/main.js --telegram # New TUI + Telegram
164
+ node dist/main.js --telegram --headless # Telegram only
165
+ node dist/main.js --teams # New TUI + Teams self-chat
166
+ node dist/main.js --feishu # New TUI + Feishu
167
+ node dist/main.js --wechat # New TUI + WeChat
168
+
169
+ # Launch with legacy readline REPL
170
+ node dist/main.js --legacy
171
+ ```
172
+
173
+ ## Usage
174
+
175
+ ### Chat Naturally
176
+
177
+ Just type your request:
178
+
179
+ ```
180
+ ❯ read my latest emails and summarize them
181
+ ❯ send a teams message to PM Team Meeting saying "heading into meeting"
182
+ ❯ what did Chenlu say in Teams this week?
183
+ ❯ open the report in Excel and add a SUM formula in B10
184
+ ```
185
+
186
+ The agent reasons about your request, picks the right tools, executes them, and shows results with real-time feedback.
187
+
188
+ ### Commands
189
+
190
+ | Command | Description |
191
+ |---------|-------------|
192
+ | `/help` | Show all commands |
193
+ | `/model` | Switch LLM provider/model (interactive picker) |
194
+ | `/connect` | Connect/disconnect/list LLM provider contexts |
195
+ | `/schedule "prompt" every 15m` | Schedule recurring tasks |
196
+ | `/schedule list` | Show active scheduled tasks |
197
+ | `/schedule stop <id>` | Cancel a scheduled task |
198
+ | `/tools` | List all available tools |
199
+ | `/mcp` | Manage MCP server connections |
200
+ | `/memory` | Search persistent memory |
201
+ | `/voice` | Toggle voice input/output |
202
+ | `/clear` | Clear conversation history (new session) |
203
+ | `/exit` | Quit the agent |
204
+
205
+ ### Switch Models at Runtime
206
+
207
+ ```
208
+ ❯ /model
209
+ Current: anthropic/claude-sonnet-4-20250514
210
+
211
+ ? Select model (↑↓ to navigate, Enter to select):
212
+ ❯ anthropic/claude-opus-4.6
213
+ anthropic/claude-sonnet-4.6
214
+ anthropic/claude-sonnet-4-20250514
215
+ anthropic/claude-haiku-4.5
216
+ Maestro/gpt-5.4
217
+ Maestro/gpt-4.1
218
+ ...
219
+ ```
220
+
221
+ `/model` shows models from connected provider contexts only. If Maestro is connected, models are grouped under `Maestro` but still select the underlying `anthropic` or `openai` provider so the correct local proxy endpoint is used. Selection is saved to config and persists across restarts.
222
+
223
+ ### Connect Providers
224
+
225
+ Use `/connect` after launch to pick the active provider context. Direct provider credentials are stored locally under `~/.openjaw-agent/auth.json`; secrets are not written to the repo config or shown in status output. Selecting a provider also applies its default model, and `/model` can change it afterward.
226
+
227
+ For direct Anthropic/OpenAI usage, run:
228
+
229
+ ```
230
+ ❯ /connect anthropic <api-key>
231
+ ❯ /connect openai <api-key>
232
+ ```
233
+
234
+ The command stores the API key locally and switches the active provider context. Local Maestro proxy mode does not require these keys:
235
+
236
+ ```
237
+ ❯ /connect maestro
238
+ ```
239
+
240
+ OpenJaw Agent also supports GitHub Copilot as a first-class provider. The bundled Copilot client ID currently uses opencode's OAuth app because testing showed it exposes the full Copilot model list. You can override it with your organization's OAuth App client ID if needed.
241
+
242
+ ```yaml
243
+ llm:
244
+ provider: github-copilot
245
+ model: gpt-5.4
246
+ api_key: proxy-token
247
+ copilot_oauth_client_id: Ov23li8tweQw6odWQebz
248
+ ```
249
+
250
+ You can also override it with `GITHUB_COPILOT_CLIENT_ID` in the environment.
251
+
252
+ ```
253
+ ❯ /connect github-copilot
254
+ ```
255
+
256
+ The command prints a GitHub device-login URL and one-time code, waits for authorization, then stores the credential. For GitHub Enterprise:
257
+
258
+ ```
259
+ ❯ /connect github-copilot enterprise company.ghe.com
260
+ ```
261
+
262
+ Then switch models:
263
+
264
+ ```
265
+ ❯ /model github-copilot gpt-5.4
266
+ ```
267
+
268
+ Useful credential commands:
269
+
270
+ | Command | Description |
271
+ |---------|-------------|
272
+ | `/connect` | Show connected provider contexts and switch options |
273
+ | `/connect maestro` | Use local Maestro proxy with no API key |
274
+ | `/connect anthropic <api-key>` | Store an Anthropic API key and select Anthropic |
275
+ | `/connect openai <api-key>` | Store an OpenAI API key and select OpenAI |
276
+ | `/connect list` | List connected contexts and stored credentials without showing secrets |
277
+ | `/connect status` | Show credential store path and provider status |
278
+ | `/connect disconnect` | Pick a connected provider, including Maestro, to disconnect |
279
+
280
+ Copilot model discovery uses GitHub Copilot's `/models` endpoint when connected and falls back to a static catalog when offline. GPT models use Copilot's OpenAI-compatible endpoints; Copilot Claude models exposed through `/v1/messages` use the Anthropic-compatible shim.
281
+
282
+ ### Schedule Recurring Tasks
283
+
284
+ ```
285
+ ❯ /schedule "check my inbox for urgent emails" every 15m
286
+ ✓ Scheduled task #1: runs every 15 minutes
287
+
288
+ ❯ /schedule list
289
+ #1 every 15m runs: 3 last: 7:35 AM
290
+ "check my inbox for urgent emails"
291
+
292
+ ❯ /schedule stop 1
293
+ ✓ Task #1 stopped
294
+ ```
295
+
296
+ ### Sessions (Resume Conversations)
297
+
298
+ Sessions auto-save after each turn. Resume anytime:
299
+
300
+ ```bash
301
+ # List recent sessions
302
+ node dist/main.js --sessions
303
+
304
+ # Resume the most recent session
305
+ node dist/main.js --continue # or -c
306
+
307
+ # Resume a specific session
308
+ node dist/main.js --resume a1b2c3d4
309
+ ```
310
+
311
+ ### Skills
312
+
313
+ 19 bundled skills provide multi-step workflows that the agent can invoke:
314
+
315
+ | Skill | Description |
316
+ |-------|-------------|
317
+ | `daily-briefing` | Morning briefing from emails, calendar, Teams |
318
+ | `deep-research` | Multi-source web research with synthesis |
319
+ | `email-drafting` | Compose polished emails |
320
+ | `email-with-attachment` | Send emails with file attachments |
321
+ | `meeting-summarizer` | Summarize meeting transcripts |
322
+ | `create-docx` | Create Word documents |
323
+ | `create-pptx` | Create PowerPoint presentations |
324
+ | `create-pdf-report` | Generate PDF reports |
325
+ | `data-analysis` | Analyze datasets and create charts |
326
+ | `web-research` | Quick web lookups |
327
+ | `translation` | Multi-language translation |
328
+ | `proofreading` | Grammar and style review |
329
+ | `summarization` | Summarize long documents |
330
+ | `desktop-cleanup` | Organize files and desktop |
331
+ | `doc-coauthoring` | Co-author documents with edit tracking |
332
+ | `internal-comms` | Draft internal communications |
333
+ | `competitive-battlecard` | Competitive analysis documents |
334
+ | `skill-creator` | Create new custom skills |
335
+ | `refresh-token` | Refresh auth tokens for bridges |
336
+
337
+ Custom skills can be added to `~/.openjaw-agent/skills/` as Markdown files. User skills override bundled skills of the same name.
338
+
339
+ ## MCP Integration
340
+
341
+ OpenJaw Agent auto-discovers and connects to external MCP servers from 5 config sources (in priority order):
342
+
343
+ 1. `~/.openjaw-agent/mcp.json` — Agent's own config (always trusted)
344
+ 2. `.mcp.json` + parent directories — Claude Code project config
345
+ 3. `~/.copilot/mcp-config.json` — GitHub Copilot CLI config
346
+ 4. `~/.copilot/installed-plugins/` — Copilot marketplace plugins (WorkIQ, etc.)
347
+ 5. `.vscode/mcp.json` — VS Code config (normalized to standard format)
348
+
349
+ Supports **stdio**, **SSE**, and **Streamable HTTP** transports. Tools from external servers appear as `mcp__<server>__<tool>` and can be used alongside built-in tools.
350
+
351
+ Use `/mcp` to interactively manage connections — toggle servers, view tools, reconnect.
352
+
353
+ ## Architecture
354
+
355
+ ```
356
+ openjaw-agent/
357
+ ├── src/
358
+ │ ├── main.ts # CLI dispatch: new TUI default, --legacy-ui, --legacy
359
+ │ ├── entry.tsx # New TUI entry; renders React with @openjaw/ink
360
+ │ ├── bootstrap.ts # Initializes AgentLoop, tools, MCP, memory, voice, bridges
361
+ │ ├── agentBus.ts # In-process GatewayClient event/RPC bus
362
+ │ ├── agentEvents.ts # GatewayEvent type union for the ported UI
363
+ │ ├── eventBridge.ts # Converts AgentLoop chunks into GatewayEvents
364
+ │ ├── rpcHandlers.ts # Hermes-style RPC handlers for UI hooks
365
+ │ ├── app.tsx # New TUI root component
366
+ │ ├── app/ # Ported hermes hooks + nanostores UI state
367
+ │ │ ├── useMainApp.ts
368
+ │ │ ├── useSessionLifecycle.ts
369
+ │ │ ├── useSubmission.ts
370
+ │ │ └── uiStore.ts # Plus overlay/turn/delegation/input stores
371
+ │ ├── components/ # New TUI React components
372
+ │ │ ├── appChrome.tsx
373
+ │ │ ├── streamingAssistant.tsx
374
+ │ │ ├── sessionPicker.tsx
375
+ │ │ ├── modelPicker.tsx
376
+ │ │ └── todoPanel.tsx
377
+ │ ├── legacy-ink-ui.tsx # Previous Ink UI (--legacy-ui)
378
+ │ ├── agent-loop.ts # ReAct orchestrator (parallel tools, usage tracking)
379
+ │ ├── mcp-client.ts # MCP client — auto-discovers external servers
380
+ │ ├── bridges/
381
+ │ │ ├── telegram.ts # Telegram bot bridge (long-polling)
382
+ │ │ ├── teams.ts # Teams self-chat bridge (Graph API)
383
+ │ │ ├── feishu.ts # Feishu/Lark bridge (WebSocket)
384
+ │ │ ├── wechat.ts # WeChat iLink bridge (HTTP polling)
385
+ │ │ └── format.ts # Platform-specific message formatting
386
+ │ ├── voice/
387
+ │ │ ├── index.ts # Voice manager (enable/disable, settings)
388
+ │ │ ├── tts.ts # Text-to-speech (edge-tts)
389
+ │ │ └── stt.ts # Speech-to-text (Windows Speech Recognition)
390
+ │ ├── prompts/
391
+ │ │ ├── index.ts # Structured prompt assembly (static/dynamic boundary)
392
+ │ │ ├── sections.ts # Memoization framework + SYSTEM_PROMPT_DYNAMIC_BOUNDARY
393
+ │ │ ├── identity.ts # Static: agent persona
394
+ │ │ ├── reasoning.ts # Static: ReAct rules
395
+ │ │ ├── safety.ts # Static: safety guardrails
396
+ │ │ ├── computerUse.ts # Static: computer use guidelines
397
+ │ │ ├── user.ts # Dynamic: user preferences
398
+ │ │ ├── memory.ts # Dynamic: persistent memory
399
+ │ │ └── context.ts # Dynamic: runtime context
400
+ │ ├── providers/
401
+ │ │ ├── types.ts # LLMProvider + streaming + usage types
402
+ │ │ ├── anthropic.ts # Anthropic (cache_control, streaming, usage)
403
+ │ │ ├── openai.ts # OpenAI (Responses + Completions API, usage)
404
+ │ │ ├── cache-control.ts # System prompt → cache-scoped blocks
405
+ │ │ └── index.ts # Provider factory
406
+ │ ├── skills/
407
+ │ │ └── registry.ts # Skill discovery (bundled + user overrides)
408
+ │ ├── tools/
409
+ │ │ └── skill-tool.ts # LLM-callable skill invocation tool
410
+ │ ├── utils/
411
+ │ │ └── frontmatter.ts # Markdown frontmatter parser for skills
412
+ │ ├── cost-tracker.ts # Per-model pricing + session cost tracking
413
+ │ ├── context-manager.ts # Token estimation + context window warnings
414
+ │ ├── cache-monitor.ts # Prompt cache break detection between turns
415
+ │ ├── telemetry.ts # JSONL event logging (~/.openjaw-agent/telemetry/)
416
+ │ ├── config.ts # Config loader (~/.openjaw-agent/config.yaml)
417
+ │ ├── session.ts # Session persistence + resume
418
+ │ ├── scheduler.ts # Recurring task scheduler
419
+ │ ├── fork.ts # Background sub-agent spawning
420
+ │ ├── pet.ts # Pet companion system (Chinese mythical creatures)
421
+ │ ├── computer-use.ts # Anthropic computer use executor
422
+ │ ├── clipboard-image.ts # Windows clipboard image reader
423
+ │ ├── image-resize.ts # Image processing for vision APIs
424
+ │ └── repl.ts # Legacy readline REPL (--legacy mode)
425
+ ├── prompts/ # Markdown prompt files
426
+ │ ├── IDENTITY.md
427
+ │ ├── REASONING.md
428
+ │ ├── SAFETY.md
429
+ │ ├── COMPUTER_USE.md
430
+ │ └── USER.md
431
+ ├── skills/ # Bundled skill definitions (19 skills)
432
+ ├── docs/
433
+ │ └── TUI.md # Concise TUI rewrite overview
434
+ ├── packages/
435
+ │ └── openjaw-ink/ # Vendored @openjaw/ink renderer forked from @hermes/ink
436
+ ├── config.yaml # Bundled default config
437
+ ├── install.bat # One-click Windows installer
438
+ ├── openjawagent.bat # Launch script
439
+ ├── package.json
440
+ └── tsconfig.json
441
+ ```
442
+
443
+ ### Key Design Decisions
444
+
445
+ **TUI Rewrite** — The default UI is an in-process React TUI rendered by `@openjaw/ink`. `GatewayEvent` streaming and RPC handlers isolate AgentLoop/service logic from ported hermes hooks, while nanostores keep UI state small and composable. Use `--legacy-ui` for the previous Ink UI when comparing behavior.
446
+
447
+ **ReAct Loop** — The agent loop implements a Reasoning + Acting pattern: the LLM reasons about the request, selects tools, the loop executes them in parallel, feeds results back, and repeats until done.
448
+
449
+ **Prompt Caching** — The system prompt is split into **static** and **dynamic** sections separated by a boundary marker. Static sections (identity, reasoning, safety, computer use) get Anthropic's `cache_control: { type: 'ephemeral' }` for prompt caching. Dynamic sections (user profile, memory, context) are memoized per session. Cache breaks are tracked by `CacheMonitor` to surface cost spikes.
450
+
451
+ **Tool Permission Model** — Sensitive tools (shell commands, file deletion, file writes) trigger an interactive permission dialog. Users can approve once or allow-all for the session.
452
+
453
+ **Fork System** — The agent can spawn background sub-agents for parallel work. Forks share the parent's system prompt and tools but run with their own conversation history.
454
+
455
+ **Telemetry** — Every agent turn is logged as structured JSONL to `~/.openjaw-agent/telemetry/` with token counts, cost, duration, and cache metrics. Files rotate daily.
456
+
457
+ ### Provider Plugin Architecture
458
+
459
+ Adding a new LLM provider:
460
+
461
+ 1. Create `src/providers/yourprovider.ts` implementing `LLMProvider`
462
+ 2. Add `case 'yourprovider':` to `src/providers/index.ts`
463
+ 3. That's it — config-driven, no other changes needed
464
+
465
+ ### Shared Memory
466
+
467
+ Both OpenJaw Agent and OpenJaw MCP server share the same SQLite database at `~/.openjaw/memory.db`:
468
+
469
+ - Hybrid search: FTS5 keyword + Jaccard + HRR semantic similarity
470
+ - Searchable via `/memory` command or `memory_search` tool
471
+
472
+ No duplication — write from either mode, search from either mode.
473
+
474
+ ### No Conflicts with MCP Server
475
+
476
+ Both can run simultaneously:
477
+
478
+ | | MCP Server | Agent |
479
+ |-|-----------|-------|
480
+ | **Transport** | stdio (pipe) | terminal (readline/Ink) |
481
+ | **Ports** | none | none |
482
+ | **Config** | `~/.openjaw/config.yaml` | `~/.openjaw-agent/config.yaml` |
483
+ | **Memory** | `~/.openjaw/memory/` (shared) | `~/.openjaw/memory/` (shared) |
484
+ | **Sessions** | managed by host | `~/.openjaw-agent/sessions/` |
485
+ | **Telemetry** | — | `~/.openjaw-agent/telemetry/` |
486
+
487
+ ## Build from Source
488
+
489
+ ```bash
490
+ cd projects/openjaw-agent
491
+
492
+ # Install dependencies (includes openjaw core as local dependency)
493
+ npm install
494
+
495
+ # Build TypeScript
496
+ npm run build
497
+
498
+ # Run
499
+ node dist/main.js
500
+
501
+ # Or use the batch file
502
+ openjawagent.bat
503
+ ```
504
+
505
+ ### Development
506
+
507
+ ```bash
508
+ # Run in dev mode (tsx, no build needed)
509
+ npm run dev
510
+
511
+ # Rebuild after changes
512
+ npm run build
513
+ ```
514
+
515
+ ## CLI Reference
516
+
517
+ ```
518
+ openjaw-agent Start new session (new TUI)
519
+ openjaw-agent --legacy-ui Start previous Ink UI (pre-rewrite) for A/B comparison
520
+ openjaw-agent --legacy Start legacy readline REPL
521
+ openjaw-agent --resume <session-id> Resume a specific session
522
+ openjaw-agent --continue (-c) Resume the most recent session
523
+ openjaw-agent --sessions List recent sessions
524
+ openjaw-agent --telegram New TUI + Telegram bridge (hybrid)
525
+ openjaw-agent --telegram --headless Telegram only (no terminal UI)
526
+ openjaw-agent --teams New TUI + Teams self-chat bridge
527
+ openjaw-agent --feishu New TUI + Feishu bot bridge
528
+ openjaw-agent --wechat New TUI + WeChat iLink bridge
529
+ openjaw-agent --help Show help
530
+ ```
531
+
532
+ ## Environment Variables (Optional Overrides)
533
+
534
+ | Variable | Description |
535
+ |----------|-------------|
536
+ | `ANTHROPIC_API_KEY` | Anthropic API key (overrides config) |
537
+ | `ANTHROPIC_AUTH_TOKEN` | Anthropic auth token (for proxy) |
538
+ | `ANTHROPIC_BASE_URL` | Anthropic proxy URL |
539
+ | `OPENAI_API_KEY` | OpenAI API key (overrides config) |
540
+ | `OPENAI_BASE_URL` | OpenAI proxy URL |
541
+
542
+ Config file values are the default. Environment variables override when set.
543
+
544
+ ## License
545
+
546
+ Internal use only. Part of the [BravoPM](https://github.com/m365-core/bravopm) monorepo.
package/config.yaml ADDED
@@ -0,0 +1,72 @@
1
+ # OpenJaw Agent Configuration
2
+ # Recommended first-run flow:
3
+ # 1. Launch OpenJaw Agent.
4
+ # 2. Run /connect to pick Maestro, Anthropic, OpenAI, or GitHub Copilot.
5
+ # 3. Run /model to choose a model from connected providers.
6
+ #
7
+ # Edit this file only for advanced defaults or non-interactive deployments.
8
+ # After editing, restart the agent for changes to take effect.
9
+
10
+ llm:
11
+ # Provider: anthropic | openai | github-copilot
12
+ # /connect updates this automatically when you switch provider contexts.
13
+ provider: anthropic
14
+
15
+ # Model name (must match the provider's supported models).
16
+ # /connect picks a provider default; /model updates this interactively.
17
+ model: claude-sonnet-4-20250514
18
+
19
+ # API key placeholder.
20
+ # Direct Anthropic/OpenAI keys and Copilot OAuth tokens are stored by /connect
21
+ # in ~/.openjaw-agent/auth.json, not in this file.
22
+ api_key: proxy-token
23
+
24
+ # Default local Maestro Anthropic proxy endpoint.
25
+ # /connect maestro selects Maestro; /model chooses the exact Maestro model.
26
+ # Direct provider connections leave base_url empty.
27
+ base_url: http://localhost:23333/api/anthropic
28
+
29
+ # Max output tokens per response (16384 matches Claude Code default)
30
+ max_tokens: 16384
31
+
32
+ # Temperature (0.0 = deterministic, 1.0 = creative)
33
+ temperature: 0.7
34
+
35
+ # Optional advanced OpenAI proxy tool exposure:
36
+ # openai_tool_mode: auto # auto | compact | full
37
+ # openai_max_tools: 32
38
+
39
+ # Optional for provider: github-copilot with GitHub Enterprise.
40
+ # Usually set by /connect github-copilot enterprise <domain>.
41
+ # copilot_enterprise_url: company.ghe.com
42
+ #
43
+ # GitHub OAuth App client ID used by /connect github-copilot.
44
+ # Currently defaults to opencode's client ID because it exposes the full Copilot model list.
45
+ copilot_oauth_client_id: Ov23li8tweQw6odWQebz
46
+
47
+ # ─── Example: OpenAI direct (normally use: /connect openai <api-key>) ───
48
+ # llm:
49
+ # provider: openai
50
+ # model: gpt-5.4
51
+ # api_key: proxy-token # actual key is read from ~/.openjaw-agent/auth.json
52
+ # max_tokens: 4096
53
+ # temperature: 0.7
54
+
55
+ # ─── Example: GitHub Copilot ───
56
+ # First run: /connect github-copilot
57
+ # Enterprise: /connect github-copilot enterprise company.ghe.com
58
+ # llm:
59
+ # provider: github-copilot
60
+ # model: gpt-5.4
61
+ # api_key: proxy-token # token is read from ~/.openjaw-agent/auth.json
62
+ # copilot_oauth_client_id: Ov23li8tweQw6odWQebz
63
+ # max_tokens: 16384
64
+ # temperature: 0.7
65
+
66
+ # ─── Example: Anthropic direct (normally use: /connect anthropic <api-key>) ───
67
+ # llm:
68
+ # provider: anthropic
69
+ # model: claude-sonnet-4-20250514
70
+ # api_key: proxy-token # actual key is read from ~/.openjaw-agent/auth.json
71
+ # max_tokens: 4096
72
+ # temperature: 0.7