agent-world 0.12.3 → 0.15.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 (263) hide show
  1. package/README.md +105 -17
  2. package/dist/cli/commands.d.ts +7 -1
  3. package/dist/cli/commands.js +27 -10
  4. package/dist/cli/hitl.d.ts +9 -2
  5. package/dist/cli/hitl.js +61 -20
  6. package/dist/cli/index.js +250 -96
  7. package/dist/cli/system-events.d.ts +27 -0
  8. package/dist/cli/system-events.js +63 -0
  9. package/dist/core/activity-tracker.d.ts +38 -2
  10. package/dist/core/activity-tracker.d.ts.map +1 -1
  11. package/dist/core/activity-tracker.js +62 -9
  12. package/dist/core/activity-tracker.js.map +1 -1
  13. package/dist/core/anthropic-direct.d.ts +2 -0
  14. package/dist/core/anthropic-direct.d.ts.map +1 -1
  15. package/dist/core/anthropic-direct.js +43 -1
  16. package/dist/core/anthropic-direct.js.map +1 -1
  17. package/dist/core/chat-constants.d.ts +12 -0
  18. package/dist/core/chat-constants.d.ts.map +1 -1
  19. package/dist/core/chat-constants.js +5 -0
  20. package/dist/core/chat-constants.js.map +1 -1
  21. package/dist/core/create-agent-tool.d.ts +28 -25
  22. package/dist/core/create-agent-tool.d.ts.map +1 -1
  23. package/dist/core/create-agent-tool.js +264 -141
  24. package/dist/core/create-agent-tool.js.map +1 -1
  25. package/dist/core/events/index.d.ts +5 -2
  26. package/dist/core/events/index.d.ts.map +1 -1
  27. package/dist/core/events/index.js +5 -2
  28. package/dist/core/events/index.js.map +1 -1
  29. package/dist/core/events/memory-manager.d.ts +26 -1
  30. package/dist/core/events/memory-manager.d.ts.map +1 -1
  31. package/dist/core/events/memory-manager.js +877 -72
  32. package/dist/core/events/memory-manager.js.map +1 -1
  33. package/dist/core/events/orchestrator.d.ts +8 -0
  34. package/dist/core/events/orchestrator.d.ts.map +1 -1
  35. package/dist/core/events/orchestrator.js +214 -38
  36. package/dist/core/events/orchestrator.js.map +1 -1
  37. package/dist/core/events/persistence.d.ts +21 -14
  38. package/dist/core/events/persistence.d.ts.map +1 -1
  39. package/dist/core/events/persistence.js +100 -61
  40. package/dist/core/events/persistence.js.map +1 -1
  41. package/dist/core/events/publishers.d.ts +13 -16
  42. package/dist/core/events/publishers.d.ts.map +1 -1
  43. package/dist/core/events/publishers.js +54 -55
  44. package/dist/core/events/publishers.js.map +1 -1
  45. package/dist/core/events/subscribers.d.ts +17 -14
  46. package/dist/core/events/subscribers.d.ts.map +1 -1
  47. package/dist/core/events/subscribers.js +68 -147
  48. package/dist/core/events/subscribers.js.map +1 -1
  49. package/dist/core/events/title-scheduler.d.ts +27 -0
  50. package/dist/core/events/title-scheduler.d.ts.map +1 -0
  51. package/dist/core/events/title-scheduler.js +135 -0
  52. package/dist/core/events/title-scheduler.js.map +1 -0
  53. package/dist/core/events/tool-bridge-logging.d.ts +4 -1
  54. package/dist/core/events/tool-bridge-logging.d.ts.map +1 -1
  55. package/dist/core/events/tool-bridge-logging.js +112 -13
  56. package/dist/core/events/tool-bridge-logging.js.map +1 -1
  57. package/dist/core/events-metadata.d.ts.map +1 -1
  58. package/dist/core/events-metadata.js +8 -4
  59. package/dist/core/events-metadata.js.map +1 -1
  60. package/dist/core/export.d.ts +1 -1
  61. package/dist/core/export.d.ts.map +1 -1
  62. package/dist/core/export.js +2 -15
  63. package/dist/core/export.js.map +1 -1
  64. package/dist/core/feature-path-logging.d.ts +50 -0
  65. package/dist/core/feature-path-logging.d.ts.map +1 -0
  66. package/dist/core/feature-path-logging.js +130 -0
  67. package/dist/core/feature-path-logging.js.map +1 -0
  68. package/dist/core/file-tools.d.ts +57 -1
  69. package/dist/core/file-tools.d.ts.map +1 -1
  70. package/dist/core/file-tools.js +329 -29
  71. package/dist/core/file-tools.js.map +1 -1
  72. package/dist/core/google-direct.d.ts +6 -1
  73. package/dist/core/google-direct.d.ts.map +1 -1
  74. package/dist/core/google-direct.js +76 -7
  75. package/dist/core/google-direct.js.map +1 -1
  76. package/dist/core/heartbeat.d.ts +34 -0
  77. package/dist/core/heartbeat.d.ts.map +1 -0
  78. package/dist/core/heartbeat.js +153 -0
  79. package/dist/core/heartbeat.js.map +1 -0
  80. package/dist/core/hitl-tool.d.ts +73 -0
  81. package/dist/core/hitl-tool.d.ts.map +1 -0
  82. package/dist/core/hitl-tool.js +284 -0
  83. package/dist/core/hitl-tool.js.map +1 -0
  84. package/dist/core/hitl.d.ts +85 -8
  85. package/dist/core/hitl.d.ts.map +1 -1
  86. package/dist/core/hitl.js +375 -61
  87. package/dist/core/hitl.js.map +1 -1
  88. package/dist/core/index.d.ts +12 -7
  89. package/dist/core/index.d.ts.map +1 -1
  90. package/dist/core/index.js +11 -6
  91. package/dist/core/index.js.map +1 -1
  92. package/dist/core/llm-manager.d.ts +17 -0
  93. package/dist/core/llm-manager.d.ts.map +1 -1
  94. package/dist/core/llm-manager.js +335 -43
  95. package/dist/core/llm-manager.js.map +1 -1
  96. package/dist/core/load-skill-tool.d.ts +36 -3
  97. package/dist/core/load-skill-tool.d.ts.map +1 -1
  98. package/dist/core/load-skill-tool.js +807 -93
  99. package/dist/core/load-skill-tool.js.map +1 -1
  100. package/dist/core/logger.d.ts +14 -0
  101. package/dist/core/logger.d.ts.map +1 -1
  102. package/dist/core/logger.js +15 -0
  103. package/dist/core/logger.js.map +1 -1
  104. package/dist/core/managers.d.ts +41 -52
  105. package/dist/core/managers.d.ts.map +1 -1
  106. package/dist/core/managers.js +422 -533
  107. package/dist/core/managers.js.map +1 -1
  108. package/dist/core/mcp-server-registry.d.ts +19 -2
  109. package/dist/core/mcp-server-registry.d.ts.map +1 -1
  110. package/dist/core/mcp-server-registry.js +168 -12
  111. package/dist/core/mcp-server-registry.js.map +1 -1
  112. package/dist/core/message-cutoff.d.ts +29 -0
  113. package/dist/core/message-cutoff.d.ts.map +1 -0
  114. package/dist/core/message-cutoff.js +63 -0
  115. package/dist/core/message-cutoff.js.map +1 -0
  116. package/dist/core/message-edit-manager.d.ts +54 -0
  117. package/dist/core/message-edit-manager.d.ts.map +1 -0
  118. package/dist/core/message-edit-manager.js +602 -0
  119. package/dist/core/message-edit-manager.js.map +1 -0
  120. package/dist/core/message-prep.d.ts +2 -0
  121. package/dist/core/message-prep.d.ts.map +1 -1
  122. package/dist/core/message-prep.js +39 -12
  123. package/dist/core/message-prep.js.map +1 -1
  124. package/dist/core/message-processing-control.d.ts +1 -0
  125. package/dist/core/message-processing-control.d.ts.map +1 -1
  126. package/dist/core/message-processing-control.js +23 -6
  127. package/dist/core/message-processing-control.js.map +1 -1
  128. package/dist/core/openai-direct.d.ts +9 -3
  129. package/dist/core/openai-direct.d.ts.map +1 -1
  130. package/dist/core/openai-direct.js +267 -33
  131. package/dist/core/openai-direct.js.map +1 -1
  132. package/dist/core/optional-tracers/opik-runtime.d.ts +32 -0
  133. package/dist/core/optional-tracers/opik-runtime.d.ts.map +1 -0
  134. package/dist/core/optional-tracers/opik-runtime.js +141 -0
  135. package/dist/core/optional-tracers/opik-runtime.js.map +1 -0
  136. package/dist/core/queue-manager.d.ts +84 -0
  137. package/dist/core/queue-manager.d.ts.map +1 -0
  138. package/dist/core/queue-manager.js +814 -0
  139. package/dist/core/queue-manager.js.map +1 -0
  140. package/dist/core/reasoning-controls.d.ts +30 -0
  141. package/dist/core/reasoning-controls.d.ts.map +1 -0
  142. package/dist/core/reasoning-controls.js +118 -0
  143. package/dist/core/reasoning-controls.js.map +1 -0
  144. package/dist/core/reliability-config.d.ts +82 -0
  145. package/dist/core/reliability-config.d.ts.map +1 -0
  146. package/dist/core/reliability-config.js +106 -0
  147. package/dist/core/reliability-config.js.map +1 -0
  148. package/dist/core/reliability-runtime.d.ts +53 -0
  149. package/dist/core/reliability-runtime.d.ts.map +1 -0
  150. package/dist/core/reliability-runtime.js +92 -0
  151. package/dist/core/reliability-runtime.js.map +1 -0
  152. package/dist/core/security/guardrails.d.ts +21 -0
  153. package/dist/core/security/guardrails.d.ts.map +1 -0
  154. package/dist/core/security/guardrails.js +111 -0
  155. package/dist/core/security/guardrails.js.map +1 -0
  156. package/dist/core/send-message-tool.d.ts +79 -0
  157. package/dist/core/send-message-tool.d.ts.map +1 -0
  158. package/dist/core/send-message-tool.js +222 -0
  159. package/dist/core/send-message-tool.js.map +1 -0
  160. package/dist/core/shell-cmd-tool.d.ts +82 -1
  161. package/dist/core/shell-cmd-tool.d.ts.map +1 -1
  162. package/dist/core/shell-cmd-tool.js +854 -42
  163. package/dist/core/shell-cmd-tool.js.map +1 -1
  164. package/dist/core/skill-registry.d.ts +2 -0
  165. package/dist/core/skill-registry.d.ts.map +1 -1
  166. package/dist/core/skill-registry.js +52 -2
  167. package/dist/core/skill-registry.js.map +1 -1
  168. package/dist/core/storage/eventStorage/fileEventStorage.d.ts +5 -0
  169. package/dist/core/storage/eventStorage/fileEventStorage.d.ts.map +1 -1
  170. package/dist/core/storage/eventStorage/fileEventStorage.js +61 -0
  171. package/dist/core/storage/eventStorage/fileEventStorage.js.map +1 -1
  172. package/dist/core/storage/eventStorage/memoryEventStorage.d.ts +5 -0
  173. package/dist/core/storage/eventStorage/memoryEventStorage.d.ts.map +1 -1
  174. package/dist/core/storage/eventStorage/memoryEventStorage.js +34 -0
  175. package/dist/core/storage/eventStorage/memoryEventStorage.js.map +1 -1
  176. package/dist/core/storage/eventStorage/sqliteEventStorage.d.ts +1 -0
  177. package/dist/core/storage/eventStorage/sqliteEventStorage.d.ts.map +1 -1
  178. package/dist/core/storage/eventStorage/sqliteEventStorage.js +19 -2
  179. package/dist/core/storage/eventStorage/sqliteEventStorage.js.map +1 -1
  180. package/dist/core/storage/eventStorage/types.d.ts +6 -0
  181. package/dist/core/storage/eventStorage/types.d.ts.map +1 -1
  182. package/dist/core/storage/eventStorage/types.js +1 -0
  183. package/dist/core/storage/eventStorage/types.js.map +1 -1
  184. package/dist/core/storage/eventStorage/validation.d.ts.map +1 -1
  185. package/dist/core/storage/eventStorage/validation.js +2 -1
  186. package/dist/core/storage/eventStorage/validation.js.map +1 -1
  187. package/dist/core/storage/github-world-import.d.ts +84 -0
  188. package/dist/core/storage/github-world-import.d.ts.map +1 -0
  189. package/dist/core/storage/github-world-import.js +365 -0
  190. package/dist/core/storage/github-world-import.js.map +1 -0
  191. package/dist/core/storage/memory-storage.d.ts +19 -8
  192. package/dist/core/storage/memory-storage.d.ts.map +1 -1
  193. package/dist/core/storage/memory-storage.js +147 -49
  194. package/dist/core/storage/memory-storage.js.map +1 -1
  195. package/dist/core/storage/queue-storage.d.ts +1 -0
  196. package/dist/core/storage/queue-storage.d.ts.map +1 -1
  197. package/dist/core/storage/queue-storage.js +3 -2
  198. package/dist/core/storage/queue-storage.js.map +1 -1
  199. package/dist/core/storage/sqlite-storage.d.ts +14 -9
  200. package/dist/core/storage/sqlite-storage.d.ts.map +1 -1
  201. package/dist/core/storage/sqlite-storage.js +131 -154
  202. package/dist/core/storage/sqlite-storage.js.map +1 -1
  203. package/dist/core/storage/storage-factory.d.ts +3 -0
  204. package/dist/core/storage/storage-factory.d.ts.map +1 -1
  205. package/dist/core/storage/storage-factory.js +175 -89
  206. package/dist/core/storage/storage-factory.js.map +1 -1
  207. package/dist/core/storage/world-storage.d.ts +1 -1
  208. package/dist/core/storage/world-storage.d.ts.map +1 -1
  209. package/dist/core/storage/world-storage.js +5 -1
  210. package/dist/core/storage/world-storage.js.map +1 -1
  211. package/dist/core/storage-init.d.ts +11 -0
  212. package/dist/core/storage-init.d.ts.map +1 -0
  213. package/dist/core/storage-init.js +122 -0
  214. package/dist/core/storage-init.js.map +1 -0
  215. package/dist/core/subscription.d.ts +8 -1
  216. package/dist/core/subscription.d.ts.map +1 -1
  217. package/dist/core/subscription.js +130 -23
  218. package/dist/core/subscription.js.map +1 -1
  219. package/dist/core/tool-approval.d.ts +45 -0
  220. package/dist/core/tool-approval.d.ts.map +1 -0
  221. package/dist/core/tool-approval.js +223 -0
  222. package/dist/core/tool-approval.js.map +1 -0
  223. package/dist/core/tool-execution-envelope.d.ts +87 -0
  224. package/dist/core/tool-execution-envelope.d.ts.map +1 -0
  225. package/dist/core/tool-execution-envelope.js +168 -0
  226. package/dist/core/tool-execution-envelope.js.map +1 -0
  227. package/dist/core/tool-utils.d.ts +9 -2
  228. package/dist/core/tool-utils.d.ts.map +1 -1
  229. package/dist/core/tool-utils.js +122 -28
  230. package/dist/core/tool-utils.js.map +1 -1
  231. package/dist/core/types.d.ts +69 -36
  232. package/dist/core/types.d.ts.map +1 -1
  233. package/dist/core/types.js +3 -2
  234. package/dist/core/types.js.map +1 -1
  235. package/dist/core/utils.d.ts +16 -0
  236. package/dist/core/utils.d.ts.map +1 -1
  237. package/dist/core/utils.js +99 -24
  238. package/dist/core/utils.js.map +1 -1
  239. package/dist/core/web-fetch-tool.d.ts +72 -0
  240. package/dist/core/web-fetch-tool.d.ts.map +1 -0
  241. package/dist/core/web-fetch-tool.js +491 -0
  242. package/dist/core/web-fetch-tool.js.map +1 -0
  243. package/dist/core/world-registry.d.ts +84 -0
  244. package/dist/core/world-registry.d.ts.map +1 -0
  245. package/dist/core/world-registry.js +247 -0
  246. package/dist/core/world-registry.js.map +1 -0
  247. package/dist/public/assets/index-Be-1xtV-.js +104 -0
  248. package/dist/public/assets/index-tsDdiXDU.css +1 -0
  249. package/dist/public/index.html +2 -2
  250. package/dist/public/mcp-sandbox-proxy.html +148 -0
  251. package/dist/server/api.js +288 -58
  252. package/dist/server/error-response.d.ts +27 -0
  253. package/dist/server/error-response.js +77 -0
  254. package/dist/server/index.d.ts +2 -1
  255. package/dist/server/index.js +6 -2
  256. package/dist/server/sse-handler.d.ts +13 -2
  257. package/dist/server/sse-handler.js +194 -26
  258. package/migrations/0015_add_message_queue.sql +36 -0
  259. package/migrations/0016_add_world_heartbeat.sql +13 -0
  260. package/migrations/0017_add_title_provenance.sql +7 -0
  261. package/package.json +31 -10
  262. package/dist/public/assets/index-BO20H4xt.js +0 -96
  263. package/dist/public/assets/index-ETY7W5_S.css +0 -1
