@chengchenccc/oh-my-agent 0.1.1-rc.3 → 0.2.0-rc.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.
Files changed (327) hide show
  1. package/README.md +5 -4
  2. package/dist/cli/args.d.ts +15 -1
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +81 -3
  5. package/dist/cli/gateway-commands.d.ts +40 -0
  6. package/dist/cli/gateway-commands.d.ts.map +1 -0
  7. package/dist/cli/gateway-commands.js +337 -0
  8. package/dist/cli/initial-input.d.ts +9 -0
  9. package/dist/cli/initial-input.d.ts.map +1 -1
  10. package/dist/cli/initial-input.js +39 -5
  11. package/dist/core/coordination/hub-tool.d.ts +30 -0
  12. package/dist/core/coordination/hub-tool.d.ts.map +1 -0
  13. package/dist/core/coordination/hub-tool.js +251 -0
  14. package/dist/core/coordination/index.d.ts +3 -0
  15. package/dist/core/coordination/index.d.ts.map +1 -0
  16. package/dist/core/coordination/index.js +2 -0
  17. package/dist/core/coordination/registry.d.ts +85 -0
  18. package/dist/core/coordination/registry.d.ts.map +1 -0
  19. package/dist/core/coordination/registry.js +164 -0
  20. package/dist/core/{workflow/workflow-executor.d.ts → delegation/executor.d.ts} +44 -22
  21. package/dist/core/delegation/executor.d.ts.map +1 -0
  22. package/dist/core/delegation/executor.fixture.d.ts +27 -0
  23. package/dist/core/delegation/executor.fixture.d.ts.map +1 -0
  24. package/dist/core/delegation/executor.fixture.js +26 -0
  25. package/dist/core/{workflow/workflow-executor.js → delegation/executor.js} +234 -258
  26. package/dist/core/delegation/pool.d.ts +20 -0
  27. package/dist/core/delegation/pool.d.ts.map +1 -0
  28. package/dist/core/delegation/pool.js +55 -0
  29. package/dist/core/delegation/results.d.ts +22 -0
  30. package/dist/core/delegation/results.d.ts.map +1 -0
  31. package/dist/core/delegation/results.js +138 -0
  32. package/dist/core/{workflow/subagent-registry.d.ts → delegation/roles.d.ts} +4 -4
  33. package/dist/core/delegation/roles.d.ts.map +1 -0
  34. package/dist/core/delegation/tool.d.ts +24 -0
  35. package/dist/core/delegation/tool.d.ts.map +1 -0
  36. package/dist/core/delegation/tool.js +188 -0
  37. package/dist/core/delegation/yield-tool.d.ts +13 -0
  38. package/dist/core/delegation/yield-tool.d.ts.map +1 -0
  39. package/dist/core/delegation/yield-tool.js +34 -0
  40. package/dist/core/gateway/artifact.d.ts +57 -0
  41. package/dist/core/gateway/artifact.d.ts.map +1 -0
  42. package/dist/core/gateway/artifact.js +255 -0
  43. package/dist/core/gateway/daemon.d.ts +43 -0
  44. package/dist/core/gateway/daemon.d.ts.map +1 -0
  45. package/dist/core/gateway/daemon.js +137 -0
  46. package/dist/core/gateway/doctor.d.ts +21 -0
  47. package/dist/core/gateway/doctor.d.ts.map +1 -0
  48. package/dist/core/gateway/doctor.js +405 -0
  49. package/dist/core/gateway/manifest.d.ts +139 -0
  50. package/dist/core/gateway/manifest.d.ts.map +1 -0
  51. package/dist/core/gateway/manifest.js +105 -0
  52. package/dist/core/gateway/supervisor.d.ts +39 -0
  53. package/dist/core/gateway/supervisor.d.ts.map +1 -0
  54. package/dist/core/gateway/supervisor.js +216 -0
  55. package/dist/core/{agent-runtime.d.ts → index.d.ts} +5 -6
  56. package/dist/core/index.d.ts.map +1 -0
  57. package/dist/core/index.js +20 -0
  58. package/dist/core/memory/autonomous-memory.d.ts +14 -0
  59. package/dist/core/memory/autonomous-memory.d.ts.map +1 -1
  60. package/dist/core/memory/autonomous-memory.js +60 -14
  61. package/dist/core/memory/embeddings.d.ts +50 -0
  62. package/dist/core/memory/embeddings.d.ts.map +1 -0
  63. package/dist/core/memory/embeddings.js +385 -0
  64. package/dist/core/memory/learn.d.ts +10 -0
  65. package/dist/core/memory/learn.d.ts.map +1 -0
  66. package/dist/core/memory/learn.js +147 -0
  67. package/dist/core/memory/manage-skill.d.ts +10 -0
  68. package/dist/core/memory/manage-skill.d.ts.map +1 -0
  69. package/dist/core/memory/manage-skill.js +65 -0
  70. package/dist/core/memory/managed-skills.d.ts +39 -0
  71. package/dist/core/memory/managed-skills.d.ts.map +1 -0
  72. package/dist/core/memory/managed-skills.js +167 -0
  73. package/dist/core/memory/vector-memory.d.ts +33 -0
  74. package/dist/core/memory/vector-memory.d.ts.map +1 -0
  75. package/dist/core/memory/vector-memory.js +98 -0
  76. package/dist/core/memory/vector-recall.d.ts +35 -0
  77. package/dist/core/memory/vector-recall.d.ts.map +1 -0
  78. package/dist/core/memory/vector-recall.js +212 -0
  79. package/dist/core/memory/vector-store.d.ts +56 -0
  80. package/dist/core/memory/vector-store.d.ts.map +1 -0
  81. package/dist/core/memory/vector-store.js +125 -0
  82. package/dist/core/memory/vector-tools.d.ts +8 -0
  83. package/dist/core/memory/vector-tools.d.ts.map +1 -0
  84. package/dist/core/memory/vector-tools.js +75 -0
  85. package/dist/core/{workflow/workflow-evaluator.d.ts → orchestrate/script-runner.d.ts} +4 -4
  86. package/dist/core/orchestrate/script-runner.d.ts.map +1 -0
  87. package/dist/core/{workflow/workflow-evaluator.js → orchestrate/script-runner.js} +1 -1
  88. package/dist/core/orchestrate/tool.d.ts +20 -0
  89. package/dist/core/orchestrate/tool.d.ts.map +1 -0
  90. package/dist/core/orchestrate/tool.js +49 -0
  91. package/dist/core/plugins/plugin-code.d.ts.map +1 -1
  92. package/dist/core/plugins/plugin-code.js +16 -0
  93. package/dist/core/plugins/plugin-marketplace.d.ts.map +1 -1
  94. package/dist/core/plugins/plugin-marketplace.js +22 -5
  95. package/dist/core/plugins/plugin-trust.d.ts +6 -2
  96. package/dist/core/plugins/plugin-trust.d.ts.map +1 -1
  97. package/dist/core/plugins/plugin-trust.js +13 -5
  98. package/dist/core/runtime/agent-event.d.ts +36 -12
  99. package/dist/core/runtime/agent-event.d.ts.map +1 -1
  100. package/dist/core/runtime/agent-loop-messages.d.ts +33 -0
  101. package/dist/core/runtime/agent-loop-messages.d.ts.map +1 -0
  102. package/dist/core/runtime/agent-loop-messages.js +133 -0
  103. package/dist/core/runtime/agent-loop-run.d.ts +35 -0
  104. package/dist/core/runtime/agent-loop-run.d.ts.map +1 -0
  105. package/dist/core/runtime/agent-loop-run.js +345 -0
  106. package/dist/core/runtime/agent-loop-runner.d.ts +60 -0
  107. package/dist/core/runtime/agent-loop-runner.d.ts.map +1 -0
  108. package/dist/core/runtime/agent-loop-runner.js +471 -0
  109. package/dist/core/runtime/agent-loop-types.d.ts +172 -0
  110. package/dist/core/runtime/agent-loop-types.d.ts.map +1 -0
  111. package/dist/core/runtime/agent-loop-utils.d.ts +8 -0
  112. package/dist/core/runtime/agent-loop-utils.d.ts.map +1 -0
  113. package/dist/core/runtime/agent-loop-utils.js +26 -0
  114. package/dist/core/runtime/agent-loop.d.ts +2 -138
  115. package/dist/core/runtime/agent-loop.d.ts.map +1 -1
  116. package/dist/core/runtime/agent-loop.js +45 -927
  117. package/dist/core/runtime/approval.d.ts +7 -2
  118. package/dist/core/runtime/approval.d.ts.map +1 -1
  119. package/dist/core/runtime/coding-agent-harness.fixture.d.ts +52 -0
  120. package/dist/core/runtime/coding-agent-harness.fixture.d.ts.map +1 -0
  121. package/dist/core/runtime/coding-agent-harness.fixture.js +84 -0
  122. package/dist/core/runtime/compaction.d.ts +1 -1
  123. package/dist/core/runtime/compaction.d.ts.map +1 -1
  124. package/dist/core/runtime/create-runtime.d.ts +41 -4
  125. package/dist/core/runtime/create-runtime.d.ts.map +1 -1
  126. package/dist/core/runtime/create-runtime.fixture.d.ts +20 -0
  127. package/dist/core/runtime/create-runtime.fixture.d.ts.map +1 -0
  128. package/dist/core/runtime/create-runtime.fixture.js +79 -0
  129. package/dist/core/runtime/create-runtime.js +67 -20
  130. package/dist/core/runtime/fake-provider.d.ts.map +1 -1
  131. package/dist/core/runtime/fake-provider.js +31 -6
  132. package/dist/core/runtime/loop-input.d.ts +1 -1
  133. package/dist/core/runtime/loop-input.d.ts.map +1 -1
  134. package/dist/core/runtime/model-effort.d.ts +11 -0
  135. package/dist/core/runtime/model-effort.d.ts.map +1 -0
  136. package/dist/core/runtime/model-effort.js +17 -0
  137. package/dist/core/runtime/permission-classifier.d.ts +39 -0
  138. package/dist/core/runtime/permission-classifier.d.ts.map +1 -0
  139. package/dist/core/runtime/permission-classifier.js +136 -0
  140. package/dist/core/runtime/plugin-runtime.d.ts +1 -1
  141. package/dist/core/runtime/plugin-runtime.d.ts.map +1 -1
  142. package/dist/core/runtime/prompt.d.ts.map +1 -1
  143. package/dist/core/runtime/prompt.js +2 -0
  144. package/dist/core/runtime/prompts.d.ts +3 -2
  145. package/dist/core/runtime/prompts.d.ts.map +1 -1
  146. package/dist/core/runtime/prompts.js +29 -5
  147. package/dist/core/runtime/run-runtime.d.ts +35 -45
  148. package/dist/core/runtime/run-runtime.d.ts.map +1 -1
  149. package/dist/core/runtime/run-runtime.js +761 -355
  150. package/dist/core/runtime/runtime-catalog.d.ts.map +1 -1
  151. package/dist/core/runtime/runtime-catalog.js +12 -1
  152. package/dist/core/runtime/stream-rules.d.ts +1 -1
  153. package/dist/core/runtime/stream-rules.d.ts.map +1 -1
  154. package/dist/core/session/session-file.d.ts +4 -0
  155. package/dist/core/session/session-file.d.ts.map +1 -1
  156. package/dist/core/session/session-file.js +32 -1
  157. package/dist/core/settings/project-settings.d.ts +66 -0
  158. package/dist/core/settings/project-settings.d.ts.map +1 -1
  159. package/dist/core/settings/project-settings.js +126 -0
  160. package/dist/core/settings/workspace-context.d.ts +16 -5
  161. package/dist/core/settings/workspace-context.d.ts.map +1 -1
  162. package/dist/core/settings/workspace-context.js +116 -10
  163. package/dist/core/store/in-memory-session-store.d.ts.map +1 -0
  164. package/dist/core/store/session-store.contract.test-helper.d.ts +10 -0
  165. package/dist/core/store/session-store.contract.test-helper.d.ts.map +1 -0
  166. package/dist/core/{persistence/session-store.contract.js → store/session-store.contract.test-helper.js} +13 -26
  167. package/dist/core/{persistence → store}/session-store.d.ts +3 -3
  168. package/dist/core/store/session-store.d.ts.map +1 -0
  169. package/dist/core/{persistence → store}/session-store.js +1 -4
  170. package/dist/core/{persistence → store}/session-tree.d.ts +1 -8
  171. package/dist/core/store/session-tree.d.ts.map +1 -0
  172. package/dist/core/store/session-tree.js +1 -0
  173. package/dist/core/tools/ask-question.d.ts +1 -1
  174. package/dist/core/tools/ask-question.d.ts.map +1 -1
  175. package/dist/core/tools/ask-question.js +14 -1
  176. package/dist/core/tools/bash-pty.d.ts +12 -0
  177. package/dist/core/tools/bash-pty.d.ts.map +1 -0
  178. package/dist/core/tools/bash-pty.js +28 -0
  179. package/dist/core/tools/bash-sandbox.d.ts +76 -0
  180. package/dist/core/tools/bash-sandbox.d.ts.map +1 -0
  181. package/dist/core/tools/bash-sandbox.js +226 -0
  182. package/dist/core/tools/bash.d.ts +27 -0
  183. package/dist/core/tools/bash.d.ts.map +1 -1
  184. package/dist/core/tools/bash.js +214 -33
  185. package/dist/core/tools/browser.d.ts +9 -0
  186. package/dist/core/tools/browser.d.ts.map +1 -0
  187. package/dist/core/tools/browser.js +355 -0
  188. package/dist/core/tools/eval.d.ts +11 -1
  189. package/dist/core/tools/eval.d.ts.map +1 -1
  190. package/dist/core/tools/eval.js +109 -39
  191. package/dist/core/tools/file-tools.d.ts +0 -4
  192. package/dist/core/tools/file-tools.d.ts.map +1 -1
  193. package/dist/core/tools/file-tools.js +36 -16
  194. package/dist/core/tools/glob.d.ts.map +1 -1
  195. package/dist/core/tools/glob.js +13 -1
  196. package/dist/core/tools/grep.d.ts.map +1 -1
  197. package/dist/core/tools/grep.js +4 -1
  198. package/dist/core/tools/index.d.ts +4 -4
  199. package/dist/core/tools/index.d.ts.map +1 -1
  200. package/dist/core/tools/index.js +4 -5
  201. package/dist/core/tools/mcp-mount.d.ts +27 -6
  202. package/dist/core/tools/mcp-mount.d.ts.map +1 -1
  203. package/dist/core/tools/mcp-mount.js +97 -23
  204. package/dist/core/tools/read-image.d.ts +2 -0
  205. package/dist/core/tools/read-image.d.ts.map +1 -1
  206. package/dist/core/tools/read-image.js +1 -1
  207. package/dist/core/tools/skill.d.ts +12 -3
  208. package/dist/core/tools/skill.d.ts.map +1 -1
  209. package/dist/core/tools/skill.js +10 -11
  210. package/dist/core/tools/skills.d.ts +8 -1
  211. package/dist/core/tools/skills.d.ts.map +1 -1
  212. package/dist/core/tools/skills.js +28 -6
  213. package/dist/core/tools/todo-store.d.ts +26 -7
  214. package/dist/core/tools/todo-store.d.ts.map +1 -1
  215. package/dist/core/tools/todo-store.js +53 -81
  216. package/dist/core/tools/todo.d.ts +3 -3
  217. package/dist/core/tools/todo.d.ts.map +1 -1
  218. package/dist/core/tools/todo.js +5 -28
  219. package/dist/core/tools/url-guard.d.ts +5 -1
  220. package/dist/core/tools/url-guard.d.ts.map +1 -1
  221. package/dist/core/tools/url-guard.js +68 -26
  222. package/dist/core/tools/web-ports-std.d.ts.map +1 -1
  223. package/dist/core/tools/web-ports-std.js +2 -2
  224. package/dist/main.d.ts +0 -1
  225. package/dist/main.d.ts.map +1 -1
  226. package/dist/main.js +34 -4
  227. package/dist/modes/json-mode.d.ts.map +1 -1
  228. package/dist/modes/json-mode.js +25 -13
  229. package/dist/modes/print-mode.d.ts +7 -0
  230. package/dist/modes/print-mode.d.ts.map +1 -1
  231. package/dist/modes/print-mode.js +11 -17
  232. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  233. package/dist/modes/rpc/rpc-mode.js +39 -11
  234. package/dist/modes/shared.d.ts +34 -0
  235. package/dist/modes/shared.d.ts.map +1 -0
  236. package/dist/modes/shared.js +47 -0
  237. package/dist/modes/tui/pty-console.d.ts +20 -0
  238. package/dist/modes/tui/pty-console.d.ts.map +1 -0
  239. package/dist/modes/tui/pty-console.js +80 -0
  240. package/dist/modes/tui/settings-overlay.d.ts.map +1 -1
  241. package/dist/modes/tui/settings-overlay.js +2 -0
  242. package/dist/modes/tui/tui-branch-layout.d.ts +10 -0
  243. package/dist/modes/tui/tui-branch-layout.d.ts.map +1 -0
  244. package/dist/modes/tui/tui-branch-layout.js +66 -0
  245. package/dist/modes/tui/tui-commands-session.d.ts.map +1 -1
  246. package/dist/modes/tui/tui-commands-session.js +81 -4
  247. package/dist/modes/tui/tui-commands.d.ts +8 -1
  248. package/dist/modes/tui/tui-commands.d.ts.map +1 -1
  249. package/dist/modes/tui/tui-commands.js +105 -1
  250. package/dist/modes/tui/tui-e2e.fixture.d.ts +11 -0
  251. package/dist/modes/tui/tui-e2e.fixture.d.ts.map +1 -0
  252. package/dist/modes/tui/tui-e2e.fixture.js +37 -0
  253. package/dist/modes/tui/tui-format.d.ts +50 -7
  254. package/dist/modes/tui/tui-format.d.ts.map +1 -1
  255. package/dist/modes/tui/tui-format.js +309 -43
  256. package/dist/modes/tui/tui-frame-provider.d.ts +6 -6
  257. package/dist/modes/tui/tui-frame-provider.d.ts.map +1 -1
  258. package/dist/modes/tui/tui-frame-provider.js +24 -10
  259. package/dist/modes/tui/tui-io.d.ts +7 -9
  260. package/dist/modes/tui/tui-io.d.ts.map +1 -1
  261. package/dist/modes/tui/tui-io.js +170 -115
  262. package/dist/modes/tui/tui-mode.d.ts +1 -113
  263. package/dist/modes/tui/tui-mode.d.ts.map +1 -1
  264. package/dist/modes/tui/tui-mode.fixture.d.ts +21 -0
  265. package/dist/modes/tui/tui-mode.fixture.d.ts.map +1 -0
  266. package/dist/modes/tui/tui-mode.fixture.js +60 -0
  267. package/dist/modes/tui/tui-mode.js +164 -25
  268. package/dist/modes/tui/tui-overlays.d.ts +30 -0
  269. package/dist/modes/tui/tui-overlays.d.ts.map +1 -0
  270. package/dist/modes/tui/tui-overlays.js +66 -0
  271. package/dist/modes/tui/tui-render.d.ts +49 -3
  272. package/dist/modes/tui/tui-render.d.ts.map +1 -1
  273. package/dist/modes/tui/tui-render.js +222 -48
  274. package/dist/modes/tui/tui-seam.d.ts +127 -0
  275. package/dist/modes/tui/tui-seam.d.ts.map +1 -0
  276. package/dist/modes/tui/tui-seam.js +1 -0
  277. package/dist/modes/tui/tui-tool-render.d.ts +32 -4
  278. package/dist/modes/tui/tui-tool-render.d.ts.map +1 -1
  279. package/dist/modes/tui/tui-tool-render.js +419 -65
  280. package/dist/modes/tui/tui-transcript-reconciler.d.ts +9 -0
  281. package/dist/modes/tui/tui-transcript-reconciler.d.ts.map +1 -1
  282. package/dist/modes/tui/tui-transcript-reconciler.js +35 -3
  283. package/dist/modes/tui/view-state.d.ts +38 -1
  284. package/dist/modes/tui/view-state.d.ts.map +1 -1
  285. package/dist/modes/tui/view-state.js +154 -20
  286. package/dist/prompts/agents/subagent.md +8 -1
  287. package/dist/prompts/system/base.md +15 -0
  288. package/dist/prompts/system/memory.md +19 -11
  289. package/dist/protocol/index.d.ts +2 -2
  290. package/dist/protocol/index.d.ts.map +1 -1
  291. package/dist/protocol/index.js +2 -2
  292. package/dist/protocol/mapping.d.ts +1 -13
  293. package/dist/protocol/mapping.d.ts.map +1 -1
  294. package/dist/protocol/mapping.js +17 -37
  295. package/dist/protocol/transport.d.ts +152 -152
  296. package/dist/protocol/transport.d.ts.map +1 -1
  297. package/dist/protocol/transport.js +4 -1
  298. package/dist/testing/test-env.d.ts +2 -0
  299. package/dist/testing/test-env.d.ts.map +1 -0
  300. package/dist/testing/test-env.js +9 -0
  301. package/package.json +18 -12
  302. package/dist/core/agent-runtime.d.ts.map +0 -1
  303. package/dist/core/agent-runtime.js +0 -14
  304. package/dist/core/persistence/in-memory-session-store.d.ts.map +0 -1
  305. package/dist/core/persistence/session-store.contract.d.ts +0 -5
  306. package/dist/core/persistence/session-store.contract.d.ts.map +0 -1
  307. package/dist/core/persistence/session-store.d.ts.map +0 -1
  308. package/dist/core/persistence/session-tree.d.ts.map +0 -1
  309. package/dist/core/runtime/logger.d.ts +0 -13
  310. package/dist/core/runtime/logger.d.ts.map +0 -1
  311. package/dist/core/runtime/logger.js +0 -38
  312. package/dist/core/runtime/todo.d.ts +0 -16
  313. package/dist/core/runtime/todo.d.ts.map +0 -1
  314. package/dist/core/runtime/todo.js +0 -40
  315. package/dist/core/tools/agent-fs-like.d.ts +0 -15
  316. package/dist/core/tools/agent-fs-like.d.ts.map +0 -1
  317. package/dist/core/tools/agent-fs-like.js +0 -4
  318. package/dist/core/workflow/subagent-registry.d.ts.map +0 -1
  319. package/dist/core/workflow/workflow-evaluator.d.ts.map +0 -1
  320. package/dist/core/workflow/workflow-executor.d.ts.map +0 -1
  321. package/dist/core/workflow/workflow-tools.d.ts +0 -50
  322. package/dist/core/workflow/workflow-tools.d.ts.map +0 -1
  323. package/dist/core/workflow/workflow-tools.js +0 -217
  324. /package/dist/core/{workflow/subagent-registry.js → delegation/roles.js} +0 -0
  325. /package/dist/core/{persistence/session-tree.js → runtime/agent-loop-types.js} +0 -0
  326. /package/dist/core/{persistence → store}/in-memory-session-store.d.ts +0 -0
  327. /package/dist/core/{persistence → store}/in-memory-session-store.js +0 -0
