prompt_objects 0.6.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 (291) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +126 -0
  3. data/README.md +93 -22
  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 +1337 -20
  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 +171 -519
  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 +549 -53
  65. data/lib/prompt_objects/server/app.rb +133 -14
  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 -227
  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 +600 -13
  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 +23 -15
  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 +8 -14
  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 +10 -14
  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/{store_env_data.rb → set_env_data.rb} +34 -20
  87. data/lib/prompt_objects/version.rb +5 -0
  88. data/lib/prompt_objects.rb +33 -8
  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 +2 -2
  92. data/templates/arc-agi-1/objects/solver.md +6 -5
  93. data/templates/arc-agi-1/objects/verifier.md +2 -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 +1 -1
  230. metadata +172 -65
  231. data/CLAUDE.md +0 -177
  232. data/Gemfile +0 -10
  233. data/Rakefile +0 -27
  234. data/frontend/.gitignore +0 -3
  235. data/frontend/index.html +0 -17
  236. data/frontend/package-lock.json +0 -4540
  237. data/frontend/package.json +0 -36
  238. data/frontend/postcss.config.js +0 -6
  239. data/frontend/src/App.tsx +0 -104
  240. data/frontend/src/canvas/CanvasView.tsx +0 -113
  241. data/frontend/src/canvas/ForceLayout.ts +0 -115
  242. data/frontend/src/canvas/SceneManager.ts +0 -587
  243. data/frontend/src/canvas/canvasStore.ts +0 -47
  244. data/frontend/src/canvas/constants.ts +0 -95
  245. data/frontend/src/canvas/controls/CameraControls.ts +0 -98
  246. data/frontend/src/canvas/edges/MessageArc.ts +0 -149
  247. data/frontend/src/canvas/inspector/InspectorPanel.tsx +0 -31
  248. data/frontend/src/canvas/inspector/POInspector.tsx +0 -262
  249. data/frontend/src/canvas/inspector/ToolCallInspector.tsx +0 -67
  250. data/frontend/src/canvas/nodes/PONode.ts +0 -249
  251. data/frontend/src/canvas/nodes/ToolCallNode.ts +0 -116
  252. data/frontend/src/canvas/types.ts +0 -24
  253. data/frontend/src/components/ContextMenu.tsx +0 -68
  254. data/frontend/src/components/EnvDataPane.tsx +0 -69
  255. data/frontend/src/components/Inspector.tsx +0 -263
  256. data/frontend/src/components/MarkdownMessage.tsx +0 -155
  257. data/frontend/src/components/MethodList.tsx +0 -90
  258. data/frontend/src/components/ModelSelector.tsx +0 -115
  259. data/frontend/src/components/NotificationPanel.tsx +0 -130
  260. data/frontend/src/components/ObjectList.tsx +0 -78
  261. data/frontend/src/components/PaneSlot.tsx +0 -30
  262. data/frontend/src/components/SourcePane.tsx +0 -202
  263. data/frontend/src/components/SystemBar.tsx +0 -74
  264. data/frontend/src/components/Transcript.tsx +0 -76
  265. data/frontend/src/components/UsagePanel.tsx +0 -105
  266. data/frontend/src/components/Workspace.tsx +0 -260
  267. data/frontend/src/components/index.ts +0 -12
  268. data/frontend/src/hooks/useResize.ts +0 -55
  269. data/frontend/src/hooks/useWebSocket.ts +0 -559
  270. data/frontend/src/index.css +0 -102
  271. data/frontend/src/main.tsx +0 -10
  272. data/frontend/src/store/index.ts +0 -311
  273. data/frontend/src/types/index.ts +0 -176
  274. data/frontend/tailwind.config.js +0 -44
  275. data/frontend/tsconfig.json +0 -30
  276. data/frontend/vite.config.ts +0 -29
  277. data/lib/prompt_objects/server/public/assets/index-DEPawnfZ.js +0 -4345
  278. data/lib/prompt_objects/server/public/assets/index-oMrRce1m.css +0 -1
  279. data/lib/prompt_objects/universal/add_primitive.rb +0 -118
  280. data/lib/prompt_objects/universal/ask_human.rb +0 -109
  281. data/lib/prompt_objects/universal/create_primitive.rb +0 -174
  282. data/lib/prompt_objects/universal/list_primitives.rb +0 -145
  283. data/lib/prompt_objects/universal/think.rb +0 -41
  284. data/lib/prompt_objects/universal/update_env_data.rb +0 -88
  285. data/prompt_objects.gemspec +0 -50
  286. data/templates/basic/.gitignore +0 -2
  287. data/templates/developer/.gitignore +0 -5
  288. data/templates/empty/.gitignore +0 -5
  289. data/templates/empty/objects/.gitkeep +0 -0
  290. data/templates/minimal/.gitignore +0 -5
  291. data/templates/writer/.gitignore +0 -5