package/README.md CHANGED
@@ -37,25 +37,31 @@ Paste that prompt. Agents come alive instantly.
37
37
  - ✅ Built-in Rules for Messages - Turn limits to prevent loops
38
38
  - ✅ Concurrent Chat Sessions - Isolated `chatId` routing enables parallel conversations
39
39
  - ✅ Progressive Agent Skills - Skills are discovered and loaded on demand via `load_skill`
40
+ - ✅ World-Level Tool Permissions - `Read`, `Ask`, and `Auto` modes control write and execution capabilities
40
41
  - ✅ Cross-Client HITL Approval - Option-based approvals in CLI, Web, and Electron
42
+ - ✅ Reasoning Controls - World-scoped reasoning effort with separate reasoning-token rendering
43
+ - ✅ Heartbeats & Queueing - Queue-backed world prompts and cron scheduling with explicit controls
44
+ - ✅ Marketplace & Imports - Bring in worlds, agents, and skills from local folders or curated GitHub sources
41
45
  - ✅ Runtime Controls - Session-scoped send/stop flows and tool lifecycle visibility
42
46
  - ✅ Safer Tool Execution - Trusted-CWD and argument-scope guards for `shell_cmd`
43
47
  - ✅ Multiple AI Providers - Use different models for different agents
44
48
  - ✅ Web + CLI + Electron - Modern interfaces with real-time streaming and status feedback