package/README.md CHANGED
@@ -18,6 +18,7 @@ Product Backend → Agent Run → Adapter → spawn oma --mode rpc
18
18
  - mermaid fence 渲染为终端 ASCII 图
19
19
  - `/resume` 列表/恢复 session,`/fork <n>` 分支
20
20
  - 模型选择持久化到项目级 `.oma/settings.json`(standalone TUI 专用;backend→oma 仍以 `agent.yml` 为默认,可被 run 参数覆盖)
21
+ - `.oma/settings.json` 里的 `prune` 块显式开启读侧工具输出裁剪(`protectTokens` / `minimumSavings` / `protectedTools`),不配就不裁
21
22
  - composer loader 实时摘要当前动作(tool intent / thinking 首行)
22
23
 
23
24
  | Real session | Tools | Mermaid |
@@ -33,7 +34,7 @@ Product Backend → Agent Run → Adapter → spawn oma --mode rpc
33
34
  | `json` | 一次 Run;stdout 全部事件 JSONL + 恰好一个 terminal outcome 行 |
34
35
  | `rpc` | 每 Run 一次 `execute` + 可选的 `steer`/`abort`;命令走 stdin,`event`/`outcome`/`response` 走 stdout(严格 LF JSONL,stdout 只承载协议) |
35
36
 
