hoomanjs 1.33.0 → 1.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/README.md +114 -270
  2. package/dist/acp/acp-agent.js +2 -16
  3. package/dist/acp/acp-agent.js.map +1 -1
  4. package/dist/acp/sessions/options.js +2 -2
  5. package/dist/acp/sessions/options.js.map +1 -1
  6. package/dist/acp/sessions/store.d.ts +0 -2
  7. package/dist/acp/sessions/store.js.map +1 -1
  8. package/dist/acp/utils/tool-kind.js +10 -2
  9. package/dist/acp/utils/tool-kind.js.map +1 -1
  10. package/dist/chat/app.d.ts +2 -1
  11. package/dist/chat/app.js +94 -23
  12. package/dist/chat/app.js.map +1 -1
  13. package/dist/chat/components/BottomChrome.d.ts +6 -2
  14. package/dist/chat/components/BottomChrome.js +2 -2
  15. package/dist/chat/components/BottomChrome.js.map +1 -1
  16. package/dist/chat/components/ChromePicker.d.ts +7 -2
  17. package/dist/chat/components/ChromePicker.js +9 -2
  18. package/dist/chat/components/ChromePicker.js.map +1 -1
  19. package/dist/chat/components/StatusBar.d.ts +1 -2
  20. package/dist/chat/components/StatusBar.js +3 -12
  21. package/dist/chat/components/StatusBar.js.map +1 -1
  22. package/dist/chat/components/ToolEvent.js +1 -1
  23. package/dist/chat/components/ToolEvent.js.map +1 -1
  24. package/dist/chat/index.d.ts +2 -1
  25. package/dist/chat/index.js +7 -0
  26. package/dist/chat/index.js.map +1 -1
  27. package/dist/cli.js +120 -4
  28. package/dist/cli.js.map +1 -1
  29. package/dist/configure/app.js +1005 -392
  30. package/dist/configure/app.js.map +1 -1
  31. package/dist/configure/index.js.map +1 -1
  32. package/dist/configure/types.d.ts +18 -0
  33. package/dist/core/agent/index.d.ts +13 -3
  34. package/dist/core/agent/index.js +83 -15
  35. package/dist/core/agent/index.js.map +1 -1
  36. package/dist/core/config.d.ts +319 -87
  37. package/dist/core/config.js +191 -218
  38. package/dist/core/config.js.map +1 -1
  39. package/dist/core/index.d.ts +1 -2
  40. package/dist/core/index.js +6 -7
  41. package/dist/core/index.js.map +1 -1
  42. package/dist/core/mcp/config.d.ts +7 -1
  43. package/dist/core/mcp/config.js +41 -8
  44. package/dist/core/mcp/config.js.map +1 -1
  45. package/dist/core/mcp/manager.js +1 -1
  46. package/dist/core/mcp/manager.js.map +1 -1
  47. package/dist/core/mcp/oauth/provider.js.map +1 -1
  48. package/dist/core/mcp/prefixed-mcp-tool.d.ts +0 -1
  49. package/dist/core/mcp/prefixed-mcp-tool.js +0 -2
  50. package/dist/core/mcp/prefixed-mcp-tool.js.map +1 -1
  51. package/dist/core/memory/index.d.ts +1 -0
  52. package/dist/core/memory/index.js +1 -0
  53. package/dist/core/memory/index.js.map +1 -1
  54. package/dist/core/memory/model-extractor.js.map +1 -0
  55. package/dist/core/models/anthropic.d.ts +3 -12
  56. package/dist/core/models/anthropic.js +20 -91
  57. package/dist/core/models/anthropic.js.map +1 -1
  58. package/dist/core/models/azure.d.ts +4 -0
  59. package/dist/core/models/azure.js +26 -0
  60. package/dist/core/models/azure.js.map +1 -0
  61. package/dist/core/models/bedrock.d.ts +3 -20
  62. package/dist/core/models/bedrock.js +22 -18
  63. package/dist/core/models/bedrock.js.map +1 -1
  64. package/dist/core/models/google.d.ts +2 -9
  65. package/dist/core/models/google.js +12 -31
  66. package/dist/core/models/google.js.map +1 -1
  67. package/dist/core/models/groq.d.ts +2 -9
  68. package/dist/core/models/groq.js +15 -25
  69. package/dist/core/models/groq.js.map +1 -1
  70. package/dist/core/models/index.d.ts +2 -1
  71. package/dist/core/models/index.js +3 -0
  72. package/dist/core/models/index.js.map +1 -1
  73. package/dist/core/models/minimax.d.ts +2 -0
  74. package/dist/core/models/minimax.js +11 -0
  75. package/dist/core/models/minimax.js.map +1 -0
  76. package/dist/core/models/moonshot.d.ts +2 -10
  77. package/dist/core/models/moonshot.js +23 -38
  78. package/dist/core/models/moonshot.js.map +1 -1
  79. package/dist/core/models/ollama/index.d.ts +2 -1
  80. package/dist/core/models/ollama/index.js +12 -5
  81. package/dist/core/models/ollama/index.js.map +1 -1
  82. package/dist/core/models/openai.d.ts +3 -4
  83. package/dist/core/models/openai.js +20 -3
  84. package/dist/core/models/openai.js.map +1 -1
  85. package/dist/core/models/openrouter.d.ts +4 -0
  86. package/dist/core/models/openrouter.js +23 -0
  87. package/dist/core/models/openrouter.js.map +1 -0
  88. package/dist/core/models/types.d.ts +346 -0
  89. package/dist/core/models/types.js +220 -0
  90. package/dist/core/models/types.js.map +1 -0
  91. package/dist/core/models/xai.d.ts +2 -9
  92. package/dist/core/models/xai.js +15 -25
  93. package/dist/core/models/xai.js.map +1 -1
  94. package/dist/core/modes/definitions.js +6 -2
  95. package/dist/core/modes/definitions.js.map +1 -1
  96. package/dist/core/prompts/agents/research.md +8 -4
  97. package/dist/core/prompts/agents/review.md +26 -0
  98. package/dist/core/prompts/agents/test-investigator.md +26 -0
  99. package/dist/core/prompts/modes/ask.md +1 -1
  100. package/dist/core/prompts/modes/plan.md +1 -1
  101. package/dist/core/prompts/runtime.js +2 -30
  102. package/dist/core/prompts/runtime.js.map +1 -1
  103. package/dist/core/prompts/static/subagents.md +12 -8
  104. package/dist/core/prompts/system.js +1 -1
  105. package/dist/core/prompts/system.js.map +1 -1
  106. package/dist/core/runtime-config.d.ts +16 -0
  107. package/dist/core/runtime-config.js +44 -0
  108. package/dist/core/runtime-config.js.map +1 -0
  109. package/dist/core/session-config.js +2 -1
  110. package/dist/core/session-config.js.map +1 -1
  111. package/dist/core/sessions/flat-file-storage.js.map +1 -0
  112. package/dist/core/sessions/lazy-session-manager.js.map +1 -0
  113. package/dist/core/sessions/list-cli-sessions.d.ts +12 -0
  114. package/dist/core/sessions/list-cli-sessions.js +174 -0
  115. package/dist/core/sessions/list-cli-sessions.js.map +1 -0
  116. package/dist/core/skills/built-in/hooman-config/SKILL.md +98 -201
  117. package/dist/core/state/tool-approvals.js +4 -3
  118. package/dist/core/state/tool-approvals.js.map +1 -1
  119. package/dist/core/subagents/index.d.ts +2 -3
  120. package/dist/core/subagents/index.js +2 -3
  121. package/dist/core/subagents/index.js.map +1 -1
  122. package/dist/core/subagents/registry.d.ts +22 -0
  123. package/dist/core/subagents/registry.js +96 -0
  124. package/dist/core/subagents/registry.js.map +1 -0
  125. package/dist/core/subagents/tool.d.ts +6 -14
  126. package/dist/core/subagents/tool.js +73 -53
  127. package/dist/core/subagents/tool.js.map +1 -1
  128. package/dist/core/tools/filesystem.js +2 -9
  129. package/dist/core/tools/filesystem.js.map +1 -1
  130. package/dist/core/tools/shell.js.map +1 -1
  131. package/dist/core/utils/discover-files.d.ts +12 -0
  132. package/dist/core/utils/discover-files.js +47 -0
  133. package/dist/core/utils/discover-files.js.map +1 -0
  134. package/dist/index.d.ts +8 -5
  135. package/dist/index.js +7 -3
  136. package/dist/index.js.map +1 -1
  137. package/package.json +2 -1
  138. package/dist/acp/meta/system-prompt.d.ts +0 -12
  139. package/dist/acp/meta/system-prompt.js +0 -41
  140. package/dist/acp/meta/system-prompt.js.map +0 -1
  141. package/dist/core/context/flat-file-storage.js.map +0 -1
  142. package/dist/core/context/index.d.ts +0 -22
  143. package/dist/core/context/index.js +0 -74
  144. package/dist/core/context/index.js.map +0 -1
  145. package/dist/core/context/lazy-session-manager.js.map +0 -1
  146. package/dist/core/context/model-extractor.js.map +0 -1
  147. package/dist/core/subagents/research.d.ts +0 -16
  148. package/dist/core/subagents/research.js +0 -58
  149. package/dist/core/subagents/research.js.map +0 -1
  150. package/dist/core/subagents/runner.d.ts +0 -37
  151. package/dist/core/subagents/runner.js +0 -273
  152. package/dist/core/subagents/runner.js.map +0 -1
  153. /package/dist/core/{context → memory}/model-extractor.d.ts +0 -0
  154. /package/dist/core/{context → memory}/model-extractor.js +0 -0
  155. /package/dist/core/{context → sessions}/flat-file-storage.d.ts +0 -0
  156. /package/dist/core/{context → sessions}/flat-file-storage.js +0 -0
  157. /package/dist/core/{context → sessions}/lazy-session-manager.d.ts +0 -0
  158. /package/dist/core/{context → sessions}/lazy-session-manager.js +0 -0