45
49
 
46
- ## Latest Highlights (since v0.11.1)
50
+ ## Latest Highlights (v0.15.0)
47
51
 
48
- - Web app now includes a Settings page, chat-history search, and branch-from-message workflow
49
- - Built-in `create_agent` tool now supports approval-first creation and inherits world chat defaults
50
- - File exploration is easier with built-in `read_file`, `list_files` (including recursive mode), and `grep`
51
- - Electron now supports folder-based world import/export with validation and conflict handling
52
- - Chat UX is smoother with clearer inline working status, better streaming feedback, and UI refinements
53
- - Real-time refresh behavior is improved across web and desktop when agents/world data changes
52
+ - World-level tool permissions add `Read`, `Ask`, and `Auto` control modes in both the web and Electron composers
53
+ - Supported providers can use world-scoped `reasoning_effort`, with reasoning tokens streamed and rendered separately from final answers
54
+ - World and heartbeat prompts now enter the same queue-backed message flow as human turns, with explicit heartbeat controls and next-run visibility
55
+ - Electron now includes marketplace-style import flows for discovering and importing worlds, agents, and skills
56
+ - Web and Electron transcripts have tighter parity with compact tool rows, improved status rendering, and cleaner working indicators
57
+ - Clicking markdown links in Electron messages now opens the external browser instead of attempting in-app navigation
54
58
 