36
- `--mode rpc` 是 Adapter 使用的模式。协议 schema 与事件/outcome mapping 定义在契约包 `@chengchenccc/agent-backend`,两侧共用同一份。
37
+ `--mode rpc` 是 Adapter 使用的模式。wire schema 归**本 app 所有**(`src/protocol/`),Adapter 侧保留一份独立的解析/映射副本(`packages/adapter-oma-agent/src/{protocol,event-mapper}.ts`)——两份靠 fixture + `src/protocol/drift.test.ts` 对齐,不共享包(ADR 0024)。改协议:先改这里,再改 adapter 那份,drift 测试会挡住漏改。
37
38
 
38
39
  ## Runtime
39
40
 
@@ -43,7 +44,7 @@ Product Backend → Agent Run → Adapter → spawn oma --mode rpc
43
44
  - `steer(input)` 注入 live loop;`stop()` 中止;
44
45
  - `close()` 拆除 MCP clients 与 SessionStore。
45
46
 
46
- Runtime 内部由 `packages/agent` 提供:OmaSession(model/tool loop、retry、compaction、插件、todo)与 in-memory SessionStoreseed 时把 **full Product history + meta + input** 原子写入,Run 结束即销毁。
47
+ Runtime 主体就在本 app 的 `src/core/`:OmaSession(model/tool loop、retry、compaction、插件、todo、tool-result pruning)与 in-memory SessionStore(`core/store/`)。seed 时把 **full Product history + meta + input** 原子写入,Run 结束即销毁。
47
48
 