package/README.md CHANGED
@@ -21,7 +21,7 @@ It gives you a practical toolkit to build and run agent workflows:
21
21
  - a one-shot `exec` command for single prompts
22
22
  - a stateful `chat` interface for iterative sessions
23
23
  - a `daemon` command for channel-driven MCP automation
24
- - an in-chat `/config` workflow (Ink-powered) for app config, prompts, MCP servers, and installed skills
24
+ - an in-chat `/config` workflow (Ink-powered) for general settings, models, MCP servers, and installed skills
25
25
  - an `acp` command for running Hooman as an Agent Client Protocol (ACP) agent over stdio
26
26
 
27
27
  ## Related
@@ -30,7 +30,7 @@ It gives you a practical toolkit to build and run agent workflows:
30
30
 
31
31
  ## Features
32
32
 
33
- - Multiple LLM providers: `anthropic`, `bedrock`, `google`, `groq`, `moonshot`, `ollama`, `openai`, `xai`
33
+ - Multiple LLM providers: `anthropic`, `azure`, `bedrock`, `google`, `groq`, `minimax`, `moonshot`, `ollama`, `openai`, `openrouter`, `xai`
34
34
  - Local configuration under `~/.hooman`
35
35
  - Optional web search tool with provider selection (`brave`, `exa`, `firecrawl`, `serper`, or `tavily`)