55
59
  ## Release Notes
56
60
 
61
+ - **v0.15.0** - Tool permission modes, reasoning-token support, queue-backed world/heartbeat flow, marketplace imports, and transcript/UI refinements
62
+ - **v0.14.0** - User message queue, `write_file`/`web_fetch`/`send_message`, shell risk gating, E2E harnesses, skill editor, and heartbeat scheduling
63
+ - **v0.13.0** - Better HITL prompts, improved streaming/main-agent UX, and smoother message rendering
57
64
  - **v0.12.0** - Web settings/search/branching, built-in `create_agent`, new file tools, Electron folder import/export, and chat/status UX improvements
58
- - **v0.11.0** - Electron desktop workflow, concurrent chat sessions, main-agent routing, progressive skills + HITL, and runtime safety hardening
59
65
  - Full history: [CHANGELOG.md](CHANGELOG.md)
60
66
 
61
67
  ## What You Can Build
@@ -102,25 +108,24 @@ Each Agent World has a collection of agents that can communicate through a share
102
108
 
103
109
  ### Message Rules
104
110
 
105
- | Message Type | Example | Who Responds |
111
+ | Message Shape | Example | Who Responds |
106
112
  |--------------|---------|--------------|
107
- | **Human message** | `Hello everyone!` | All active agents |
108
- | **Direct mention** | `@alice Can you help?` | Only @alice |
109
- | **Paragraph mention** | `Please review this:\n@alice` | Only @alice |
110
- | **Mid-text mention** | `I think @alice should help` | Nobody (event is persisted; no agent-memory save) |
113
+ | **Public human or world message** | `Hello everyone!` | All active agents |
114
+ | **Paragraph-start mention** | `@alice Can you help?` | Only mentioned agents |
115
+ | **Paragraph-start mention after text** | `Please review this:\n@alice` | Only mentioned agents |
116
+ | **Mid-text mention only** | `I think @alice should help` | Nobody (event is persisted; no agent-memory save) |
111
117
  | **Stop World** | `<world>pass</world>` | No agents |
112
118
 
113
119
  ### Agent Behavior
114
120
 
115
121
  **Agents always respond to:**
116
- - Human messages (unless mentioned agents exist)
122
+ - Public human or world messages when there is no paragraph-start mention
117
123
  - Direct @mentions at paragraph start
118
- - World messages
119
124
 
120
125
  **Agents never respond to:**
121
126
  - Their own messages
122
127
  - Other agents (unless @mentioned at paragraph start)
123
- - Mid-text mentions (not at paragraph start)
128
+ - Mid-text mentions (not at paragraph start), including world prompts
124
129
 
125
130
  **When messages are saved to agent memory:**
126
131
  - Incoming messages are saved only for agents that will respond
@@ -169,7 +174,13 @@ npm run electron:dev
169
174
 
170
175
  ## Project Structure
171
176
 
