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
@@ -1,155 +0,0 @@
1
- import ReactMarkdown from 'react-markdown'
2
- import remarkGfm from 'remark-gfm'
3
- import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
4
- import { oneDark } from 'react-syntax-highlighter/dist/esm/styles/prism'
5
- import { useState } from 'react'
6
-
7
- interface MarkdownMessageProps {
8
- content: string
9
- className?: string
10
- }
11
-
12
- export function MarkdownMessage({ content, className = '' }: MarkdownMessageProps) {
13
- return (
14
- <div className={`markdown-content ${className}`}>
15
- <ReactMarkdown
16
- remarkPlugins={[remarkGfm]}
17
- components={{
18
- // Code blocks with syntax highlighting
19
- code({ className, children, ...props }) {
20
- const match = /language-(\w+)/.exec(className || '')
21
- const language = match ? match[1] : ''
22
- const codeString = String(children).replace(/\n$/, '')
23
- const isBlock = codeString.includes('\n') || match
24
-
25
- if (isBlock) {
26
- return (
27
- <CodeBlock language={language} code={codeString} />
28
- )
29
- }
30
-
31
- return (
32
- <code
33
- className="bg-po-surface-2 px-1 py-0.5 rounded text-po-accent font-mono text-[0.9em]"
34
- {...props}
35
- >
36
- {children}
37
- </code>
38
- )
39
- },
40
- // Styled links
41
- a({ href, children }) {
42
- return (
43
- <a
44
- href={href}
45
- target="_blank"
46
- rel="noopener noreferrer"
47
- className="text-po-accent hover:underline"
48
- >
49
- {children}
50
- </a>
51
- )
52
- },
53
- // Styled paragraphs
54
- p({ children }) {
55
- return <p className="mb-2 last:mb-0">{children}</p>
56
- },
57
- // Styled lists
58
- ul({ children }) {
59
- return <ul className="list-disc list-inside mb-2 space-y-0.5">{children}</ul>
60
- },
61
- ol({ children }) {
62
- return <ol className="list-decimal list-inside mb-2 space-y-0.5">{children}</ol>
63
- },
64
- // Styled headings
65
- h1({ children }) {
66
- return <h1 className="text-base font-bold mb-1.5 mt-3 first:mt-0 text-po-text-primary">{children}</h1>
67
- },
68
- h2({ children }) {
69
- return <h2 className="text-sm font-bold mb-1.5 mt-2 first:mt-0 text-po-text-primary">{children}</h2>
70
- },
71
- h3({ children }) {
72
- return <h3 className="text-xs font-bold mb-1 mt-1.5 first:mt-0 text-po-text-primary">{children}</h3>
73
- },
74
- // Styled blockquotes
75
- blockquote({ children }) {
76
- return (
77
- <blockquote className="border-l-2 border-po-accent pl-3 my-2 text-po-text-secondary italic">
78
- {children}
79
- </blockquote>
80
- )
81
- },
82
- // Styled tables
83
- table({ children }) {
84
- return (
85
- <div className="overflow-x-auto my-2">
86
- <table className="min-w-full border border-po-border text-xs">{children}</table>
87
- </div>
88
- )
89
- },
90
- th({ children }) {
91
- return (
92
- <th className="border border-po-border bg-po-surface-2 px-2 py-1 text-left font-medium text-po-text-primary">
93
- {children}
94
- </th>
95
- )
96
- },
97
- td({ children }) {
98
- return (
99
- <td className="border border-po-border px-2 py-1 text-po-text-secondary">{children}</td>
100
- )
101
- },
102
- // Horizontal rule
103
- hr() {
104
- return <hr className="border-po-border my-3" />
105
- },
106
- }}
107
- >
108
- {content}
109
- </ReactMarkdown>
110
- </div>
111
- )
112
- }
113
-
114
- function CodeBlock({ language, code }: { language: string; code: string }) {
115
- const [copied, setCopied] = useState(false)
116
-
117
- const handleCopy = async () => {
118
- await navigator.clipboard.writeText(code)
119
- setCopied(true)
120
- setTimeout(() => setCopied(false), 2000)
121
- }
122
-
123
- return (
124
- <div className="relative group my-2">
125
- {/* Language label and copy button */}
126
- <div className="flex items-center justify-between bg-po-surface-2 px-2.5 py-1 rounded-t border border-b-0 border-po-border">
127
- <span className="text-2xs text-po-text-ghost font-mono">
128
- {language || 'text'}
129
- </span>
130
- <button
131
- onClick={handleCopy}
132
- className="text-2xs text-po-text-ghost hover:text-po-text-primary transition-colors duration-150"
133
- >
134
- {copied ? 'Copied' : 'Copy'}
135
- </button>
136
- </div>
137
- {/* Code with syntax highlighting */}
138
- <SyntaxHighlighter
139
- style={oneDark}
140
- language={language || 'text'}
141
- PreTag="div"
142
- customStyle={{
143
- margin: 0,
144
- borderRadius: '0 0 0.25rem 0.25rem',
145
- border: '1px solid #3d3a37',
146
- borderTop: 'none',
147
- fontSize: '11px',
148
- background: '#222120',
149
- }}
150
- >
151
- {code}
152
- </SyntaxHighlighter>
153
- </div>
154
- )
155
- }
@@ -1,90 +0,0 @@
1
- import type { PromptObject, CapabilityInfo } from '../types'
2
-
3
- interface MethodListProps {
4
- po: PromptObject
5
- selectedCapability: CapabilityInfo | null
6
- onSelectCapability: (cap: CapabilityInfo | null) => void
7
- }
8
-
9
- export function MethodList({ po, selectedCapability, onSelectCapability }: MethodListProps) {
10
- const capabilities = po.capabilities || []
11
- const universalCapabilities = po.universal_capabilities || []
12
-
13
- const handleClick = (cap: CapabilityInfo) => {
14
- if (selectedCapability?.name === cap.name) {
15
- onSelectCapability(null) // Toggle off
16
- } else {
17
- onSelectCapability(cap)
18
- }
19
- }
20
-
21
- return (
22
- <div className="h-full border-r border-po-border overflow-auto bg-po-surface">
23
- {/* Source (prompt view) */}
24
- <button
25
- onClick={() => onSelectCapability(null)}
26
- className={`w-full text-left px-2.5 py-1 text-xs font-mono border-b border-po-border transition-colors duration-150 ${
27
- selectedCapability === null
28
- ? 'bg-po-accent-wash text-po-accent'
29
- : 'text-po-text-secondary hover:bg-po-surface-2'
30
- }`}
31
- >
32
- Source
33
- </button>
34
-
35
- {/* Declared capabilities */}
36
- {capabilities.length > 0 && (
37
- <div>
38
- <div className="px-2.5 py-1.5 border-b border-po-border">
39
- <span className="text-2xs font-medium text-po-text-ghost uppercase tracking-wider">
40
- Methods ({capabilities.length})
41
- </span>
42
- </div>
43
- {capabilities.map((cap) => (
44
- <button
45
- key={cap.name}
46
- onClick={() => handleClick(cap)}
47
- className={`w-full text-left px-2.5 py-1 text-xs font-mono transition-colors duration-150 ${
48
- selectedCapability?.name === cap.name
49
- ? 'bg-po-accent-wash text-po-accent'
50
- : 'text-po-accent hover:bg-po-surface-2'
51
- }`}
52
- >
53
- {cap.name}
54
- </button>
55
- ))}
56
- </div>
57
- )}
58
-
59
- {/* Universal capabilities */}
60
- {universalCapabilities.length > 0 && (
61
- <div>
62
- <div className="px-2.5 py-1.5 border-b border-po-border border-t border-po-border">
63
- <span className="text-2xs font-medium text-po-text-ghost uppercase tracking-wider">
64
- Universal ({universalCapabilities.length})
65
- </span>
66
- </div>
67
- {universalCapabilities.map((cap) => (
68
- <button
69
- key={cap.name}
70
- onClick={() => handleClick(cap)}
71
- className={`w-full text-left px-2.5 py-1 text-xs font-mono transition-colors duration-150 ${
72
- selectedCapability?.name === cap.name
73
- ? 'bg-po-accent-wash text-po-text-secondary'
74
- : 'text-po-text-secondary hover:bg-po-surface-2'
75
- }`}
76
- >
77
- {cap.name}
78
- </button>
79
- ))}
80
- </div>
81
- )}
82
-
83
- {capabilities.length === 0 && universalCapabilities.length === 0 && (
84
- <div className="px-2.5 py-4 text-2xs text-po-text-ghost text-center">
85
- No capabilities
86
- </div>
87
- )}
88
- </div>
89
- )
90
- }
@@ -1,115 +0,0 @@
1
- import { useState, useRef, useEffect } from 'react'
2
- import { useStore } from '../store'
3
-
4
- interface Props {
5
- switchLLM: (provider: string, model?: string) => void
6
- }
7
-
8
- export function ModelSelector({ switchLLM }: Props) {
9
- const { llmConfig } = useStore()
10
- const [isOpen, setIsOpen] = useState(false)
11
- const dropdownRef = useRef<HTMLDivElement>(null)
12
-
13
- // Close dropdown when clicking outside
14
- useEffect(() => {
15
- function handleClickOutside(event: MouseEvent) {
16
- if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
17
- setIsOpen(false)
18
- }
19
- }
20
- document.addEventListener('mousedown', handleClickOutside)
21
- return () => document.removeEventListener('mousedown', handleClickOutside)
22
- }, [])
23
-
24
- if (!llmConfig) return null
25
-
26
- const handleSelectModel = (provider: string, model: string) => {
27
- switchLLM(provider, model)
28
- setIsOpen(false)
29
- }
30
-
31
- const providerNames: Record<string, string> = {
32
- openai: 'OpenAI',
33
- anthropic: 'Anthropic',
34
- gemini: 'Gemini',
35
- ollama: 'Ollama',
36
- openrouter: 'OpenRouter',
37
- }
38
-
39
- return (
40
- <div className="relative" ref={dropdownRef}>
41
- <button
42
- onClick={() => setIsOpen(!isOpen)}
43
- className="flex items-center gap-1.5 px-2 py-0.5 text-xs bg-po-surface-2 border border-po-border rounded hover:border-po-border-focus transition-colors duration-150"
44
- >
45
- <span className="text-po-text-tertiary">
46
- {providerNames[llmConfig.current_provider] || llmConfig.current_provider}
47
- </span>
48
- <span className="font-mono text-po-text-primary">{llmConfig.current_model}</span>
49
- <svg
50
- className={`w-3 h-3 text-po-text-ghost transition-transform ${isOpen ? 'rotate-180' : ''}`}
51
- fill="none"
52
- stroke="currentColor"
53
- viewBox="0 0 24 24"
54
- >
55
- <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
56
- </svg>
57
- </button>
58
-
59
- {isOpen && (
60
- <div className="absolute right-0 top-full mt-1 w-60 bg-po-surface-2 border border-po-border rounded shadow-xl z-50 overflow-hidden">
61
- {llmConfig.providers.map((provider) => (
62
- <div key={provider.name}>
63
- <div className="px-2.5 py-1.5 bg-po-surface text-2xs font-medium text-po-text-ghost uppercase tracking-wider flex items-center justify-between">
64
- <span>{providerNames[provider.name] || provider.name}</span>
65
- {!provider.available && (
66
- <span className="text-po-error text-2xs normal-case">
67
- {provider.name === 'ollama' ? 'Not Running' : 'No API Key'}
68
- </span>
69
- )}
70
- </div>
71
- {provider.models.map((model) => {
72
- const isSelected =
73
- provider.name === llmConfig.current_provider &&
74
- model === llmConfig.current_model
75
- const isAvailable = provider.available
76
- const isDefault = model === provider.default_model
77
-
78
- return (
79
- <button
80
- key={`${provider.name}-${model}`}
81
- onClick={() => isAvailable && handleSelectModel(provider.name, model)}
82
- disabled={!isAvailable}
83
- className={`w-full px-2.5 py-1.5 text-left text-xs font-mono flex items-center justify-between transition-colors duration-150 ${
84
- isSelected
85
- ? 'bg-po-accent-wash text-po-accent'
86
- : isAvailable
87
- ? 'text-po-text-secondary hover:bg-po-surface-3'
88
- : 'text-po-text-ghost cursor-not-allowed'
89
- }`}
90
- >
91
- <span className="flex items-center gap-2">
92
- {model}
93
- {isDefault && (
94
- <span className="text-2xs text-po-text-ghost">(default)</span>
95
- )}
96
- </span>
97
- {isSelected && (
98
- <svg className="w-3 h-3" fill="currentColor" viewBox="0 0 20 20">
99
- <path
100
- fillRule="evenodd"
101
- d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
102
- clipRule="evenodd"
103
- />
104
- </svg>
105
- )}
106
- </button>
107
- )
108
- })}
109
- </div>
110
- ))}
111
- </div>
112
- )}
113
- </div>
114
- )
115
- }
@@ -1,130 +0,0 @@
1
- import { useState } from 'react'
2
- import { useStore } from '../store'
3
-
4
- interface NotificationPanelProps {
5
- respondToNotification: (id: string, response: string) => void
6
- }
7
-
8
- export function NotificationPanel({ respondToNotification }: NotificationPanelProps) {
9
- const { notifications, selectPO } = useStore()
10
-
11
- if (notifications.length === 0) return null
12
-
13
- return (
14
- <div className="fixed bottom-4 right-4 w-96 max-h-[60vh] overflow-auto bg-po-surface-2 border border-po-warning/30 rounded-lg shadow-2xl z-50">
15
- {/* Header */}
16
- <div className="sticky top-0 bg-po-surface-2 border-b border-po-border px-3 py-2 flex items-center gap-2">
17
- <div className="w-2 h-2 rounded-full bg-po-warning animate-pulse" />
18
- <span className="text-xs font-medium text-po-text-primary flex-1">
19
- Pending Requests ({notifications.length})
20
- </span>
21
- </div>
22
-
23
- {/* Notifications */}
24
- <div className="p-2 space-y-2">
25
- {notifications.map((notification) => (
26
- <NotificationCard
27
- key={notification.id}
28
- notification={notification}
29
- onRespond={(response) => respondToNotification(notification.id, response)}
30
- onViewPO={() => selectPO(notification.po_name)}
31
- />
32
- ))}
33
- </div>
34
- </div>
35
- )
36
- }
37
-
38
- interface NotificationCardProps {
39
- notification: {
40
- id: string
41
- po_name: string
42
- type: string
43
- message: string
44
- options: string[]
45
- }
46
- onRespond: (response: string) => void
47
- onViewPO: () => void
48
- }
49
-
50
- function NotificationCard({ notification, onRespond, onViewPO }: NotificationCardProps) {
51
- const [customInput, setCustomInput] = useState('')
52
- const [showCustom, setShowCustom] = useState(false)
53
-
54
- const handleCustomSubmit = () => {
55
- if (customInput.trim()) {
56
- onRespond(customInput.trim())
57
- setCustomInput('')
58
- setShowCustom(false)
59
- }
60
- }
61
-
62
- return (
63
- <div className="bg-po-surface border border-po-border rounded-lg p-3">
64
- {/* Header: type badge + PO name */}
65
- <div className="flex items-center gap-2 mb-2">
66
- <span className="text-2xs font-mono bg-po-warning text-po-bg px-1.5 py-0.5 rounded font-bold">
67
- {notification.type}
68
- </span>
69
- <button
70
- onClick={onViewPO}
71
- className="text-xs font-mono text-po-accent hover:underline"
72
- >
73
- {notification.po_name}
74
- </button>
75
- </div>
76
-
77
- {/* Message */}
78
- <p className="text-xs text-po-text-primary mb-3">{notification.message}</p>
79
-
80
- {/* Quick response options */}
81
- {notification.options.length > 0 && (
82
- <div className="flex flex-wrap gap-1.5 mb-2">
83
- {notification.options.map((option, index) => (
84
- <button
85
- key={index}
86
- onClick={() => onRespond(option)}
87
- className="px-2.5 py-1 text-xs bg-po-surface-2 border border-po-border rounded hover:border-po-accent hover:text-po-accent transition-colors duration-150 text-po-text-secondary"
88
- >
89
- {option}
90
- </button>
91
- ))}
92
- </div>
93
- )}
94
-
95
- {/* Custom response */}
96
- {showCustom ? (
97
- <div className="flex gap-1.5">
98
- <input
99
- type="text"
100
- value={customInput}
101
- onChange={(e) => setCustomInput(e.target.value)}
102
- placeholder="Custom response..."
103
- className="flex-1 bg-po-surface-2 border border-po-border rounded px-2 py-1 text-xs text-po-text-primary placeholder-po-text-ghost focus:outline-none focus:border-po-accent"
104
- onKeyDown={(e) => e.key === 'Enter' && handleCustomSubmit()}
105
- autoFocus
106
- />
107
- <button
108
- onClick={handleCustomSubmit}
109
- className="px-2 py-1 text-xs bg-po-accent text-po-bg rounded font-medium hover:bg-po-accent-muted transition-colors duration-150"
110
- >
111
- Send
112
- </button>
113
- <button
114
- onClick={() => setShowCustom(false)}
115
- className="text-po-text-ghost hover:text-po-text-secondary transition-colors duration-150"
116
- >
117
- {'\u2715'}
118
- </button>
119
- </div>
120
- ) : (
121
- <button
122
- onClick={() => setShowCustom(true)}
123
- className="text-2xs text-po-text-ghost hover:text-po-text-secondary transition-colors duration-150"
124
- >
125
- + Custom response
126
- </button>
127
- )}
128
- </div>
129
- )
130
- }
@@ -1,78 +0,0 @@
1
- import { usePromptObjects, useStore, usePONotifications } from '../store'
2
- import type { PromptObject } from '../types'
3
-
4
- export function ObjectList() {
5
- const promptObjects = usePromptObjects()
6
-
7
- return (
8
- <aside className="h-full bg-po-surface border-r border-po-border flex flex-col overflow-hidden">
9
- {/* Header */}
10
- <div className="px-3 py-2 border-b border-po-border">
11
- <span className="text-2xs font-medium text-po-text-ghost uppercase tracking-wider">
12
- Objects ({promptObjects.length})
13
- </span>
14
- </div>
15
-
16
- {/* List */}
17
- <div className="flex-1 overflow-auto py-1">
18
- {promptObjects.length === 0 ? (
19
- <div className="px-3 py-4 text-2xs text-po-text-ghost text-center">
20
- Waiting for connection...
21
- </div>
22
- ) : (
23
- promptObjects.map((po) => (
24
- <ObjectItem key={po.name} po={po} />
25
- ))
26
- )}
27
- </div>
28
- </aside>
29
- )
30
- }
31
-
32
- function ObjectItem({ po }: { po: PromptObject }) {
33
- const { selectPO, selectedPO } = useStore()
34
- const notifications = usePONotifications(po.name)
35
- const isSelected = selectedPO === po.name
36
-
37
- const isActive = po.status !== 'idle'
38
-
39
- const statusDot = {
40
- idle: 'bg-po-status-idle',
41
- thinking: 'bg-po-status-active',
42
- calling_tool: 'bg-po-status-calling',
43
- }[po.status] || 'bg-po-status-idle'
44
-
45
- const statusGlow = {
46
- idle: '',
47
- thinking: 'shadow-[0_0_5px_rgba(212,149,42,0.6)]',
48
- calling_tool: 'shadow-[0_0_5px_rgba(59,154,110,0.6)]',
49
- }[po.status] || ''
50
-
51
- return (
52
- <button
53
- onClick={() => selectPO(po.name)}
54
- className={`w-full text-left h-7 px-3 flex items-center gap-2 transition-colors duration-150 ${
55
- isSelected
56
- ? 'bg-po-accent-wash border-l-2 border-po-accent'
57
- : 'border-l-2 border-transparent hover:bg-po-surface-2'
58
- }`}
59
- >
60
- <div className={`w-2 h-2 rounded-full flex-shrink-0 ${statusDot} ${statusGlow} ${isActive ? 'animate-pulse' : ''}`} />
61
- <span className={`flex-1 truncate font-mono text-xs ${
62
- isSelected ? 'text-po-text-primary' : 'text-po-text-secondary'
63
- }`}>
64
- {po.name}
65
- </span>
66
- {po.delegated_by && (
67
- <span className="text-2xs text-po-status-delegated truncate max-w-[60px]">
68
- {po.delegated_by}
69
- </span>
70
- )}
71
- {notifications.length > 0 && (
72
- <span className="text-2xs font-mono bg-po-warning text-po-bg px-1 rounded font-bold flex-shrink-0">
73
- {notifications.length}
74
- </span>
75
- )}
76
- </button>
77
- )
78
- }
@@ -1,30 +0,0 @@
1
- interface PaneSlotProps {
2
- label: string
3
- collapsed: boolean
4
- onToggle: () => void
5
- height: number
6
- resizeHandle?: React.ReactNode
7
- children: React.ReactNode
8
- }
9
-
10
- export function PaneSlot({ label, collapsed, onToggle, height, resizeHandle, children }: PaneSlotProps) {
11
- return (
12
- <>
13
- <div
14
- className="h-7 bg-po-surface-2 border-b border-po-border flex items-center px-3 cursor-pointer hover:bg-po-surface-3 transition-colors duration-150 flex-shrink-0 select-none"
15
- onClick={onToggle}
16
- >
17
- <span className="text-2xs font-mono text-po-text-secondary flex-1">{label}</span>
18
- <span className="text-xs text-po-text-ghost">{collapsed ? '▼' : '▲'}</span>
19
- </div>
20
- {!collapsed && (
21
- <>
22
- <div className="flex-shrink-0 overflow-hidden" style={{ height }}>
23
- {children}
24
- </div>
25
- {resizeHandle}
26
- </>
27
- )}
28
- </>
29
- )
30
- }