48
49
  ## 运行
49
50
 
@@ -75,5 +76,5 @@ src/
75
76
 
76
77
  ## 相关文档
77
78
 
78
- - [架构 Wiki — Oma](docs/architecture/runtime/oma.md)
79
- - [Agent Backend 协议](docs/architecture/execution/agent-backend.md)
79
+ - [架构 Wiki — Oma](../../docs/architecture/runtime/oma.md)
80
+ - [Agent Backend 协议](../../docs/architecture/execution/agent-backend.md)
@@ -1,4 +1,6 @@
1
+ import { type GatewayCommand } from "./gateway-commands.js";
1
2
  export type CliMode = "print" | "json" | "rpc" | "tui";
3
+ export type PermissionFlag = "ask" | "auto" | "deny" | "off";
2
4
  export interface CliArgs {
3
5
  mode: CliMode;
4
6
  /** True when -p/--mode was given explicitly; a bare positional prompt
@@ -8,8 +10,20 @@ export interface CliArgs {
8
10
  listModels: boolean;
9
11
  /** Canonical `<provider>/<model>` id; undefined = first available model. */
10
12
  model?: string;
11
- /** Resume a session file by id (TUI mode). */
13
+ /** Resume a session file by id (all modes; TUI and one-shot). */
12
14
  session?: string;
15
+ /** --continue: resume the workspace's most recent session. */
16
+ continueLast?: boolean;
17
+ /** Standalone permission gate; undefined = .oma/settings.json decides. */
18
+ permission?: PermissionFlag;
19
+ /** --read-only: run with no write/edit/bash/eval tools. */
20
+ readOnly?: boolean;
21
+ /** `oma gateway <command>`: the gateway domain (backend + web) verbs. */
22
+ gateway?: GatewayCommand;
23
+ /** `oma gateway up|fetch --version <v>`: pin the artifact version. */
24
+ gatewayVersion?: string;
25
+ /** `oma gateway up -d`: run detached. */
26
+ gatewayDetach?: boolean;
13
27
  /** Tool filter: comma-separated tool names or groups. Plain names form a
14
28
  * whitelist (ONLY those tools run); `!name` entries form a blacklist
15
29
  * (all but those). Applied to the FINAL tool table (native + MCP +
@@ -1 +1 @@
1
- {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC;AAEvD,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,OAAO,CAAC;IACd;yEACqE;IACrE,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;mCAG+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,UAAW,SAAQ,KAAK;CAAG;AA0BxC;6DAC6D;AAC7D,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CA6E1D"}
1
+ {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,cAAc,EAAoB,MAAM,uBAAuB,CAAC;AAE7F,MAAM,MAAM,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC;AAEvD,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAE7D,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,OAAO,CAAC;IACd;yEACqE;IACrE,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8DAA8D;IAC9D,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yEAAyE;IACzE,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,sEAAsE;IACtE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yCAAyC;IACzC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;mCAG+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,UAAW,SAAQ,KAAK;CAAG;AAkCxC;6DAC6D;AAC7D,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAuG1D"}
package/dist/cli/args.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { GATEWAY_USAGE, isGatewayCommand } from "./gateway-commands.js";
1
2
  export class UsageError extends Error {
2
3
  }
3
4
  const USAGE = `oma - Oma coding agent
@@ -10,11 +11,18 @@ Usage:
10
11
  oma --mode json "<prompt>" json mode: all events + one outcome as JSONL
11
12
  oma --mode rpc rpc mode: stdin/stdout JSONL protocol
12
13
  oma --list-models print the model catalog as JSON
14
+ oma gateway up start backend + web (foreground, Ctrl-C stops)
15
+ oma gateway up -d same, detached (returns once healthy)
16
+ oma gateway down stop a detached gateway
17
+ oma gateway status installed version, running state, health
18
+ oma gateway fetch download + verify the gateway artifact
19
+ oma --continue resume the most recent session
20
+ oma --session <id> -p "..." one-shot follow-up on a session
21
+ oma --permission ask -p "..." gate bash/write/mcp behind approval cards
22
+ oma --read-only -p "..." research-only run (no mutating tools)
13
23
  oma --model <provider/model> -p "<prompt>"
14
24
  pick a model by canonical id
15
25
  (default: first available model)
16
- oma --tools todo_write,read -p "..." only these tools enter the Run
17
- oma --tools '!todo_write' -p "..." all tools except todo_write
18
26
 
19
27
  Piped stdin (print/json modes):
20
28
  cat file | oma -p "Review"
@@ -22,6 +30,7 @@ Piped stdin (print/json modes):
22
30
  cat error.log | oma -p (stdin only)
23
31
  `;
24
32
  const MODES = ["print", "json", "rpc", "tui"];
33
+ const PERMISSIONS = ["ask", "auto", "deny", "off"];
25
34
  /** Parse argv SYNTAX only: whether a run actually has an input (prompt or
26
35
  * piped stdin) is decided in main() after stdin is read. */
27
36
  export function parseArgs(argv) {
@@ -33,11 +42,19 @@ export function parseArgs(argv) {
33
42
  };
34
43
  const positional = [];
35
44
  let modeFlag = null;
45
+ // `oma gateway <verb>` — a reserved first word, because the first positional
46
+ // is otherwise the prompt (`oma "explain this"`). `oma -p "gateway up"` is the
47
+ // escape hatch when the word really is part of a prompt.
48
+ if (argv[0] === "gateway")
49
+ return parseGatewayArgs(argv.slice(1), args);
36
50
  let i = 0;
37
51
  while (i < argv.length) {
38
52
  const arg = argv[i];
39
53
  if (arg === "-p") {
40
- modeFlag = "print";
54
+ // `-p` means "one-shot with this prompt", NOT "force print mode": an
55
+ // explicit --mode (either order) must win, or `--mode json -p x` would
56
+ // silently run print mode and print bare text where JSONL was expected.
57
+ modeFlag ??= "print";
41
58
  args.modeExplicit = true;
42
59
  }
43
60
  else if (arg === "--mode") {
@@ -88,6 +105,27 @@ export function parseArgs(argv) {
88
105
  throw new UsageError("--session requires a session id");
89
106
  args.session = value;
90
107
  }
108
+ else if (arg === "--continue" || arg === "-c") {
109
+ args.continueLast = true;
110
+ }
111
+ else if (arg === "--read-only") {
112
+ args.readOnly = true;
113
+ }
114
+ else if (arg === "--permission") {
115
+ const value = argv[i + 1];
116
+ if (!value || !PERMISSIONS.includes(value)) {
117
+ throw new UsageError(`--permission requires one of: ${PERMISSIONS.join(" | ")}`);
118
+ }
119
+ args.permission = value;
120
+ i++;
121
+ }
122
+ else if (arg.startsWith("--permission=")) {
123
+ const value = arg.slice("--permission=".length);
124
+ if (!PERMISSIONS.includes(value)) {
125
+ throw new UsageError(`--permission requires one of: ${PERMISSIONS.join(" | ")}`);
126
+ }
127
+ args.permission = value;
128
+ }
91
129
  else if (arg === "--tools") {
92
130
  const value = argv[i + 1];
93
131
  if (!value || value.startsWith("-")) {
@@ -118,3 +156,43 @@ export function parseArgs(argv) {
118
156
  args.prompt = positional.join(" ");
119
157
  return args;
120
158
  }
159
+ /** Parse `oma gateway <verb> [--version <v>]`. Kept separate from the main
160
+ * loop: the gateway surface takes no prompt, session or mode. */
161
+ function parseGatewayArgs(rest, args) {
162
+ const verb = rest[0];
163
+ if (verb === undefined || verb.startsWith("-")) {
164
+ throw new UsageError(`oma gateway needs a command\n\n${GATEWAY_USAGE}`);
165
+ }
166
+ if (!isGatewayCommand(verb)) {
167
+ throw new UsageError(`unknown gateway command: ${verb}\n\n${GATEWAY_USAGE}`);
168
+ }
169
+ args.gateway = verb;
170
+ let i = 1;
171
+ while (i < rest.length) {
172
+ const arg = rest[i] ?? "";
173
+ if (arg === "--version") {
174
+ const value = rest[i + 1];
175
+ if (!value || value.startsWith("-")) {
176
+ throw new UsageError("oma gateway --version needs a version like 0.2.0");
177
+ }
178
+ args.gatewayVersion = value;
179
+ i += 2;
180
+ continue;
181
+ }
182
+ if (arg.startsWith("--version=")) {
183
+ const value = arg.slice("--version=".length);
184
+ if (!value)
185
+ throw new UsageError("oma gateway --version needs a version like 0.2.0");
186
+ args.gatewayVersion = value;
187
+ i += 1;
188
+ continue;
189
+ }
190
+ if (arg === "--detach" || arg === "-d") {
191
+ args.gatewayDetach = true;
192
+ i += 1;
193
+ continue;
194
+ }
195
+ throw new UsageError(`unknown gateway option: ${arg}\n\n${GATEWAY_USAGE}`);
196
+ }
197
+ return args;
198
+ }
@@ -0,0 +1,40 @@
1
+ /** The gateway domain's verbs. `oma gateway <verb>` is the CLI surface for
2
+ * backend + web: fetch their artifact, run it, report on it. */
3
+ export declare const GATEWAY_VERBS: readonly ["up", "down", "fetch", "status", "doctor", "passwd"];
4
+ export type GatewayCommand = (typeof GATEWAY_VERBS)[number];
5
+ export declare const GATEWAY_USAGE = "oma gateway <command>\n\n up start backend + web; stays in the foreground (Ctrl-C stops it)\n up -d same, but detached: returns once it is healthy\n down stop a detached gateway\n fetch download, verify and unpack the gateway artifact for a version\n status which version is installed, is it running, is it answering\n doctor why nothing can run: artifact, tools, catalog, keys, ports, oma bin\n passwd replace the login password with a fresh random one\n\n --version <v> artifact version for up/fetch (default: oma's own)\n\nNote: 'gateway' is a reserved first word. To send it as a prompt, use\n'oma -p \"gateway ...\"'.";
6
+ export declare function isGatewayCommand(value: string): value is GatewayCommand;
7
+ /** What to tell the operator about logging in. The password is only echoed on
8
+ * an interactive terminal: a detached run's stdout is redirected into a log
9
+ * file, and a secret must not be filed away there. The pointer is always
10
+ * printed, so a missed banner is never a dead end. */
11
+ export declare function credentialLines(home: string, secrets: Record<string, string>, interactive: boolean): string[];
12
+ export interface GatewayCommandOptions {
13
+ home?: string;
14
+ version?: string;
15
+ /** `up -d`: run detached, with a pidfile and a log file. */
16
+ detach?: boolean;
17
+ quiet?: boolean;
18
+ log?: (line: string) => void;
19
+ }
20
+ /** `oma gateway fetch`: download, verify and unpack the artifact for one
21
+ * version (default: oma's own) so `up` can start it. Idempotent. */
22
+ export declare function runGatewayFetch(opts?: GatewayCommandOptions): Promise<number>;
23
+ /** `oma gateway status`: what is installed, which version is current, and
24
+ * whether the gateway answers right now. Never mutates anything. */
25
+ export declare function runGatewayStatus(opts?: GatewayCommandOptions): Promise<number>;
26
+ /** `oma gateway up`: fetch the version if it is missing, then run the whole gateway in
27
+ * the foreground (Ctrl-C stops it, children are signalled in reverse order). */
28
+ export declare function runGatewayUp(opts?: GatewayCommandOptions): Promise<number>;
29
+ /** `oma gateway passwd`: rotate the login password. Generated, never read from
30
+ * argv — an argument would land in shell history and process listings.
31
+ * Takes effect on the next start, because the web component reads it from its
32
+ * environment. */
33
+ export declare function runGatewayPasswd(opts?: GatewayCommandOptions): Promise<number>;
34
+ /** `oma gateway doctor`: check the deployment and say how to fix what is wrong. */
35
+ export declare function runGatewayDoctor(opts?: GatewayCommandOptions): Promise<number>;
36
+ /** `oma gateway down`: stop whatever `up -d` started. */
37
+ export declare function runGatewayDown(opts?: GatewayCommandOptions): Promise<number>;
38
+ /** `oma gateway <verb>`: single entry point so the CLI owns one code path. */
39
+ export declare function runGatewayCommand(verb: GatewayCommand, opts?: GatewayCommandOptions): Promise<number>;
40
+ //# sourceMappingURL=gateway-commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway-commands.d.ts","sourceRoot":"","sources":["../../src/cli/gateway-commands.ts"],"names":[],"mappings":"AAwBA;iEACiE;AACjE,eAAO,MAAM,aAAa,gEAAiE,CAAC;AAC5F,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5D,eAAO,MAAM,aAAa,0pBAaF,CAAC;AAEzB,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,cAAc,CAKvE;AAED;;;uDAGuD;AACvD,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,WAAW,EAAE,OAAO,GACnB,MAAM,EAAE,CAMV;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B;AAyBD;qEACqE;AACrE,wBAAsB,eAAe,CAAC,IAAI,GAAE,qBAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,CAmBvF;AAED;qEACqE;AACrE,wBAAsB,gBAAgB,CAAC,IAAI,GAAE,qBAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,CAgExF;AAED;iFACiF;AACjF,wBAAsB,YAAY,CAAC,IAAI,GAAE,qBAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,CAoCpF;AAED;;;mBAGmB;AACnB,wBAAsB,gBAAgB,CAAC,IAAI,GAAE,qBAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BxF;AA2BD,mFAAmF;AACnF,wBAAsB,gBAAgB,CAAC,IAAI,GAAE,qBAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBxF;AAED,yDAAyD;AACzD,wBAAsB,cAAc,CAAC,IAAI,GAAE,qBAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,CAUtF;AA+DD,8EAA8E;AAC9E,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,cAAc,EACpB,IAAI,GAAE,qBAA0B,GAC/B,OAAO,CAAC,MAAM,CAAC,CAOjB"}
@@ -0,0 +1,337 @@
1
+ import { existsSync } from "node:fs";
2
+ import { writeFile } from "node:fs/promises";
3
+ import { join, resolve } from "node:path";
4
+ import { currentVersion, fetchGatewayArtifact, gatewayPaths, generatePassword, installedVersions, omaHome, omaVersion, readSecrets, } from "../core/gateway/artifact.js";
5
+ import { isProcessAlive, readDaemon, startDetachedGateway, stopDetachedGateway, tailDaemonLog, } from "../core/gateway/daemon.js";
6
+ import { diagnoseGateway } from "../core/gateway/doctor.js";
7
+ import { readGatewayManifest } from "../core/gateway/manifest.js";
8
+ import { runGateway } from "../core/gateway/supervisor.js";
9
+ /** The gateway domain's verbs. `oma gateway <verb>` is the CLI surface for
10
+ * backend + web: fetch their artifact, run it, report on it. */
11
+ export const GATEWAY_VERBS = ["up", "down", "fetch", "status", "doctor", "passwd"];
12
+ export const GATEWAY_USAGE = `oma gateway <command>
13
+
14
+ up start backend + web; stays in the foreground (Ctrl-C stops it)
15
+ up -d same, but detached: returns once it is healthy
16
+ down stop a detached gateway
17
+ fetch download, verify and unpack the gateway artifact for a version
18
+ status which version is installed, is it running, is it answering
19
+ doctor why nothing can run: artifact, tools, catalog, keys, ports, oma bin
20
+ passwd replace the login password with a fresh random one
21
+
22
+ --version <v> artifact version for up/fetch (default: oma's own)
23
+
24
+ Note: 'gateway' is a reserved first word. To send it as a prompt, use
25
+ 'oma -p "gateway ..."'.`;
26
+ export function isGatewayCommand(value) {
27
+ for (const verb of GATEWAY_VERBS) {
28
+ if (verb === value)
29
+ return true;
30
+ }
31
+ return false;
32
+ }
33
+ /** What to tell the operator about logging in. The password is only echoed on
34
+ * an interactive terminal: a detached run's stdout is redirected into a log
35
+ * file, and a secret must not be filed away there. The pointer is always
36
+ * printed, so a missed banner is never a dead end. */
37
+ export function credentialLines(home, secrets, interactive) {
38
+ const lines = [];
39
+ const password = secrets.MOCK_PASSWORD;
40
+ if (password && interactive)
41
+ lines.push(`login: user-001 / ${password}`);
42
+ lines.push(`login password: oma gateway status (or read ${gatewayPaths(home).secrets})`);
43
+ return lines;
44
+ }
45
+ /** A source checkout runs the gateway from the repo, so the release artifact it
46
+ * would download is unused. Only stay quiet there: an explicit CLI call still
47
+ * fetches. `npm_lifecycle_event` is set while a package's postinstall runs. */
48
+ function inMonorepoCheckoutPostinstall() {
49
+ if (process.env.npm_lifecycle_event !== "postinstall")
50
+ return false;
51
+ // src/cli (dist/cli) is TWO levels under the package root — unlike
52
+ // core/gateway/*, which sits three. Getting this wrong made the guard a no-op.
53
+ const packageRoot = resolve(import.meta.dirname, "../..");
54
+ return existsSync(join(packageRoot, "..", "..", "turbo.json"));
55
+ }
56
+ function loggerFor(opts, stream) {
57
+ if (opts.log)
58
+ return opts.log;
59
+ if (opts.quiet)
60
+ return () => { };
61
+ const write = (line) => {
62
+ process[stream].write(`${line}\n`);
63
+ };
64
+ return write;
65
+ }
66
+ /** `oma gateway fetch`: download, verify and unpack the artifact for one
67
+ * version (default: oma's own) so `up` can start it. Idempotent. */
68
+ export async function runGatewayFetch(opts = {}) {
69
+ const log = loggerFor(opts, "stderr");
70
+ if (inMonorepoCheckoutPostinstall()) {
71
+ log("gateway fetch skipped: source checkout (the gateway runs from the repo here)");
72
+ return 0;
73
+ }
74
+ try {
75
+ const result = await fetchGatewayArtifact({
76
+ log,
77
+ ...(opts.home ? { home: opts.home } : {}),
78
+ ...(opts.version ? { version: opts.version } : {}),
79
+ });
80
+ log(`gateway ${result.version} ready at ${result.dir}`);
81
+ log("start it with: oma gateway up");
82
+ return 0;
83
+ }
84
+ catch (err) {
85
+ log(`gateway fetch failed: ${err instanceof Error ? err.message : String(err)}`);
86
+ return 1;
87
+ }
88
+ }
89
+ /** `oma gateway status`: what is installed, which version is current, and
90
+ * whether the gateway answers right now. Never mutates anything. */
91
+ export async function runGatewayStatus(opts = {}) {
92
+ const home = opts.home ?? omaHome();
93
+ const paths = gatewayPaths(home);
94
+ const log = loggerFor(opts, "stdout");
95
+ const versions = installedVersions(home);
96
+ const current = currentVersion(home);
97
+ log(`gateway home: ${paths.home}`);
98
+ log(`versions: ${versions.length > 0 ? versions.join(", ") : "(none installed)"}`);
99
+ log(`current: ${current ?? "(none)"}`);
100
+ // Which catalog the gateway's children will read: product runs deliberately
101
+ // ignore ~/.oma/models.yml (the agent's own bash tool can write there), so a
102
+ // custom provider only counts when OMA_HOME points at its models.yml.
103
+ const catalogHome = process.env.OMA_HOME;
104
+ log(catalogHome
105
+ ? `catalog: ${catalogHome}/models.yml via OMA_HOME`
106
+ : "catalog: built-in providers only (OMA_HOME unset — a custom models.yml is not read)");
107
+ if (versions.length === 0) {
108
+ log(`install one: oma gateway fetch (oma ${omaVersion()})`);
109
+ return 1;
110
+ }
111
+ const version = opts.version ?? current ?? versions[versions.length - 1] ?? "";
112
+ const dir = join(paths.versions, version);
113
+ const manifestPath = join(dir, "gateway.json");
114
+ if (!existsSync(manifestPath)) {
115
+ log(`version ${version} is incomplete at ${dir} — re-run: oma gateway fetch`);
116
+ return 1;
117
+ }
118
+ const daemon = readDaemon(home);
119
+ if (daemon && isProcessAlive(daemon.pid)) {
120
+ log(`running: detached, pid ${daemon.pid}, since ${daemon.startedAt}`);
121
+ log(`log: ${daemon.logPath}`);
122
+ }
123
+ else if (daemon) {
124
+ log(`running: no (stale pidfile for pid ${daemon.pid}; 'oma gateway down' clears it)`);
125
+ }
126
+ else {
127
+ log("running: no pidfile (started in the foreground, or not started)");
128
+ }
129
+ const manifest = readGatewayManifest(manifestPath);
130
+ let allUp = true;
131
+ for (const component of manifest.components) {
132
+ if (!component.healthUrl)
133
+ continue;
134
+ let state = "down";
135
+ try {
136
+ const res = await fetch(component.healthUrl, { signal: AbortSignal.timeout(2000) });
137
+ if (res.ok)
138
+ state = "up";
139
+ }
140
+ catch {
141
+ // down
142
+ }
143
+ if (state === "down")
144
+ allUp = false;
145
+ log(`${component.name.padEnd(8)} ${state.padEnd(4)} ${component.healthUrl}`);
146
+ }
147
+ const password = readSecrets(home).MOCK_PASSWORD;
148
+ if (allUp) {
149
+ log(`login: http://127.0.0.1:3001/login (user-001 / ${password ?? "?"})`);
150
+ return 0;
151
+ }
152
+ log("start it with: oma gateway up");
153
+ return 1;
154
+ }
155
+ /** `oma gateway up`: fetch the version if it is missing, then run the whole gateway in
156
+ * the foreground (Ctrl-C stops it, children are signalled in reverse order). */
157
+ export async function runGatewayUp(opts = {}) {
158
+ const home = opts.home ?? omaHome();
159
+ const log = loggerFor(opts, "stdout");
160
+ const version = opts.version ?? currentVersion(home) ?? omaVersion();
161
+ const dir = join(gatewayPaths(home).versions, version);
162
+ if (!existsSync(join(dir, "gateway.json"))) {
163
+ log(`gateway ${version} is not installed yet — fetching it`);
164
+ const code = await runGatewayFetch({ ...opts, version, log });
165
+ if (code !== 0)
166
+ return code;
167
+ }
168
+ if (opts.detach)
169
+ return startGatewayDetached({ ...opts, home, version, log });
170
+ try {
171
+ return await runGateway({
172
+ home,
173
+ version,
174
+ log,
175
+ onReady: (handle) => {
176
+ const web = handle.manifest.components.find((component) => component.port === 3001);
177
+ log("");
178
+ log(`gateway ${handle.manifest.version} is up (${handle.manifest.components.length} processes)`);
179
+ log(`open http://127.0.0.1:${web?.port ?? 3001}/login`);
180
+ for (const line of credentialLines(home, handle.secrets, process.stdout.isTTY === true)) {
181
+ log(line);
182
+ }
183
+ log("Ctrl-C stops the gateway");
184
+ },
185
+ });
186
+ }
187
+ catch (err) {
188
+ log(`gateway failed to start: ${err instanceof Error ? err.message : String(err)}`);
189
+ return 1;
190
+ }
191
+ }
192
+ /** `oma gateway passwd`: rotate the login password. Generated, never read from
193
+ * argv — an argument would land in shell history and process listings.
194
+ * Takes effect on the next start, because the web component reads it from its
195
+ * environment. */
196
+ export async function runGatewayPasswd(opts = {}) {
197
+ const home = opts.home ?? omaHome();
198
+ const log = loggerFor(opts, "stdout");
199
+ const secretsPath = gatewayPaths(home).secrets;
200
+ if (!existsSync(secretsPath)) {
201
+ log(`no secrets at ${secretsPath} — run 'oma gateway up' once first`);
202
+ return 1;
203
+ }
204
+ const password = generatePassword();
205
+ const secrets = { ...readSecrets(home), MOCK_PASSWORD: password };
206
+ await writeFile(secretsPath, `${JSON.stringify(secrets, null, 2)}\n`, { mode: 0o600 });
207
+ log(`login password replaced: user-001 / ${password}`);
208
+ // A password set in the console is stored as a hash and wins over this file,
209
+ // so push the new one there too when the gateway is up — otherwise rotating
210
+ // here would silently not take effect.
211
+ const pushed = await pushPasswordToRunningGateway(secrets, password);
212
+ if (pushed) {
213
+ log("the running gateway took it too (console-set password updated)");
214
+ }
215
+ else {
216
+ log("restart to apply: oma gateway down && oma gateway up -d");
217
+ log("note: a password set in the web console wins over this file — change it there if you used that");
218
+ }
219
+ return 0;
220
+ }
221
+ /** Update the console-set password (a hash in the backend's settings) when the
222
+ * gateway is reachable. Returns false when it is not: the file value then
223
+ * applies after the next start. */
224
+ async function pushPasswordToRunningGateway(secrets, password) {
225
+ const token = secrets.BACKEND_AUTH_TOKEN;
226
+ if (!token)
227
+ return false;
228
+ try {
229
+ const res = await fetch(`${process.env.BACKEND_URL ?? "http://127.0.0.1:3000"}/api/auth/password`, {
230
+ method: "PUT",
231
+ headers: { "content-type": "application/json", "x-auth-token": token },
232
+ body: JSON.stringify({ password }),
233
+ signal: AbortSignal.timeout(2000),
234
+ });
235
+ return res.ok;
236
+ }
237
+ catch {
238
+ return false;
239
+ }
240
+ }
241
+ /** `oma gateway doctor`: check the deployment and say how to fix what is wrong. */
242
+ export async function runGatewayDoctor(opts = {}) {
243
+ const home = opts.home ?? omaHome();
244
+ const log = loggerFor(opts, "stdout");
245
+ const checks = await diagnoseGateway({ home });
246
+ log(`oma gateway doctor (home: ${home})`);
247
+ for (const check of checks) {
248
+ log(`${check.ok ? "✓" : "✗"} ${check.id.padEnd(9)} ${check.detail}`);
249
+ if (check.fix)
250
+ log(` ${check.ok ? "note" : "fix"}: ${check.fix}`);
251
+ }
252
+ const failed = checks.filter((check) => !check.ok);
253
+ log("");
254
+ log(failed.length === 0
255
+ ? "no problems found"
256
+ : `${failed.length} problem(s): ${failed.map((c) => c.id).join(", ")}`);
257
+ return failed.length === 0 ? 0 : 1;
258
+ }
259
+ /** `oma gateway down`: stop whatever `up -d` started. */
260
+ export async function runGatewayDown(opts = {}) {
261
+ const home = opts.home ?? omaHome();
262
+ const log = loggerFor(opts, "stdout");
263
+ const result = await stopDetachedGateway(home);
264
+ if (result.stopped) {
265
+ log(`gateway stopped${result.reason ? ` (${result.reason})` : ""}`);
266
+ return 0;
267
+ }
268
+ log(`nothing stopped: ${result.reason ?? "unknown reason"}`);
269
+ return result.reason?.startsWith("stale pidfile") ? 0 : 1;
270
+ }
271
+ /** Relaunch this CLI in the background and wait until it answers, so the command
272
+ * reports the truth instead of "started something, maybe". */
273
+ async function startGatewayDetached(opts) {
274
+ const entry = process.argv[1];
275
+ if (!entry) {
276
+ opts.log("cannot detach: no CLI entry path in argv");
277
+ return 1;
278
+ }
279
+ const command = [process.execPath, entry, "gateway", "up"];
280
+ if (opts.version)
281
+ command.push("--version", opts.version);
282
+ const daemon = await startDetachedGateway({
283
+ home: opts.home,
284
+ version: opts.version,
285
+ command,
286
+ });
287
+ opts.log(`gateway ${opts.version} starting detached (pid ${daemon.pid})`);
288
+ opts.log(`log: ${daemon.logPath}`);
289
+ const manifest = readGatewayManifest(join(gatewayPaths(opts.home).versions, opts.version, "gateway.json"));
290
+ const web = manifest.components.find((component) => component.port === 3001);
291
+ const healthUrl = web?.healthUrl;
292
+ const deadline = Date.now() + 60_000;
293
+ while (Date.now() < deadline) {
294
+ if (!isProcessAlive(daemon.pid))
295
+ break;
296
+ if (healthUrl) {
297
+ try {
298
+ const res = await fetch(healthUrl, { signal: AbortSignal.timeout(2000) });
299
+ if (res.ok) {
300
+ opts.log("");
301
+ opts.log(`gateway ${opts.version} is up in the background (pid ${daemon.pid})`);
302
+ opts.log(`open http://127.0.0.1:${web?.port ?? 3001}/login`);
303
+ for (const line of credentialLines(opts.home, readSecrets(opts.home), process.stdout.isTTY === true)) {
304
+ opts.log(line);
305
+ }
306
+ opts.log("stop it with: oma gateway down");
307
+ return 0;
308
+ }
309
+ }
310
+ catch {
311
+ // not listening yet
312
+ }
313
+ }
314
+ await new Promise((res) => {
315
+ setTimeout(res, 500);
316
+ });
317
+ }
318
+ opts.log("gateway did not become healthy in 60s — last log lines:");
319
+ for (const line of tailDaemonLog(opts.home))
320
+ opts.log(` ${line}`);
321
+ opts.log("stop it with: oma gateway down");
322
+ return 1;
323
+ }
324
+ /** `oma gateway <verb>`: single entry point so the CLI owns one code path. */
325
+ export async function runGatewayCommand(verb, opts = {}) {
326
+ if (verb === "up")
327
+ return runGatewayUp(opts);
328
+ if (verb === "down")
329
+ return runGatewayDown(opts);
330
+ if (verb === "fetch")
331
+ return runGatewayFetch(opts);
332
+ if (verb === "doctor")
333
+ return runGatewayDoctor(opts);
334
+ if (verb === "passwd")
335
+ return runGatewayPasswd(opts);
336
+ return runGatewayStatus(opts);
337
+ }
@@ -28,5 +28,14 @@ export declare function buildCliRunInput(opts: {
28
28
  modelRuntime: ModelRuntime;
29
29
  /** Canonical `<provider>/<model>` id; undefined = first available. */
30
30
  modelId?: string;
31
+ /** Standalone permission gate. undefined = ungated (legacy default). */
32
+ permissionMode?: "ask" | "auto" | "deny";
33
+ /** --read-only: advertise no write/edit/bash/eval to the model. */
34
+ readOnly?: boolean;
35
+ /** Clipboard/pasted images riding this prompt (vision input). */
36
+ images?: ReadonlyArray<{
37
+ mediaType: "image/png" | "image/jpeg" | "image/gif" | "image/webp";
38
+ base64: string;
39
+ }>;
31
40
  }): Promise<BackendRunInput<"oma">>;
32
41
  //# sourceMappingURL=initial-input.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"initial-input.d.ts","sourceRoot":"","sources":["../../src/cli/initial-input.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAQrD;;;;;wDAKwD;AACxD,wBAAgB,2BAA2B,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,CAqC3E;AAMD;;yCAEyC;AACzC,wBAAsB,cAAc,CAClC,MAAM,GAAE,cAAc,CAAC,UAAU,CAAsB,GACtD,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAsB7B;AAED;;iDAEiD;AACjD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAKpF;AAED;;;wBAGwB;AACxB,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,YAAY,CAAC;IAC3B,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAqClC"}
1
+ {"version":3,"file":"initial-input.d.ts","sourceRoot":"","sources":["../../src/cli/initial-input.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAUrD;;;;;wDAKwD;AACxD,wBAAgB,2BAA2B,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,CA+C3E;AAMD;;yCAEyC;AACzC,wBAAsB,cAAc,CAClC,MAAM,GAAE,cAAc,CAAC,UAAU,CAAsB,GACtD,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAsB7B;AAED;;iDAEiD;AACjD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAKpF;AA0BD;;;wBAGwB;AAExB,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,YAAY,CAAC;IAC3B,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,cAAc,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;IACzC,mEAAmE;IACnE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iEAAiE;IACjE,MAAM,CAAC,EAAE,aAAa,CAAC;QACrB,SAAS,EAAE,WAAW,GAAG,YAAY,GAAG,WAAW,GAAG,YAAY,CAAC;QACnE,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;CACJ,GAAG,OAAO,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAyClC"}