172
- See [Project Structure Documentation](project.md)
177
+ - `core/` - shared runtime, storage, tools, provider integrations, and event flow
178
+ - `server/` - REST API and SSE transport
179
+ - `web/` - browser app
180
+ - `electron/` - desktop app (main, preload, renderer)
181
+ - `cli/` - terminal interface
182
+
183
+ For broader architecture and usage docs, start with [Docs Home](docs/docs-home.md).
173
184
 
174
185
  ## Development Scripts
175
186
 
@@ -237,6 +248,38 @@ AZURE_OPENAI_API_VERSION=2024-10-21-preview
237
248
  OLLAMA_BASE_URL=http://localhost:11434
238
249
  ```
239
250
 
251
+ ### Optional Opik Layer
252
+
253
+ Opik is optional and fully gated.
254
+
255
+ ```bash
256
+ OPIK_ENABLED=false
257
+ OPIK_SAFETY_ENABLED=false
258
+ OPIK_EVAL_ENABLED=false
259
+ OPIK_API_KEY=
260
+ OPIK_WORKSPACE=
261
+ OPIK_PROJECT=agent-world-debugging
262
+ ```
263
+
264
+ Rules:
265
+ - `OPIK_ENABLED=false`: all Opik integration/safety/eval paths are inert.
266
+ - `OPIK_ENABLED=true`: tracing can attach only if `OPIK_API_KEY` + `OPIK_WORKSPACE` are set.
267
+ - Safety and eval still require their sub-flags (`OPIK_SAFETY_ENABLED`, `OPIK_EVAL_ENABLED`).
268
+
269
+ #### Fallback Behavior
270
+
271
+ When Opik is enabled but something is missing, startup always continues normally — no crashes.
272
+
273
+ | Condition | Result | Log |
274
+ |-----------|--------|-----|
275
+ | `OPIK_ENABLED=false` | No Opik code runs | none |
276
+ | Enabled but `OPIK_API_KEY` or `OPIK_WORKSPACE` missing | Tracer skipped | warning: `Opik enabled but required env is missing` |
277
+ | Enabled + config present but `packages/opik` not installed | Tracer skipped | warning: `Opik enabled but optional dependency is unavailable` |
278
+ | Enabled + config present + module loaded but tracer init fails | Tracer skipped | warning: `Opik module loaded but tracer initialization failed` |
279
+ | Enabled + config present + module loaded + tracer created | Tracer attaches to world | info: `Opik tracer attached` |
280
+
281
+ Opik is storage-agnostic — it attaches to `world.eventEmitter` and works identically with sqlite, file, or memory storage backends.
282
+
240
283
  ## Testing
241
284
 
242
285
  **Run all tests:**
@@ -245,6 +288,7 @@ npm test # Run all unit tests
245
288
  npm run test:watch # Watch mode with hot reload
246
289
  npm run test:ui # Visual test UI
247
290
  npm run test:coverage # Generate coverage report
291
+ npm run test:coverage:gate # Coverage + core threshold gate + subsystem scorecard
248
292
  ```
249
293
 
250
294
  **Run specific tests:**
@@ -256,10 +300,23 @@ npm test -- message-saving # Test files matching pattern
256
300
  **Integration tests:**
257
301
  ```bash
258
302
  npm run test:integration # Run integration tests with real filesystem
303
+ npm run ci:test # CI gate: coverage threshold + integration
259
304
  ```
260
305
 
261
306
  Agent World uses Vitest for fast, modern testing with native TypeScript support.
262
307
 
308
+ ### Coverage Gates
309
+
310
+ `npm run test:coverage:gate` enforces minimum core coverage thresholds and generates a subsystem scorecard:
311
+ - core statements >= 68%
312
+ - core branches >= 56%
313
+ - core functions >= 75%
314
+ - core lines >= 69%
315
+
316
+ The scorecard is written to:
317
+ - `coverage/scorecard.md`
318
+ - `coverage/scorecard.json`
319
+
263
320
  ## Logging and Debugging
264
321
 
265
322
  Agent World uses **scenario-based logging** to help you debug specific issues without noise. Enable only the logs you need for your current task.
@@ -275,6 +332,9 @@ LOG_MCP=debug npm run web:dev
275
332
 
276
333
  # Agent response debugging
277
334
  LOG_EVENTS_AGENT=debug LOG_LLM=debug npm run web:dev
