prompt_objects 0.5.0 → 0.7.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 (292) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +142 -0
  3. data/README.md +211 -19
  4. data/exe/poop +5 -0
  5. data/exe/prompt_objects +1 -1108
  6. data/exe/prompt_objects_mcp +5 -3
  7. data/lib/prompt_objects/capability.rb +33 -0
  8. data/lib/prompt_objects/cli/diagnostics_command.rb +69 -0
  9. data/lib/prompt_objects/cli/env_command.rb +435 -0
  10. data/lib/prompt_objects/cli/events_command.rb +145 -0
  11. data/lib/prompt_objects/cli/explore_command.rb +155 -0
  12. data/lib/prompt_objects/cli/helpers.rb +91 -0
  13. data/lib/prompt_objects/cli/message_command.rb +216 -0
  14. data/lib/prompt_objects/cli/repl_command.rb +366 -0
  15. data/lib/prompt_objects/cli/serve_command.rb +162 -0
  16. data/lib/prompt_objects/cli.rb +64 -422
  17. data/lib/prompt_objects/connectors/base.rb +16 -29
  18. data/lib/prompt_objects/connectors/mcp.rb +82 -98
  19. data/lib/prompt_objects/domain/records.rb +45 -0
  20. data/lib/prompt_objects/environment/exporter.rb +5 -4
  21. data/lib/prompt_objects/environment/git.rb +21 -1
  22. data/lib/prompt_objects/environment/importer.rb +5 -4
  23. data/lib/prompt_objects/environment/manager.rb +44 -6
  24. data/lib/prompt_objects/environment/manifest.rb +26 -4
  25. data/lib/prompt_objects/environment.rb +1350 -18
  26. data/lib/prompt_objects/execution/blocking_executor.rb +88 -0
  27. data/lib/prompt_objects/execution/context.rb +137 -0
  28. data/lib/prompt_objects/execution/contracts.rb +59 -0
  29. data/lib/prompt_objects/execution/permit_pool.rb +49 -0
  30. data/lib/prompt_objects/execution/policy.rb +47 -0
  31. data/lib/prompt_objects/execution/resource_lock_manager.rb +63 -0
  32. data/lib/prompt_objects/execution/runner.rb +498 -0
  33. data/lib/prompt_objects/execution/scheduler.rb +325 -0
  34. data/lib/prompt_objects/llm/factory.rb +4 -4
  35. data/lib/prompt_objects/llm/gemini_adapter.rb +25 -8
  36. data/lib/prompt_objects/llm/openai_adapter.rb +9 -1
  37. data/lib/prompt_objects/llm/pricing.rb +9 -2
  38. data/lib/prompt_objects/llm/response.rb +9 -4
  39. data/lib/prompt_objects/loader.rb +28 -1
  40. data/lib/prompt_objects/mcp/server.rb +6 -3
  41. data/lib/prompt_objects/mcp/tools/get_conversation.rb +15 -11
  42. data/lib/prompt_objects/mcp/tools/get_pending_requests.rb +2 -2
  43. data/lib/prompt_objects/mcp/tools/respond_to_request.rb +3 -3
  44. data/lib/prompt_objects/mcp/tools/send_message.rb +42 -32
  45. data/lib/prompt_objects/operations/diagnostics.rb +115 -0
  46. data/lib/prompt_objects/operations/retention.rb +75 -0
  47. data/lib/prompt_objects/operations/run_trace_builder.rb +152 -0
  48. data/lib/prompt_objects/primitives/http_get.rb +2 -0
  49. data/lib/prompt_objects/primitives/list_files.rb +2 -0
  50. data/lib/prompt_objects/primitives/read_file.rb +2 -0
  51. data/lib/prompt_objects/primitives/think.rb +36 -0
  52. data/lib/prompt_objects/primitives/write_file.rb +9 -0
  53. data/lib/prompt_objects/prompt_object.rb +190 -432
  54. data/lib/prompt_objects/repositories/artifact_repository.rb +109 -0
  55. data/lib/prompt_objects/repositories/base_repository.rb +37 -0
  56. data/lib/prompt_objects/repositories/definition_repository.rb +36 -0
  57. data/lib/prompt_objects/repositories/env_data_repository.rb +103 -0
  58. data/lib/prompt_objects/repositories/event_repository.rb +105 -0
  59. data/lib/prompt_objects/repositories/message_repository.rb +73 -0
  60. data/lib/prompt_objects/repositories/run_repository.rb +254 -0
  61. data/lib/prompt_objects/repositories/thread_repository.rb +87 -0
  62. data/lib/prompt_objects/repositories/tool_execution_repository.rb +88 -0
  63. data/lib/prompt_objects/repositories/workspace_session_repository.rb +61 -0
  64. data/lib/prompt_objects/server/api/routes.rb +561 -52
  65. data/lib/prompt_objects/server/app.rb +134 -1
  66. data/lib/prompt_objects/server/file_watcher.rb +9 -0
  67. data/lib/prompt_objects/server/public/assets/index-BjKlODDD.js +90 -0
  68. data/lib/prompt_objects/server/public/assets/index-w3fpIb5c.css +1 -0
  69. data/lib/prompt_objects/server/public/index.html +2 -2
  70. data/lib/prompt_objects/server/websocket_handler.rb +202 -207
  71. data/lib/prompt_objects/server.rb +170 -1
  72. data/lib/prompt_objects/service.rb +129 -0
  73. data/lib/prompt_objects/session/store.rb +774 -15
  74. data/lib/prompt_objects/universal/add_capability.rb +1 -1
  75. data/lib/prompt_objects/universal/create_capability.rb +4 -2
  76. data/lib/prompt_objects/universal/delete_env_data.rb +78 -0
  77. data/lib/prompt_objects/universal/delete_primitive.rb +1 -1
  78. data/lib/prompt_objects/universal/dispatch_po.rb +54 -0
  79. data/lib/prompt_objects/universal/get_env_data.rb +58 -0
  80. data/lib/prompt_objects/universal/get_run_status.rb +30 -0
  81. data/lib/prompt_objects/universal/join_runs.rb +35 -0
  82. data/lib/prompt_objects/universal/list_env_data.rb +57 -0
  83. data/lib/prompt_objects/universal/modify_primitive.rb +1 -1
  84. data/lib/prompt_objects/universal/render_artifact.rb +91 -0
  85. data/lib/prompt_objects/universal/request_primitive.rb +1 -1
  86. data/lib/prompt_objects/universal/set_env_data.rb +101 -0
  87. data/lib/prompt_objects/version.rb +5 -0
  88. data/lib/prompt_objects.rb +36 -6
  89. data/objects/coordinator.md +8 -4
  90. data/templates/arc-agi-1/objects/data_manager.md +2 -2
  91. data/templates/arc-agi-1/objects/observer.md +6 -2
  92. data/templates/arc-agi-1/objects/solver.md +14 -4
  93. data/templates/arc-agi-1/objects/verifier.md +6 -2
  94. data/templates/arc-agi-3/manifest.yml +19 -0
  95. data/templates/arc-agi-3/objects/analyst.md +79 -0
  96. data/templates/arc-agi-3/objects/player.md +76 -0
  97. data/templates/arc-agi-3/objects/strategist.md +97 -0
  98. data/templates/arc-agi-3/primitives/action_log.rb +133 -0
  99. data/templates/arc-agi-3/primitives/arc3_api.rb +223 -0
  100. data/templates/arc-agi-3/primitives/arc3_scorecard.rb +131 -0
  101. data/templates/arc-agi-3/primitives/frame_diff.rb +143 -0
  102. data/templates/arc-agi-3/primitives/frame_info.rb +96 -0
  103. data/templates/arc-agi-3/primitives/render_frame.rb +140 -0
  104. data/templates/basic/objects/basic.md +11 -3
  105. data/templates/chiptune/extras/sonic_pi_boot.rb +220 -0
  106. data/templates/chiptune/manifest.yml +20 -0
  107. data/templates/chiptune/objects/conductor.md +184 -0
  108. data/templates/chiptune/objects/sonic_pi.md +65 -0
  109. data/templates/chiptune/objects/voice_bass.md +44 -0
  110. data/templates/chiptune/objects/voice_lead.md +44 -0
  111. data/templates/chiptune/objects/voice_pad.md +43 -0
  112. data/templates/chiptune/objects/voice_perc.md +45 -0
  113. data/templates/chiptune/primitives/play_note.rb +59 -0
  114. data/templates/chiptune/primitives/play_sequence.rb +55 -0
  115. data/templates/chiptune/primitives/query_sonic_pi.rb +141 -0
  116. data/templates/chiptune/primitives/set_synth.rb +57 -0
  117. data/templates/chiptune/primitives/set_tempo.rb +45 -0
  118. data/templates/chiptune/primitives/stop_voice.rb +46 -0
  119. data/templates/chiptune/primitives/support/osc_bridge.rb +33 -0
  120. data/templates/chiptune/vendor/osc-ruby-1.1.5/LICENSE +19 -0
  121. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/address_pattern.rb +58 -0
  122. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/broadcast_client.rb +24 -0
  123. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/bundle.rb +46 -0
  124. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/client.rb +13 -0
  125. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/core_ext/time.rb +6 -0
  126. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/em_server.rb +63 -0
  127. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/message.rb +46 -0
  128. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/network_packet.rb +42 -0
  129. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_argument.rb +26 -0
  130. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_packet.rb +140 -0
  131. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_types.rb +53 -0
  132. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/server.rb +91 -0
  133. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby.rb +18 -0
  134. data/templates/developer/objects/code_reviewer.md +1 -1
  135. data/templates/developer/objects/coordinator.md +16 -3
  136. data/templates/developer/objects/debugger.md +3 -3
  137. data/templates/empty/objects/assistant.md +10 -5
  138. data/templates/minimal/objects/assistant.md +10 -5
  139. data/templates/music/extras/sonic_pi_boot.rb +220 -0
  140. data/templates/music/manifest.yml +16 -0
  141. data/templates/music/objects/conductor.md +154 -0
  142. data/templates/music/objects/sonic_pi.md +65 -0
  143. data/templates/music/primitives/play_note.rb +55 -0
  144. data/templates/music/primitives/play_sequence.rb +51 -0
  145. data/templates/music/primitives/query_sonic_pi.rb +139 -0
  146. data/templates/music/primitives/set_synth.rb +53 -0
  147. data/templates/music/primitives/set_tempo.rb +43 -0
  148. data/templates/music/primitives/stop_voice.rb +44 -0
  149. data/templates/music/primitives/support/osc_bridge.rb +33 -0
  150. data/templates/music/vendor/osc-ruby-1.1.5/LICENSE +19 -0
  151. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/address_pattern.rb +58 -0
  152. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/broadcast_client.rb +24 -0
  153. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/bundle.rb +46 -0
  154. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/client.rb +13 -0
  155. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/core_ext/time.rb +6 -0
  156. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/em_server.rb +63 -0
  157. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/message.rb +46 -0
  158. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/network_packet.rb +42 -0
  159. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_argument.rb +26 -0
  160. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_packet.rb +140 -0
  161. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_types.rb +53 -0
  162. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/server.rb +91 -0
  163. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby.rb +18 -0
  164. data/templates/music-beginner/README.md +100 -0
  165. data/templates/music-beginner/extras/README.md +27 -0
  166. data/templates/music-beginner/extras/sonic_pi_boot.rb +297 -0
  167. data/templates/music-beginner/manifest.yml +25 -0
  168. data/templates/music-beginner/objects/conductor.md +222 -0
  169. data/templates/music-beginner/objects/engine_setup.md +54 -0
  170. data/templates/music-beginner/objects/voice_bass.md +43 -0
  171. data/templates/music-beginner/objects/voice_keys.md +48 -0
  172. data/templates/music-beginner/objects/voice_pad.md +46 -0
  173. data/templates/music-beginner/objects/voice_percussion.md +45 -0
  174. data/templates/music-beginner/objects/voice_texture.md +37 -0
  175. data/templates/music-beginner/primitives/play_pattern.rb +118 -0
  176. data/templates/music-beginner/primitives/query_music_engine.rb +94 -0
  177. data/templates/music-beginner/primitives/set_instrument.rb +47 -0
  178. data/templates/music-beginner/primitives/set_tempo.rb +43 -0
  179. data/templates/music-beginner/primitives/set_voice_level.rb +46 -0
  180. data/templates/music-beginner/primitives/stop_voice.rb +37 -0
  181. data/templates/music-beginner/primitives/support/osc_bridge.rb +25 -0
  182. data/templates/music-beginner/vendor/osc-ruby-1.1.5/LICENSE +19 -0
  183. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/address_pattern.rb +58 -0
  184. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/broadcast_client.rb +24 -0
  185. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/bundle.rb +46 -0
  186. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/client.rb +13 -0
  187. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/core_ext/time.rb +6 -0
  188. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/em_server.rb +63 -0
  189. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/message.rb +46 -0
  190. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/network_packet.rb +42 -0
  191. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_argument.rb +26 -0
  192. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_packet.rb +140 -0
  193. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_types.rb +53 -0
  194. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/server.rb +91 -0
  195. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby.rb +18 -0
  196. data/templates/music-pro/extras/AUDITION.md +100 -0
  197. data/templates/music-pro/extras/sonic_pi_boot.rb +546 -0
  198. data/templates/music-pro/manifest.yml +19 -0
  199. data/templates/music-pro/objects/conductor.md +126 -0
  200. data/templates/music-pro/objects/sonic_pi.md +35 -0
  201. data/templates/music-pro/objects/voice_harmony.md +48 -0
  202. data/templates/music-pro/objects/voice_rhythm.md +43 -0
  203. data/templates/music-pro/objects/voice_texture.md +42 -0
  204. data/templates/music-pro/primitives/define_patch.rb +46 -0
  205. data/templates/music-pro/primitives/query_music_engine.rb +69 -0
  206. data/templates/music-pro/primitives/set_live_pattern.rb +70 -0
  207. data/templates/music-pro/primitives/set_tempo.rb +31 -0
  208. data/templates/music-pro/primitives/stop_voice.rb +31 -0
  209. data/templates/music-pro/primitives/support/music_protocol.rb +136 -0
  210. data/templates/music-pro/primitives/support/osc_bridge.rb +33 -0
  211. data/templates/music-pro/primitives/trigger_event.rb +44 -0
  212. data/templates/music-pro/vendor/osc-ruby-1.1.5/LICENSE +19 -0
  213. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/address_pattern.rb +58 -0
  214. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/broadcast_client.rb +24 -0
  215. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/bundle.rb +46 -0
  216. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/client.rb +13 -0
  217. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/core_ext/time.rb +6 -0
  218. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/em_server.rb +63 -0
  219. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/message.rb +46 -0
  220. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/network_packet.rb +42 -0
  221. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_argument.rb +26 -0
  222. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_packet.rb +140 -0
  223. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_types.rb +53 -0
  224. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/server.rb +91 -0
  225. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby.rb +18 -0
  226. data/templates/writer/objects/coordinator.md +14 -3
  227. data/templates/writer/objects/editor.md +1 -1
  228. data/templates/writer/objects/researcher.md +2 -2
  229. data/tools/thread-explorer.html +28 -1
  230. metadata +175 -65
  231. data/CLAUDE.md +0 -176
  232. data/Gemfile +0 -10
  233. data/Gemfile.lock +0 -233
  234. data/IMPLEMENTATION_PLAN.md +0 -1073
  235. data/Rakefile +0 -27
  236. data/design-doc-v2.md +0 -1232
  237. data/frontend/.gitignore +0 -3
  238. data/frontend/index.html +0 -17
  239. data/frontend/package-lock.json +0 -4540
  240. data/frontend/package.json +0 -36
  241. data/frontend/postcss.config.js +0 -6
  242. data/frontend/src/App.tsx +0 -103
  243. data/frontend/src/canvas/CanvasView.tsx +0 -113
  244. data/frontend/src/canvas/ForceLayout.ts +0 -115
  245. data/frontend/src/canvas/SceneManager.ts +0 -587
  246. data/frontend/src/canvas/canvasStore.ts +0 -47
  247. data/frontend/src/canvas/constants.ts +0 -95
  248. data/frontend/src/canvas/controls/CameraControls.ts +0 -98
  249. data/frontend/src/canvas/edges/MessageArc.ts +0 -149
  250. data/frontend/src/canvas/inspector/InspectorPanel.tsx +0 -31
  251. data/frontend/src/canvas/inspector/POInspector.tsx +0 -262
  252. data/frontend/src/canvas/inspector/ToolCallInspector.tsx +0 -67
  253. data/frontend/src/canvas/nodes/PONode.ts +0 -249
  254. data/frontend/src/canvas/nodes/ToolCallNode.ts +0 -116
  255. data/frontend/src/canvas/types.ts +0 -24
  256. data/frontend/src/components/ContextMenu.tsx +0 -68
  257. data/frontend/src/components/Inspector.tsx +0 -232
  258. data/frontend/src/components/MarkdownMessage.tsx +0 -155
  259. data/frontend/src/components/MethodList.tsx +0 -90
  260. data/frontend/src/components/ModelSelector.tsx +0 -115
  261. data/frontend/src/components/NotificationPanel.tsx +0 -130
  262. data/frontend/src/components/ObjectList.tsx +0 -78
  263. data/frontend/src/components/PaneSlot.tsx +0 -30
  264. data/frontend/src/components/SourcePane.tsx +0 -202
  265. data/frontend/src/components/SystemBar.tsx +0 -74
  266. data/frontend/src/components/Transcript.tsx +0 -76
  267. data/frontend/src/components/UsagePanel.tsx +0 -105
  268. data/frontend/src/components/Workspace.tsx +0 -260
  269. data/frontend/src/components/index.ts +0 -12
  270. data/frontend/src/hooks/useResize.ts +0 -55
  271. data/frontend/src/hooks/useWebSocket.ts +0 -517
  272. data/frontend/src/index.css +0 -103
  273. data/frontend/src/main.tsx +0 -10
  274. data/frontend/src/store/index.ts +0 -279
  275. data/frontend/src/types/index.ts +0 -165
  276. data/frontend/tailwind.config.js +0 -44
  277. data/frontend/tsconfig.json +0 -30
  278. data/frontend/vite.config.ts +0 -29
  279. data/lib/prompt_objects/server/public/assets/index-D1myxE0l.js +0 -4345
  280. data/lib/prompt_objects/server/public/assets/index-DdCcwC-Z.css +0 -1
  281. data/lib/prompt_objects/universal/add_primitive.rb +0 -118
  282. data/lib/prompt_objects/universal/ask_human.rb +0 -109
  283. data/lib/prompt_objects/universal/create_primitive.rb +0 -174
  284. data/lib/prompt_objects/universal/list_primitives.rb +0 -145
  285. data/lib/prompt_objects/universal/think.rb +0 -41
  286. data/prompt_objects.gemspec +0 -50
  287. data/templates/basic/.gitignore +0 -2
  288. data/templates/developer/.gitignore +0 -5
  289. data/templates/empty/.gitignore +0 -5
  290. data/templates/empty/objects/.gitkeep +0 -0
  291. data/templates/minimal/.gitignore +0 -5
  292. data/templates/writer/.gitignore +0 -5