36
36
  - MCP server support via `stdio`, `streamable-http`, and `sse`
@@ -38,7 +38,7 @@ It gives you a practical toolkit to build and run agent workflows:
38
38
  - MCP channel notifications: `hooman daemon` subscribes to servers that advertise `hooman/channel`
39
39
  - Runtime skills via Strands `AgentSkills`, loading bundled built-in skills plus local `~/.hooman/skills`
40
40
  - Bundled prompt harness toggles (`behaviour`, `communication`, `execution`, `guardrails`); coding guidance ships as the built-in `hooman-coding` skill
41
- - Built-in research sub-agent runner (`research`) with configurable concurrency
41
+ - Built-in read-only subagent tools (`subagent_research`, `subagent_review`, `subagent_test_investigator`)
42
42
  - Built-in `grep` tool backed by ripgrep (`rg`), with runtime bootstrap when `rg` is not available on PATH
43
43
  - Toolkit-oriented architecture with configurable tools, prompts, and transports
44
44
  - Interactive terminal UI for chat and configuration
@@ -231,6 +231,15 @@ Log raw notification payloads:
231
231
  hooman daemon --debug
232
232
  ```
233
233
 
234
+ ### `hooman config`
235
+
236
+ Print the effective runtime `config.json` for the current working directory in
237
+ the same shape as `config.json`, with credential-like values redacted.
238
+
239
+ ```bash
240
+ hooman config
241
+ ```
242
+
234
243
  ### Feature Flags
235
244
 
236
245
  Runtime tool and prompt switches are controlled from `config.json`:
@@ -251,12 +260,11 @@ Runtime tool and prompt switches are controlled from `config.json`:
251
260
  - `tools.filesystem.enabled`
252
261
  - `tools.shell.enabled`
253
262
  - `tools.sleep.enabled`
254
- - `tools.agents.enabled` (enables built-in `run_subagents` tool)
255
- - `tools.agents.concurrency` (defaults to `3` when omitted on load; a freshly generated default `config.json` uses `2`)
263
+ - `tools.subagents.enabled` (enables built-in subagent tools)
256
264
 
257
265
  ### `/config`
258
266
 
259
- The configuration workflow is launched from inside a `chat` session with the `/config` slash command (there is no separate top-level `configure` command). It takes over the terminal on the alternate screen buffer while open, and restores the chat session on exit. Any config changes are picked up when the session re-bootstraps.
267
+ The interactive configuration workflow is launched from inside a `chat` session with the `/config` slash command (there is no separate top-level `configure` command). It takes over the terminal on the alternate screen buffer while open, and restores the chat session on exit. Any config changes are picked up when the session re-bootstraps.
260
268
 
261
269
  ```text
262
270
  /config