@@ -0,0 +1,58 @@
1
+ module OSC
2
+ class AddressPattern
3
+ def initialize(pattern)
4
+ @pattern = pattern
5
+
6
+ generate_regex_from_pattern
7
+ end
8
+
9
+ def match?(address)
10
+ !!(@re.nil? || @re.match(address))
11
+ end
12
+
13
+ private
14
+
15
+ def generate_regex_from_pattern
16
+ case @pattern
17
+ when nil
18
+ @re = @pattern
19
+ when Regexp
20
+ @re = @pattern
21
+ when String
22
+ # i'm unsure what this does
23
+ # @pattern.gsub!(/[.^(|)]/, '\\1')
24
+
25
+ # handles osc single char wildcard matching
26
+ @pattern.gsub!(/\?/, '[^/]')
27
+
28
+ # handles ** - used in creating osc routers
29
+ # TODO: turns out the OSC 1.1 spec says that we shoudl use "//"
30
+ # this will be implemented in the next major release of this gem
31
+ #@pattern.gsub!(/\*\*/, '.*' )
32
+
33
+ # handles osc * - 0 or more matching
34
+ @pattern.gsub!(/\*[^\*]/, '[^/]*')
35
+
36
+ # handles [!] matching
37
+ @pattern.gsub!(/\[!/, '[^')
38
+
39
+ # handles {} matching
40
+ @pattern.gsub!(/\{/, '(')
41
+ @pattern.gsub!(/,/, '|')
42
+ @pattern.gsub!(/\}/, ')')
43
+
44
+
45
+ # keeps from matching before the begining of the pattern
46
+ @pattern.gsub!(/\A/, '\A')
47
+
48
+ # keeps from matching beyond the end,
49
+ # eg. pattern /hi does not match /hidden
50
+ @pattern.gsub!(/\z/, '\z')
51
+
52
+ @re = Regexp.new(@pattern)
53
+ else
54
+ raise(ArgumentError, 'invalid pattern')
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,24 @@
1
+ require 'ipaddr'
2
+
3
+ module OSC
4
+ class BroadcastClient
5
+
6
+ BROADCAST_ADDRESS = '<broadcast>'
7
+
8
+ attr_reader :port
9
+
10
+ def initialize(port, local_ip = nil)
11
+ @port = port
12
+ @so = UDPSocket.new
13
+ @so.setsockopt Socket::SOL_SOCKET, Socket::SO_BROADCAST, true
14
+ if local_ip
15
+ @so.setsockopt Socket::IPPROTO_IP, Socket::IP_MULTICAST_IF, IPAddr.new(local_ip).hton
16
+ @so.bind(local_ip, 0)
17
+ end
18
+ end
19
+
20
+ def send(mesg)
21
+ @so.send(mesg.encode, 0, BROADCAST_ADDRESS, @port)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,46 @@
1
+ module OSC
2
+ class Bundle
3
+ attr_accessor :timetag
4
+
5
+ def initialize(timetag=nil, *args)
6
+ @timetag = timetag
7
+ @args = args
8
+ end
9
+
10
+ def encode()
11
+ s = OSCString.new('#bundle').encode
12
+ s << encode_timetag(@timetag)
13
+ s << @args.collect do |x|
14
+ x2 = x.encode; [x2.size].pack('N') + x2
15
+ end.join
16
+ end
17
+
18
+ def to_a
19
+ @args.collect{|x| x.to_a}
20
+ end
21
+
22
+ private
23
+
24
+ def encode_timetag(t)
25
+ case t
26
+ when nil # immediately
27
+ t1 = 0
28
+ t2 = 1
29
+ when Numeric
30
+ t1, t2 = construct_timetag(t)
31
+ when Time
32
+ t1, t2 = construct_timetag(t.to_ntp)
33
+ else
34
+ raise(ArgumentError, 'invalid time')
35
+ end
36
+ [t1, t2].pack('N2')
37
+ end
38
+
39
+ def construct_timetag(time)
40
+ t1, fr = time.divmod(1)
41
+ t2 = (fr * (2**32)).to_i
42
+
43
+ [t1, t2]
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,13 @@
1
+ module OSC
2
+ class Client
3
+
4
+ def initialize(host, port)
5
+ @so = UDPSocket.new
6
+ @so.connect(host, port)
7
+ end
8
+
9
+ def send(mesg)
10
+ @so.send(mesg.encode, 0)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,6 @@
1
+ class Time
2
+
3
+ def to_ntp
4
+ self.to_f + 2208988800
5
+ end
6
+ end
@@ -0,0 +1,63 @@
1
+ require 'eventmachine'
2
+
3
+ module OSC
4
+ Channel = EM::Channel.new
5
+
6
+ class Connection < EventMachine::Connection
7
+ def receive_data(data)
8
+ ip_info = get_peername[2,6].unpack("nC4")
9
+ Channel << OSC::OSCPacket.messages_from_network(data, ip_info)
10
+ end
11
+ end
12
+
13
+ class EMServer
14
+
15
+ def initialize(port = 3333)
16
+ @port = port
17
+ setup_dispatcher
18
+ @tuples = []
19
+ end
20
+
21
+ def run
22
+ EM.error_handler{ |e|
23
+ Thread.main.raise e
24
+ }
25
+
26
+ EM.run do
27
+ EM::open_datagram_socket "0.0.0.0", @port, Connection
28
+ end
29
+ end
30
+
31
+ def add_method(address_pattern, &proc)
32
+ matcher = AddressPattern.new(address_pattern)
33
+
34
+ @tuples << [matcher, proc]
35
+ end
36
+
37
+ private
38
+ def setup_dispatcher
39
+ Channel.subscribe do |messages|
40
+ messages.each do |message|
41
+ diff = (message.time || 0) - Time.now.to_ntp
42
+
43
+ if diff <= 0
44
+ sendmesg(message)
45
+ else
46
+ EM.defer do
47
+ sleep(diff)
48
+ sendmesg(message)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ def sendmesg(mesg)
56
+ @tuples.each do |matcher, obj|
57
+ if matcher.match?(mesg.address)
58
+ obj.call(mesg)
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,46 @@
1
+ module OSC
2
+ class Message
3
+ attr_accessor :address
4
+ attr_accessor :time
5
+ attr_accessor :ip_address
6
+ attr_accessor :ip_port
7
+
8
+ def self.new_with_time(address, time, tags=nil, *args)
9
+ message = new(address, tags, *args)
10
+ message.time = time
11
+ message
12
+ end
13
+
14
+ def initialize(address, *args)
15
+ @address = address
16
+ @args = []
17
+
18
+ args.each do |arg|
19
+ case arg
20
+ when Integer; @args << OSCInt32.new(arg)
21
+ when Float; @args << OSCFloat32.new(arg)
22
+ when String; @args << OSCString.new(arg)
23
+ when OSCArgument; @args << arg
24
+ end
25
+ end
26
+ end
27
+
28
+ def tags
29
+ @args.collect{|x| x.tag}.join
30
+ end
31
+
32
+ def encode
33
+ s = OSCString.new(@address).encode
34
+ s << OSCString.new(',' + tags).encode
35
+ s << @args.collect{|x| x.encode}.join
36
+ end
37
+
38
+ def to_a
39
+ @args.collect{|x| x.val}
40
+ end
41
+
42
+ def ==(other)
43
+ @address == other.address && to_a == other.to_a
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,42 @@
1
+ module OSC
2
+ class NetworkPacket
3
+ def initialize(str)
4
+ @str = str.force_encoding("BINARY")
5
+ @index = 0
6
+ end
7
+
8
+ def to_s
9
+ @str
10
+ end
11
+
12
+ def rem
13
+ @str.length - @index
14
+ end
15
+
16
+ def eof?
17
+ rem <= 0
18
+ end
19
+
20
+ def skip(n)
21
+ @index += n
22
+ end
23
+
24
+ def skip_padding
25
+ skip((4 - (@index % 4)) % 4)
26
+ end
27
+
28
+ def getn(n)
29
+ raise(EOFError) if rem < n
30
+ s = @str[@index, n]
31
+ skip(n)
32
+ s
33
+ end
34
+
35
+ def getc
36
+ raise(EOFError) if rem < 1
37
+ c = @str[@index]
38
+ skip(1)
39
+ c
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,26 @@
1
+ module OSC
2
+ class OSCArgument
3
+ def initialize(val)
4
+ @val = val
5
+ end
6
+
7
+ attr_accessor :val
8
+
9
+ def to_i()
10
+ @val.to_i
11
+ end
12
+
13
+ def to_f()
14
+ @val.to_f
15
+ end
16
+
17
+ def to_s()
18
+ @val.to_s
19
+ end
20
+
21
+ private
22
+ def padding(s)
23
+ s + ("\000" * ((4 - (s.size % 4)) % 4))
24
+ end
25
+ end
26
+ end
@@ -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'
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: code_reviewer
3
3
  description: Reviews code for quality, bugs, and improvements
4
- capabilities:
4
+ tools:
5
5
  - read_file
6
6
  ---
7
7
 
@@ -1,9 +1,10 @@
1
1
  ---
2
2
  name: coordinator
3
3
  description: Coordinates between coding specialists to help with development tasks
4
- capabilities:
4
+ delegates_to:
5
5
  - code_reviewer
6
6
  - debugger
7
+ tools:
7
8
  - read_file
8
9
  - list_files
9
10
  ---
@@ -31,8 +32,20 @@ For quick file exploration:
31
32
  - Use read_file and list_files directly
32
33
 
33
34
  When you need a new kind of specialist:
34
- - Use ask_human to confirm
35
- - Use create_capability to build it
35
+ - Inspect and delegate to the existing specialists first
36
+ - Use create_capability only when no existing PO can do the work
37
+
38
+ ## Your interface
39
+
40
+ For multi-step work, render a **Workbench** artifact and keep it current: the task list with
41
+ status, findings from each specialist as they report back, and buttons wired to
42
+ `PromptObjects.send(...)` — "review this next", "dig into this finding", "mark resolved".
43
+ Re-render the same title as work progresses so the human steers the work by clicking, not
44
+ re-typing context.
45
+
46
+ ## Conversation Threads
47
+
48
+ Treat every human thread as an independent development task. Keep its repository assumptions, files, decisions, and specialist findings inside that thread; never import details from another conversation just because it also addresses the same project. If the human opens two threads, advance both independently. Put only intentionally shared, durable facts in env_data, under descriptive keys, and explain when you do so.
36
49
 
37
50
  ## Notes
38
51
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: debugger
3
3
  description: Helps diagnose and fix bugs through systematic investigation
4
- capabilities:
4
+ tools:
5
5
  - read_file
6
6
  - list_files
7
7
  ---
@@ -26,9 +26,9 @@ When you find the cause:
26
26
  - Note any related issues you spotted
27
27
 
28
28
  When stuck:
29
- - Ask for more information
29
+ - Inspect the available evidence and delegate focused investigation to a capable PO
30
30
  - Suggest diagnostic steps the user can try
31
- - Use ask_human to clarify symptoms
31
+ - If essential evidence is unavailable, state the missing evidence and continue with the best-supported hypothesis instead of blocking
32
32
 
33
33
  ## Notes
34
34