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
@@ -0,0 +1,140 @@
1
+ require File.join(File.dirname( __FILE__ ), 'network_packet')
2
+ require 'ostruct'
3
+
4
+ module OSC
5
+ class UnknownType < StandardError; end
6
+
7
+ class OSCPacket
8
+ def self.messages_from_network(string, ip_info=nil)
9
+ messages = []
10
+ osc = new(string)
11
+
12
+ if osc.bundle?
13
+ osc.get_string
14
+ time = osc.get_timestamp
15
+
16
+ osc.get_bundle_messages.each do |message|
17
+ msg = decode_simple_message(time, OSCPacket.new(message))
18
+ if ip_info
19
+ # Append info for the ip address
20
+ msg.ip_port = ip_info.shift
21
+ msg.ip_address = ip_info.join(".")
22
+ end
23
+ messages << msg
24
+ end
25
+
26
+ else
27
+ msg = decode_simple_message(time, osc)
28
+ if ip_info
29
+ # Append info for the ip address
30
+ msg.ip_port = ip_info.shift
31
+ msg.ip_address = ip_info.join(".")
32
+ end
33
+ messages << msg
34
+ end
35
+
36
+ return messages
37
+ end
38
+
39
+ def self.decode_simple_message(time, osc_packet)
40
+ address = osc_packet.get_string
41
+ args = osc_packet.get_arguments
42
+
43
+ Message.new_with_time(address, time, nil, *args)
44
+ end
45
+
46
+ def initialize(string)
47
+ @packet = NetworkPacket.new(string)
48
+
49
+ @types = {
50
+ "i" => lambda{OSCInt32.new(get_int32)},
51
+ "f" => lambda{ OSCFloat32.new(get_float32)},
52
+ "d" => lambda{ OSCDouble64.new(get_double64)},
53
+ "s" => lambda{ OSCString.new(get_string)},
54
+ "b" => lambda{ OSCBlob.new(get_blob)}
55
+ }
56
+ end
57
+
58
+ def get_bundle_messages
59
+ bundle_messages = []
60
+
61
+ until @packet.eof?
62
+ l = @packet.getn(4).unpack('N')[0]
63
+ bundle_messages << @packet.getn(l)
64
+ end
65
+ bundle_messages
66
+ end
67
+
68
+ def get_string
69
+ result = ''
70
+ until ((c = @packet.getc) == string_delemeter)
71
+ result << c
72
+ end
73
+ @packet.skip_padding
74
+ result
75
+ end
76
+
77
+ def get_timestamp
78
+ #TODO: refactor this so a mortal can figure it out
79
+ t1 = @packet.getn(4).unpack('N')[0]
80
+ t2 = @packet.getn(4).unpack('N')[0]
81
+ @packet.skip_padding
82
+
83
+ if t1 == 0 && t2 == 1
84
+ time = nil
85
+ else
86
+ time = t1 + t2.to_f / (2**32)
87
+ end
88
+
89
+ time
90
+ end
91
+
92
+ def get_arguments
93
+ if (@packet.getc == ?,)
94
+ tags = get_string
95
+ args = []
96
+
97
+ tags.scan(/./) do |tag|
98
+ type_handler = @types[tag]
99
+ raise(UnknownType, "Unknown OSC type: #{tag}") unless type_handler
100
+ args << type_handler.call
101
+ end
102
+ args
103
+ end
104
+ end
105
+
106
+ def get_int32
107
+ i = @packet.getn(4).unpack('N')[0]
108
+ i -= 2**32 if i > (2**31-1)
109
+ @packet.skip_padding
110
+ i
111
+ end
112
+
113
+ def get_float32
114
+ f = @packet.getn(4).unpack('g')[0]
115
+ @packet.skip_padding
116
+ f
117
+ end
118
+
119
+ def get_double64
120
+ f = @packet.getn(8).unpack('G')[0]
121
+ @packet.skip_padding
122
+ f
123
+ end
124
+
125
+ def get_blob
126
+ l = @packet.getn(4).unpack('N')[0]
127
+ b = @packet.getn(l)
128
+ @packet.skip_padding
129
+ b
130
+ end
131
+
132
+ def bundle?
133
+ !(@packet.to_s =~ /\A\#bundle/).nil?
134
+ end
135
+
136
+ def string_delemeter
137
+ "\x00"
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,53 @@
1
+ require File.join(File.dirname(__FILE__), "osc_argument")
2
+
3
+ module OSC
4
+ class OSCInt32 < OSCArgument
5
+ def tag
6
+ 'i'
7
+ end
8
+
9
+ def encode
10
+ [@val].pack('N').force_encoding("BINARY")
11
+ end
12
+ end
13
+
14
+ class OSCFloat32 < OSCArgument
15
+ def tag
16
+ 'f'
17
+ end
18
+
19
+ def encode
20
+ [@val].pack('g').force_encoding("BINARY")
21
+ end
22
+ end
23
+
24
+ class OSCDouble64 < OSCArgument
25
+ def tag
26
+ 'd'
27
+ end
28
+
29
+ def encode
30
+ [@val].pack('G').force_encoding("BINARY")
31
+ end
32
+ end
33
+
34
+ class OSCString < OSCArgument
35
+ def tag
36
+ 's'
37
+ end
38
+
39
+ def encode
40
+ padding(@val.sub(/\000.*\z/, '') + "\000").force_encoding("BINARY")
41
+ end
42
+ end
43
+
44
+ class OSCBlob < OSCArgument
45
+ def tag
46
+ 'b'
47
+ end
48
+
49
+ def encode
50
+ padding([@val.size].pack('N') + @val).force_encoding("BINARY")
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,91 @@
1
+ module OSC
2
+ class Server
3
+ def initialize(port)
4
+ @socket = UDPSocket.new
5
+ @socket.bind('', port)
6
+ @matchers = []
7
+ @queue = Queue.new
8
+ end
9
+
10
+ def run
11
+ start_dispatcher
12
+
13
+ start_detector
14
+ end
15
+
16
+ def stop
17
+ @socket.close
18
+ end
19
+
20
+ def add_method(address_pattern, &proc)
21
+ matcher = AddressPattern.new(address_pattern)
22
+
23
+ @matchers << [matcher, proc]
24
+ end
25
+
26
+ private
27
+
28
+ def start_detector
29
+ begin
30
+ detector
31
+ rescue
32
+ Thread.main.raise($!)
33
+ end
34
+ end
35
+
36
+ def start_dispatcher
37
+ Thread.fork do
38
+ begin
39
+ dispatcher
40
+ rescue
41
+ Thread.main.raise($!)
42
+ end
43
+ end
44
+ end
45
+
46
+ def dispatcher
47
+ loop do
48
+ mesg = @queue.pop
49
+ dispatch_message(mesg)
50
+ end
51
+ end
52
+
53
+ def dispatch_message(message)
54
+ diff = (message.time || 0) - Time.now.to_ntp
55
+
56
+ if diff <= 0
57
+ sendmesg(message)
58
+ else # spawn a thread to wait until it's time
59
+ Thread.fork do
60
+ sleep(diff)
61
+ sendmesg(message)
62
+ Thread.exit
63
+ end
64
+ end
65
+ end
66
+
67
+ def sendmesg(mesg)
68
+ @matchers.each do |matcher, proc|
69
+ if matcher.match?(mesg.address)
70
+ proc.call(mesg)
71
+ end
72
+ end
73
+ end
74
+
75
+ def detector
76
+ loop do
77
+ osc_data, network = @socket.recvfrom(16384)
78
+ begin
79
+ ip_info = Array.new
80
+ ip_info << network[1]
81
+ ip_info.concat(network[2].split('.'))
82
+ OSCPacket.messages_from_network( osc_data, ip_info ).each do |message|
83
+ @queue.push(message)
84
+ end
85
+
86
+ rescue(EOFError)
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,18 @@
1
+ require 'socket'
2
+ require 'thread'
3
+
4
+ # core extensions
5
+ require 'osc-ruby/core_ext/time'
6
+
7
+ # jus the basics
8
+ require 'osc-ruby/osc_types'
9
+ require 'osc-ruby/osc_packet'
10
+
11
+ require 'osc-ruby/message'
12
+ require 'osc-ruby/bundle'
13
+ require 'osc-ruby/address_pattern'
14
+
15
+ # now we gettin fancy
16
+ require 'osc-ruby/server'
17
+ require 'osc-ruby/client'
18
+ require 'osc-ruby/broadcast_client'
@@ -0,0 +1,100 @@
1
+ # Music Beginner
2
+
3
+ `music-beginner` is a constrained-but-generative Sonic Pi ensemble. Five Prompt
4
+ Objects own distinct musical roles, communicate through a shared composition
5
+ contract, and keep rewriting their own looping patterns. The constraints are a
6
+ musical guardrail, not a prerecorded arrangement: agents still choose the
7
+ notes, chords, rests, rhythms, instrumentation, and evolution.
8
+
9
+ New environments default to Gemini 3.5 Flash for a responsive balance of tool
10
+ use and musical direction. The selected provider and model are stored in the
11
+ environment manifest, so the choice survives a server restart. Set
12
+ `GEMINI_API_KEY` before serving the environment.
13
+
14
+ ## Start it
15
+
16
+ 1. Create a new environment from this template and start Prompt Objects.
17
+ 2. Open Sonic Pi.
18
+ 3. In an empty Sonic Pi buffer, run one line, replacing the path with the new
19
+ environment's absolute path:
20
+
21
+ ```ruby
22
+ run_file "/Users/you/.prompt_objects/environments/my-music/extras/sonic_pi_boot.rb"
23
+ ```
24
+
25
+ 4. Send the conductor: `Hit it.` The conductor treats that as a complete cue to
26
+ check Sonic Pi and launch the template's talk-safe backing-track contract.
27
+ 5. Start with your computer volume low and bring it up gradually.
28
+
29
+ Once it is playing, the conductor also understands `change it up`, `bring it
30
+ down`, and `stop`/`cut`. These are performance cues rather than fixed songs:
31
+ the voices still compose and perform their own material within the template's
32
+ musical guardrails.
33
+
34
+ The autonomous timer stays dormant until the conductor receives a new human
35
+ message after the server starts. It then waits 45 seconds before its first
36
+ evolution turn, so your initialization prompt always establishes the piece.
37
+ Later timer turns use the short evolution instruction configured in the
38
+ conductor's frontmatter; they do not reuse your original prompt.
39
+
40
+ The conductor verifies every activation against live engine state. “Connected”
41
+ only means the boot engine is reachable; a connected engine with zero active
42
+ voices is silent. Musicians are instructed to perform their playback tool calls
43
+ in the same turn instead of stopping at a prose proposal.
44
+
45
+ The engine listens for OSC on Sonic Pi's standard port `4560`. The Prompt
46
+ Objects query state on port `4561`. Set `SONIC_PI_HOST` or `SONIC_PI_PORT` before
47
+ starting Prompt Objects if you need different OSC settings.
48
+
49
+ The supplied patch set requires Sonic Pi 4.0 or newer (`:bass_foundation` was
50
+ introduced in 4.0). It is developed against Sonic Pi 4.6.0. The Ruby tests can
51
+ verify the protocol and template wiring without audio, but the final balance is
52
+ speaker-, room-, and voice-dependent, so audition it in Sonic Pi before a live
53
+ performance.
54
+
55
+ ## Pattern notation
56
+
57
+ A voice sends semicolon-separated events:
58
+
59
+ ```text
60
+ C3+E3+G3@4@0.7@4.5;R@1;F3+A3+C4@3@0.6@3.2
61
+ ```
62
+
63
+ Each event is `sound@step_beats@amplitude@gate_beats`. Amplitude and gate are
64
+ optional. `step_beats` controls when the next event begins; `gate_beats`
65
+ controls how long sustained presets such as pads, bass, and tonal textures ring,
66
+ so pads may overlap slightly while a keys phrase stays articulated. Amplitude
67
+ is clamped to `0.0..1.0`. Sounds are:
68
+
69
+ - a note: `C4`, `Fs3`, `Eb5`, or MIDI `60`
70
+ - a chord joined with `+`: `C3+E3+G3`
71
+ - a rest: `R`
72
+ - with `gentle_kit`, a real sample token: `kick`, `hat`, `snare`, or `tick`
73
+
74
+ Patterns may contain up to 32 events and 64 beats. The engine pads their length
75
+ to the next whole bar and applies replacements at a synchronized pattern/bar
76
+ boundary, so an agent changing a loop does not knock the ensemble out of time.
77
+
78
+ ## The safe palette
79
+
80
+ - `soft_keys` — rounded electric piano
81
+ - `air_pad` — slow, filtered pad
82
+ - `warm_bass` — centered low foundation
83
+ - `felt_pluck` — quiet kalimba-like accents
84
+ - `glass_bell` — very sparse bell color
85
+ - `sine_glow` — nearly pure tonal texture
86
+ - `gentle_kit` — real kick, closed-hat, snare, and tick samples
87
+
88
+ Preset gains, envelopes, filtering, and effects are deliberately conservative.
89
+ Agents can change voice level and per-event amplitude, but the engine applies a
90
+ second hard level clamp. `stop_voice(voice: "all")` is the emergency silence.
91
+
92
+ ## A useful first audition
93
+
94
+ Tell the conductor `Hit it.` Its default is `96 BPM, C major pentatonic, Cmaj7 /
95
+ Am7 / Fmaj7 / G6, one chord per bar, flowing-light density`. Bring voices in one
96
+ at a time: connected pad, phrase-based keys, bass, quiet percussion, then
97
+ optional texture. For background use, lower levels rather than asking every
98
+ voice to add more rests. Let it evolve for several minutes; autonomous changes
99
+ develop recognizable new movements by coordinating a few voices around one
100
+ intention while keeping an unchanged voice as a continuity anchor.
@@ -0,0 +1,27 @@
1
+ # Start the Music Beginner engine
2
+
3
+ Open Sonic Pi and run this one line from an empty buffer, replacing the path
4
+ with this environment's absolute path:
5
+
6
+ ```ruby
7
+ run_file "/Users/you/.prompt_objects/environments/my-music/extras/sonic_pi_boot.rb"
8
+ ```
9
+
10
+ Then tell the conductor `Hit it.` It will check the connection and begin a
11
+ quiet talk-safe composition using the template's default musical contract.
12
+ Start with your computer volume low. For immediate silence, tell the conductor
13
+ to stop all voices or press Sonic Pi's Stop button.
14
+
15
+ The default contract uses connected one-bar chord changes and a quiet rhythmic
16
+ spine. If the result sounds like isolated notes separated by long gaps, query
17
+ the live engine: the pad should report `air_pad`, and keys or percussion should
18
+ remain rhythmically active.
19
+
20
+ `connected: true` confirms only that the engine is reachable. The conductor
21
+ must make each musician perform its playback tools and verify that the engine
22
+ reports an active voice; an engine with zero active voices is silent.
23
+
24
+ Pattern notation and audition suggestions are documented in the source
25
+ template's `README.md`. You can also ask the `engine_setup` Prompt Object for
26
+ connection, setup, and notation help. It is intentionally read-only and cannot
27
+ change the music.