335
+
336
+ # Chat restore/HITL replay debugging
337
+ LOG_CHAT_RESTORE=debug LOG_CHAT_RESTORE_RESUME=debug LOG_CHAT_RESTORE_RESUME_TOOLS=debug LOG_HITL=debug npm run web:dev
278
338
  ```
279
339
 
280
340
  **For complete logging documentation**, see [Logging Guide](docs/logging-guide.md).
@@ -299,6 +359,7 @@ export AGENT_WORLD_DATA_PATH=./data/worlds
299
359
  - **[Building Agents with Just Words](docs/Building%20Agents%20with%20Just%20Words.md)** - Complete guide with examples
300
360
  - **[Shell Command Tool (shell_cmd)](docs/shell-cmd-tool.md)** - Built-in tool for executing shell commands
301
361
  - **[HITL Approval Flow](docs/hitl-approval-flow.md)** - Option-based approval flow across Core/Electron/Web/CLI
362
+ - **[API Reference](openapi.yaml)** - OpenAPI 3.1 spec for the REST API
302
363
  - **[Using Core from npm](docs/core-npm-usage.md)** - Integration guide for server and browser apps
303
364
  - **[Electron Desktop App](docs/electron-desktop.md)** - Open-folder workflow and local world creation
304
365
 
@@ -307,6 +368,17 @@ export AGENT_WORLD_DATA_PATH=./data/worlds
307
368
 
308
369
  Agent World includes built-in tools that are automatically available to all agents:
309
370
 
371
+ - `read_file`, `list_files`, `grep` - inspect project files and source trees
372
+ - `write_file` - update files inside trusted workspace scope
373
+ - `web_fetch` - fetch web pages and convert them to Markdown for agent use
374
+ - `send_message` - dispatch trusted chat-context messages to other agents
375
+ - `create_agent` - create new agents during a conversation
376
+ - `shell_cmd` - run shell commands with trusted-scope validation and lifecycle controls
377
+ - `load_skill` - progressively load `SKILL.md` instructions and related scripts
378
+ - `human_intervention_request` - ask the user for structured options and approvals
379
+
380
+ World owners can set built-in tool access to `Read`, `Ask`, or `Auto` so write/execute actions are blocked, approval-gated, or automatic depending on the world.
381
+
310
382
  ### shell_cmd
311
383
  Execute shell commands with full output capture and execution history. Perfect for file operations, system information, and automation tasks.
312
384
 
@@ -333,6 +405,7 @@ Agent World includes progressive skill loading through the `load_skill` built-in
333
405
  - User roots: `~/.agents/skills`, `~/.codex/skills`
334
406
  - The model receives compact skill summaries first, then calls `load_skill` only when full instructions are needed.
335
407
  - Skill activation in interactive runtimes is HITL-gated.
408
+ - `load_skill` always performs the same preflight flow: script references are discovered from instructions, script execution is HITL-approved and scope-validated, and reference-file context is collected when active resources are present.
336
409
 
337
410
  Minimal `SKILL.md` example:
338
411
 
@@ -355,6 +428,21 @@ HITL options for skill activation:
355
428
  - `yes_in_session`: approve this `skill_id` in the current world/chat session
356
429
  - `no`: decline
357
430
 
431
+ ### human_intervention_request (Generic Human Input)
432
+
433
+ `human_intervention_request` lets the model ask a human question, present options, and optionally require explicit confirmation.
434
+ The tool is options-only (no free-text mode).
435
+
436
+ Option example:
437
+
438
+ ```json
439
+ {
440
+ "question": "Choose deployment strategy",
441
+ "options": ["Blue/Green", "Canary", "Rolling"],
442
+ "requireConfirmation": true
443
+ }
444
+ ```
445
+
358
446
  ## Experimental Features
359
447
 
360
448
  - **MCP Support** - *Currently in experiment* - Model Context Protocol integration for tools like search and code execution. e.g.,
@@ -43,6 +43,11 @@
43
43
  * - Creates target directory if it doesn't exist
44
44
  * - Supports migration between storage types
45
45
  * - Event history preserved across different storage backends
46
+ *
47
+ * Recent Changes:
48
+ * - 2026-03-06: Removed runtime message/export fallback to `world.currentChatId`; CLI execution now requires explicit selected chat state.
49
+ * - 2026-03-10: Switched CLI user message send path to the queue-only `enqueueAndProcessUserTurn` API.
50
+ * - 2026-03-04: Added queue metadata (`messageId`, `queueStatus`, `queueRetryCount`) to successful message-send CLI results for queue error visibility.
46
51
  */
47
52
  import { World } from '../core/types.js';
48
53
  export interface CLIResponse {
@@ -57,6 +62,7 @@ export interface CLIResponse {
57
62
  export interface CLIContext {
58
63
  currentWorldName?: string;
59
64
  currentWorld?: World | null;
65
+ selectedChatId?: string | null;
60
66
  }
61
67
  export type PromptFunction = (question: string, options?: string[]) => Promise<string>;
62
68
  /**
@@ -105,5 +111,5 @@ export declare function deleteExistingData(targetPath: string, storageType: 'fil
105
111
  }>;
106
112
  export declare function performWorldSave(world: World, storageType: 'file' | 'sqlite', targetPath: string): Promise<CLIResponse>;
107
113
  export declare function processCLICommand(input: string, context: CLIContext, promptFn: PromptFunction): Promise<CLIResponse>;
108
- export declare function processCLIInput(input: string, world: World | null, sender?: string): Promise<CLIResponse>;
114
+ export declare function processCLIInput(input: string, world: World | null, sender?: string, selectedChatId?: string | null): Promise<CLIResponse>;
109
115
  export {};
@@ -43,8 +43,13 @@
43
43
  * - Creates target directory if it doesn't exist
44
44
  * - Supports migration between storage types
45
45
  * - Event history preserved across different storage backends
46
+ *
47
+ * Recent Changes:
48
+ * - 2026-03-06: Removed runtime message/export fallback to `world.currentChatId`; CLI execution now requires explicit selected chat state.
49
+ * - 2026-03-10: Switched CLI user message send path to the queue-only `enqueueAndProcessUserTurn` API.
50
+ * - 2026-03-04: Added queue metadata (`messageId`, `queueStatus`, `queueRetryCount`) to successful message-send CLI results for queue error visibility.
46
51
  */
47
- import { LLMProvider, createWorld, getWorld, updateWorld, publishMessage, listWorlds, deleteWorld, listAgents, getAgent, updateAgent, deleteAgent, createAgent, clearAgentMemory, listChats, updateChat, exportWorldToMarkdown, exportChatToMarkdown, newChat, restoreChat, deleteChat, getMemory } from '../core/index.js';
52
+ import { LLMProvider, createWorld, getWorld, updateWorld, enqueueAndProcessUserTurn, listWorlds, deleteWorld, listAgents, getAgent, updateAgent, deleteAgent, createAgent, clearAgentMemory, listChats, updateChat, exportWorldToMarkdown, exportChatToMarkdown, newChat, restoreChat, deleteChat, getMemory } from '../core/index.js';
48
53
  import { createStorage } from '../core/storage/storage-factory.js';
49
54
  import { createCategoryLogger } from '../core/logger.js';
50
55
  import readline from 'readline';
@@ -83,7 +88,12 @@ const boldRed = (text) => `\x1b[1m\x1b[31m${text}\x1b[0m`;
83
88
  */
84
89
  export async function displayChatMessages(worldId, chatId) {
85
90
  try {
86
- const messages = await getMemory(worldId, chatId);
91
+ const resolvedChatId = String(chatId || '').trim();
92
+ if (!resolvedChatId) {
93
+ console.log(gray('\n No active chat selected.\n'));
94
+ return;
95
+ }
96
+ const messages = await getMemory(worldId, resolvedChatId);
87
97
  if (!messages || messages.length === 0) {
88
98
  console.log(gray('\n No messages in current chat.\n'));
89
99
  return;
@@ -1900,7 +1910,7 @@ export async function processCLICommand(input, context, promptFn) {
1900
1910
  const worldError = requireWorldOrError(world, command);
1901
1911
  if (worldError)
1902
1912
  return worldError;
1903
- const chatId = collectedParams.chatId || world.currentChatId;
1913
+ const chatId = collectedParams.chatId || context.selectedChatId;
1904
1914
  if (!chatId) {
1905
1915
  cliResponse = {
1906
1916
  success: false,
@@ -1946,10 +1956,11 @@ export async function processCLICommand(input, context, promptFn) {
1946
1956
  }
1947
1957
  }
1948
1958
  // Main CLI input processor - handles both commands and messages
1949
- export async function processCLIInput(input, world, sender = 'human') {
1959
+ export async function processCLIInput(input, world, sender = 'human', selectedChatId = null) {
1950
1960
  const context = {
1951
1961
  currentWorld: world,
1952
- currentWorldName: world?.name
1962
+ currentWorldName: world?.name,
1963
+ selectedChatId,
1953
1964
  };
1954
1965
  // Simple prompt function for CLI
1955
1966
  const promptFunction = async (question, options) => {
@@ -1989,7 +2000,7 @@ export async function processCLIInput(input, world, sender = 'human') {
1989
2000
  };
1990
2001
  }
1991
2002
  try {
1992
- const currentChatId = String(world?.currentChatId || '').trim();
2003
+ const currentChatId = String(selectedChatId || '').trim();
1993
2004
  if (!currentChatId) {
1994
2005
  return {
1995
2006
  success: false,
@@ -1998,19 +2009,25 @@ export async function processCLIInput(input, world, sender = 'human') {
1998
2009
  };
1999
2010
  }
2000
2011
  const restoredWorld = await restoreChat(world.id, currentChatId);
2001
- if (!restoredWorld || restoredWorld.currentChatId !== currentChatId) {
2012
+ if (!restoredWorld || !restoredWorld.chats?.has?.(currentChatId)) {
2002
2013
  return {
2003
2014
  success: false,
2004
2015
  message: `Cannot send message - chat not found: ${currentChatId}`,
2005
2016
  technicalDetails: `Failed to restore active chat '${currentChatId}' before message publish`
2006
2017
  };
2007
2018
  }
2008
- publishMessage(world, input, sender, currentChatId);
2019
+ const queuedMessage = await enqueueAndProcessUserTurn(world.id, currentChatId, input, sender, world);
2009
2020
  return {
2010
2021
  success: true,
2011
2022
  message: '',
2012
- data: { sender, chatId: currentChatId },
2013
- technicalDetails: `Message published to world '${world.name}' (chat '${currentChatId}')`
2023
+ data: {
2024
+ sender,
2025
+ chatId: currentChatId,
2026
+ messageId: queuedMessage?.messageId || null,
2027
+ queueStatus: queuedMessage?.status || null,
2028
+ queueRetryCount: typeof queuedMessage?.retryCount === 'number' ? queuedMessage.retryCount : null,
2029
+ },
2030
+ technicalDetails: `Message enqueued for world '${world.name}' (chat '${currentChatId}')`
2014
2031
  };
2015
2032
  }
2016
2033
  catch (error) {
@@ -5,15 +5,17 @@
5
5
  * - Provide pure parsing/selection helpers for HITL option requests used by the CLI.
6
6
  *
7
7
  * Key Features:
8
- * - Parse `hitl-option-request` system payloads into normalized structures.
8
+ * - Parse HITL prompt payloads from tool-progress metadata and pending prompt envelopes.
9
9
  * - Resolve user input into option IDs (by number or option id).
10
10
  * - Provide deterministic fallback option resolution.
11
+ * - Guard duplicate replayed requests via requestId-tracking helper.
11
12
  *
12
13
  * Implementation Notes:
13
14
  * - Parser accepts generic event payloads and rejects incomplete requests.
14
- * - Fallback defaults to explicit `no` when available, otherwise first option.
15
+ * - Option fallback defaults to explicit `no` when available, otherwise first option.
15
16
  *
16
17
  * Recent Changes:
18
+ * - 2026-02-20: Enforced options-only HITL parsing in CLI helpers.
17
19
  * - 2026-02-14: Added initial helper module for CLI HITL response flow support.
18
20
  */
19
21
  export interface HitlOptionPayload {
@@ -26,8 +28,13 @@ export interface HitlOptionRequestPayload {
26
28
  title: string;
27
29
  message: string;
28
30
  chatId: string | null;
31
+ mode: 'option';
29
32
  options: HitlOptionPayload[];
30
33
  defaultOptionId: string;
31
34
  }
35
+ export type HitlPromptRequestPayload = HitlOptionRequestPayload;
36
+ export declare function parseHitlPromptRequest(eventData: unknown): HitlPromptRequestPayload | null;
37
+ export declare function parseHitlPromptFromToolEvent(eventData: unknown): HitlPromptRequestPayload | null;
32
38
  export declare function parseHitlOptionRequest(eventData: unknown): HitlOptionRequestPayload | null;
33
39
  export declare function resolveHitlOptionSelectionInput(options: HitlOptionPayload[], rawInput: string, fallbackOptionId: string): string | null;
40
+ export declare function markHitlRequestHandled(handledRequestIds: Set<string>, requestId: string): boolean;
package/dist/cli/hitl.js CHANGED
@@ -5,34 +5,26 @@
5
5
  * - Provide pure parsing/selection helpers for HITL option requests used by the CLI.
6
6
  *
7
7
  * Key Features:
8
- * - Parse `hitl-option-request` system payloads into normalized structures.
8
+ * - Parse HITL prompt payloads from tool-progress metadata and pending prompt envelopes.
9
9
  * - Resolve user input into option IDs (by number or option id).
10
10
  * - Provide deterministic fallback option resolution.
11
+ * - Guard duplicate replayed requests via requestId-tracking helper.
11
12
  *
12
13
  * Implementation Notes:
13
14
  * - Parser accepts generic event payloads and rejects incomplete requests.
14
- * - Fallback defaults to explicit `no` when available, otherwise first option.
15
+ * - Option fallback defaults to explicit `no` when available, otherwise first option.
15
16
  *
16
17
  * Recent Changes:
18
+ * - 2026-02-20: Enforced options-only HITL parsing in CLI helpers.
17
19
  * - 2026-02-14: Added initial helper module for CLI HITL response flow support.
18
20
  */
19
- export function parseHitlOptionRequest(eventData) {
20
- if (!eventData || typeof eventData !== 'object') {
21
- return null;
22
- }
23
- const payload = eventData;
24
- const content = payload.content && typeof payload.content === 'object'
25
- ? payload.content
26
- : null;
27
- if (!content || String(content.eventType || '').trim() !== 'hitl-option-request') {
28
- return null;
29
- }
30
- const requestId = String(content.requestId || '').trim();
21
+ function normalizePromptPayload(promptData, fallbackChatId) {
22
+ const requestId = String(promptData.requestId || '').trim();
31
23
  if (!requestId) {
32
24
  return null;
33
25
  }
34
- const options = Array.isArray(content.options)
35
- ? content.options
26
+ const options = Array.isArray(promptData.options)
27
+ ? promptData.options
36
28
  .map((option) => {
37
29
  const optionRecord = option && typeof option === 'object'
38
30
  ? option
@@ -48,19 +40,57 @@ export function parseHitlOptionRequest(eventData) {
48
40
  if (options.length === 0) {
49
41
  return null;
50
42
  }
51
- const preferredDefault = String(content.defaultOptionId || '').trim();
43
+ const preferredDefault = String(promptData.defaultOptionId || '').trim();
52
44
  const defaultOptionId = options.some((option) => option.id === preferredDefault)
53
45
  ? preferredDefault
54
46
  : (options.find((option) => option.id === 'no')?.id || options[0].id);
55
47
  return {
56
48
  requestId,
57
- title: String(content.title || 'Approval required').trim() || 'Approval required',
58
- message: String(content.message || '').trim(),
59
- chatId: payload.chatId ? String(payload.chatId) : null,
49
+ title: String(promptData.title || 'Approval required').trim() || 'Approval required',
50
+ message: String(promptData.message || '').trim(),
51
+ chatId: fallbackChatId,
52
+ mode: 'option',
60
53
  options,
61
54
  defaultOptionId
62
55
  };
63
56
  }
57
+ export function parseHitlPromptRequest(eventData) {
58
+ if (!eventData || typeof eventData !== 'object') {
59
+ return null;
60
+ }
61
+ const payload = eventData;
62
+ const prompt = payload.prompt && typeof payload.prompt === 'object'
63
+ ? payload.prompt
64
+ : null;
65
+ if (!prompt) {
66
+ return null;
67
+ }
68
+ const chatId = payload.chatId ? String(payload.chatId) : null;
69
+ return normalizePromptPayload(prompt, chatId);
70
+ }
71
+ export function parseHitlPromptFromToolEvent(eventData) {
72
+ if (!eventData || typeof eventData !== 'object') {
73
+ return null;
74
+ }
75
+ const payload = eventData;
76
+ const toolExecution = payload.toolExecution && typeof payload.toolExecution === 'object'
77
+ ? payload.toolExecution
78
+ : null;
79
+ const metadata = toolExecution?.metadata && typeof toolExecution.metadata === 'object'
80
+ ? toolExecution.metadata
81
+ : null;
82
+ const prompt = metadata?.hitlPrompt && typeof metadata.hitlPrompt === 'object'
83
+ ? metadata.hitlPrompt
84
+ : null;
85
+ if (!toolExecution || !prompt) {
86
+ return null;
87
+ }
88
+ const chatId = prompt.chatId ? String(prompt.chatId) : (payload.chatId ? String(payload.chatId) : null);
89
+ return normalizePromptPayload(prompt, chatId);
90
+ }
91
+ export function parseHitlOptionRequest(eventData) {
92
+ return parseHitlPromptRequest(eventData);
93
+ }
64
94
  export function resolveHitlOptionSelectionInput(options, rawInput, fallbackOptionId) {
65
95
  const normalizedInput = String(rawInput || '').trim();
66
96
  if (!normalizedInput) {
@@ -79,3 +109,14 @@ export function resolveHitlOptionSelectionInput(options, rawInput, fallbackOptio
79
109
  }
80
110
  return null;
81
111
  }
112
+ export function markHitlRequestHandled(handledRequestIds, requestId) {
113
+ const normalizedRequestId = String(requestId || '').trim();
114
+ if (!normalizedRequestId) {
115
+ return false;
116
+ }
117
+ if (handledRequestIds.has(normalizedRequestId)) {
118
+ return false;
119
+ }
120
+ handledRequestIds.add(normalizedRequestId);
121
+ return true;
122
+ }