@@ -1,432 +1,74 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "cli/helpers"
4
+ require_relative "cli/env_command"
5
+ require_relative "cli/repl_command"
6
+ require_relative "cli/serve_command"
7
+ require_relative "cli/message_command"
8
+ require_relative "cli/events_command"
9
+ require_relative "cli/diagnostics_command"
10
+ require_relative "cli/explore_command"
11
+
3
12
  module PromptObjects
4
- # Command-line interface for environment management.
13
+ # Command-line interface. `CLI.run` is the single entry point used by the
14
+ # `prompt_objects` and `poop` executables; each command lives in its own
15
+ # class under lib/prompt_objects/cli/.
5
16
  module CLI
6
- # Handle env subcommands: list, create, info, archive, restore, clone, etc.
7
- class EnvCommand
8
- def initialize(manager: nil)
9
- @manager = manager || Env::Manager.new
10
- end
11
-
12
- # Run the env subcommand.
13
- # @param args [Array<String>] Arguments after 'env'
14
- def run(args)
15
- subcommand = args.shift || "list"
16
-
17
- case subcommand
18
- when "list", "ls"
19
- list
20
- when "create", "new"
21
- create(args)
22
- when "info"
23
- info(args)
24
- when "export"
25
- export(args)
26
- when "import"
27
- import(args)
28
- when "archive"
29
- archive(args)
30
- when "restore"
31
- restore(args)
32
- when "clone", "cp"
33
- clone(args)
34
- when "delete"
35
- delete(args)
36
- when "default"
37
- set_default(args)
38
- else
39
- puts "Unknown env command: #{subcommand}"
40
- puts
41
- help
42
- exit 1
43
- end
44
- end
45
-
46
- def list
47
- @manager.setup!
48
- envs = @manager.list_with_manifests
49
-
50
- if envs.empty?
51
- puts "No environments found."
52
- puts "Create one with: prompt_objects env create <name>"
53
- return
54
- end
55
-
56
- default = @manager.default_environment
57
-
58
- puts "Environments:"
59
- puts
60
- envs.each do |manifest|
61
- default_marker = manifest.name == default ? " (default)" : ""
62
- last_opened = manifest.last_opened&.strftime("%Y-%m-%d") || "never"
63
- puts " #{manifest.icon} #{manifest.name}#{default_marker}"
64
- puts " #{manifest.description}" if manifest.description
65
- puts " Last opened: #{last_opened}, Objects: #{manifest.stats['po_count']}"
66
- puts
67
- end
68
- end
69
-
70
- def create(args)
71
- name = args.shift
72
- unless name
73
- puts "Usage: prompt_objects env create <name> [--template <template>]"
74
- exit 1
75
- end
76
-
77
- template = nil
78
- args.each_with_index do |arg, i|
79
- if arg == "--template" || arg == "-t"
80
- template = args[i + 1]
81
- end
82
- end
83
-
84
- @manager.setup!
85
-
86
- path = @manager.create(name: name, template: template)
87
- puts "Created environment: #{name}"
88
- puts "Location: #{path}"
89
-
90
- if @manager.list.size == 1
91
- @manager.set_default_environment(name)
92
- puts "Set as default environment."
93
- end
94
- end
95
-
96
- def info(args)
97
- name = args.shift || @manager.default_environment
98
- unless name
99
- puts "Usage: prompt_objects env info <name>"
100
- exit 1
101
- end
102
-
103
- manifest = @manager.manifest_for(name)
104
- unless manifest
105
- puts "Environment '#{name}' not found."
106
- exit 1
107
- end
108
-
109
- path = @manager.environment_path(name)
110
- objects = Dir.glob(File.join(path, "objects", "*.md")).map { |f| File.basename(f, ".md") }
111
- primitives = Dir.glob(File.join(path, "primitives", "*.rb")).map { |f| File.basename(f, ".rb") }
112
-
113
- puts manifest.info
114
- puts
115
- puts " Location: #{path}"
116
- puts " Objects: #{objects.join(', ')}" if objects.any?
117
- puts " Custom primitives: #{primitives.join(', ')}" if primitives.any?
118
- puts
119
-
120
- if Env::Git.repo?(path)
121
- commits = Env::Git.commit_count(path)
122
- dirty = Env::Git.dirty?(path)
123
- puts " Git: #{commits} commits#{dirty ? ' (uncommitted changes)' : ''}"
124
- end
125
- end
126
-
127
- def export(args)
128
- @manager.setup!
129
-
130
- # Parse arguments
131
- name = nil
132
- output = nil
133
-
134
- i = 0
135
- while i < args.length
136
- case args[i]
137
- when "-o", "--output"
138
- output = args[i + 1]
139
- i += 1
140
- else
141
- name ||= args[i]
142
- end
143
- i += 1
144
- end
145
-
146
- # Default to current directory name if no output specified
147
- name ||= @manager.default_environment
148
- unless name
149
- puts "Usage: prompt_objects env export <name> [-o output.poenv]"
150
- exit 1
151
- end
152
-
153
- unless @manager.environment_exists?(name)
154
- puts "Environment '#{name}' not found."
155
- exit 1
156
- end
157
-
158
- output ||= "#{name}.poenv"
159
- env_path = @manager.environment_path(name)
160
-
161
- exporter = Env::Exporter.new(env_path)
162
- result = exporter.export(output)
163
-
164
- if result[:success]
165
- puts "Exported '#{name}' to: #{result[:path]}"
166
- puts
167
- puts "Stats:"
168
- puts " Commits: #{result[:stats][:commits]}"
169
- puts " Objects: #{result[:stats][:objects]}"
170
- puts " Primitives: #{result[:stats][:primitives]}"
171
- else
172
- puts "Export failed: #{result[:error]}"
173
- exit 1
174
- end
175
- end
176
-
177
- def import(args)
178
- @manager.setup!
179
-
180
- # Parse arguments
181
- bundle_path = nil
182
- import_as = nil
183
- trust = false
184
-
185
- i = 0
186
- while i < args.length
187
- case args[i]
188
- when "--as"
189
- import_as = args[i + 1]
190
- i += 1
191
- when "--trust"
192
- trust = true
193
- else
194
- bundle_path ||= args[i]
195
- end
196
- i += 1
197
- end
198
-
199
- unless bundle_path
200
- puts "Usage: prompt_objects env import <bundle.poenv> [--as <name>] [--trust]"
201
- puts
202
- puts "Options:"
203
- puts " --as <name> Import with a different name"
204
- puts " --trust Trust custom primitives (skip sandbox warnings)"
205
- exit 1
206
- end
207
-
208
- importer = Env::Importer.new(bundle_path)
209
-
210
- # First, inspect and show what's in the bundle
211
- info = importer.inspect_bundle
212
- unless info.valid
213
- puts "Invalid bundle: #{info.error}"
214
- exit 1
215
- end
216
-
217
- puts "Bundle contents:"
218
- puts " Name: #{info.name}"
219
- puts " Description: #{info.description}" if info.description
220
- puts " Objects: #{info.objects.join(', ')}" if info.objects.any?
221
- puts " Primitives: #{info.primitives.join(', ')}" if info.primitives.any?
222
- puts " Commits: #{info.commits}"
223
- puts
224
-
225
- # Warn about primitives
226
- if info.primitives.any? && !trust
227
- puts "⚠️ WARNING: This bundle contains custom primitives."
228
- puts "Custom primitives can execute arbitrary Ruby code."
229
- puts "Review the code before running, or use --trust to skip this warning."
230
- puts
231
- end
232
-
233
- # Import
234
- import_name = import_as || info.name
235
- result = importer.import(manager: @manager, name: import_name, trust_primitives: trust)
236
-
237
- if result[:success]
238
- puts "Imported as '#{result[:name]}'"
239
- puts "Location: #{result[:path]}"
240
-
241
- if result[:warnings].any?
242
- puts
243
- result[:warnings].each { |w| puts w }
244
- end
245
- else
246
- puts "Import failed: #{result[:error]}"
247
- exit 1
248
- end
249
- end
250
-
251
- def archive(args)
252
- name = args.shift
253
- unless name
254
- puts "Usage: prompt_objects env archive <name>"
255
- exit 1
256
- end
257
-
258
- path = @manager.archive(name)
259
- puts "Archived environment '#{name}' to:"
260
- puts " #{path}"
261
- end
262
-
263
- def restore(args)
264
- archived_name = args.shift
265
- unless archived_name
266
- # Show available archived environments
267
- archived = @manager.list_archived
268
- if archived.empty?
269
- puts "No archived environments."
270
- else
271
- puts "Archived environments:"
272
- archived.each { |name| puts " - #{name}" }
273
- puts
274
- puts "Usage: prompt_objects env restore <archived_name> [--as <new_name>]"
275
- end
276
- return
277
- end
278
-
279
- restore_as = nil
280
- args.each_with_index do |arg, i|
281
- restore_as = args[i + 1] if arg == "--as"
282
- end
283
-
284
- path = @manager.restore(archived_name, restore_as: restore_as)
285
- puts "Restored to: #{path}"
286
- end
287
-
288
- def clone(args)
289
- source = args.shift
290
- target = args.shift
291
-
292
- unless source && target
293
- puts "Usage: prompt_objects env clone <source> <target>"
294
- exit 1
295
- end
296
-
297
- path = @manager.clone(source, target)
298
- puts "Cloned '#{source}' to '#{target}'"
299
- puts "Location: #{path}"
300
- end
301
-
302
- def delete(args)
303
- name = args.shift
304
- permanent = args.include?("--permanent")
305
-
306
- unless name
307
- puts "Usage: prompt_objects env delete <archived_name> --permanent"
308
- puts
309
- puts "Note: Only archived environments can be permanently deleted."
310
- puts "First archive an environment, then delete it."
311
- return
312
- end
313
-
314
- unless permanent
315
- puts "Use --permanent to confirm deletion."
316
- puts "This cannot be undone."
317
- return
318
- end
319
-
320
- @manager.delete_archived(name)
321
- puts "Permanently deleted: #{name}"
322
- end
323
-
324
- def set_default(args)
325
- name = args.shift
326
- unless name
327
- current = @manager.default_environment
328
- if current
329
- puts "Current default: #{current}"
330
- else
331
- puts "No default environment set."
332
- end
333
- puts
334
- puts "Usage: prompt_objects env default <name>"
335
- return
336
- end
337
-
338
- @manager.set_default_environment(name)
339
- puts "Default environment set to: #{name}"
340
- end
341
-
342
- def help
343
- puts <<~HELP
344
- Environment management commands:
345
-
346
- prompt_objects env list List all environments
347
- prompt_objects env create <name> Create new environment
348
- --template, -t <template> Use template (minimal, developer, writer, empty)
349
- prompt_objects env info <name> Show environment details
350
- prompt_objects env export <name> Export environment as .poenv bundle
351
- -o, --output <file> Output file path
352
- prompt_objects env import <file> Import environment from .poenv bundle
353
- --as <name> Import with different name
354
- --trust Trust custom primitives
355
- prompt_objects env archive <name> Archive (soft delete) environment
356
- prompt_objects env restore <name> Restore archived environment
357
- --as <new_name> Restore with different name
358
- prompt_objects env clone <src> <dest> Clone environment
359
- prompt_objects env default <name> Set default environment
360
- prompt_objects env delete <name> --permanent Delete archived env
361
-
362
- Available templates:
363
- basic - No capabilities, learns as needed (great for demos!)
364
- minimal - Basic assistant with file reading
365
- developer - Code review, debugging, testing specialists
366
- writer - Editor, researcher for content creation
367
- empty - Bootstrap assistant only
368
- arc-agi-1 - ARC-AGI-1 challenge solving with grid primitives
369
- HELP
17
+ def self.run(argv)
18
+ command = argv[0]
19
+ args = argv[1..] || []
20
+
21
+ case command
22
+ when nil, "help", "--help", "-h"
23
+ print_main_help
24
+ when "version", "--version", "-v"
25
+ puts PromptObjects::VERSION
26
+ when "env"
27
+ EnvCommand.new.run(args)
28
+ when "serve"
29
+ ServeCommand.new.run(args)
30
+ when "message", "msg"
31
+ MessageCommand.new.run(args)
32
+ when "events"
33
+ EventsCommand.new.run(args)
34
+ when "diagnostics", "diag"
35
+ DiagnosticsCommand.new.run(args)
36
+ when "explore"
37
+ ExploreCommand.new.run(args)
38
+ when "repl"
39
+ ReplCommand.new.run(args)
40
+ else
41
+ # Legacy behavior: treat as repl with name argument
42
+ ReplCommand.new.run(argv)
370
43
  end