@@ -264,11 +272,12 @@ The configuration workflow is launched from inside a `chat` session with the `/c
264
272
 
265
273
  The configuration UI currently lets you:
266
274
 
267
- - edit app configuration values
275
+ - manage general settings such as name, prompts, tools, and compaction
276
+ - manage models and providers with field-by-field editors
268
277
  - choose search provider and set its API key
269
278
  - toggle bundled harness prompts (`behaviour`, `communication`, `execution`, `guardrails`)
270
279
  - edit `instructions.md` in your `$VISUAL` / `$EDITOR` (cross-platform fallback included)
271
- - add, edit, and delete MCP servers with confirmation
280
+ - add, edit, and delete MCP servers with field-by-field editors and confirmation
272
281
  - search, install, refresh, and remove skills
273
282
 
274
283
  ### `hooman acp`
@@ -283,8 +292,7 @@ ACP notes:
283
292
 
284
293
  - ACP sessions are stored under the active Hooman data directory in `acp-sessions/`
285
294
  - ACP loads MCP servers passed on `session/new` and `session/load`, in addition to Hooman's local `mcp.json`
286
- - ACP `session/new` and `session/load` support `_meta.userId` and `_meta.systemPrompt`
287
- - when `_meta.systemPrompt` is provided, it is appended to the agent system prompt with a section break
295
+ - ACP `session/new` and `session/load` support `_meta.userId`
288
296
  - session configuration includes `hooman.sessionMode` (`agent`, `plan`, or `ask`); see [Session mode](#session-mode)
289
297
 
290
298
  ## Configuration Layout
@@ -306,6 +314,33 @@ Important files and folders:
306
314
  - `sessions/` - persisted session data
307
315
  - `acp-sessions/` - persisted ACP session metadata and message snapshots
308
316
 
317
+ ### Repo-local runtime overlays
318
+
319
+ At runtime, Hooman resolves configuration in this order:
320
+
321
+ 1. `~/.hooman/config.json` and `~/.hooman/mcp.json`
322
+ 2. `<git-root>/config.json` and `<git-root>/mcp.json` (if present)
323
+ 3. matching files in nested directories from git root to current working directory
324
+
325
+ Nearest files win when keys overlap.
326
+
327
+ For app config (`config.json`):
328
+
329
+ - plain objects are deep-merged
330
+ - scalar values are overridden by the nearest file
331
+ - `providers` and `llms` are merged by `name` (nearest entry with the same name replaces inherited entries)
332
+
333
+ For MCP config (`mcp.json`):
334
+
335
+ - `mcpServers` is merged by server name (nearest entry with the same name wins)
336
+
337
+ Notes:
338
+
339
+ - Runtime overlays apply to `chat`, `exec`, `daemon`, and `acp` bootstraps.
340
+ - `hooman config` prints only the merged effective `config.json` shape with credential-like values redacted.
341
+ - The `/config` UI and `hooman mcp auth/logout/auth-status` still target home config (`~/.hooman/*`) directly.
342
+ - Keep secrets in home config unless you explicitly want project-scoped credentials.
343
+
309
344
  `grep` tool binary resolution order:
310
345
 
311
346
  1. Use system `rg` when available.
@@ -314,27 +349,24 @@ Important files and folders:
314
349
 
315
350
  ## Example `config.json`
316
351
 
317
- The on-disk shape uses a reusable **`providers`** array plus a non-empty **`llms`** array. Each provider stores the shared runtime type and params once; each LLM references a provider by name, sets its `model`, optional model-specific `params`, and `default`. The bundled **hooman-config** skill documents the full schema.
352
+ The on-disk shape uses a reusable **`providers`** array plus a non-empty **`llms`** array. Each provider stores a runtime `provider` id plus provider-specific `options`; each LLM references a provider by name, stores its model `options`, and marks one entry as the default. The bundled **hooman-config** skill documents the full schema.
318
353
 
319
354
  ```json
320
355
  {
321
356
  "name": "Hooman",
322
357
  "providers": [
323
358
  {
324
- "name": "ollama-local",
325
- "options": {
326
- "provider": "ollama",
327
- "params": {}
328
- }
359
+ "name": "Ollama",
360
+ "provider": "ollama",
361
+ "options": {}
329
362
  }
330
363
  ],
331
364
  "llms": [
332
365
  {
333
366
  "name": "Default",
367
+ "provider": "Ollama",
334
368
  "options": {
335
- "provider": "ollama-local",
336
- "model": "gemma4:e4b",
337
- "params": {}
369
+ "model": "gemma4:e4b"
338
370
  },
339
371
  "default": true
340
372
  }
@@ -355,25 +387,12 @@ The on-disk shape uses a reusable **`providers`** array plus a non-empty **`llms
355
387
  "guardrails": true
356
388
  },
357
389
  "tools": {
358
- "todo": {
359
- "enabled": true
360
- },
361
- "fetch": {
362
- "enabled": true
363
- },
364
- "filesystem": {
365
- "enabled": true
366
- },
367
- "shell": {
368
- "enabled": true
369
- },
370
- "sleep": {
371
- "enabled": true
372
- },
373
- "agents": {
374
- "enabled": true,
375
- "concurrency": 2
376
- }
390
+ "todo": { "enabled": true },
391
+ "fetch": { "enabled": true },
392
+ "filesystem": { "enabled": true },
393
+ "shell": { "enabled": true },
394
+ "sleep": { "enabled": true },
395
+ "subagents": { "enabled": true }
377
396
  },
378
397
  "compaction": {
379
398
  "ratio": 0.75,
@@ -386,19 +405,20 @@ Tool approvals are session-scoped and are not persisted in `config.json`.
386
405
 
387
406
  Hooman enables Strands `ContextOffloader` by default with file-backed storage under `~/.hooman/sessions/offloaded-content`, so large tool results can be previewed in-context and retrieved later without bloating the active conversation window.
388
407
 
389
- Supported `providers[].options.provider` values registered in this release (see `src/core/models/index.ts`):
408
+ Supported `providers[].provider` values registered in this release (see `src/core/models/index.ts`):
390
409
 
391
410
  - `anthropic`
411
+ - `azure`
392
412
  - `bedrock`
393
413
  - `google`
394
414
  - `groq`
415
+ - `minimax`
395
416
  - `moonshot`
396
417
  - `ollama`
397
418
  - `openai`
419
+ - `openrouter`
398
420
  - `xai`
399
421
 
400
- The `LlmProvider` enum in `src/core/config.ts` may list additional strings for forwards compatibility; unknown providers are not loaded at runtime.
401
-
402
422
  Supported `search.provider` values:
403
423
 
404
424
  - `brave`
@@ -409,253 +429,62 @@ Supported `search.provider` values:
409
429
 
410
430
  ## Provider Notes
411
431
 
412
- ### Ollama
413
-
414
- Good default for local usage. Example:
415
-
416
- ```json
417
- {
418
- "providers": [
419
- {
420
- "name": "ollama-local",
421
- "options": {
422
- "provider": "ollama",
423
- "params": {}
424
- }
425
- }
426
- ],
427
- "llms": [
428
- {
429
- "name": "Default",
430
- "options": {
431
- "provider": "ollama-local",
432
- "model": "gemma4:e4b",
433
- "params": {}
434
- },
435
- "default": true
436
- }
437
- ]
438
- }
439
- ```
440
-
441
- ### OpenAI
442
-
443
- Uses Strands **OpenAIModel** (Chat Completions). `apiKey` is optional if `OPENAI_API_KEY` is set. Use `clientConfig` for a custom base URL or other OpenAI client options (OpenAI-compatible proxies and gateways).
444
-
445
- Example:
446
-
447
- ```json
448
- {
449
- "providers": [
450
- {
451
- "name": "openai",
452
- "options": {
453
- "provider": "openai",
454
- "params": {
455
- "apiKey": "..."
456
- }
457
- }
458
- }
459
- ],
460
- "llms": [
461
- {
462
- "name": "GPT-5",
463
- "options": {
464
- "provider": "openai",
465
- "model": "gpt-5",
466
- "params": {}
467
- },
468
- "default": true
469
- }
470
- ]
471
- }
472
- ```
473
-
474
- OpenAI-compatible gateways that put token `usage` on the last streamed chunk together with `choices` are handled via a small stream shim so usage still surfaces in the UI.
475
-
476
- ### Anthropic
477
-
478
- Uses Strands **AnthropicModel** (Anthropic Messages API). `apiKey` or `authToken`, optional `baseURL` and `headers` (merged into `clientConfig`), optional `clientConfig`, and model fields such as `temperature` and `maxTokens`. A prebuilt `client` is not configurable from JSON.
479
-
480
- ```json
481
- {
482
- "providers": [
483
- {
484
- "name": "anthropic",
485
- "options": {
486
- "provider": "anthropic",
487
- "params": {
488
- "apiKey": "..."
489
- }
490
- }
491
- }
492
- ],
493
- "llms": [
494
- {
495
- "name": "Claude Sonnet",
496
- "options": {
497
- "provider": "anthropic",
498
- "model": "claude-sonnet-4-20250514",
499
- "params": {
500
- "temperature": 0.7
501
- }
502
- },
503
- "default": true
504
- }
505
- ]
506
- }
507
- ```
508
-
509
- ### Google
510
-
511
- Uses Strands `GoogleModel` on top of `@google/genai`. Top-level options like `apiKey`, `client`, `clientConfig`, and `builtInTools` are supported; other values go into Google generation params.
512
-
513
- ```json
514
- {
515
- "providers": [
516
- {
517
- "name": "google",
518
- "options": {
519
- "provider": "google",
520
- "params": {
521
- "apiKey": "..."
522
- }
523
- }
524
- }
525
- ],
526
- "llms": [
527
- {
528
- "name": "Gemini Flash",
529
- "options": {
530
- "provider": "google",
531
- "model": "gemini-2.5-flash",
532
- "params": {
533
- "temperature": 0.7,
534
- "maxOutputTokens": 2048,
535
- "topP": 0.9,
536
- "topK": 40
537
- }
538
- },
539
- "default": true
540
- }
541
- ]
542
- }
543
- ```
544
-
545
- ### Bedrock
546
-
547
- Supports `region`, `clientConfig`, and optional `apiKey`, with all other values forwarded as Bedrock model options.
548
-
549
- ```json
550
- {
551
- "providers": [
552
- {
553
- "name": "bedrock-dev",
554
- "options": {
555
- "provider": "bedrock",
556
- "params": {
557
- "region": "us-east-1",
558
- "clientConfig": {
559
- "profile": "dev",
560
- "maxAttempts": 3,
561
- "credentials": {
562
- "accessKeyId": "AKIA...",
563
- "secretAccessKey": "...",
564
- "sessionToken": "..."
565
- }
566
- }
567
- }
568
- }
569
- }
570
- ],
571
- "llms": [
572
- {
573
- "name": "Claude Sonnet",
574
- "options": {
575
- "provider": "bedrock-dev",
576
- "model": "anthropic.claude-sonnet-4-20250514-v1:0",
577
- "params": {
578
- "temperature": 0.7,
579
- "maxTokens": 1024
580
- }
581
- },
582
- "default": true
583
- }
584
- ]
585
- }
586
- ```
587
-
588
- You can also rely on the AWS default credential chain (recommended) by setting environment variables such as `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and optionally `AWS_SESSION_TOKEN`.
589
-
590
- ### Groq
591
-
592
- ### Anthropic
593
-
594
- Uses Strands `AnthropicModel` on top of `@anthropic-ai/sdk`. Provider-specific settings `apiKey`/`authToken`, `baseURL`, `headers`, `clientConfig`, `betas`, and `useNativeTokenCount` are picked up directly. Standard model config such as `temperature`, `topP`, `maxTokens`, and `stopSequences` stays top-level. Any other keys are forwarded to the Anthropic Messages request body, which is useful for Anthropic-compatible providers such as MiniMax.
595
-
596
- For MiniMax specifically:
597
-
598
- - Use `baseURL: "https://api.minimax.io/anthropic"`.
599
- - `MiniMax-M3` can emit visible thinking blocks when you set `thinking: { "type": "adaptive" }`.
600
- - `MiniMax-M2.7` / `M2.5` / `M2.1` / `M2` do internal reasoning, but MiniMax’s Anthropic-compatible API does not expose those as `thinking` content blocks, so Hooman has nothing to render in the transcript.
432
+ Provider entries now look like:
601
433
 
602
434
  ```json
603
435
  {
604
- "provider": "anthropic",
605
- "model": "MiniMax-M3",
606
- "params": {
607
- "apiKey": "...",
608
- "baseURL": "https://api.minimax.io/anthropic",
609
- "thinking": { "type": "adaptive" },
610
- "temperature": 1
436
+ "name": "MiniMax",
437
+ "provider": "minimax",
438
+ "options": {
439
+ "apiKey": "..."
611
440
  }
612
441
  }
613
442
  ```
614
443
 
615
- ### Groq
616
-
617
- Uses the Vercel AI SDK Groq provider (`@ai-sdk/groq`) on top of Strands `VercelModel`. Provider-specific settings `apiKey`, `baseURL`, and `headers` are picked up; other values are forwarded into the model config (`temperature`, `maxTokens`, etc.). Defaults to `GROQ_API_KEY` from the environment when no `apiKey` is supplied.
444
+ LLM entries reference a provider by name and carry normalized model options:
618
445
 
619
446
  ```json
620
447
  {
621
- "provider": "groq",
622
- "model": "gemma2-9b-it",
623
- "params": {
624
- "apiKey": "...",
625
- "temperature": 0.7
626
- }
448
+ "name": "MiniMax M3",
449
+ "provider": "MiniMax",
450
+ "options": {
451
+ "model": "MiniMax-M3",
452
+ "temperature": 1,
453
+ "maxTokens": 4096
454
+ },
455
+ "default": true
627
456
  }
628
457
  ```
629
458
 
630
- ### Moonshot
459
+ Supported provider option fields:
631
460
 
632
- Uses the Vercel AI SDK Moonshot provider (`@ai-sdk/moonshotai`) on top of Strands `VercelModel`. Provider-specific settings `apiKey`, `baseURL`, `headers`, and `fetch` are picked up; other values are forwarded into the model config (`temperature`, `maxTokens`, `providerOptions`, etc.). Defaults to `MOONSHOT_API_KEY` from the environment when no `apiKey` is supplied. Moonshot reasoning models such as `kimi-k2-thinking` can be configured through `params.providerOptions.moonshotai`.
461
+ - `anthropic`: `apiKey`, optional `baseURL`, optional `headers`, optional `thinking`
462
+ - `azure`: optional `resourceName`, optional `baseURL`, optional `apiKey`, optional `headers`, optional `apiVersion`, optional `useDeploymentBasedUrls`
463
+ - `bedrock`: `region`, `accessKeyId`, `secretAccessKey`, optional `sessionToken`, optional `apiKey`
464
+ - `google`: `apiKey`
465
+ - `groq`: `apiKey`, optional `baseURL`, optional `headers`
466
+ - `minimax`: `apiKey`, optional `headers`, optional `thinking`
467
+ - `moonshot`: `apiKey`, optional `baseURL`, optional `headers`
468
+ - `ollama`: optional `baseURL`, optional `thinking`
469
+ - `openai`: `apiKey`, optional `baseURL`, optional `headers`
470
+ - `openrouter`: `apiKey`, optional `baseURL`, optional `headers`
471
+ - `xai`: `apiKey`, optional `baseURL`, optional `headers`
633
472
 
634
- ```json
635
- {
636
- "provider": "moonshot",
637
- "model": "kimi-k2.5",
638
- "params": {
639
- "apiKey": "...",
640
- "temperature": 0.7
641
- }
642
- }
643
- ```
473
+ Normalized LLM option fields:
644
474
 
645
- ### xAI
475
+ - `model`
476
+ - optional `temperature`
477
+ - optional `maxTokens`
646
478
 
647
- Uses the Vercel AI SDK xAI provider (`@ai-sdk/xai`) on top of Strands `VercelModel`. Provider-specific settings `apiKey`, `baseURL`, and `headers` are picked up; other values are forwarded into the model config (`temperature`, `maxTokens`, etc.). Defaults to `XAI_API_KEY` from the environment when no `apiKey` is supplied.
479
+ Notes:
648
480
 
649
- ```json
650
- {
651
- "provider": "xai",
652
- "model": "grok-4.20-non-reasoning",
653
- "params": {
654
- "apiKey": "...",
655
- "temperature": 0.7
656
- }
657
- }
658
- ```
481
+ - Google maps normalized `maxTokens` to the SDK's `maxOutputTokens` internally.
482
+ - Azure uses the Vercel AI SDK `@ai-sdk/azure` provider. Set the LLM `model` to your Azure deployment name, not the raw OpenAI model id.
483
+ - Ollama maps normalized `temperature` into Ollama `options.temperature`.
484
+ - MiniMax uses the Anthropic-compatible endpoint `https://api.minimax.io/anthropic` automatically.
485
+ - Moonshot defaults `baseURL` to `https://api.moonshot.ai/v1` when it is omitted.
486
+ - OpenRouter defaults `baseURL` to `https://openrouter.ai/api/v1` when it is omitted, and model names are usually provider-qualified ids such as `anthropic/claude-3.5-sonnet`.
487
+ - Bedrock can rely on the AWS default credential chain when explicit credentials are not provided.
659
488
 
660
489
  ## MCP Configuration
661
490
 
@@ -669,6 +498,8 @@ Detailed design notes for planned OAuth-enabled remote MCP support live in [docs
669
498
  }
670
499
  ```
671
500
 
501
+ At runtime, project-local `mcp.json` files are merged on top of `~/.hooman/mcp.json` from git root to current directory. On name conflicts, the nearest `mcpServers.<name>` entry wins.
502
+
672
503
  ### Example stdio server
673
504
 
674
505
  ```json
@@ -797,6 +628,19 @@ Run typecheck:
797
628
  npm run typecheck
798
629
  ```
799
630
 
631
+ Build the project:
632
+
633
+ ```bash
634
+ npm run build
635
+ ```
636
+
637
+ After making any code change, run both verification steps:
638
+
639
+ ```bash
640
+ npm run typecheck
641
+ npm run build
642
+ ```
643
+
800
644
  ## License
801
645
 
802
646
  MIT. See `LICENSE`.
@@ -17,7 +17,6 @@ import { copyAgentAppState } from "../core/state/agent-app-state.js";
17
17
  import { getModeState } from "../core/state/session-mode.js";
18
18
  import { ENTER_PLAN_MODE_TOOL, EXIT_PLAN_MODE_TOOL, } from "../core/state/tool-approvals.js";
19
19
  import { isYoloEnabled } from "../core/state/yolo.js";
20
- import { extractAcpClientSystemPrompt } from "./meta/system-prompt.js";
21
20
  import { extractAcpClientUserId } from "./meta/user-id.js";
22
21
  import { deriveSessionTitleFromEcho } from "./sessions/title.js";
23
22
  import { acpPromptEchoText, acpPromptToInvokeArgs } from "./prompt-invoke.js";
@@ -230,7 +229,6 @@ export class AcpAgent {
230
229
  assertAbsolutePath(params.cwd, "cwd");
231
230
  const sessionId = crypto.randomUUID();
232
231
  const clientUserId = extractAcpClientUserId(params._meta) ?? null;
233
- const clientSystemPrompt = extractAcpClientSystemPrompt(params._meta) ?? null;
234
232
  const bootstrapUserId = clientUserId ?? sessionId;
235
233
  const mcpServers = normalizeAcpSessionMcpServers(params.mcpServers);
236
234
  const now = new Date().toISOString();
@@ -240,7 +238,6 @@ export class AcpAgent {
240
238
  updatedAt: now,
241
239
  title: null,
242
240
  userId: clientUserId,
243
- systemPrompt: clientSystemPrompt,
244
241
  mcpServers,
245
242
  };
246
243
  await writeSessionMeta(this.#acpRoot, sessionId, meta);
@@ -253,7 +250,6 @@ export class AcpAgent {
253
250
  ],
254
251
  acp: {
255
252
  mcpServers,
256
- ...(clientSystemPrompt ? { systemPrompt: clientSystemPrompt } : {}),
257
253
  },
258
254
  }, false, createSessionConfig());
259
255
  const config = bootConfig;
@@ -308,13 +304,8 @@ export class AcpAgent {
308
304
  }
309
305
  assertAbsolutePath(params.cwd, "cwd");
310
306
  const fromRequest = extractAcpClientUserId(params._meta);
311
- const requestedSystemPrompt = extractAcpClientSystemPrompt(params._meta);
312
307
  const storedUserId = existing.userId ?? null;
313
- const storedSystemPrompt = existing.systemPrompt ?? null;
314
308
  const clientUserId = fromRequest !== undefined ? fromRequest : storedUserId;
315
- const clientSystemPrompt = requestedSystemPrompt !== undefined
316
- ? requestedSystemPrompt
317
- : storedSystemPrompt;
318
309
  const bootstrapUserId = clientUserId ?? params.sessionId;
319
310
  const mcpServers = params.mcpServers.length > 0
320
311
  ? normalizeAcpSessionMcpServers(params.mcpServers)
@@ -323,14 +314,13 @@ export class AcpAgent {
323
314
  userId: bootstrapUserId,
324
315
  sessionId: params.sessionId,
325
316
  yolo: existing.yolo === true,
326
- sessionMode: existing.sessionMode ?? "agent",
317
+ mode: existing.sessionMode ?? "agent",
327
318
  createInterventions: () => [
328
319
  createAcpToolApprovalIntervention(this.#connection, params.sessionId, () => this.#sessions.get(params.sessionId)?.streamedToolCallIds ??
329
320
  EMPTY_STREAMED_TOOL_CALL_IDS),
330
321
  ],
331
322
  acp: {
332
323
  mcpServers,
333
- ...(clientSystemPrompt ? { systemPrompt: clientSystemPrompt } : {}),
334
324
  },
335
325
  }, false, createSessionConfig());
336
326
  const config = bootConfig;
@@ -366,9 +356,6 @@ export class AcpAgent {
366
356
  cwd: params.cwd,
367
357
  updatedAt: new Date().toISOString(),
368
358
  ...(fromRequest !== undefined ? { userId: fromRequest || null } : {}),
369
- ...(requestedSystemPrompt !== undefined
370
- ? { systemPrompt: requestedSystemPrompt || null }
371
- : {}),
372
359
  mcpServers,
373
360
  });
374
361
  return {
@@ -415,14 +402,13 @@ export class AcpAgent {
415
402
  userId: bootstrapUserId,
416
403
  sessionId,
417
404
  yolo: isYoloEnabled(rec.agent),
418
- sessionMode: getModeState(rec.agent).mode,
405
+ mode: getModeState(rec.agent).mode,
419
406
  createInterventions: () => [
420
407
  createAcpToolApprovalIntervention(this.#connection, sessionId, () => this.#sessions.get(sessionId)?.streamedToolCallIds ??
421
408
  EMPTY_STREAMED_TOOL_CALL_IDS),
422
409
  ],
423
410
  acp: {
424
411
  mcpServers,
425
- ...(meta.systemPrompt ? { systemPrompt: meta.systemPrompt } : {}),
426
412
  },
427
413
  }, false, rec.config);
428
414
  const config = bootConfig;