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
@@ -1,249 +0,0 @@
1
- import * as THREE from 'three'
2
- import { CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js'
3
- import { COLORS, CSS_COLORS, NODE, ANIMATION } from '../constants'
4
-
5
- const vertexShader = /* glsl */ `
6
- varying vec2 vUv;
7
- void main() {
8
- vUv = uv;
9
- gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
10
- }
11
- `
12
-
13
- const fragmentShader = /* glsl */ `
14
- uniform vec3 uColor;
15
- uniform vec3 uGlowColor;
16
- uniform float uGlowIntensity;
17
- uniform float uTime;
18
- uniform float uHovered;
19
- uniform float uSelected;
20
-
21
- varying vec2 vUv;
22
-
23
- void main() {
24
- // Distance from center (0 at center, 1 at edge)
25
- float dist = length(vUv - 0.5) * 2.0;
26
-
27
- // Base dark fill
28
- vec3 base = uColor * 0.3;
29
-
30
- // Edge glow
31
- float edgeGlow = smoothstep(0.5, 1.0, dist) * uGlowIntensity;
32
- // Animated pulse
33
- float pulse = sin(uTime * ${ANIMATION.pulseSpeed.toFixed(1)}) * 0.15 + 0.85;
34
- edgeGlow *= pulse;
35
-
36
- vec3 color = mix(base, uGlowColor, edgeGlow);
37
-
38
- // Hover brightening
39
- color = mix(color, uGlowColor * 1.2, uHovered * 0.3);
40
-
41
- // Selection brightening
42
- color = mix(color, uGlowColor * 1.5, uSelected * 0.4);
43
-
44
- // Alpha: solid center, slight transparency at edges
45
- float alpha = smoothstep(1.0, 0.8, dist);
46
-
47
- gl_FragColor = vec4(color, alpha);
48
- }
49
- `
50
-
51
- type POStatus = 'idle' | 'thinking' | 'calling_tool'
52
-
53
- const STATUS_COLORS: Record<POStatus, number> = {
54
- idle: COLORS.statusIdle,
55
- thinking: COLORS.statusThinking,
56
- calling_tool: COLORS.statusCallingTool,
57
- }
58
-
59
- const STATUS_CSS_COLORS: Record<POStatus, string> = {
60
- idle: CSS_COLORS.statusIdle,
61
- thinking: CSS_COLORS.statusThinking,
62
- calling_tool: CSS_COLORS.statusCallingTool,
63
- }
64
-
65
- // Color for when this PO is being called by another PO (delegation)
66
- const DELEGATED_COLOR = 0x5a8fc2 // steel blue (matches po-status-delegated)
67
- const DELEGATED_CSS_COLOR = '#5a8fc2'
68
-
69
- export class PONode {
70
- readonly id: string
71
- readonly group: THREE.Group
72
- readonly mesh: THREE.Mesh
73
-
74
- private material: THREE.ShaderMaterial
75
- private statusRing: THREE.LineLoop
76
- private statusRingMaterial: THREE.LineBasicMaterial
77
- private label: CSS2DObject
78
- private labelEl: HTMLDivElement
79
- private nameEl: HTMLSpanElement
80
- private statusEl: HTMLSpanElement
81
- private badge: CSS2DObject
82
- private badgeEl: HTMLDivElement
83
- private badgeCountEl: HTMLSpanElement
84
-
85
- private targetPosition = new THREE.Vector3()
86
-
87
- constructor(id: string, name: string) {
88
- this.id = id
89
- this.group = new THREE.Group()
90
- this.group.userData = { type: 'po', id }
91
-
92
- // Hexagonal geometry
93
- const geometry = new THREE.CircleGeometry(NODE.poRadius, NODE.poSides)
94
-
95
- // Shader material
96
- this.material = new THREE.ShaderMaterial({
97
- vertexShader,
98
- fragmentShader,
99
- uniforms: {
100
- uColor: { value: new THREE.Color(COLORS.nodeFill) },
101
- uGlowColor: { value: new THREE.Color(COLORS.nodeGlow) },
102
- uGlowIntensity: { value: 0.5 },
103
- uTime: { value: 0 },
104
- uHovered: { value: 0 },
105
- uSelected: { value: 0 },
106
- },
107
- transparent: true,
108
- })
109
-
110
- this.mesh = new THREE.Mesh(geometry, this.material)
111
- this.mesh.userData = { type: 'po', id }
112
- this.group.add(this.mesh)
113
-
114
- // Status ring (hex outline)
115
- const ringGeometry = new THREE.BufferGeometry()
116
- const ringPoints: THREE.Vector3[] = []
117
- for (let i = 0; i <= NODE.poSides; i++) {
118
- const angle = (i / NODE.poSides) * Math.PI * 2 - Math.PI / 2
119
- ringPoints.push(
120
- new THREE.Vector3(
121
- Math.cos(angle) * (NODE.poRadius + 3),
122
- Math.sin(angle) * (NODE.poRadius + 3),
123
- 0
124
- )
125
- )
126
- }
127
- ringGeometry.setFromPoints(ringPoints)
128
-
129
- this.statusRingMaterial = new THREE.LineBasicMaterial({
130
- color: STATUS_COLORS.idle,
131
- transparent: true,
132
- opacity: 0.6,
133
- })
134
- this.statusRing = new THREE.LineLoop(ringGeometry, this.statusRingMaterial)
135
- this.group.add(this.statusRing)
136
-
137
- // CSS2D Label (name + status)
138
- this.labelEl = document.createElement('div')
139
- this.labelEl.className = 'canvas-node-label'
140
-
141
- this.nameEl = document.createElement('span')
142
- this.nameEl.className = 'canvas-node-name'
143
- this.nameEl.textContent = name
144
-
145
- this.statusEl = document.createElement('span')
146
- this.statusEl.className = 'canvas-node-status'
147
- this.statusEl.textContent = 'idle'
148
-
149
- this.labelEl.appendChild(this.nameEl)
150
- this.labelEl.appendChild(this.statusEl)
151
-
152
- this.label = new CSS2DObject(this.labelEl)
153
- this.label.position.set(0, -NODE.labelOffsetY, 0)
154
- this.group.add(this.label)
155
-
156
- // Notification badge
157
- this.badgeEl = document.createElement('div')
158
- this.badgeEl.className = 'canvas-node-badge'
159
- this.badgeEl.style.display = 'none'
160
-
161
- this.badgeCountEl = document.createElement('span')
162
- this.badgeCountEl.textContent = '0'
163
- this.badgeEl.appendChild(this.badgeCountEl)
164
-
165
- this.badge = new CSS2DObject(this.badgeEl)
166
- this.badge.position.set(NODE.badgeOffsetX, -NODE.badgeOffsetY, 0)
167
- this.group.add(this.badge)
168
- }
169
-
170
- setStatus(status: POStatus): void {
171
- this.statusRingMaterial.color.setHex(STATUS_COLORS[status])
172
-
173
- // Update glow intensity based on status
174
- const intensity = status === 'idle' ? 0.3 : status === 'thinking' ? 0.8 : 0.6
175
- this.material.uniforms.uGlowIntensity.value = intensity
176
-
177
- // Update glow color for calling_tool
178
- if (status === 'calling_tool') {
179
- this.material.uniforms.uGlowColor.value.setHex(COLORS.statusCallingTool)
180
- } else {
181
- this.material.uniforms.uGlowColor.value.setHex(COLORS.nodeGlow)
182
- }
183
-
184
- this.statusEl.textContent = status.replace('_', ' ')
185
- this.statusEl.style.color = STATUS_CSS_COLORS[status]
186
- }
187
-
188
- setDelegatedBy(callerName: string): void {
189
- // Override visual to show this PO is working on behalf of another PO.
190
- // The server doesn't send status updates for delegated POs, so we
191
- // infer this from the caller's tool_calls.
192
- this.statusRingMaterial.color.setHex(DELEGATED_COLOR)
193
- this.statusRingMaterial.opacity = 1.0
194
- this.material.uniforms.uGlowColor.value.setHex(DELEGATED_COLOR)
195
- this.material.uniforms.uGlowIntensity.value = 0.7
196
- this.statusEl.textContent = `called by ${callerName}`
197
- this.statusEl.style.color = DELEGATED_CSS_COLOR
198
- }
199
-
200
- clearDelegated(): void {
201
- // Restore to whatever the server status is — caller should
202
- // call setStatus() after this to re-apply server state.
203
- this.statusRingMaterial.opacity = 0.6
204
- }
205
-
206
- setNotificationCount(count: number): void {
207
- if (count > 0) {
208
- this.badgeEl.style.display = 'flex'
209
- this.badgeCountEl.textContent = String(count)
210
- } else {
211
- this.badgeEl.style.display = 'none'
212
- }
213
- }
214
-
215
- setHovered(hovered: boolean): void {
216
- this.material.uniforms.uHovered.value = hovered ? 1 : 0
217
- }
218
-
219
- setSelected(selected: boolean): void {
220
- this.material.uniforms.uSelected.value = selected ? 1 : 0
221
- this.statusRingMaterial.opacity = selected ? 1.0 : 0.6
222
- }
223
-
224
- setPosition(x: number, y: number): void {
225
- this.targetPosition.set(x, y, 0)
226
- }
227
-
228
- getPosition(): THREE.Vector3 {
229
- return this.group.position.clone()
230
- }
231
-
232
- update(_delta: number, elapsed: number): void {
233
- // Lerp toward target position
234
- this.group.position.lerp(this.targetPosition, ANIMATION.positionLerpFactor)
235
-
236
- // Update time uniform for pulse animation
237
- this.material.uniforms.uTime.value = elapsed
238
- }
239
-
240
- dispose(): void {
241
- this.mesh.geometry.dispose()
242
- this.material.dispose()
243
- this.statusRing.geometry.dispose()
244
- this.statusRingMaterial.dispose()
245
- this.labelEl.remove()
246
- this.badgeEl.remove()
247
- this.group.parent?.remove(this.group)
248
- }
249
- }
@@ -1,116 +0,0 @@
1
- import * as THREE from 'three'
2
- import { CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js'
3
- import { COLORS, NODE, ANIMATION } from '../constants'
4
-
5
- type Phase = 'fadein' | 'active' | 'fadeout' | 'expired'
6
-
7
- export class ToolCallNode {
8
- readonly id: string
9
- readonly callerPO: string
10
- readonly group: THREE.Group
11
- readonly mesh: THREE.Mesh
12
-
13
- private material: THREE.MeshBasicMaterial
14
- private label: CSS2DObject
15
- private labelEl: HTMLDivElement
16
- private phase: Phase = 'fadein'
17
- private phaseTime = 0
18
- private targetPosition = new THREE.Vector3()
19
-
20
- constructor(id: string, toolName: string, callerPO: string) {
21
- this.id = id
22
- this.callerPO = callerPO
23
- this.group = new THREE.Group()
24
- this.group.userData = { type: 'toolcall', id }
25
-
26
- // Diamond shape (rotated square)
27
- const r = NODE.toolCallRadius
28
- const shape = new THREE.Shape()
29
- shape.moveTo(0, r)
30
- shape.lineTo(r, 0)
31
- shape.lineTo(0, -r)
32
- shape.lineTo(-r, 0)
33
- shape.closePath()
34
-
35
- const geometry = new THREE.ShapeGeometry(shape)
36
-
37
- this.material = new THREE.MeshBasicMaterial({
38
- color: COLORS.toolCallFill,
39
- transparent: true,
40
- opacity: 0,
41
- })
42
-
43
- this.mesh = new THREE.Mesh(geometry, this.material)
44
- this.mesh.userData = { type: 'toolcall', id }
45
- this.group.add(this.mesh)
46
-
47
- // Label
48
- this.labelEl = document.createElement('div')
49
- this.labelEl.className = 'canvas-toolcall-label'
50
- this.labelEl.textContent = toolName
51
-
52
- this.label = new CSS2DObject(this.labelEl)
53
- this.label.position.set(0, -(NODE.toolCallRadius + 12), 0)
54
- this.group.add(this.label)
55
- }
56
-
57
- setPosition(x: number, y: number): void {
58
- this.targetPosition.set(x, y, 0)
59
- }
60
-
61
- triggerFadeOut(): void {
62
- if (this.phase !== 'expired') {
63
- this.phase = 'fadeout'
64
- this.phaseTime = 0
65
- }
66
- }
67
-
68
- isExpired(): boolean {
69
- return this.phase === 'expired'
70
- }
71
-
72
- update(delta: number): void {
73
- this.phaseTime += delta
74
- this.group.position.lerp(this.targetPosition, ANIMATION.positionLerpFactor)
75
-
76
- switch (this.phase) {
77
- case 'fadein':
78
- this.material.opacity = Math.min(this.phaseTime / ANIMATION.toolCallFadeInDuration, 1)
79
- if (this.phaseTime >= ANIMATION.toolCallFadeInDuration) {
80
- this.phase = 'active'
81
- this.phaseTime = 0
82
- }
83
- break
84
-
85
- case 'active':
86
- this.material.opacity = 1
87
- if (this.phaseTime >= ANIMATION.toolCallActiveDuration) {
88
- this.phase = 'fadeout'
89
- this.phaseTime = 0
90
- }
91
- break
92
-
93
- case 'fadeout':
94
- this.material.opacity = Math.max(
95
- 1 - this.phaseTime / ANIMATION.toolCallFadeOutDuration,
96
- 0
97
- )
98
- this.labelEl.style.opacity = String(this.material.opacity)
99
- if (this.phaseTime >= ANIMATION.toolCallFadeOutDuration) {
100
- this.phase = 'expired'
101
- }
102
- break
103
-
104
- case 'expired':
105
- this.material.opacity = 0
106
- break
107
- }
108
- }
109
-
110
- dispose(): void {
111
- this.mesh.geometry.dispose()
112
- this.material.dispose()
113
- this.labelEl.remove()
114
- this.group.parent?.remove(this.group)
115
- }
116
- }
@@ -1,24 +0,0 @@
1
- // Canvas-specific type definitions
2
-
3
- export interface CanvasNodeSelection {
4
- type: 'po' | 'toolcall'
5
- id: string
6
- }
7
-
8
- export interface ActiveToolCall {
9
- id: string
10
- toolName: string
11
- callerPO: string
12
- params: Record<string, unknown>
13
- status: 'active' | 'completed' | 'error'
14
- result?: string
15
- startedAt: number
16
- completedAt?: number
17
- }
18
-
19
- export interface ActiveMessageArc {
20
- id: string
21
- from: string
22
- to: string
23
- timestamp: number
24
- }
@@ -1,68 +0,0 @@
1
- import { useEffect, useRef } from 'react'
2
-
3
- interface ContextMenuItem {
4
- label: string
5
- onClick: () => void
6
- icon?: string
7
- danger?: boolean
8
- }
9
-
10
- interface ContextMenuProps {
11
- x: number
12
- y: number
13
- items: ContextMenuItem[]
14
- onClose: () => void
15
- }
16
-
17
- export function ContextMenu({ x, y, items, onClose }: ContextMenuProps) {
18
- const menuRef = useRef<HTMLDivElement>(null)
19
-
20
- useEffect(() => {
21
- const handleClickOutside = (e: MouseEvent) => {
22
- if (menuRef.current && !menuRef.current.contains(e.target as Node)) {
23
- onClose()
24
- }
25
- }
26
- const handleEscape = (e: KeyboardEvent) => {
27
- if (e.key === 'Escape') onClose()
28
- }
29
-
30
- document.addEventListener('mousedown', handleClickOutside)
31
- document.addEventListener('keydown', handleEscape)
32
- return () => {
33
- document.removeEventListener('mousedown', handleClickOutside)
34
- document.removeEventListener('keydown', handleEscape)
35
- }
36
- }, [onClose])
37
-
38
- const adjustedStyle = {
39
- top: y,
40
- left: x,
41
- }
42
-
43
- return (
44
- <div
45
- ref={menuRef}
46
- className="fixed z-50 bg-po-surface-2 border border-po-border rounded shadow-xl py-0.5 min-w-[140px]"
47
- style={adjustedStyle}
48
- >
49
- {items.map((item, idx) => (
50
- <button
51
- key={idx}
52
- onClick={() => {
53
- item.onClick()
54
- onClose()
55
- }}
56
- className={`w-full text-left px-2.5 py-1.5 text-xs transition-colors duration-150 flex items-center gap-1.5 ${
57
- item.danger
58
- ? 'text-po-error hover:bg-po-surface-3'
59
- : 'text-po-text-secondary hover:bg-po-surface-3 hover:text-po-text-primary'
60
- }`}
61
- >
62
- {item.icon && <span>{item.icon}</span>}
63
- {item.label}
64
- </button>
65
- ))}
66
- </div>
67
- )
68
- }
@@ -1,69 +0,0 @@
1
- import { useState, useEffect } from 'react'
2
- import { useStore, useEnvData } from '../store'
3
- import type { EnvDataEntry } from '../types'
4
-
5
- interface EnvDataPaneProps {
6
- sessionId: string | undefined
7
- requestEnvData: (sessionId: string) => void
8
- }
9
-
10
- export function EnvDataPane({ sessionId, requestEnvData }: EnvDataPaneProps) {
11
- const sessionRootMap = useStore((s) => s.sessionRootMap)
12
- const rootThreadId = sessionId ? sessionRootMap[sessionId] : undefined
13
- const entries = useEnvData(rootThreadId)
14
- const [expandedKey, setExpandedKey] = useState<string | null>(null)
15
-
16
- useEffect(() => {
17
- if (sessionId) {
18
- requestEnvData(sessionId)
19
- }
20
- }, [sessionId, requestEnvData])
21
-
22
- if (entries.length === 0) {
23
- return (
24
- <div className="h-full flex items-center justify-center">
25
- <span className="font-mono text-xs text-po-text-ghost">No shared data</span>
26
- </div>
27
- )
28
- }
29
-
30
- return (
31
- <div className="h-full overflow-auto px-2 py-1">
32
- {entries.map((entry) => (
33
- <EnvDataRow
34
- key={entry.key}
35
- entry={entry}
36
- expanded={expandedKey === entry.key}
37
- onToggle={() => setExpandedKey(expandedKey === entry.key ? null : entry.key)}
38
- />
39
- ))}
40
- </div>
41
- )
42
- }
43
-
44
- function EnvDataRow({ entry, expanded, onToggle }: { entry: EnvDataEntry; expanded: boolean; onToggle: () => void }) {
45
- return (
46
- <div className="border-b border-po-border last:border-b-0">
47
- <button
48
- onClick={onToggle}
49
- className="w-full text-left px-1.5 py-1.5 hover:bg-po-surface-3 transition-colors duration-150 flex items-center gap-2"
50
- >
51
- <span className="text-2xs text-po-text-ghost">{expanded ? '▼' : '▶'}</span>
52
- <span className="font-mono text-sm text-po-accent truncate">{entry.key}</span>
53
- <span className="text-xs text-po-text-ghost truncate flex-1">{entry.short_description}</span>
54
- <span className="text-xs text-po-text-ghost flex-shrink-0">{entry.stored_by}</span>
55
- </button>
56
- {expanded && (
57
- <div className="px-2 pb-2">
58
- <div className="text-xs text-po-text-ghost mb-1">
59
- stored by <span className="text-po-text-secondary">{entry.stored_by}</span>
60
- {entry.updated_at && <> &middot; {new Date(entry.updated_at).toLocaleTimeString()}</>}
61
- </div>
62
- <pre className="font-mono text-xs text-po-text-primary bg-po-surface-1 rounded p-2 overflow-auto max-h-40 whitespace-pre-wrap break-all">
63
- {typeof entry.value === 'string' ? entry.value : JSON.stringify(entry.value, null, 2)}
64
- </pre>
65
- </div>
66
- )}
67
- </div>
68
- )
69
- }