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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +142 -0
- data/README.md +211 -19
- 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 +1350 -18
- 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 +190 -432
- 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 +561 -52
- data/lib/prompt_objects/server/app.rb +134 -1
- 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 -207
- data/lib/prompt_objects/server.rb +170 -1
- data/lib/prompt_objects/service.rb +129 -0
- data/lib/prompt_objects/session/store.rb +774 -15
- 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 +78 -0
- 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 +58 -0
- 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 +57 -0
- 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/set_env_data.rb +101 -0
- data/lib/prompt_objects/version.rb +5 -0
- data/lib/prompt_objects.rb +36 -6
- 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 +6 -2
- data/templates/arc-agi-1/objects/solver.md +14 -4
- data/templates/arc-agi-1/objects/verifier.md +6 -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 +28 -1
- metadata +175 -65
- data/CLAUDE.md +0 -176
- data/Gemfile +0 -10
- data/Gemfile.lock +0 -233
- data/IMPLEMENTATION_PLAN.md +0 -1073
- data/Rakefile +0 -27
- data/design-doc-v2.md +0 -1232
- 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 -103
- 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/Inspector.tsx +0 -232
- 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 -517
- data/frontend/src/index.css +0 -103
- data/frontend/src/main.tsx +0 -10
- data/frontend/src/store/index.ts +0 -279
- data/frontend/src/types/index.ts +0 -165
- 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-D1myxE0l.js +0 -4345
- data/lib/prompt_objects/server/public/assets/index-DdCcwC-Z.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/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
|
@@ -1 +0,0 @@
|
|
|
1
|
-
*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:Geist Mono,IBM Plex Mono,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.\!container{width:100%!important}.container{width:100%}@media(min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media(min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media(min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media(min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media(min-width:1536px){.\!container{max-width:1536px!important}.container{max-width:1536px}}.visible{visibility:visible}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.bottom-3{bottom:.75rem}.bottom-4{bottom:1rem}.left-3{left:.75rem}.right-0{right:0}.right-4{right:1rem}.top-0{top:0}.top-3{top:.75rem}.top-full{top:100%}.z-10{z-index:10}.z-50{z-index:50}.my-0\.5{margin-top:.125rem;margin-bottom:.125rem}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-3{margin-top:.75rem;margin-bottom:.75rem}.mb-0\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-1\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.ml-0\.5{margin-left:.125rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-auto{margin-left:auto}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.inline-block{display:inline-block}.flex{display:flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-1\.5{height:.375rem}.h-2{height:.5rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-40{height:10rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-full{height:100%}.h-screen{height:100vh}.max-h-32{max-height:8rem}.max-h-48{max-height:12rem}.max-h-64{max-height:16rem}.max-h-\[60vh\]{max-height:60vh}.max-h-\[80vh\]{max-height:80vh}.w-1\.5{width:.375rem}.w-2{width:.5rem}.w-3{width:.75rem}.w-56{width:14rem}.w-60{width:15rem}.w-80{width:20rem}.w-96{width:24rem}.w-\[400px\]{width:400px}.w-full{width:100%}.min-w-\[140px\]{min-width:140px}.min-w-full{min-width:100%}.max-w-\[60px\]{max-width:60px}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize-none{resize:none}.resize{resize:both}.list-inside{list-style-position:inside}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-baseline{align-items:baseline}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.125rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem * var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.375rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem * var(--tw-space-y-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-b{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.rounded-r{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.rounded-t{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-b-0{border-bottom-width:0px}.border-l{border-left-width:1px}.border-l-2{border-left-width:2px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-po-accent{--tw-border-opacity: 1;border-color:rgb(212 149 42 / var(--tw-border-opacity, 1))}.border-po-border{--tw-border-opacity: 1;border-color:rgb(61 58 55 / var(--tw-border-opacity, 1))}.border-po-status-calling{--tw-border-opacity: 1;border-color:rgb(59 154 110 / var(--tw-border-opacity, 1))}.border-po-warning{--tw-border-opacity: 1;border-color:rgb(212 149 42 / var(--tw-border-opacity, 1))}.border-po-warning\/30{border-color:#d4952a4d}.border-transparent{border-color:transparent}.bg-black\/50{background-color:#00000080}.bg-po-accent{--tw-bg-opacity: 1;background-color:rgb(212 149 42 / var(--tw-bg-opacity, 1))}.bg-po-accent-wash{background-color:#d4952a14}.bg-po-bg{--tw-bg-opacity: 1;background-color:rgb(26 25 24 / var(--tw-bg-opacity, 1))}.bg-po-error{--tw-bg-opacity: 1;background-color:rgb(196 92 74 / var(--tw-bg-opacity, 1))}.bg-po-status-active{--tw-bg-opacity: 1;background-color:rgb(212 149 42 / var(--tw-bg-opacity, 1))}.bg-po-status-calling{--tw-bg-opacity: 1;background-color:rgb(59 154 110 / var(--tw-bg-opacity, 1))}.bg-po-status-idle{--tw-bg-opacity: 1;background-color:rgb(120 114 106 / var(--tw-bg-opacity, 1))}.bg-po-success{--tw-bg-opacity: 1;background-color:rgb(59 154 110 / var(--tw-bg-opacity, 1))}.bg-po-surface{--tw-bg-opacity: 1;background-color:rgb(34 33 32 / var(--tw-bg-opacity, 1))}.bg-po-surface-2{--tw-bg-opacity: 1;background-color:rgb(44 42 40 / var(--tw-bg-opacity, 1))}.bg-po-surface-2\/80{background-color:#2c2a28cc}.bg-po-text-ghost{--tw-bg-opacity: 1;background-color:rgb(82 78 72 / var(--tw-bg-opacity, 1))}.bg-po-warning{--tw-bg-opacity: 1;background-color:rgb(212 149 42 / var(--tw-bg-opacity, 1))}.bg-transparent{background-color:transparent}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-4{padding:1rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-4{padding-top:1rem;padding-bottom:1rem}.pb-1\.5{padding-bottom:.375rem}.pb-2{padding-bottom:.5rem}.pl-3{padding-left:.75rem}.pl-4{padding-left:1rem}.pl-\[4\.5rem\]{padding-left:4.5rem}.text-left{text-align:left}.text-center{text-align:center}.align-text-bottom{vertical-align:text-bottom}.font-mono{font-family:Geist Mono,IBM Plex Mono,monospace}.font-ui{font-family:Geist,system-ui,sans-serif}.text-2xs{font-size:11px;line-height:15px}.text-\[0\.9em\]{font-size:.9em}.text-base{font-size:1rem;line-height:1.5rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.uppercase{text-transform:uppercase}.normal-case{text-transform:none}.italic{font-style:italic}.leading-relaxed{line-height:1.625}.tracking-wider{letter-spacing:.05em}.text-po-accent{--tw-text-opacity: 1;color:rgb(212 149 42 / var(--tw-text-opacity, 1))}.text-po-bg{--tw-text-opacity: 1;color:rgb(26 25 24 / var(--tw-text-opacity, 1))}.text-po-error{--tw-text-opacity: 1;color:rgb(196 92 74 / var(--tw-text-opacity, 1))}.text-po-status-active{--tw-text-opacity: 1;color:rgb(212 149 42 / var(--tw-text-opacity, 1))}.text-po-status-calling{--tw-text-opacity: 1;color:rgb(59 154 110 / var(--tw-text-opacity, 1))}.text-po-status-delegated{--tw-text-opacity: 1;color:rgb(90 143 194 / var(--tw-text-opacity, 1))}.text-po-success{--tw-text-opacity: 1;color:rgb(59 154 110 / var(--tw-text-opacity, 1))}.text-po-text-ghost{--tw-text-opacity: 1;color:rgb(82 78 72 / var(--tw-text-opacity, 1))}.text-po-text-primary{--tw-text-opacity: 1;color:rgb(232 226 218 / var(--tw-text-opacity, 1))}.text-po-text-secondary{--tw-text-opacity: 1;color:rgb(168 162 154 / var(--tw-text-opacity, 1))}.text-po-text-tertiary{--tw-text-opacity: 1;color:rgb(120 114 106 / var(--tw-text-opacity, 1))}.text-po-warning{--tw-text-opacity: 1;color:rgb(212 149 42 / var(--tw-text-opacity, 1))}.placeholder-po-text-ghost::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(82 78 72 / var(--tw-placeholder-opacity, 1))}.placeholder-po-text-ghost::placeholder{--tw-placeholder-opacity: 1;color:rgb(82 78 72 / var(--tw-placeholder-opacity, 1))}.shadow-2xl{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_5px_rgba\(212\,149\,42\,0\.6\)\]{--tw-shadow: 0 0 5px rgba(212,149,42,.6);--tw-shadow-colored: 0 0 5px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_5px_rgba\(59\,154\,110\,0\.6\)\]{--tw-shadow: 0 0 5px rgba(59,154,110,.6);--tw-shadow-colored: 0 0 5px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_6px_rgba\(212\,149\,42\,0\.7\)\]{--tw-shadow: 0 0 6px rgba(212,149,42,.7);--tw-shadow-colored: 0 0 6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_6px_rgba\(59\,154\,110\,0\.7\)\]{--tw-shadow: 0 0 6px rgba(59,154,110,.7);--tw-shadow-colored: 0 0 6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline{outline-style:solid}.ring{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur{--tw-backdrop-blur: blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-150{transition-duration:.15s}html{color-scheme:dark;font-size:14px}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{--tw-bg-opacity: 1;background-color:rgb(26 25 24 / var(--tw-bg-opacity, 1))}::-webkit-scrollbar-thumb{border-radius:9999px;--tw-bg-opacity: 1;background-color:rgb(61 58 55 / var(--tw-bg-opacity, 1))}::-webkit-scrollbar-thumb:hover{--tw-bg-opacity: 1;background-color:rgb(92 87 82 / var(--tw-bg-opacity, 1))}::-moz-selection{background:#d4952a4d}::selection{background:#d4952a4d}.resize-handle{width:.25rem;cursor:col-resize;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.resize-handle:hover{background-color:#d4952a4d}.resize-handle:active{background-color:#d4952a80}.resize-handle-h{height:.25rem;cursor:row-resize;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.resize-handle-h:hover{background-color:#d4952a4d}.resize-handle-h:active{background-color:#d4952a80}.canvas-node-label{text-align:center;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.canvas-node-name{display:block;color:#e8e2da;font-size:12px;font-weight:500;font-family:Geist Mono,IBM Plex Mono,monospace;text-shadow:0 1px 4px rgba(0,0,0,.8)}.canvas-node-status{display:block;color:#78726a;font-size:10px;font-family:Geist Mono,IBM Plex Mono,monospace;text-shadow:0 1px 4px rgba(0,0,0,.8)}.canvas-node-badge{display:flex;align-items:center;justify-content:center;width:20px;height:20px;background:#d4952a;color:#1a1918;font-size:10px;font-weight:700;border-radius:50%;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;box-shadow:0 0 8px #d4952a99}.canvas-toolcall-label{color:#3b9a6e;font-size:10px;font-family:Geist Mono,IBM Plex Mono,monospace;text-align:center;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;text-shadow:0 1px 4px rgba(0,0,0,.8)}.first\:mt-0:first-child{margin-top:0}.last\:mb-0:last-child{margin-bottom:0}.hover\:border-po-accent:hover{--tw-border-opacity: 1;border-color:rgb(212 149 42 / var(--tw-border-opacity, 1))}.hover\:border-po-border-focus:hover{--tw-border-opacity: 1;border-color:rgb(92 87 82 / var(--tw-border-opacity, 1))}.hover\:bg-po-accent-muted:hover{--tw-bg-opacity: 1;background-color:rgb(154 109 32 / var(--tw-bg-opacity, 1))}.hover\:bg-po-surface-2:hover{--tw-bg-opacity: 1;background-color:rgb(44 42 40 / var(--tw-bg-opacity, 1))}.hover\:bg-po-surface-3:hover{--tw-bg-opacity: 1;background-color:rgb(54 52 50 / var(--tw-bg-opacity, 1))}.hover\:text-po-accent:hover{--tw-text-opacity: 1;color:rgb(212 149 42 / var(--tw-text-opacity, 1))}.hover\:text-po-text-primary:hover{--tw-text-opacity: 1;color:rgb(232 226 218 / var(--tw-text-opacity, 1))}.hover\:text-po-text-secondary:hover{--tw-text-opacity: 1;color:rgb(168 162 154 / var(--tw-text-opacity, 1))}.hover\:underline:hover{text-decoration-line:underline}.focus\:border-po-accent:focus{--tw-border-opacity: 1;border-color:rgb(212 149 42 / var(--tw-border-opacity, 1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.disabled\:opacity-50:disabled{opacity:.5}@media(min-width:640px){.sm\:inline{display:inline}}
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module PromptObjects
|
|
4
|
-
module Universal
|
|
5
|
-
# Universal capability to add primitives to the current PO.
|
|
6
|
-
# Focused version of add_capability specifically for primitives with better UX.
|
|
7
|
-
class AddPrimitive < Primitive
|
|
8
|
-
# Names of stdlib primitives (built into the framework)
|
|
9
|
-
STDLIB_PRIMITIVES = %w[read_file list_files write_file http_get].freeze
|
|
10
|
-
|
|
11
|
-
def name
|
|
12
|
-
"add_primitive"
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def description
|
|
16
|
-
"Add a primitive (deterministic Ruby tool) to your capabilities. Use list_primitives first to see what's available."
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def parameters
|
|
20
|
-
{
|
|
21
|
-
type: "object",
|
|
22
|
-
properties: {
|
|
23
|
-
primitive: {
|
|
24
|
-
type: "string",
|
|
25
|
-
description: "Name of the primitive to add (e.g., 'read_file', 'write_file')"
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
required: ["primitive"]
|
|
29
|
-
}
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def receive(message, context:)
|
|
33
|
-
primitive_name = message[:primitive] || message["primitive"]
|
|
34
|
-
|
|
35
|
-
# Find the calling PO
|
|
36
|
-
caller = context.calling_po
|
|
37
|
-
unless caller
|
|
38
|
-
return "Error: No calling PO context. This capability adds primitives to the current PO."
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
target_po = context.env.registry.get(caller)
|
|
42
|
-
unless target_po.is_a?(PromptObject)
|
|
43
|
-
return "Error: Could not find calling PO '#{caller}'."
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
# Check if primitive exists
|
|
47
|
-
primitive = context.env.registry.get(primitive_name)
|
|
48
|
-
unless primitive
|
|
49
|
-
return suggest_primitives(primitive_name, context)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
unless primitive.is_a?(Primitive)
|
|
53
|
-
return "Error: '#{primitive_name}' is not a primitive (it's a prompt object). Use add_capability for POs."
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
# Check if it's a universal capability (shouldn't be added explicitly)
|
|
57
|
-
if universal_primitive?(primitive)
|
|
58
|
-
return "Error: '#{primitive_name}' is a universal capability and is already available to all POs."
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
# Check if already has it
|
|
62
|
-
current_caps = target_po.config["capabilities"] || []
|
|
63
|
-
if current_caps.include?(primitive_name)
|
|
64
|
-
return "You already have the '#{primitive_name}' primitive."
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
# Add the primitive
|
|
68
|
-
target_po.config["capabilities"] ||= []
|
|
69
|
-
target_po.config["capabilities"] << primitive_name
|
|
70
|
-
|
|
71
|
-
# Persist to file so it's available on restart
|
|
72
|
-
saved = target_po.save
|
|
73
|
-
|
|
74
|
-
# Notify for real-time UI update
|
|
75
|
-
context.env.notify_po_modified(target_po)
|
|
76
|
-
|
|
77
|
-
if saved
|
|
78
|
-
"Added '#{primitive_name}' to your capabilities and saved to file. You can now use it."
|
|
79
|
-
else
|
|
80
|
-
"Added '#{primitive_name}' to your capabilities (in-memory only). You can now use it."
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
private
|
|
85
|
-
|
|
86
|
-
def suggest_primitives(name, context)
|
|
87
|
-
# Get all available primitives (excluding universal ones)
|
|
88
|
-
available = context.env.registry.primitives
|
|
89
|
-
.reject { |p| universal_primitive?(p) }
|
|
90
|
-
.map(&:name)
|
|
91
|
-
|
|
92
|
-
# Find similar names
|
|
93
|
-
suggestions = available.select { |n| n.include?(name) || name.include?(n) || levenshtein_similar?(n, name) }
|
|
94
|
-
|
|
95
|
-
if suggestions.any?
|
|
96
|
-
"Error: Primitive '#{name}' not found. Did you mean: #{suggestions.join(', ')}?"
|
|
97
|
-
else
|
|
98
|
-
"Error: Primitive '#{name}' not found. Available primitives: #{available.join(', ')}"
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
def universal_primitive?(primitive)
|
|
103
|
-
primitive.class.name&.start_with?("PromptObjects::Universal")
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
# Simple check for similar strings (within 2 edits)
|
|
107
|
-
def levenshtein_similar?(a, b)
|
|
108
|
-
return true if a == b
|
|
109
|
-
return false if (a.length - b.length).abs > 2
|
|
110
|
-
|
|
111
|
-
# Simple approximation: check if they share most characters
|
|
112
|
-
common = (a.chars & b.chars).length
|
|
113
|
-
max_len = [a.length, b.length].max
|
|
114
|
-
common.to_f / max_len > 0.6
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
end
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module PromptObjects
|
|
4
|
-
module Universal
|
|
5
|
-
# Universal capability to pause and ask the human a question.
|
|
6
|
-
# For now this is synchronous (blocking). In Phase 5 with the TUI,
|
|
7
|
-
# this will become async with a notification queue.
|
|
8
|
-
class AskHuman < Primitive
|
|
9
|
-
def name
|
|
10
|
-
"ask_human"
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def description
|
|
14
|
-
"Pause and ask the human a question. Use this when you need confirmation, clarification, or input."
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def parameters
|
|
18
|
-
{
|
|
19
|
-
type: "object",
|
|
20
|
-
properties: {
|
|
21
|
-
question: {
|
|
22
|
-
type: "string",
|
|
23
|
-
description: "The question to ask the human"
|
|
24
|
-
},
|
|
25
|
-
options: {
|
|
26
|
-
type: "array",
|
|
27
|
-
items: { type: "string" },
|
|
28
|
-
description: "Optional list of choices to present"
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
required: ["question"]
|
|
32
|
-
}
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def receive(message, context:)
|
|
36
|
-
question = message[:question] || message["question"]
|
|
37
|
-
options = message[:options] || message["options"]
|
|
38
|
-
|
|
39
|
-
# In TUI mode, use the human queue (non-blocking for UI)
|
|
40
|
-
if context.tui_mode && context.human_queue
|
|
41
|
-
return receive_tui(question, options, context)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# REPL mode - use stdin directly
|
|
45
|
-
receive_repl(question, options, context)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
private
|
|
49
|
-
|
|
50
|
-
def receive_tui(question, options, context)
|
|
51
|
-
# Queue the request and wait for response
|
|
52
|
-
request = context.human_queue.enqueue(
|
|
53
|
-
capability: context.current_capability,
|
|
54
|
-
question: question,
|
|
55
|
-
options: options
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
# Log to message bus
|
|
59
|
-
context.bus.publish(
|
|
60
|
-
from: context.current_capability,
|
|
61
|
-
to: "human",
|
|
62
|
-
message: "[waiting] #{question}"
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
# Block this thread until human responds via UI
|
|
66
|
-
response = request.wait_for_response
|
|
67
|
-
|
|
68
|
-
# Log the response
|
|
69
|
-
context.bus.publish(
|
|
70
|
-
from: "human",
|
|
71
|
-
to: context.current_capability,
|
|
72
|
-
message: response
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
response
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def receive_repl(question, options, context)
|
|
79
|
-
puts
|
|
80
|
-
puts "┌─ #{context.current_capability} asks ──────────────────────────────────┐"
|
|
81
|
-
puts "│"
|
|
82
|
-
puts "│ #{question}"
|
|
83
|
-
puts "│"
|
|
84
|
-
|
|
85
|
-
if options && !options.empty?
|
|
86
|
-
options.each_with_index do |opt, i|
|
|
87
|
-
puts "│ [#{i + 1}] #{opt}"
|
|
88
|
-
end
|
|
89
|
-
puts "│"
|
|
90
|
-
puts "└──────────────────────────────────────────────────────────────┘"
|
|
91
|
-
print "Your choice (1-#{options.length}): "
|
|
92
|
-
|
|
93
|
-
choice = $stdin.gets&.chomp
|
|
94
|
-
index = choice.to_i - 1
|
|
95
|
-
|
|
96
|
-
if index >= 0 && index < options.length
|
|
97
|
-
options[index]
|
|
98
|
-
else
|
|
99
|
-
choice # Return raw input if not a valid index
|
|
100
|
-
end
|
|
101
|
-
else
|
|
102
|
-
puts "└──────────────────────────────────────────────────────────────┘"
|
|
103
|
-
print "Your answer: "
|
|
104
|
-
$stdin.gets&.chomp || ""
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
end
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "fileutils"
|
|
4
|
-
|
|
5
|
-
module PromptObjects
|
|
6
|
-
module Universal
|
|
7
|
-
# Universal capability to create new primitives (deterministic Ruby code).
|
|
8
|
-
# This enables POs to create their own tools at runtime.
|
|
9
|
-
class CreatePrimitive < Primitive
|
|
10
|
-
def name
|
|
11
|
-
"create_primitive"
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def description
|
|
15
|
-
"Create a new primitive (deterministic Ruby tool). The primitive will be saved to the environment and added to your capabilities."
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def parameters
|
|
19
|
-
{
|
|
20
|
-
type: "object",
|
|
21
|
-
properties: {
|
|
22
|
-
name: {
|
|
23
|
-
type: "string",
|
|
24
|
-
description: "Name for the primitive (lowercase, underscores allowed, e.g., 'parse_json')"
|
|
25
|
-
},
|
|
26
|
-
description: {
|
|
27
|
-
type: "string",
|
|
28
|
-
description: "Brief description of what this primitive does"
|
|
29
|
-
},
|
|
30
|
-
code: {
|
|
31
|
-
type: "string",
|
|
32
|
-
description: "Ruby code for the primitive's receive method. Has access to 'message' (Hash with parameters) and 'context'. Should return a String result."
|
|
33
|
-
},
|
|
34
|
-
parameters_schema: {
|
|
35
|
-
type: "object",
|
|
36
|
-
description: "Optional JSON Schema for the parameters this primitive accepts"
|
|
37
|
-
}
|
|
38
|
-
},
|
|
39
|
-
required: ["name", "description", "code"]
|
|
40
|
-
}
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def receive(message, context:)
|
|
44
|
-
prim_name = message[:name] || message["name"]
|
|
45
|
-
description = message[:description] || message["description"]
|
|
46
|
-
code = message[:code] || message["code"]
|
|
47
|
-
params_schema = message[:parameters_schema] || message["parameters_schema"] || default_params_schema
|
|
48
|
-
|
|
49
|
-
# Validate name
|
|
50
|
-
unless prim_name && prim_name.match?(/\A[a-z][a-z0-9_]*\z/)
|
|
51
|
-
return "Error: Name must be lowercase letters, numbers, and underscores, starting with a letter."
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# Check if already exists
|
|
55
|
-
if context.env.registry.exists?(prim_name)
|
|
56
|
-
return "Error: A capability named '#{prim_name}' already exists. Use modify_primitive to update it."
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
# Validate code syntax
|
|
60
|
-
syntax_error = validate_syntax(code)
|
|
61
|
-
return "Error: Invalid Ruby syntax - #{syntax_error}" if syntax_error
|
|
62
|
-
|
|
63
|
-
# Generate the Ruby class
|
|
64
|
-
class_name = prim_name.split("_").map(&:capitalize).join
|
|
65
|
-
ruby_content = generate_ruby_class(class_name, prim_name, description, params_schema, code)
|
|
66
|
-
|
|
67
|
-
# Write to primitives directory
|
|
68
|
-
FileUtils.mkdir_p(context.env.primitives_dir)
|
|
69
|
-
path = File.join(context.env.primitives_dir, "#{prim_name}.rb")
|
|
70
|
-
File.write(path, ruby_content, encoding: "UTF-8")
|
|
71
|
-
|
|
72
|
-
# Load and register
|
|
73
|
-
begin
|
|
74
|
-
load(path)
|
|
75
|
-
klass = PromptObjects::Primitives.const_get(class_name)
|
|
76
|
-
context.env.registry.register(klass.new)
|
|
77
|
-
rescue SyntaxError => e
|
|
78
|
-
File.delete(path) if File.exist?(path)
|
|
79
|
-
return "Error: Invalid Ruby syntax in generated code - #{e.message}"
|
|
80
|
-
rescue StandardError => e
|
|
81
|
-
File.delete(path) if File.exist?(path)
|
|
82
|
-
return "Error creating primitive: #{e.message}"
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
# Auto-add to the creating PO
|
|
86
|
-
added_msg = add_to_caller(prim_name, context)
|
|
87
|
-
|
|
88
|
-
result = "Created primitive '#{prim_name}' at #{path}."
|
|
89
|
-
result += " #{added_msg}" if added_msg
|
|
90
|
-
result
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
private
|
|
94
|
-
|
|
95
|
-
def default_params_schema
|
|
96
|
-
{
|
|
97
|
-
type: "object",
|
|
98
|
-
properties: {},
|
|
99
|
-
required: []
|
|
100
|
-
}
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def validate_syntax(code)
|
|
104
|
-
# Try to parse the code to check for syntax errors
|
|
105
|
-
eval("proc { #{code} }")
|
|
106
|
-
nil
|
|
107
|
-
rescue SyntaxError => e
|
|
108
|
-
e.message.sub(/^\(eval\):\d+: /, "")
|
|
109
|
-
rescue StandardError
|
|
110
|
-
nil # Other errors are OK at this stage
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def generate_ruby_class(class_name, prim_name, description, params_schema, code)
|
|
114
|
-
# Escape description for string literal
|
|
115
|
-
escaped_desc = description.gsub('\\', '\\\\\\\\').gsub('"', '\\"')
|
|
116
|
-
|
|
117
|
-
<<~RUBY
|
|
118
|
-
# frozen_string_literal: true
|
|
119
|
-
# Auto-generated primitive: #{prim_name}
|
|
120
|
-
# Created by PO at #{Time.now.iso8601}
|
|
121
|
-
|
|
122
|
-
module PromptObjects
|
|
123
|
-
module Primitives
|
|
124
|
-
class #{class_name} < Primitive
|
|
125
|
-
def name
|
|
126
|
-
"#{prim_name}"
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
def description
|
|
130
|
-
"#{escaped_desc}"
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
def parameters
|
|
134
|
-
#{params_schema.inspect}
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
def receive(message, context:)
|
|
138
|
-
#{indent_code(code, 10)}
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
RUBY
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
def indent_code(code, spaces)
|
|
147
|
-
code.lines.map.with_index do |line, i|
|
|
148
|
-
i.zero? ? line.rstrip : (" " * spaces) + line.rstrip
|
|
149
|
-
end.join("\n")
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
def add_to_caller(prim_name, context)
|
|
153
|
-
caller_name = context.calling_po
|
|
154
|
-
return nil unless caller_name
|
|
155
|
-
|
|
156
|
-
caller_po = context.env.registry.get(caller_name)
|
|
157
|
-
return nil unless caller_po.is_a?(PromptObject)
|
|
158
|
-
|
|
159
|
-
caller_po.config["capabilities"] ||= []
|
|
160
|
-
unless caller_po.config["capabilities"].include?(prim_name)
|
|
161
|
-
caller_po.config["capabilities"] << prim_name
|
|
162
|
-
saved = caller_po.save ? " and saved to file" : ""
|
|
163
|
-
|
|
164
|
-
# Notify for real-time UI update
|
|
165
|
-
context.env.notify_po_modified(caller_po)
|
|
166
|
-
|
|
167
|
-
return "Added '#{prim_name}' to your capabilities#{saved}."
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
nil
|
|
171
|
-
end
|
|
172
|
-
end
|
|
173
|
-
end
|
|
174
|
-
end
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module PromptObjects
|
|
4
|
-
module Universal
|
|
5
|
-
# Universal capability to list available primitives.
|
|
6
|
-
# Shows stdlib primitives, custom (environment) primitives, and which ones
|
|
7
|
-
# the current PO has active.
|
|
8
|
-
class ListPrimitives < Primitive
|
|
9
|
-
# Names of stdlib primitives (built into the framework)
|
|
10
|
-
STDLIB_PRIMITIVES = %w[read_file list_files write_file http_get].freeze
|
|
11
|
-
|
|
12
|
-
def name
|
|
13
|
-
"list_primitives"
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def description
|
|
17
|
-
"List available primitives (deterministic Ruby tools). Filter by type: stdlib (built-in), custom (environment-specific), active (on this PO), or available (all)."
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def parameters
|
|
21
|
-
{
|
|
22
|
-
type: "object",
|
|
23
|
-
properties: {
|
|
24
|
-
filter: {
|
|
25
|
-
type: "string",
|
|
26
|
-
enum: ["available", "active", "stdlib", "custom"],
|
|
27
|
-
description: "Filter primitives: 'available' (all), 'active' (currently on this PO), 'stdlib' (built-in), 'custom' (environment-specific). Default: 'available'"
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
required: []
|
|
31
|
-
}
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def receive(message, context:)
|
|
35
|
-
filter = (message[:filter] || message["filter"] || "available").to_s
|
|
36
|
-
|
|
37
|
-
case filter
|
|
38
|
-
when "stdlib"
|
|
39
|
-
list_stdlib(context)
|
|
40
|
-
when "custom"
|
|
41
|
-
list_custom(context)
|
|
42
|
-
when "active"
|
|
43
|
-
list_active(context)
|
|
44
|
-
when "available"
|
|
45
|
-
list_available(context)
|
|
46
|
-
else
|
|
47
|
-
"Error: Unknown filter '#{filter}'. Use: available, active, stdlib, or custom."
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
private
|
|
52
|
-
|
|
53
|
-
def list_stdlib(context)
|
|
54
|
-
primitives = STDLIB_PRIMITIVES.filter_map do |name|
|
|
55
|
-
prim = context.env.registry.get(name)
|
|
56
|
-
prim if prim.is_a?(Primitive)
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
format_list("Stdlib Primitives (built-in)", primitives)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def list_custom(context)
|
|
63
|
-
primitives = context.env.registry.primitives.reject do |prim|
|
|
64
|
-
STDLIB_PRIMITIVES.include?(prim.name) || universal_primitive?(prim)
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
if primitives.empty?
|
|
68
|
-
"No custom primitives found.\nCustom primitives are stored in: #{context.env.primitives_dir}"
|
|
69
|
-
else
|
|
70
|
-
format_list("Custom Primitives (environment-specific)", primitives)
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def list_active(context)
|
|
75
|
-
caller = context.calling_po
|
|
76
|
-
unless caller
|
|
77
|
-
return "Error: No calling PO context. This filter shows primitives active on the current PO."
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
po = context.env.registry.get(caller)
|
|
81
|
-
unless po.is_a?(PromptObject)
|
|
82
|
-
return "Error: Could not find calling PO '#{caller}'."
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
capabilities = po.config["capabilities"] || []
|
|
86
|
-
active_primitives = capabilities.filter_map do |cap_name|
|
|
87
|
-
cap = context.env.registry.get(cap_name)
|
|
88
|
-
cap if cap.is_a?(Primitive) && !universal_primitive?(cap)
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
if active_primitives.empty?
|
|
92
|
-
"No primitives currently active on #{caller}.\nUse add_primitive to add primitives to your capabilities."
|
|
93
|
-
else
|
|
94
|
-
format_list("Active Primitives on #{caller}", active_primitives)
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def list_available(context)
|
|
99
|
-
# All registered primitives except universal ones
|
|
100
|
-
primitives = context.env.registry.primitives.reject { |p| universal_primitive?(p) }
|
|
101
|
-
|
|
102
|
-
# Categorize them
|
|
103
|
-
stdlib = primitives.select { |p| STDLIB_PRIMITIVES.include?(p.name) }
|
|
104
|
-
custom = primitives.reject { |p| STDLIB_PRIMITIVES.include?(p.name) }
|
|
105
|
-
|
|
106
|
-
lines = []
|
|
107
|
-
|
|
108
|
-
unless stdlib.empty?
|
|
109
|
-
lines << "## Stdlib Primitives (built-in)"
|
|
110
|
-
stdlib.each { |p| lines << format_primitive(p) }
|
|
111
|
-
lines << ""
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
unless custom.empty?
|
|
115
|
-
lines << "## Custom Primitives (environment-specific)"
|
|
116
|
-
custom.each { |p| lines << format_primitive(p) }
|
|
117
|
-
lines << ""
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
if lines.empty?
|
|
121
|
-
"No primitives available."
|
|
122
|
-
else
|
|
123
|
-
lines.join("\n")
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
def format_list(title, primitives)
|
|
128
|
-
return "#{title}: (none)" if primitives.empty?
|
|
129
|
-
|
|
130
|
-
lines = ["## #{title}", ""]
|
|
131
|
-
primitives.each { |p| lines << format_primitive(p) }
|
|
132
|
-
lines.join("\n")
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
def format_primitive(primitive)
|
|
136
|
-
"- **#{primitive.name}**: #{primitive.description}"
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
def universal_primitive?(primitive)
|
|
140
|
-
# Universal capabilities live in PromptObjects::Universal module
|
|
141
|
-
primitive.class.name&.start_with?("PromptObjects::Universal")
|
|
142
|
-
end
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
|
-
end
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module PromptObjects
|
|
4
|
-
module Universal
|
|
5
|
-
# Universal capability for internal reasoning.
|
|
6
|
-
# Thoughts are logged to the message bus but displayed differently (dimmed).
|
|
7
|
-
# This helps POs "think out loud" without cluttering the conversation.
|
|
8
|
-
class Think < Primitive
|
|
9
|
-
def name
|
|
10
|
-
"think"
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def description
|
|
14
|
-
"Internal reasoning step. Use this to think through a problem before acting. The thought is logged but not shown prominently to the human."
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def parameters
|
|
18
|
-
{
|
|
19
|
-
type: "object",
|
|
20
|
-
properties: {
|
|
21
|
-
thought: {
|
|
22
|
-
type: "string",
|
|
23
|
-
description: "Your internal reasoning or thought process"
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
required: ["thought"]
|
|
27
|
-
}
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def receive(message, context:)
|
|
31
|
-
thought = message[:thought] || message["thought"]
|
|
32
|
-
|
|
33
|
-
# Display dimmed (using ANSI codes)
|
|
34
|
-
puts "\e[2m 💭 #{context.current_capability} thinks: #{thought}\e[0m"
|
|
35
|
-
|
|
36
|
-
# Return acknowledgment
|
|
37
|
-
"Thought recorded."
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
data/prompt_objects.gemspec
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
Gem::Specification.new do |spec|
|
|
4
|
-
spec.name = "prompt_objects"
|
|
5
|
-
spec.version = "0.5.0"
|
|
6
|
-
spec.authors = ["Scott Werner"]
|
|
7
|
-
spec.email = ["scott@sublayer.com"]
|
|
8
|
-
|
|
9
|
-
spec.summary = "LLM-backed entities as first-class autonomous objects"
|
|
10
|
-
spec.description = "A framework where markdown files with LLM-backed behavior act as first-class autonomous entities. Features inter-object communication and environment management."
|
|
11
|
-
spec.homepage = "https://github.com/works-on-your-machine/prompt_objects"
|
|
12
|
-
spec.license = "MIT"
|
|
13
|
-
spec.required_ruby_version = ">= 3.2.0"
|
|
14
|
-
|
|
15
|
-
spec.metadata["homepage_uri"] = spec.homepage
|
|
16
|
-
spec.metadata["source_code_uri"] = spec.homepage
|
|
17
|
-
spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
|
|
18
|
-
|
|
19
|
-
# Include lib, exe, templates, and objects (stdlib)
|
|
20
|
-
spec.files = Dir.chdir(__dir__) do
|
|
21
|
-
`git ls-files -z`.split("\x0").reject do |f|
|
|
22
|
-
(File.expand_path(f) == __FILE__) ||
|
|
23
|
-
f.start_with?(*%w[test/ spec/ features/ .git .github docs/])
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
spec.bindir = "exe"
|
|
27
|
-
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
28
|
-
spec.require_paths = ["lib"]
|
|
29
|
-
|
|
30
|
-
# Runtime dependencies
|
|
31
|
-
spec.add_dependency "ruby-openai", "~> 7.0"
|
|
32
|
-
spec.add_dependency "anthropic", "~> 1.0"
|
|
33
|
-
spec.add_dependency "front_matter_parser", "~> 1.0"
|
|
34
|
-
spec.add_dependency "sqlite3", "~> 2.0"
|
|
35
|
-
|
|
36
|
-
# Web server dependencies
|
|
37
|
-
spec.add_dependency "falcon", "~> 0.50"
|
|
38
|
-
spec.add_dependency "async-websocket", "~> 0.28"
|
|
39
|
-
spec.add_dependency "rack", "~> 3.0"
|
|
40
|
-
spec.add_dependency "listen", "~> 3.9"
|
|
41
|
-
|
|
42
|
-
# MCP server
|
|
43
|
-
spec.add_dependency "mcp", "~> 0.4"
|
|
44
|
-
|
|
45
|
-
# Development dependencies
|
|
46
|
-
spec.add_development_dependency "rake", "~> 13.0"
|
|
47
|
-
spec.add_development_dependency "minitest", "~> 5.0"
|
|
48
|
-
spec.add_development_dependency "rubocop", "~> 1.50"
|
|
49
|
-
spec.add_development_dependency "debug", "~> 1.0"
|
|
50
|
-
end
|