hyperclaw 5.2.1 → 5.2.2

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/README.md CHANGED
@@ -1,3 +1,4 @@
1
+ <a name="top"></a>
1
2
  <div align="center">
2
3
  <img src="assets/icon.png" width="140" alt="HyperClaw">
3
4
  <h1>🦅 HyperClaw</h1>
@@ -34,6 +35,28 @@
34
35
 
35
36
  ---
36
37
 
38
+ ## 📋 Table of Contents
39
+
40
+ | | |
41
+ |---|---|
42
+ | [Why HyperClaw?](#why-hyperclaw) | [Use cases](#use-cases) |
43
+ | [Screenshots](#screenshots) | [🚀 Get started in 60 seconds](#-get-started-in-60-seconds) |
44
+ | [▶️ Running your bot](#️-running-your-bot) | [Channels](#channels) |
45
+ | [Architecture](#architecture) | [AI Models](#ai-models) |
46
+ | [Channels](#channels) | [Configuration](#configuration) |
47
+ | [Security defaults](#security-defaults) | [Features](#features) |
48
+ | [Apps (optional)](#apps-optional) | [Integrations (Skills & Tools)](#integrations-skills--tools) |
49
+ | [Agent-to-Agent](#agent-to-agent-sessions-tools) | [Terminal chat](#terminal-chat-hyperclaw-chat) |
50
+ | [Chat commands](#chat-commands) | [SkillHub](#skillhub) |
51
+ | [HyperClaw Bot commands](#hyperclaw-bot-commands) | [From source](#from-source) |
52
+ | [Docker](#docker) | [Monorepo structure](#monorepo-structure) |
53
+ | [Documentation](#documentation) | [Contributing](#contributing) |
54
+ | [Roadmap](#roadmap) | [Changelog](#changelog) |
55
+ | [Community](#community) | [License](#license) |
56
+
57
+ <div align="right"><a href="#top">▲ Back to top</a></div>
58
+ ---
59
+
37
60
  ## Why HyperClaw?
38
61
 
39
62
  | Feature | HyperClaw | Cloud assistants | Self-hosted alternatives |
@@ -51,6 +74,7 @@
51
74
  | One-command wizard (`hyperclaw onboard`) | ✅ | — | ❌ |
52
75
  | OSINT / Ethical hacking mode (`hyperclaw osint`) | ✅ | ❌ | ❌ |
53
76
 
77
+ <div align="right"><a href="#top">▲ Back to top</a></div>
54
78
  ---
55
79
 
56
80
  ## Use cases
@@ -66,6 +90,129 @@
66
90
 
67
91
  > HyperClaw runs **locally on your machine** — your data, your keys, your control.
68
92
 
93
+ <div align="right"><a href="#top">▲ Back to top</a></div>
94
+
95
+ ---
96
+
97
+ ## Screenshots
98
+
99
+ ### Main banner (`hyperclaw`)
100
+
101
+ <div align="center">
102
+ <img src="assets/screenshot-banner.png" width="700" alt="HyperClaw main banner with quick actions">
103
+ </div>
104
+
105
+ ---
106
+
107
+ ### Setup wizard — start (`hyperclaw onboard`)
108
+
109
+ <div align="center">
110
+ <img src="assets/screenshot-onboard-start.png" width="700" alt="HyperClaw onboard wizard start">
111
+ </div>
112
+
113
+ ---
114
+
115
+ ### Setup wizard — AI providers
116
+
117
+ <div align="center">
118
+ <img src="assets/screenshot-onboard-providers.png" width="700" alt="HyperClaw onboard AI provider selection">
119
+ </div>
120
+
121
+ ---
122
+
123
+ ### Setup wizard — API key step
124
+
125
+ <div align="center">
126
+ <img src="assets/screenshot-onboard-apikey.png" width="700" alt="HyperClaw onboard API key entry">
127
+ </div>
128
+
129
+ ---
130
+
131
+ ### Daemon install mode (`hyperclaw onboard --install-daemon`)
132
+
133
+ <div align="center">
134
+ <img src="assets/screenshot-onboard-daemon.png" width="700" alt="HyperClaw daemon install mode">
135
+ </div>
136
+
137
+ ---
138
+
139
+ ### Security notice
140
+
141
+ <div align="center">
142
+ <img src="assets/screenshot-security-notice.png" width="700" alt="HyperClaw security notice screen">
143
+ </div>
144
+
145
+ ---
146
+
147
+ ### Theme selection
148
+
149
+ <div align="center">
150
+ <img src="assets/screenshot-theme-select.png" width="700" alt="HyperClaw color theme selector">
151
+ </div>
152
+
153
+ ---
154
+
155
+ ### Gateway Dashboard (`hyperclaw dashboard`)
156
+
157
+ <div align="center">
158
+ <img src="assets/screenshot-dashboard.png" width="700" alt="HyperClaw Gateway Dashboard TUI">
159
+ </div>
160
+
161
+ > Live status, active channels, installed skills, and logs. Press `[d]` daemon · `[h]` hub · `[g]` gateway · `[m]` memory · `[q]` quit.
162
+
163
+ ---
164
+
165
+ ### Terminal chat (`hyperclaw chat`)
166
+
167
+ <div align="center">
168
+ <img src="assets/screenshot-chat.png" width="700" alt="HyperClaw terminal chat interface">
169
+ </div>
170
+
171
+ ---
172
+
173
+ ### All commands (`hyperclaw --help`)
174
+
175
+ <div align="center">
176
+ <img src="assets/screenshot-help.png" width="700" alt="HyperClaw --help output showing all commands">
177
+ </div>
178
+
179
+ ---
180
+
181
+ ### System status (`hyperclaw status`)
182
+
183
+ <div align="center">
184
+ <img src="assets/screenshot-status.png" width="700" alt="HyperClaw status output">
185
+ </div>
186
+
187
+ ---
188
+
189
+ ### Health check (`hyperclaw health`)
190
+
191
+ <div align="center">
192
+ <img src="assets/screenshot-health.png" width="700" alt="HyperClaw health check output">
193
+ </div>
194
+
195
+ ---
196
+
197
+ ### Security tools (`hyperclaw security`)
198
+
199
+ <div align="center">
200
+ <img src="assets/screenshot-security.png" width="700" alt="HyperClaw security tools">
201
+ </div>
202
+
203
+ ---
204
+
205
+ ### OSINT / Ethical Hacking mode (`hyperclaw osint`)
206
+
207
+ <div align="center">
208
+ <img src="assets/screenshot-osint.png" width="700" alt="HyperClaw OSINT mode with recon, bugbounty, pentest workflows">
209
+ </div>
210
+
211
+ > Passive recon, bug bounty, pentest, digital footprint — all from your terminal.
212
+ > For authorized security research only.
213
+
214
+ <div align="right"><a href="#top">▲ Back to top</a></div>
215
+
69
216
  ---
70
217
 
71
218
  ## 🚀 Get started in 60 seconds
@@ -305,6 +452,7 @@ brew install --cask iterm2
305
452
 
306
453
  </details>
307
454
 
455
+ <div align="right"><a href="#top">▲ Back to top</a></div>
308
456
  ---
309
457
 
310
458
  ## Channels
@@ -350,6 +498,7 @@ Add a channel:
350
498
  hyperclaw channels add telegram
351
499
  ```
352
500
 
501
+ <div align="right"><a href="#top">▲ Back to top</a></div>
353
502
  ---
354
503
 
355
504
  ## Architecture
@@ -374,6 +523,7 @@ Google Chat / Matrix / IRC / Mattermost / Teams / Nostr / WebChat
374
523
  OpenAI…)
375
524
  ```
376
525
 
526
+ <div align="right"><a href="#top">▲ Back to top</a></div>
377
527
  ---
378
528
 
379
529
  ## AI Models
@@ -401,6 +551,7 @@ HyperClaw supports 20+ providers. Pick one in the wizard or set `provider.provid
401
551
  | **LM Studio** | `lmstudio` | Local models — enable local server |
402
552
  | **Custom** | `custom` | Any OpenAI-compatible `/chat/completions` |
403
553
 
554
+ <div align="right"><a href="#top">▲ Back to top</a></div>
404
555
  ---
405
556
 
406
557
  ## Configuration
@@ -475,6 +626,7 @@ Isolate DM sessions per channel/peer (useful when multiple people share one gate
475
626
  }
476
627
  ```
477
628
 
629
+ <div align="right"><a href="#top">▲ Back to top</a></div>
478
630
  ---
479
631
 
480
632
  ## Security defaults
@@ -499,6 +651,7 @@ hyperclaw security audit --json # machine-readable output
499
651
 
500
652
  Full guide: [docs/security.md](docs/security.md)
501
653
 
654
+ <div align="right"><a href="#top">▲ Back to top</a></div>
502
655
  ---
503
656
 
504
657
  ## Features
@@ -520,6 +673,7 @@ Full guide: [docs/security.md](docs/security.md)
520
673
  - **Docker** — sandboxed agent execution, browser tools with Puppeteer
521
674
  - **Tailscale** — Serve/Funnel for remote access without port forwarding
522
675
 
676
+ <div align="right"><a href="#top">▲ Back to top</a></div>
523
677
  ---
524
678
 
525
679
  ## Apps (optional)
@@ -545,6 +699,7 @@ The Gateway alone delivers a great experience. Apps add extra features:
545
699
  - Camera, screen capture, device commands
546
700
  - Notifications, contacts, calendar, photos
547
701
 
702
+ <div align="right"><a href="#top">▲ Back to top</a></div>
548
703
  ---
549
704
 
550
705
  ## Development channels
@@ -563,6 +718,7 @@ hyperclaw update --channel dev # moving head of main
563
718
  | `beta` | `beta` | Prerelease — new features, may have rough edges |
564
719
  | `dev` | `dev` | Latest main branch (when published) |
565
720
 
721
+ <div align="right"><a href="#top">▲ Back to top</a></div>
566
722
  ---
567
723
 
568
724
  ## Integrations (Skills & Tools)
@@ -678,6 +834,7 @@ OP_SERVICE_ACCOUNT_TOKEN=ops_xxxx
678
834
 
679
835
  All keys are stored locally in `~/.hyperclaw/.env` — never sent anywhere except the respective service.
680
836
 
837
+ <div align="right"><a href="#top">▲ Back to top</a></div>
681
838
  ---
682
839
 
683
840
  ## Agent-to-Agent (sessions tools)
@@ -695,6 +852,7 @@ Example — ask the agent:
695
852
  "List all connected sessions and send a briefing to the first one"
696
853
  ```
697
854
 
855
+ <div align="right"><a href="#top">▲ Back to top</a></div>
698
856
  ---
699
857
 
700
858
  ## Terminal chat (`hyperclaw chat`)
@@ -720,6 +878,7 @@ hyperclaw chat --model claude-opus-4-6 # override model
720
878
 
721
879
  Responses stream token-by-token as they are generated. The full conversation history is kept for the entire session (true multi-turn context).
722
880
 
881
+ <div align="right"><a href="#top">▲ Back to top</a></div>
723
882
  ---
724
883
 
725
884
  ## Chat commands
@@ -818,6 +977,7 @@ The agent can create fully custom skills on demand:
818
977
 
819
978
  Skills are saved to `~/.hyperclaw/workspace/skills/{id}/` and loaded on the next message.
820
979
 
980
+ <div align="right"><a href="#top">▲ Back to top</a></div>
821
981
  ---
822
982
 
823
983
  ## HyperClaw Bot commands
@@ -857,6 +1017,7 @@ node dist/run-main.js onboard
857
1017
  npm run gateway:watch
858
1018
  ```
859
1019
 
1020
+ <div align="right"><a href="#top">▲ Back to top</a></div>
860
1021
  ---
861
1022
 
862
1023
  ## Docker
@@ -889,6 +1050,7 @@ docker compose --profile full up -d
889
1050
 
890
1051
  See [`docker-compose.yml`](docker-compose.yml) and [`env.example`](env.example) for all options.
891
1052
 
1053
+ <div align="right"><a href="#top">▲ Back to top</a></div>
892
1054
  ---
893
1055
 
894
1056
  ## Monorepo structure
@@ -927,6 +1089,7 @@ hyperclaw/
927
1089
  └── docs/ # Full documentation
928
1090
  ```
929
1091
 
1092
+ <div align="right"><a href="#top">▲ Back to top</a></div>
930
1093
  ---
931
1094
 
932
1095
  ## Documentation
@@ -978,6 +1141,49 @@ hyperclaw/
978
1141
  | Troubleshooting | [docs/troubleshooting.md](docs/troubleshooting.md) |
979
1142
  | Contributing | [docs/contributing.md](docs/contributing.md) |
980
1143
 
1144
+ <div align="right"><a href="#top">▲ Back to top</a></div>
1145
+
1146
+ ---
1147
+
1148
+ ## Roadmap
1149
+
1150
+ > See [ROADMAP.md](ROADMAP.md) for the full plan.
1151
+
1152
+ | Status | Feature |
1153
+ |--------|---------|
1154
+ | ✅ Done | 28+ messaging channels |
1155
+ | ✅ Done | Config hot-reload |
1156
+ | ✅ Done | MCP (Model Context Protocol) |
1157
+ | ✅ Done | OSINT / Ethical hacking mode |
1158
+ | ✅ Done | Docker sandboxing |
1159
+ | ✅ Done | TUI dashboard |
1160
+ | ✅ Done | macOS / iOS / Android companion apps |
1161
+ | 🔄 In progress | Web UI (browser-based dashboard) |
1162
+ | 🔄 In progress | Skill marketplace (HyperClaw Hub) |
1163
+ | 📅 Planned | Voice-first mode (always-on mic) |
1164
+ | 📅 Planned | Multi-agent collaboration |
1165
+ | 📅 Planned | Fine-tuned HyperClaw model |
1166
+ | 📅 Planned | One-click cloud deploy (Railway / Render) |
1167
+
1168
+ <div align="right"><a href="#top">▲ Back to top</a></div>
1169
+
1170
+ ---
1171
+
1172
+ ## Changelog
1173
+
1174
+ > Full history in [CHANGELOG.md](CHANGELOG.md).
1175
+
1176
+ | Version | Highlights |
1177
+ |---------|-----------|
1178
+ | **v5.2.1** | Fix postinstall BOM, clean package-lock, nav links in all docs |
1179
+ | **v5.2.0** | MCP custom servers, OSINT mode, Tlon/Urbit integration |
1180
+ | **v5.1.0** | Config hot-reload, trustedProxies, session.dmScope, Google Chat guide |
1181
+ | **v5.0.7** | Groq model IDs fix, Cohere/HuggingFace baseUrl corrections |
1182
+ | **v5.0.0** | Major rewrite — monorepo, tsdown bundler, 20+ AI providers |
1183
+ | **v4.0.0** | Initial public release |
1184
+
1185
+ <div align="right"><a href="#top">▲ Back to top</a></div>
1186
+
981
1187
  ---
982
1188
 
983
1189
  ## Contributing
@@ -987,6 +1193,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. AI/vibe-coded PRs welcome
987
1193
  Found a bug? [Open an issue](https://github.com/mylo-2001/hyperclaw/issues/new/choose).
988
1194
  Found a vulnerability? Email [securityhyperclaw.ai@gmail.com](mailto:securityhyperclaw.ai@gmail.com) — we respond within 48 h.
989
1195
 
1196
+ <div align="right"><a href="#top">▲ Back to top</a></div>
990
1197
  ---
991
1198
 
992
1199
  ## Community
@@ -997,6 +1204,22 @@ Found a vulnerability? Email [securityhyperclaw.ai@gmail.com](mailto:securityhyp
997
1204
  | 🐛 **Bug reports** | [GitHub Issues](https://github.com/mylo-2001/hyperclaw/issues) — templates for bugs & features |
998
1205
  | 🔒 **Security** | [SECURITY.md](SECURITY.md) — responsible disclosure |
999
1206
 
1207
+ ### Contributors
1208
+
1209
+ <a href="https://github.com/mylo-2001/hyperclaw/graphs/contributors">
1210
+ <img src="https://contrib.rocks/image?repo=mylo-2001/hyperclaw" alt="Contributors" />
1211
+ </a>
1212
+
1213
+ ### Star History
1214
+
1215
+ <a href="https://star-history.com/#mylo-2001/hyperclaw&Date">
1216
+ <picture>
1217
+ <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=mylo-2001/hyperclaw&type=Date&theme=dark" />
1218
+ <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=mylo-2001/hyperclaw&type=Date" />
1219
+ <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=mylo-2001/hyperclaw&type=Date" />
1220
+ </picture>
1221
+ </a>
1222
+
1000
1223
  ---
1001
1224
 
1002
1225
  <div align="center">
@@ -1007,6 +1230,7 @@ Found a vulnerability? Email [securityhyperclaw.ai@gmail.com](mailto:securityhyp
1007
1230
 
1008
1231
  </div>
1009
1232
 
1233
+ <div align="right"><a href="#top">▲ Back to top</a></div>
1010
1234
  ---
1011
1235
 
1012
1236
  ## License
@@ -0,0 +1,324 @@
1
+ const require_chunk = require('./chunk-jS-bbMI5.js');
2
+ const require_paths = require('./paths-AIyBxIzm.js');
3
+ require('./browser-tools-Btu_vB2d.js');
4
+ require('./src-CbTAVbeI.js');
5
+ const require_engine = require('./engine-DJSfl_Hc.js');
6
+ require('./extraction-tools-BX5HGgko.js');
7
+ const require_inference = require('./inference-C2HOfRf8.js');
8
+ require('./memory-auto-CSUt3aas.js');
9
+ require('./orchestrator-C9I6EVhh.js');
10
+ require('./pc-access-D5k6dAfU.js');
11
+ require('./session-store-Bx7lBD_a.js');
12
+ require('./sessions-tools-DVSejkNU.js');
13
+ require('./skill-loader-99egKAGN.js');
14
+ require('./skill-runtime-BGNtPD_L.js');
15
+ require('./vision-tools-DnUjpQhI.js');
16
+ require('./website-watch-tools-Oxf8Mv4j.js');
17
+ const require_src$1 = require('./src-zUHOCQgl.js');
18
+ const chalk = require_chunk.__toESM(require("chalk"));
19
+ const ora = require_chunk.__toESM(require("ora"));
20
+ const fs_extra = require_chunk.__toESM(require("fs-extra"));
21
+ const readline = require_chunk.__toESM(require("readline"));
22
+
23
+ //#region src/cli/chat.ts
24
+ require_src$1.init_src();
25
+ const DIVIDER = chalk.default.gray(" " + "─".repeat(56));
26
+ function printHeader(model, sessionId) {
27
+ console.log();
28
+ console.log(DIVIDER);
29
+ console.log(chalk.default.bold.cyan(" 🦅 HYPERCLAW CHAT"));
30
+ console.log(chalk.default.gray(` Model: ${model} · Session: ${sessionId}`));
31
+ console.log(DIVIDER);
32
+ console.log(chalk.default.gray(" Type your message and press Enter."));
33
+ console.log(chalk.default.gray(" Commands: /exit /clear /model [id] /skills /help"));
34
+ console.log(DIVIDER);
35
+ console.log();
36
+ }
37
+ function printHelp() {
38
+ console.log();
39
+ console.log(chalk.default.bold(" Commands:"));
40
+ console.log(` ${chalk.default.cyan("/exit")} — quit the chat`);
41
+ console.log(` ${chalk.default.cyan("/clear")} — clear conversation history`);
42
+ console.log(` ${chalk.default.cyan("/model")} — show current model`);
43
+ console.log(` ${chalk.default.cyan("/model <id>")} — switch model (e.g. /model claude-sonnet-4-5)`);
44
+ console.log(` ${chalk.default.cyan("/skills")} — list installed skills + how to add more`);
45
+ console.log(` ${chalk.default.cyan("/help")} — show this help`);
46
+ console.log();
47
+ console.log(chalk.default.gray(" Tip: you can also tell the agent to install a skill:"));
48
+ console.log(chalk.default.gray(" \"Install the web-search skill\" or paste a clawhub.ai link"));
49
+ console.log();
50
+ }
51
+ async function printSkills() {
52
+ console.log();
53
+ try {
54
+ const { loadSkills } = await Promise.resolve().then(() => require("./skill-loader-DwbmjEDa.js"));
55
+ const skills = await loadSkills();
56
+ if (skills.length === 0) console.log(chalk.default.gray(" No skills installed yet."));
57
+ else {
58
+ console.log(chalk.default.bold(" Installed skills:"));
59
+ for (const s of skills) {
60
+ console.log(` ${chalk.default.cyan("•")} ${chalk.default.bold(s.title || s.id)} ${chalk.default.gray(`(${s.id})`)}`);
61
+ if (s.capabilities) console.log(chalk.default.gray(` ${s.capabilities}`));
62
+ }
63
+ }
64
+ } catch (e) {
65
+ console.log(chalk.default.gray(" Could not load skills list."));
66
+ console.log(chalk.default.gray(` ${(e?.message || String(e)).slice(0, 80)}`));
67
+ console.log(chalk.default.gray(" Run: hyperclaw doctor or hyperclaw hub to check setup."));
68
+ }
69
+ console.log();
70
+ console.log(chalk.default.bold(" How to add a skill:"));
71
+ console.log(` ${chalk.default.gray("1.")} Tell the agent: ${chalk.default.cyan("\"Install the web-search skill\"")}`);
72
+ console.log(` ${chalk.default.gray("2.")} Paste a link: ${chalk.default.cyan("\"Install this: https://clawhub.ai/user/skill-name\"")}`);
73
+ console.log(` ${chalk.default.gray("3.")} CLI (outside chat): ${chalk.default.cyan("hyperclaw skill install <name>")}`);
74
+ console.log(` ${chalk.default.gray("4.")} Re-run wizard: ${chalk.default.cyan("hyperclaw onboard")}`);
75
+ console.log();
76
+ }
77
+ function makeSessionId() {
78
+ return Math.random().toString(36).slice(2, 9);
79
+ }
80
+ async function runChat(opts) {
81
+ const cfg = await fs_extra.default.readJson(require_paths.getConfigPath()).catch(() => null);
82
+ if (!cfg) {
83
+ console.log(chalk.default.red("\n No configuration found.\n"));
84
+ console.log(chalk.default.gray(" Chat works without the gateway. Run: hyperclaw onboard\n"));
85
+ return;
86
+ }
87
+ const { getProviderCredentialAsync } = await Promise.resolve().then(() => require("./env-resolve-CC_po9t5.js"));
88
+ const apiKey = await getProviderCredentialAsync(cfg).catch(() => null);
89
+ const isLocal = [
90
+ "local",
91
+ "ollama",
92
+ "lmstudio"
93
+ ].includes(cfg?.provider?.providerId ?? "");
94
+ if (!apiKey && !isLocal) {
95
+ console.log(chalk.default.red("\n No API key configured.\n"));
96
+ console.log(chalk.default.gray(" Chat uses your AI provider directly (no gateway needed). Run: hyperclaw config set-key\n"));
97
+ return;
98
+ }
99
+ const { getProvider } = await Promise.resolve().then(() => require("./providers-CFQC39vg.js"));
100
+ const providerMeta = getProvider(cfg?.provider?.providerId ?? "");
101
+ const CUSTOM_IDS = new Set([
102
+ "groq",
103
+ "mistral",
104
+ "deepseek",
105
+ "perplexity",
106
+ "huggingface",
107
+ "ollama",
108
+ "lmstudio",
109
+ "local",
110
+ "xai",
111
+ "openai",
112
+ "google",
113
+ "minimax",
114
+ "moonshot",
115
+ "qwen",
116
+ "zai",
117
+ "litellm",
118
+ "cloudflare",
119
+ "copilot",
120
+ "vercel-ai",
121
+ "opencode-zen"
122
+ ]);
123
+ const isAnthropicVariant = [
124
+ "anthropic",
125
+ "anthropic-oauth",
126
+ "anthropic-setup-token"
127
+ ].includes(cfg?.provider?.providerId ?? "");
128
+ const provider = isAnthropicVariant ? "anthropic" : cfg?.provider?.providerId === "custom" || isLocal || CUSTOM_IDS.has(cfg?.provider?.providerId ?? "") ? "custom" : "openrouter";
129
+ let rawModel = opts.model || cfg?.provider?.modelId || "claude-sonnet-4-5";
130
+ const model = rawModel.startsWith("ollama/") ? rawModel.slice(7) : rawModel;
131
+ const resolvedBaseUrl = cfg?.provider?.baseUrl || providerMeta?.baseUrl || (isLocal ? "http://localhost:11434/v1" : void 0);
132
+ const THINKING_BUDGET = {
133
+ high: 1e4,
134
+ medium: 4e3,
135
+ low: 1e3,
136
+ none: 0
137
+ };
138
+ const thinkingBudget = THINKING_BUDGET[opts.thinking ?? "none"] ?? 0;
139
+ const maxTokens = thinkingBudget > 0 ? thinkingBudget + 4096 : 4096;
140
+ const context = await require_engine.loadWorkspaceContext(opts.workspace) + await require_engine.loadSkillsContext();
141
+ const tools = await require_engine.resolveTools({
142
+ config: cfg,
143
+ source: "cli",
144
+ elevated: true,
145
+ daemonMode: false
146
+ });
147
+ const engineOpts = {
148
+ model,
149
+ apiKey,
150
+ provider,
151
+ system: context || void 0,
152
+ tools,
153
+ maxTokens,
154
+ onToken: () => {},
155
+ ...provider === "custom" ? { baseUrl: resolvedBaseUrl || "" } : {},
156
+ ...thinkingBudget > 0 && model.includes("claude") ? { thinking: { budget_tokens: thinkingBudget } } : {}
157
+ };
158
+ const sessionId = opts.sessionId ?? makeSessionId();
159
+ const messages = [];
160
+ let autoMem = null;
161
+ try {
162
+ const { AutoMemory } = await Promise.resolve().then(() => require("./memory-auto-D_mPVYqI.js"));
163
+ autoMem = new AutoMemory({ extractEveryNTurns: 3 });
164
+ } catch {}
165
+ printHeader(rawModel, sessionId);
166
+ try {
167
+ const { maybeShowUpdateNotice } = await Promise.resolve().then(() => require("./update-check-CaHNCDqe.js"));
168
+ maybeShowUpdateNotice();
169
+ } catch {}
170
+ const rl = readline.default.createInterface({
171
+ input: process.stdin,
172
+ output: process.stdout,
173
+ terminal: true
174
+ });
175
+ rl.on("SIGINT", () => {
176
+ console.log(chalk.default.gray("\n\n Bye!\n"));
177
+ rl.close();
178
+ process.exit(0);
179
+ });
180
+ await new Promise((resolve) => {
181
+ rl.on("close", resolve);
182
+ const prompt = () => {
183
+ rl.question(chalk.default.bold.green(" You › "), async (input) => {
184
+ const text = input.trim();
185
+ if (!text) {
186
+ prompt();
187
+ return;
188
+ }
189
+ if ([
190
+ "/exit",
191
+ "/quit",
192
+ "/bye",
193
+ "exit",
194
+ "quit",
195
+ "bye"
196
+ ].includes(text.toLowerCase())) {
197
+ console.log(chalk.default.gray("\n Bye!\n"));
198
+ rl.close();
199
+ process.exit(0);
200
+ }
201
+ if (text === "/help") {
202
+ printHelp();
203
+ prompt();
204
+ return;
205
+ }
206
+ if (text === "/skills") {
207
+ await printSkills();
208
+ prompt();
209
+ return;
210
+ }
211
+ if (text === "/model" || text.startsWith("/model ")) {
212
+ const newModelArg = text.slice(7).trim().replace(/^<|>$/g, "");
213
+ if (newModelArg) {
214
+ rawModel = newModelArg;
215
+ engineOpts.model = rawModel.startsWith("ollama/") ? rawModel.slice(7) : rawModel;
216
+ console.log(chalk.default.green(`\n ✔ Model switched to: ${chalk.default.bold(rawModel)}\n`));
217
+ } else if (providerMeta?.models?.length) {
218
+ rl.pause();
219
+ try {
220
+ const inquirer = (await import("inquirer")).default;
221
+ const defaultIdx = Math.max(0, providerMeta.models.findIndex((m) => m.id === rawModel));
222
+ const { selected } = await inquirer.prompt([{
223
+ type: "list",
224
+ name: "selected",
225
+ message: chalk.default.cyan("Select model") + chalk.default.gray(" (↑↓ arrows, Enter to confirm):"),
226
+ choices: providerMeta.models.map((m) => ({
227
+ name: `${m.id} ${chalk.default.gray(m.name)}`,
228
+ value: m.id,
229
+ short: m.id
230
+ })),
231
+ default: defaultIdx,
232
+ prefix: " "
233
+ }]);
234
+ rawModel = selected;
235
+ engineOpts.model = rawModel.startsWith("ollama/") ? rawModel.slice(7) : rawModel;
236
+ console.log(chalk.default.green(`\n ✔ Model switched to: ${chalk.default.bold(rawModel)}\n`));
237
+ } catch {
238
+ console.log(chalk.default.gray("\n Selection failed. Use: /model <model-id> (e.g. claude-sonnet-4-5)\n"));
239
+ } finally {
240
+ rl.resume();
241
+ }
242
+ } else {
243
+ console.log(chalk.default.gray(`\n Current model: ${chalk.default.bold(rawModel)}`));
244
+ console.log(chalk.default.gray(" Use: /model <model-id>\n"));
245
+ }
246
+ prompt();
247
+ return;
248
+ }
249
+ if (text === "/clear") {
250
+ messages.length = 0;
251
+ console.log(chalk.default.gray("\n Conversation cleared.\n"));
252
+ prompt();
253
+ return;
254
+ }
255
+ messages.push({
256
+ role: "user",
257
+ content: text
258
+ });
259
+ const spinner = (0, ora.default)({
260
+ text: chalk.default.gray("Thinking..."),
261
+ color: "cyan",
262
+ prefixText: " "
263
+ }).start();
264
+ let responseText = "";
265
+ try {
266
+ let prefixPrinted = false;
267
+ const engine = new require_inference.InferenceEngine({
268
+ ...engineOpts,
269
+ onToken: (token) => {
270
+ if (spinner.isSpinning) spinner.stop();
271
+ if (!prefixPrinted) {
272
+ process.stdout.write(chalk.default.bold.blue("\n Agent › "));
273
+ prefixPrinted = true;
274
+ }
275
+ process.stdout.write(token);
276
+ },
277
+ onToolCall: (name) => {
278
+ if (spinner.isSpinning) spinner.stop();
279
+ console.log(chalk.default.gray(`\n [tool: ${name}]`));
280
+ prefixPrinted = false;
281
+ }
282
+ });
283
+ const result = await engine.run(messages);
284
+ responseText = result.text || "";
285
+ spinner.stop();
286
+ if (!prefixPrinted) {
287
+ process.stdout.write(chalk.default.bold.blue("\n Agent › "));
288
+ process.stdout.write(responseText || chalk.default.gray("(empty — try rephrasing or check model/tools)"));
289
+ } else if (!responseText) process.stdout.write(chalk.default.gray("(empty — try rephrasing or check model/tools)"));
290
+ console.log("\n");
291
+ if (result.usage) console.log(chalk.default.gray(` Tokens — in: ${result.usage.input} out: ${result.usage.output}\n`));
292
+ } catch (e) {
293
+ spinner.stop();
294
+ const msg = e?.message || String(e);
295
+ responseText = `Error: ${msg}`;
296
+ console.log(chalk.default.red(`\n Error: ${msg}\n`));
297
+ const hint = (() => {
298
+ if (/401|unauthorized|invalid.*key|authentication/i.test(msg)) return "Check API key: hyperclaw config set-key";
299
+ if (/429|rate.?limit|quota/i.test(msg)) return "Rate limited. Wait a moment and retry.";
300
+ if (/500|503|service.?unavailable/i.test(msg)) return "Provider temporarily down. Try again later.";
301
+ if (/network|ECONNREFUSED|ETIMEDOUT|fetch failed/i.test(msg)) return "Network error. Check connection and base URL.";
302
+ if (/model|not found|invalid model/i.test(msg)) return "Try: /model <id> to switch model.";
303
+ return "Run: hyperclaw doctor for setup checks.";
304
+ })();
305
+ console.log(chalk.default.gray(` ${hint}\n`));
306
+ }
307
+ if (responseText) messages.push({
308
+ role: "assistant",
309
+ content: responseText
310
+ });
311
+ if (autoMem) {
312
+ autoMem.addTurn("user", text);
313
+ if (responseText) autoMem.addTurn("assistant", responseText);
314
+ autoMem.extract().catch(() => {});
315
+ }
316
+ prompt();
317
+ });
318
+ };
319
+ prompt();
320
+ });
321
+ }
322
+
323
+ //#endregion
324
+ exports.runChat = runChat;