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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +126 -0
- data/README.md +93 -22
- data/exe/poop +5 -0
- data/exe/prompt_objects +1 -1108
- data/exe/prompt_objects_mcp +5 -3
- data/lib/prompt_objects/capability.rb +33 -0
- data/lib/prompt_objects/cli/diagnostics_command.rb +69 -0
- data/lib/prompt_objects/cli/env_command.rb +435 -0
- data/lib/prompt_objects/cli/events_command.rb +145 -0
- data/lib/prompt_objects/cli/explore_command.rb +155 -0
- data/lib/prompt_objects/cli/helpers.rb +91 -0
- data/lib/prompt_objects/cli/message_command.rb +216 -0
- data/lib/prompt_objects/cli/repl_command.rb +366 -0
- data/lib/prompt_objects/cli/serve_command.rb +162 -0
- data/lib/prompt_objects/cli.rb +64 -422
- data/lib/prompt_objects/connectors/base.rb +16 -29
- data/lib/prompt_objects/connectors/mcp.rb +82 -98
- data/lib/prompt_objects/domain/records.rb +45 -0
- data/lib/prompt_objects/environment/exporter.rb +5 -4
- data/lib/prompt_objects/environment/git.rb +21 -1
- data/lib/prompt_objects/environment/importer.rb +5 -4
- data/lib/prompt_objects/environment/manager.rb +44 -6
- data/lib/prompt_objects/environment/manifest.rb +26 -4
- data/lib/prompt_objects/environment.rb +1337 -20
- data/lib/prompt_objects/execution/blocking_executor.rb +88 -0
- data/lib/prompt_objects/execution/context.rb +137 -0
- data/lib/prompt_objects/execution/contracts.rb +59 -0
- data/lib/prompt_objects/execution/permit_pool.rb +49 -0
- data/lib/prompt_objects/execution/policy.rb +47 -0
- data/lib/prompt_objects/execution/resource_lock_manager.rb +63 -0
- data/lib/prompt_objects/execution/runner.rb +498 -0
- data/lib/prompt_objects/execution/scheduler.rb +325 -0
- data/lib/prompt_objects/llm/factory.rb +4 -4
- data/lib/prompt_objects/llm/gemini_adapter.rb +25 -8
- data/lib/prompt_objects/llm/openai_adapter.rb +9 -1
- data/lib/prompt_objects/llm/pricing.rb +9 -2
- data/lib/prompt_objects/llm/response.rb +9 -4
- data/lib/prompt_objects/loader.rb +28 -1
- data/lib/prompt_objects/mcp/server.rb +6 -3
- data/lib/prompt_objects/mcp/tools/get_conversation.rb +15 -11
- data/lib/prompt_objects/mcp/tools/get_pending_requests.rb +2 -2
- data/lib/prompt_objects/mcp/tools/respond_to_request.rb +3 -3
- data/lib/prompt_objects/mcp/tools/send_message.rb +42 -32
- data/lib/prompt_objects/operations/diagnostics.rb +115 -0
- data/lib/prompt_objects/operations/retention.rb +75 -0
- data/lib/prompt_objects/operations/run_trace_builder.rb +152 -0
- data/lib/prompt_objects/primitives/http_get.rb +2 -0
- data/lib/prompt_objects/primitives/list_files.rb +2 -0
- data/lib/prompt_objects/primitives/read_file.rb +2 -0
- data/lib/prompt_objects/primitives/think.rb +36 -0
- data/lib/prompt_objects/primitives/write_file.rb +9 -0
- data/lib/prompt_objects/prompt_object.rb +171 -519
- data/lib/prompt_objects/repositories/artifact_repository.rb +109 -0
- data/lib/prompt_objects/repositories/base_repository.rb +37 -0
- data/lib/prompt_objects/repositories/definition_repository.rb +36 -0
- data/lib/prompt_objects/repositories/env_data_repository.rb +103 -0
- data/lib/prompt_objects/repositories/event_repository.rb +105 -0
- data/lib/prompt_objects/repositories/message_repository.rb +73 -0
- data/lib/prompt_objects/repositories/run_repository.rb +254 -0
- data/lib/prompt_objects/repositories/thread_repository.rb +87 -0
- data/lib/prompt_objects/repositories/tool_execution_repository.rb +88 -0
- data/lib/prompt_objects/repositories/workspace_session_repository.rb +61 -0
- data/lib/prompt_objects/server/api/routes.rb +549 -53
- data/lib/prompt_objects/server/app.rb +133 -14
- data/lib/prompt_objects/server/file_watcher.rb +9 -0
- data/lib/prompt_objects/server/public/assets/index-BjKlODDD.js +90 -0
- data/lib/prompt_objects/server/public/assets/index-w3fpIb5c.css +1 -0
- data/lib/prompt_objects/server/public/index.html +2 -2
- data/lib/prompt_objects/server/websocket_handler.rb +202 -227
- data/lib/prompt_objects/server.rb +170 -1
- data/lib/prompt_objects/service.rb +129 -0
- data/lib/prompt_objects/session/store.rb +600 -13
- data/lib/prompt_objects/universal/add_capability.rb +1 -1
- data/lib/prompt_objects/universal/create_capability.rb +4 -2
- data/lib/prompt_objects/universal/delete_env_data.rb +23 -15
- data/lib/prompt_objects/universal/delete_primitive.rb +1 -1
- data/lib/prompt_objects/universal/dispatch_po.rb +54 -0
- data/lib/prompt_objects/universal/get_env_data.rb +8 -14
- data/lib/prompt_objects/universal/get_run_status.rb +30 -0
- data/lib/prompt_objects/universal/join_runs.rb +35 -0
- data/lib/prompt_objects/universal/list_env_data.rb +10 -14
- data/lib/prompt_objects/universal/modify_primitive.rb +1 -1
- data/lib/prompt_objects/universal/render_artifact.rb +91 -0
- data/lib/prompt_objects/universal/request_primitive.rb +1 -1
- data/lib/prompt_objects/universal/{store_env_data.rb → set_env_data.rb} +34 -20
- data/lib/prompt_objects/version.rb +5 -0
- data/lib/prompt_objects.rb +33 -8
- data/objects/coordinator.md +8 -4
- data/templates/arc-agi-1/objects/data_manager.md +2 -2
- data/templates/arc-agi-1/objects/observer.md +2 -2
- data/templates/arc-agi-1/objects/solver.md +6 -5
- data/templates/arc-agi-1/objects/verifier.md +2 -2
- data/templates/arc-agi-3/manifest.yml +19 -0
- data/templates/arc-agi-3/objects/analyst.md +79 -0
- data/templates/arc-agi-3/objects/player.md +76 -0
- data/templates/arc-agi-3/objects/strategist.md +97 -0
- data/templates/arc-agi-3/primitives/action_log.rb +133 -0
- data/templates/arc-agi-3/primitives/arc3_api.rb +223 -0
- data/templates/arc-agi-3/primitives/arc3_scorecard.rb +131 -0
- data/templates/arc-agi-3/primitives/frame_diff.rb +143 -0
- data/templates/arc-agi-3/primitives/frame_info.rb +96 -0
- data/templates/arc-agi-3/primitives/render_frame.rb +140 -0
- data/templates/basic/objects/basic.md +11 -3
- data/templates/chiptune/extras/sonic_pi_boot.rb +220 -0
- data/templates/chiptune/manifest.yml +20 -0
- data/templates/chiptune/objects/conductor.md +184 -0
- data/templates/chiptune/objects/sonic_pi.md +65 -0
- data/templates/chiptune/objects/voice_bass.md +44 -0
- data/templates/chiptune/objects/voice_lead.md +44 -0
- data/templates/chiptune/objects/voice_pad.md +43 -0
- data/templates/chiptune/objects/voice_perc.md +45 -0
- data/templates/chiptune/primitives/play_note.rb +59 -0
- data/templates/chiptune/primitives/play_sequence.rb +55 -0
- data/templates/chiptune/primitives/query_sonic_pi.rb +141 -0
- data/templates/chiptune/primitives/set_synth.rb +57 -0
- data/templates/chiptune/primitives/set_tempo.rb +45 -0
- data/templates/chiptune/primitives/stop_voice.rb +46 -0
- data/templates/chiptune/primitives/support/osc_bridge.rb +33 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/LICENSE +19 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/address_pattern.rb +58 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/broadcast_client.rb +24 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/bundle.rb +46 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/client.rb +13 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/core_ext/time.rb +6 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/em_server.rb +63 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/message.rb +46 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/network_packet.rb +42 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_argument.rb +26 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_packet.rb +140 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_types.rb +53 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/server.rb +91 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby.rb +18 -0
- data/templates/developer/objects/code_reviewer.md +1 -1
- data/templates/developer/objects/coordinator.md +16 -3
- data/templates/developer/objects/debugger.md +3 -3
- data/templates/empty/objects/assistant.md +10 -5
- data/templates/minimal/objects/assistant.md +10 -5
- data/templates/music/extras/sonic_pi_boot.rb +220 -0
- data/templates/music/manifest.yml +16 -0
- data/templates/music/objects/conductor.md +154 -0
- data/templates/music/objects/sonic_pi.md +65 -0
- data/templates/music/primitives/play_note.rb +55 -0
- data/templates/music/primitives/play_sequence.rb +51 -0
- data/templates/music/primitives/query_sonic_pi.rb +139 -0
- data/templates/music/primitives/set_synth.rb +53 -0
- data/templates/music/primitives/set_tempo.rb +43 -0
- data/templates/music/primitives/stop_voice.rb +44 -0
- data/templates/music/primitives/support/osc_bridge.rb +33 -0
- data/templates/music/vendor/osc-ruby-1.1.5/LICENSE +19 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/address_pattern.rb +58 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/broadcast_client.rb +24 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/bundle.rb +46 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/client.rb +13 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/core_ext/time.rb +6 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/em_server.rb +63 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/message.rb +46 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/network_packet.rb +42 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_argument.rb +26 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_packet.rb +140 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_types.rb +53 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/server.rb +91 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby.rb +18 -0
- data/templates/music-beginner/README.md +100 -0
- data/templates/music-beginner/extras/README.md +27 -0
- data/templates/music-beginner/extras/sonic_pi_boot.rb +297 -0
- data/templates/music-beginner/manifest.yml +25 -0
- data/templates/music-beginner/objects/conductor.md +222 -0
- data/templates/music-beginner/objects/engine_setup.md +54 -0
- data/templates/music-beginner/objects/voice_bass.md +43 -0
- data/templates/music-beginner/objects/voice_keys.md +48 -0
- data/templates/music-beginner/objects/voice_pad.md +46 -0
- data/templates/music-beginner/objects/voice_percussion.md +45 -0
- data/templates/music-beginner/objects/voice_texture.md +37 -0
- data/templates/music-beginner/primitives/play_pattern.rb +118 -0
- data/templates/music-beginner/primitives/query_music_engine.rb +94 -0
- data/templates/music-beginner/primitives/set_instrument.rb +47 -0
- data/templates/music-beginner/primitives/set_tempo.rb +43 -0
- data/templates/music-beginner/primitives/set_voice_level.rb +46 -0
- data/templates/music-beginner/primitives/stop_voice.rb +37 -0
- data/templates/music-beginner/primitives/support/osc_bridge.rb +25 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/LICENSE +19 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/address_pattern.rb +58 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/broadcast_client.rb +24 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/bundle.rb +46 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/client.rb +13 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/core_ext/time.rb +6 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/em_server.rb +63 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/message.rb +46 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/network_packet.rb +42 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_argument.rb +26 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_packet.rb +140 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_types.rb +53 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/server.rb +91 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby.rb +18 -0
- data/templates/music-pro/extras/AUDITION.md +100 -0
- data/templates/music-pro/extras/sonic_pi_boot.rb +546 -0
- data/templates/music-pro/manifest.yml +19 -0
- data/templates/music-pro/objects/conductor.md +126 -0
- data/templates/music-pro/objects/sonic_pi.md +35 -0
- data/templates/music-pro/objects/voice_harmony.md +48 -0
- data/templates/music-pro/objects/voice_rhythm.md +43 -0
- data/templates/music-pro/objects/voice_texture.md +42 -0
- data/templates/music-pro/primitives/define_patch.rb +46 -0
- data/templates/music-pro/primitives/query_music_engine.rb +69 -0
- data/templates/music-pro/primitives/set_live_pattern.rb +70 -0
- data/templates/music-pro/primitives/set_tempo.rb +31 -0
- data/templates/music-pro/primitives/stop_voice.rb +31 -0
- data/templates/music-pro/primitives/support/music_protocol.rb +136 -0
- data/templates/music-pro/primitives/support/osc_bridge.rb +33 -0
- data/templates/music-pro/primitives/trigger_event.rb +44 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/LICENSE +19 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/address_pattern.rb +58 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/broadcast_client.rb +24 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/bundle.rb +46 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/client.rb +13 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/core_ext/time.rb +6 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/em_server.rb +63 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/message.rb +46 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/network_packet.rb +42 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_argument.rb +26 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_packet.rb +140 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_types.rb +53 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/server.rb +91 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby.rb +18 -0
- data/templates/writer/objects/coordinator.md +14 -3
- data/templates/writer/objects/editor.md +1 -1
- data/templates/writer/objects/researcher.md +2 -2
- data/tools/thread-explorer.html +1 -1
- metadata +172 -65
- data/CLAUDE.md +0 -177
- data/Gemfile +0 -10
- data/Rakefile +0 -27
- data/frontend/.gitignore +0 -3
- data/frontend/index.html +0 -17
- data/frontend/package-lock.json +0 -4540
- data/frontend/package.json +0 -36
- data/frontend/postcss.config.js +0 -6
- data/frontend/src/App.tsx +0 -104
- data/frontend/src/canvas/CanvasView.tsx +0 -113
- data/frontend/src/canvas/ForceLayout.ts +0 -115
- data/frontend/src/canvas/SceneManager.ts +0 -587
- data/frontend/src/canvas/canvasStore.ts +0 -47
- data/frontend/src/canvas/constants.ts +0 -95
- data/frontend/src/canvas/controls/CameraControls.ts +0 -98
- data/frontend/src/canvas/edges/MessageArc.ts +0 -149
- data/frontend/src/canvas/inspector/InspectorPanel.tsx +0 -31
- data/frontend/src/canvas/inspector/POInspector.tsx +0 -262
- data/frontend/src/canvas/inspector/ToolCallInspector.tsx +0 -67
- data/frontend/src/canvas/nodes/PONode.ts +0 -249
- data/frontend/src/canvas/nodes/ToolCallNode.ts +0 -116
- data/frontend/src/canvas/types.ts +0 -24
- data/frontend/src/components/ContextMenu.tsx +0 -68
- data/frontend/src/components/EnvDataPane.tsx +0 -69
- data/frontend/src/components/Inspector.tsx +0 -263
- data/frontend/src/components/MarkdownMessage.tsx +0 -155
- data/frontend/src/components/MethodList.tsx +0 -90
- data/frontend/src/components/ModelSelector.tsx +0 -115
- data/frontend/src/components/NotificationPanel.tsx +0 -130
- data/frontend/src/components/ObjectList.tsx +0 -78
- data/frontend/src/components/PaneSlot.tsx +0 -30
- data/frontend/src/components/SourcePane.tsx +0 -202
- data/frontend/src/components/SystemBar.tsx +0 -74
- data/frontend/src/components/Transcript.tsx +0 -76
- data/frontend/src/components/UsagePanel.tsx +0 -105
- data/frontend/src/components/Workspace.tsx +0 -260
- data/frontend/src/components/index.ts +0 -12
- data/frontend/src/hooks/useResize.ts +0 -55
- data/frontend/src/hooks/useWebSocket.ts +0 -559
- data/frontend/src/index.css +0 -102
- data/frontend/src/main.tsx +0 -10
- data/frontend/src/store/index.ts +0 -311
- data/frontend/src/types/index.ts +0 -176
- data/frontend/tailwind.config.js +0 -44
- data/frontend/tsconfig.json +0 -30
- data/frontend/vite.config.ts +0 -29
- data/lib/prompt_objects/server/public/assets/index-DEPawnfZ.js +0 -4345
- data/lib/prompt_objects/server/public/assets/index-oMrRce1m.css +0 -1
- data/lib/prompt_objects/universal/add_primitive.rb +0 -118
- data/lib/prompt_objects/universal/ask_human.rb +0 -109
- data/lib/prompt_objects/universal/create_primitive.rb +0 -174
- data/lib/prompt_objects/universal/list_primitives.rb +0 -145
- data/lib/prompt_objects/universal/think.rb +0 -41
- data/lib/prompt_objects/universal/update_env_data.rb +0 -88
- data/prompt_objects.gemspec +0 -50
- data/templates/basic/.gitignore +0 -2
- data/templates/developer/.gitignore +0 -5
- data/templates/empty/.gitignore +0 -5
- data/templates/empty/objects/.gitkeep +0 -0
- data/templates/minimal/.gitignore +0 -5
- 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,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
|
-
|
|
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
|
-
-
|
|
29
|
-
- Use create_capability
|
|
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: researcher
|
|
3
3
|
description: Researches topics and verifies facts for writing projects
|
|
4
|
-
|
|
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
|
-
-
|
|
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
|
|
data/tools/thread-explorer.html
CHANGED
|
@@ -311,7 +311,7 @@ let activeFilters = new Set(); // PO name filters
|
|
|
311
311
|
let allNodes = {}; // id -> node for quick lookup
|
|
312
312
|
|
|
313
313
|
const COLORS = ['#33ff66','#ffaa33','#33ddff','#dd55ff','#ff6699','#33ffcc','#ffdd44','#88aaff','#ff8844','#99ff33'];
|
|
314
|
-
const STRUCTURAL_TOOLS = new Set(['create_capability','add_capability','request_capability','remove_capability','modify_prompt','create_po','delete_primitive'
|
|
314
|
+
const STRUCTURAL_TOOLS = new Set(['create_capability','add_capability','request_capability','remove_capability','modify_prompt','create_po','delete_primitive']);
|
|
315
315
|
|
|
316
316
|
// --- DOM refs ---
|
|
317
317
|
const dropZone = document.getElementById('drop-zone');
|