371
44
  end
372
45
 
373
- # Parse arguments and run appropriate command.
374
- # @param args [Array<String>] Command line arguments
375
- # @return [Hash] Parsed options for main command
376
- def self.parse(args)
377
- options = {
378
- env_name: nil,
379
- dev_mode: false,
380
- sandbox: false,
381
- command: :run
382
- }
383
-
384
- i = 0
385
- while i < args.length
386
- arg = args[i]
387
- case arg
388
- when "env"
389
- options[:command] = :env
390
- options[:env_args] = args[(i + 1)..]
391
- return options
392
- when "--env", "-e"
393
- options[:env_name] = args[i + 1]
394
- i += 1
395
- when "--dev"
396
- options[:dev_mode] = true
397
- when "--sandbox", "-s"
398
- options[:sandbox] = true
399
- when "--help", "-h"
400
- options[:command] = :help
401
- return options
402
- else
403
- # Assume it's a PO name or objects_dir (legacy)
404
- options[:legacy_args] ||= []
405
- options[:legacy_args] << arg
406
- end
407
- i += 1
408
- end
409
-
410
- options
411
- end
412
-
413
- # List available templates.
414
- # @return [Array<Hash>] Template info
415
- def self.list_templates
416
- templates_dir = File.expand_path("../../templates", __dir__)
417
- return [] unless Dir.exist?(templates_dir)
418
-
419
- Dir.children(templates_dir).filter_map do |name|
420
- manifest_path = File.join(templates_dir, name, "manifest.yml")
421
- next unless File.exist?(manifest_path)
422
-
423
- manifest = YAML.safe_load(File.read(manifest_path))
424
- {
425
- name: name,
426
- description: manifest["description"],
427
- icon: manifest["icon"]
428
- }
429
- end
46
+ def self.print_main_help
47
+ prog = Helpers.program_name
48
+ puts <<~HELP
49
+ Usage: #{prog} <command> [options]
50
+
51
+ Commands:
52
+ env Manage environments (create, list, export, etc.)
53
+ serve <env> Run environment as a web server
54
+ message <env> <po> "text" Send a message to a PO and print the response
55
+ events <env> [--session ID] Show recent events from the message bus
56
+ diagnostics <env> [--json] Show content-free runtime health metrics
57
+ explore [env] [--session ID] Open Thread Explorer to visualize conversations
58
+ repl [name] [objects_dir] Start interactive REPL with a prompt object
59
+ help Show this help message
60
+
61
+ Run '#{prog} <command> --help' for command-specific help.
62
+
63
+ Examples:
64
+ #{prog} env list # List all environments
65
+ #{prog} env create demo --template basic # Create from template
66
+ #{prog} serve my-env # Start web UI
67
+ #{prog} serve my-env --open # Start and open browser
68
+ #{prog} message my-env solver "Hello" # Send a message
69
+ #{prog} message my-env solver "Hello" --json # JSON output
70
+ #{prog} explore my-env # Visualize conversations
71
+ HELP
430
72
  end
