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,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: coordinator
3
3
  description: Coordinates between writing specialists for content creation
4
- capabilities:
4
+ delegates_to:
5
5
  - editor
6
6
  - researcher
7
7
  ---
@@ -25,8 +25,19 @@ For fact-checking and research:
25
25
  - Delegate to researcher
26
26
 
27
27
  When you need a new kind of specialist:
28
- - Use ask_human to confirm
29
- - Use create_capability to build it
28
+ - Inspect and delegate to the existing specialists first
29
+ - Use create_capability only when no existing PO can do the work
30
+
31
+ ## Your interface
32
+
33
+ For a piece in progress, render a **Drafting Desk** artifact: the current draft (or outline),
34
+ its status (researching / drafting / editing), and buttons wired to `PromptObjects.send(...)` —
35
+ "tighten this section", "fact-check the claims", "make it warmer", "approve". Re-render the same
36
+ title as the piece evolves so the human can direct revisions by clicking instead of re-explaining.
37
+
38
+ ## Conversation Threads
39
+
40
+ Treat every human thread as an independent piece or editorial assignment. Preserve the brief, voice, sources, draft, and specialist feedback within that thread; never blend in material from another conversation merely because the topics overlap. If the human opens two threads, advance both independently. Put only deliberately shared, durable research in env_data, under descriptive keys, and say when you do so.
30
41
 
31
42
  ## Notes
32
43
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: editor
3
3
  description: Provides writing feedback and helps polish prose
4
- capabilities: []
4
+ tools: []
5
5
  ---
6
6
 
7
7
  # Editor
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: researcher
3
3
  description: Researches topics and verifies facts for writing projects
4
- capabilities:
4
+ tools:
5
5
  - http_get
6
6
  ---
7
7
 
@@ -27,7 +27,7 @@ When fact-checking:
27
27
  When you can't find something:
28
28
  - Say so clearly
29
29
  - Suggest alternative approaches
30
- - Use ask_human if the user might have sources
30
+ - Delegate another search strategy when a capable PO is available; otherwise identify the missing source without blocking the run
31
31
 
32
32
  ## Notes
33
33