431
73
  end
432
74
  end
@@ -36,38 +36,25 @@ module PromptObjects
36
36
  raise NotImplementedError, "#{self.class} must implement #source_name"
37
37
  end
38
38
 
39
- protected
40
-
41
- # Helper to get or create a session for a PO with source tracking
42
- # @param po [PromptObject] The prompt object
43
- # @param session_name [String, nil] Optional session name
44
- # @return [String] Session ID
45
- def get_or_create_session(po, session_name: nil)
46
- return nil unless runtime.session_store
47
-
48
- # Check if PO already has a session
49
- session_id = po.instance_variable_get(:@session_id)
50
- return session_id if session_id
51
-
52
- # Create new session with source tracking
53
- session_id = runtime.session_store.create_session(
54
- po_name: po.name,
55
- name: session_name || "#{source_name.upcase} Session #{Time.now.strftime('%H:%M')}",
56
- source: source_name
39
+ # Route an inbound external event to a PO through the unified entry point.
40
+ # The message is tagged with this connector's source, so its provenance
41
+ # shows up in the timeline (e.g. "← discord"). This is how a Discord/Slack/
42
+ # webhook connector forwards an incoming message to a Prompt-Object.
43
+ # @param target_po [String] PO to deliver to
44
+ # @param content [String] Message content
45
+ # @return [String] The PO's response
46
+ def inject(target_po:, content:, workspace_session_id: nil,
47
+ thread_id: nil, client_request_id: nil)
48
+ runtime.inject_message(
49
+ target_po: target_po,
50
+ content: content,
51
+ from_source: "service:#{source_name}",
52
+ workspace_session_id: workspace_session_id,
53
+ thread_id: thread_id,
54
+ client_request_id: client_request_id
57
55
  )
58
-
59
- # Attach to PO
60
- po.instance_variable_set(:@session_id, session_id)
61
- session_id
62
56
  end
63
57
 
64
- # Update last_message_source when a message is sent
65
- # @param session_id [String] Session ID
66
- def update_session_source(session_id)
67
- return unless runtime.session_store && session_id
68
-
69
- runtime.session_store.update_session(session_id, last_message_source: source_name)
70
- end
71
58
  end
72
59
  end
73
60
  end