prompt_objects 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +126 -0
- data/README.md +93 -22
- data/exe/poop +5 -0
- data/exe/prompt_objects +1 -1108
- data/exe/prompt_objects_mcp +5 -3
- data/lib/prompt_objects/capability.rb +33 -0
- data/lib/prompt_objects/cli/diagnostics_command.rb +69 -0
- data/lib/prompt_objects/cli/env_command.rb +435 -0
- data/lib/prompt_objects/cli/events_command.rb +145 -0
- data/lib/prompt_objects/cli/explore_command.rb +155 -0
- data/lib/prompt_objects/cli/helpers.rb +91 -0
- data/lib/prompt_objects/cli/message_command.rb +216 -0
- data/lib/prompt_objects/cli/repl_command.rb +366 -0
- data/lib/prompt_objects/cli/serve_command.rb +162 -0
- data/lib/prompt_objects/cli.rb +64 -422
- data/lib/prompt_objects/connectors/base.rb +16 -29
- data/lib/prompt_objects/connectors/mcp.rb +82 -98
- data/lib/prompt_objects/domain/records.rb +45 -0
- data/lib/prompt_objects/environment/exporter.rb +5 -4
- data/lib/prompt_objects/environment/git.rb +21 -1
- data/lib/prompt_objects/environment/importer.rb +5 -4
- data/lib/prompt_objects/environment/manager.rb +44 -6
- data/lib/prompt_objects/environment/manifest.rb +26 -4
- data/lib/prompt_objects/environment.rb +1337 -20
- data/lib/prompt_objects/execution/blocking_executor.rb +88 -0
- data/lib/prompt_objects/execution/context.rb +137 -0
- data/lib/prompt_objects/execution/contracts.rb +59 -0
- data/lib/prompt_objects/execution/permit_pool.rb +49 -0
- data/lib/prompt_objects/execution/policy.rb +47 -0
- data/lib/prompt_objects/execution/resource_lock_manager.rb +63 -0
- data/lib/prompt_objects/execution/runner.rb +498 -0
- data/lib/prompt_objects/execution/scheduler.rb +325 -0
- data/lib/prompt_objects/llm/factory.rb +4 -4
- data/lib/prompt_objects/llm/gemini_adapter.rb +25 -8
- data/lib/prompt_objects/llm/openai_adapter.rb +9 -1
- data/lib/prompt_objects/llm/pricing.rb +9 -2
- data/lib/prompt_objects/llm/response.rb +9 -4
- data/lib/prompt_objects/loader.rb +28 -1
- data/lib/prompt_objects/mcp/server.rb +6 -3
- data/lib/prompt_objects/mcp/tools/get_conversation.rb +15 -11
- data/lib/prompt_objects/mcp/tools/get_pending_requests.rb +2 -2
- data/lib/prompt_objects/mcp/tools/respond_to_request.rb +3 -3
- data/lib/prompt_objects/mcp/tools/send_message.rb +42 -32
- data/lib/prompt_objects/operations/diagnostics.rb +115 -0
- data/lib/prompt_objects/operations/retention.rb +75 -0
- data/lib/prompt_objects/operations/run_trace_builder.rb +152 -0
- data/lib/prompt_objects/primitives/http_get.rb +2 -0
- data/lib/prompt_objects/primitives/list_files.rb +2 -0
- data/lib/prompt_objects/primitives/read_file.rb +2 -0
- data/lib/prompt_objects/primitives/think.rb +36 -0
- data/lib/prompt_objects/primitives/write_file.rb +9 -0
- data/lib/prompt_objects/prompt_object.rb +171 -519
- data/lib/prompt_objects/repositories/artifact_repository.rb +109 -0
- data/lib/prompt_objects/repositories/base_repository.rb +37 -0
- data/lib/prompt_objects/repositories/definition_repository.rb +36 -0
- data/lib/prompt_objects/repositories/env_data_repository.rb +103 -0
- data/lib/prompt_objects/repositories/event_repository.rb +105 -0
- data/lib/prompt_objects/repositories/message_repository.rb +73 -0
- data/lib/prompt_objects/repositories/run_repository.rb +254 -0
- data/lib/prompt_objects/repositories/thread_repository.rb +87 -0
- data/lib/prompt_objects/repositories/tool_execution_repository.rb +88 -0
- data/lib/prompt_objects/repositories/workspace_session_repository.rb +61 -0
- data/lib/prompt_objects/server/api/routes.rb +549 -53
- data/lib/prompt_objects/server/app.rb +133 -14
- data/lib/prompt_objects/server/file_watcher.rb +9 -0
- data/lib/prompt_objects/server/public/assets/index-BjKlODDD.js +90 -0
- data/lib/prompt_objects/server/public/assets/index-w3fpIb5c.css +1 -0
- data/lib/prompt_objects/server/public/index.html +2 -2
- data/lib/prompt_objects/server/websocket_handler.rb +202 -227
- data/lib/prompt_objects/server.rb +170 -1
- data/lib/prompt_objects/service.rb +129 -0
- data/lib/prompt_objects/session/store.rb +600 -13
- data/lib/prompt_objects/universal/add_capability.rb +1 -1
- data/lib/prompt_objects/universal/create_capability.rb +4 -2
- data/lib/prompt_objects/universal/delete_env_data.rb +23 -15
- data/lib/prompt_objects/universal/delete_primitive.rb +1 -1
- data/lib/prompt_objects/universal/dispatch_po.rb +54 -0
- data/lib/prompt_objects/universal/get_env_data.rb +8 -14
- data/lib/prompt_objects/universal/get_run_status.rb +30 -0
- data/lib/prompt_objects/universal/join_runs.rb +35 -0
- data/lib/prompt_objects/universal/list_env_data.rb +10 -14
- data/lib/prompt_objects/universal/modify_primitive.rb +1 -1
- data/lib/prompt_objects/universal/render_artifact.rb +91 -0
- data/lib/prompt_objects/universal/request_primitive.rb +1 -1
- data/lib/prompt_objects/universal/{store_env_data.rb → set_env_data.rb} +34 -20
- data/lib/prompt_objects/version.rb +5 -0
- data/lib/prompt_objects.rb +33 -8
- data/objects/coordinator.md +8 -4
- data/templates/arc-agi-1/objects/data_manager.md +2 -2
- data/templates/arc-agi-1/objects/observer.md +2 -2
- data/templates/arc-agi-1/objects/solver.md +6 -5
- data/templates/arc-agi-1/objects/verifier.md +2 -2
- data/templates/arc-agi-3/manifest.yml +19 -0
- data/templates/arc-agi-3/objects/analyst.md +79 -0
- data/templates/arc-agi-3/objects/player.md +76 -0
- data/templates/arc-agi-3/objects/strategist.md +97 -0
- data/templates/arc-agi-3/primitives/action_log.rb +133 -0
- data/templates/arc-agi-3/primitives/arc3_api.rb +223 -0
- data/templates/arc-agi-3/primitives/arc3_scorecard.rb +131 -0
- data/templates/arc-agi-3/primitives/frame_diff.rb +143 -0
- data/templates/arc-agi-3/primitives/frame_info.rb +96 -0
- data/templates/arc-agi-3/primitives/render_frame.rb +140 -0
- data/templates/basic/objects/basic.md +11 -3
- data/templates/chiptune/extras/sonic_pi_boot.rb +220 -0
- data/templates/chiptune/manifest.yml +20 -0
- data/templates/chiptune/objects/conductor.md +184 -0
- data/templates/chiptune/objects/sonic_pi.md +65 -0
- data/templates/chiptune/objects/voice_bass.md +44 -0
- data/templates/chiptune/objects/voice_lead.md +44 -0
- data/templates/chiptune/objects/voice_pad.md +43 -0
- data/templates/chiptune/objects/voice_perc.md +45 -0
- data/templates/chiptune/primitives/play_note.rb +59 -0
- data/templates/chiptune/primitives/play_sequence.rb +55 -0
- data/templates/chiptune/primitives/query_sonic_pi.rb +141 -0
- data/templates/chiptune/primitives/set_synth.rb +57 -0
- data/templates/chiptune/primitives/set_tempo.rb +45 -0
- data/templates/chiptune/primitives/stop_voice.rb +46 -0
- data/templates/chiptune/primitives/support/osc_bridge.rb +33 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/LICENSE +19 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/address_pattern.rb +58 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/broadcast_client.rb +24 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/bundle.rb +46 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/client.rb +13 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/core_ext/time.rb +6 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/em_server.rb +63 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/message.rb +46 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/network_packet.rb +42 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_argument.rb +26 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_packet.rb +140 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_types.rb +53 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/server.rb +91 -0
- data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby.rb +18 -0
- data/templates/developer/objects/code_reviewer.md +1 -1
- data/templates/developer/objects/coordinator.md +16 -3
- data/templates/developer/objects/debugger.md +3 -3
- data/templates/empty/objects/assistant.md +10 -5
- data/templates/minimal/objects/assistant.md +10 -5
- data/templates/music/extras/sonic_pi_boot.rb +220 -0
- data/templates/music/manifest.yml +16 -0
- data/templates/music/objects/conductor.md +154 -0
- data/templates/music/objects/sonic_pi.md +65 -0
- data/templates/music/primitives/play_note.rb +55 -0
- data/templates/music/primitives/play_sequence.rb +51 -0
- data/templates/music/primitives/query_sonic_pi.rb +139 -0
- data/templates/music/primitives/set_synth.rb +53 -0
- data/templates/music/primitives/set_tempo.rb +43 -0
- data/templates/music/primitives/stop_voice.rb +44 -0
- data/templates/music/primitives/support/osc_bridge.rb +33 -0
- data/templates/music/vendor/osc-ruby-1.1.5/LICENSE +19 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/address_pattern.rb +58 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/broadcast_client.rb +24 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/bundle.rb +46 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/client.rb +13 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/core_ext/time.rb +6 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/em_server.rb +63 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/message.rb +46 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/network_packet.rb +42 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_argument.rb +26 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_packet.rb +140 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_types.rb +53 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/server.rb +91 -0
- data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby.rb +18 -0
- data/templates/music-beginner/README.md +100 -0
- data/templates/music-beginner/extras/README.md +27 -0
- data/templates/music-beginner/extras/sonic_pi_boot.rb +297 -0
- data/templates/music-beginner/manifest.yml +25 -0
- data/templates/music-beginner/objects/conductor.md +222 -0
- data/templates/music-beginner/objects/engine_setup.md +54 -0
- data/templates/music-beginner/objects/voice_bass.md +43 -0
- data/templates/music-beginner/objects/voice_keys.md +48 -0
- data/templates/music-beginner/objects/voice_pad.md +46 -0
- data/templates/music-beginner/objects/voice_percussion.md +45 -0
- data/templates/music-beginner/objects/voice_texture.md +37 -0
- data/templates/music-beginner/primitives/play_pattern.rb +118 -0
- data/templates/music-beginner/primitives/query_music_engine.rb +94 -0
- data/templates/music-beginner/primitives/set_instrument.rb +47 -0
- data/templates/music-beginner/primitives/set_tempo.rb +43 -0
- data/templates/music-beginner/primitives/set_voice_level.rb +46 -0
- data/templates/music-beginner/primitives/stop_voice.rb +37 -0
- data/templates/music-beginner/primitives/support/osc_bridge.rb +25 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/LICENSE +19 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/address_pattern.rb +58 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/broadcast_client.rb +24 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/bundle.rb +46 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/client.rb +13 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/core_ext/time.rb +6 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/em_server.rb +63 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/message.rb +46 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/network_packet.rb +42 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_argument.rb +26 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_packet.rb +140 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_types.rb +53 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/server.rb +91 -0
- data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby.rb +18 -0
- data/templates/music-pro/extras/AUDITION.md +100 -0
- data/templates/music-pro/extras/sonic_pi_boot.rb +546 -0
- data/templates/music-pro/manifest.yml +19 -0
- data/templates/music-pro/objects/conductor.md +126 -0
- data/templates/music-pro/objects/sonic_pi.md +35 -0
- data/templates/music-pro/objects/voice_harmony.md +48 -0
- data/templates/music-pro/objects/voice_rhythm.md +43 -0
- data/templates/music-pro/objects/voice_texture.md +42 -0
- data/templates/music-pro/primitives/define_patch.rb +46 -0
- data/templates/music-pro/primitives/query_music_engine.rb +69 -0
- data/templates/music-pro/primitives/set_live_pattern.rb +70 -0
- data/templates/music-pro/primitives/set_tempo.rb +31 -0
- data/templates/music-pro/primitives/stop_voice.rb +31 -0
- data/templates/music-pro/primitives/support/music_protocol.rb +136 -0
- data/templates/music-pro/primitives/support/osc_bridge.rb +33 -0
- data/templates/music-pro/primitives/trigger_event.rb +44 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/LICENSE +19 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/address_pattern.rb +58 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/broadcast_client.rb +24 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/bundle.rb +46 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/client.rb +13 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/core_ext/time.rb +6 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/em_server.rb +63 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/message.rb +46 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/network_packet.rb +42 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_argument.rb +26 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_packet.rb +140 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_types.rb +53 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/server.rb +91 -0
- data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby.rb +18 -0
- data/templates/writer/objects/coordinator.md +14 -3
- data/templates/writer/objects/editor.md +1 -1
- data/templates/writer/objects/researcher.md +2 -2
- data/tools/thread-explorer.html +1 -1
- metadata +172 -65
- data/CLAUDE.md +0 -177
- data/Gemfile +0 -10
- data/Rakefile +0 -27
- data/frontend/.gitignore +0 -3
- data/frontend/index.html +0 -17
- data/frontend/package-lock.json +0 -4540
- data/frontend/package.json +0 -36
- data/frontend/postcss.config.js +0 -6
- data/frontend/src/App.tsx +0 -104
- data/frontend/src/canvas/CanvasView.tsx +0 -113
- data/frontend/src/canvas/ForceLayout.ts +0 -115
- data/frontend/src/canvas/SceneManager.ts +0 -587
- data/frontend/src/canvas/canvasStore.ts +0 -47
- data/frontend/src/canvas/constants.ts +0 -95
- data/frontend/src/canvas/controls/CameraControls.ts +0 -98
- data/frontend/src/canvas/edges/MessageArc.ts +0 -149
- data/frontend/src/canvas/inspector/InspectorPanel.tsx +0 -31
- data/frontend/src/canvas/inspector/POInspector.tsx +0 -262
- data/frontend/src/canvas/inspector/ToolCallInspector.tsx +0 -67
- data/frontend/src/canvas/nodes/PONode.ts +0 -249
- data/frontend/src/canvas/nodes/ToolCallNode.ts +0 -116
- data/frontend/src/canvas/types.ts +0 -24
- data/frontend/src/components/ContextMenu.tsx +0 -68
- data/frontend/src/components/EnvDataPane.tsx +0 -69
- data/frontend/src/components/Inspector.tsx +0 -263
- data/frontend/src/components/MarkdownMessage.tsx +0 -155
- data/frontend/src/components/MethodList.tsx +0 -90
- data/frontend/src/components/ModelSelector.tsx +0 -115
- data/frontend/src/components/NotificationPanel.tsx +0 -130
- data/frontend/src/components/ObjectList.tsx +0 -78
- data/frontend/src/components/PaneSlot.tsx +0 -30
- data/frontend/src/components/SourcePane.tsx +0 -202
- data/frontend/src/components/SystemBar.tsx +0 -74
- data/frontend/src/components/Transcript.tsx +0 -76
- data/frontend/src/components/UsagePanel.tsx +0 -105
- data/frontend/src/components/Workspace.tsx +0 -260
- data/frontend/src/components/index.ts +0 -12
- data/frontend/src/hooks/useResize.ts +0 -55
- data/frontend/src/hooks/useWebSocket.ts +0 -559
- data/frontend/src/index.css +0 -102
- data/frontend/src/main.tsx +0 -10
- data/frontend/src/store/index.ts +0 -311
- data/frontend/src/types/index.ts +0 -176
- data/frontend/tailwind.config.js +0 -44
- data/frontend/tsconfig.json +0 -30
- data/frontend/vite.config.ts +0 -29
- data/lib/prompt_objects/server/public/assets/index-DEPawnfZ.js +0 -4345
- data/lib/prompt_objects/server/public/assets/index-oMrRce1m.css +0 -1
- data/lib/prompt_objects/universal/add_primitive.rb +0 -118
- data/lib/prompt_objects/universal/ask_human.rb +0 -109
- data/lib/prompt_objects/universal/create_primitive.rb +0 -174
- data/lib/prompt_objects/universal/list_primitives.rb +0 -145
- data/lib/prompt_objects/universal/think.rb +0 -41
- data/lib/prompt_objects/universal/update_env_data.rb +0 -88
- data/prompt_objects.gemspec +0 -50
- data/templates/basic/.gitignore +0 -2
- data/templates/developer/.gitignore +0 -5
- data/templates/empty/.gitignore +0 -5
- data/templates/empty/objects/.gitkeep +0 -0
- data/templates/minimal/.gitignore +0 -5
- data/templates/writer/.gitignore +0 -5
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PromptObjects
|
|
4
|
+
module Repositories
|
|
5
|
+
class ArtifactRepository < BaseRepository
|
|
6
|
+
Mutation = Data.define(:artifact, :cursor)
|
|
7
|
+
|
|
8
|
+
def upsert(**attributes)
|
|
9
|
+
upsert_with_cursor(**attributes).artifact
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def upsert_with_cursor(workspace_session_id:, owner_po:, owner_thread_id:, producing_run_id:,
|
|
13
|
+
title:, html:, mode: "replace", metadata: {}, id: nil)
|
|
14
|
+
raise ArgumentError, "unknown artifact mode: #{mode}" unless %w[replace version].include?(mode.to_s)
|
|
15
|
+
|
|
16
|
+
transaction do |db|
|
|
17
|
+
existing = if mode.to_s == "replace"
|
|
18
|
+
db.get_first_row(<<~SQL, [workspace_session_id, title])
|
|
19
|
+
SELECT * FROM artifacts
|
|
20
|
+
WHERE workspace_session_id = ? AND title = ? AND mode = 'replace'
|
|
21
|
+
ORDER BY updated_at DESC LIMIT 1
|
|
22
|
+
SQL
|
|
23
|
+
end
|
|
24
|
+
artifact_id = existing ? existing["id"] : (id || "artifact_#{SecureRandom.uuid}")
|
|
25
|
+
revision = existing ? existing["revision"].to_i + 1 : 1
|
|
26
|
+
now = Time.now.utc.iso8601
|
|
27
|
+
created_at = existing ? existing["created_at"] : now
|
|
28
|
+
params = [
|
|
29
|
+
artifact_id, workspace_session_id, owner_po, owner_thread_id,
|
|
30
|
+
producing_run_id, title, html, revision, mode.to_s, created_at,
|
|
31
|
+
now, JSON.generate(metadata)
|
|
32
|
+
]
|
|
33
|
+
db.execute(<<~SQL, params)
|
|
34
|
+
INSERT INTO artifacts (
|
|
35
|
+
id, workspace_session_id, owner_po, owner_thread_id, producing_run_id,
|
|
36
|
+
title, html, revision, mode, created_at, updated_at, metadata
|
|
37
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
38
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
39
|
+
owner_po = excluded.owner_po,
|
|
40
|
+
owner_thread_id = excluded.owner_thread_id,
|
|
41
|
+
producing_run_id = excluded.producing_run_id,
|
|
42
|
+
title = excluded.title,
|
|
43
|
+
html = excluded.html,
|
|
44
|
+
revision = excluded.revision,
|
|
45
|
+
mode = excluded.mode,
|
|
46
|
+
updated_at = excluded.updated_at,
|
|
47
|
+
metadata = excluded.metadata
|
|
48
|
+
SQL
|
|
49
|
+
row = db.get_first_row("SELECT * FROM artifacts WHERE id = ?", [artifact_id])
|
|
50
|
+
artifact = parse(row)
|
|
51
|
+
cursor = append_workspace_event(db, artifact)
|
|
52
|
+
Mutation.new(artifact: artifact, cursor: cursor)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def get(id)
|
|
57
|
+
row = read { |db| db.get_first_row("SELECT * FROM artifacts WHERE id = ?", [id]) }
|
|
58
|
+
row && parse(row)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def list(workspace_session_id:)
|
|
62
|
+
read do |db|
|
|
63
|
+
db.execute(
|
|
64
|
+
"SELECT * FROM artifacts WHERE workspace_session_id = ? ORDER BY updated_at ASC, id ASC",
|
|
65
|
+
[workspace_session_id]
|
|
66
|
+
).map { |row| parse(row) }
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def delete(id)
|
|
71
|
+
transaction do |db|
|
|
72
|
+
artifact = db.get_first_row("SELECT * FROM artifacts WHERE id = ?", [id])
|
|
73
|
+
next false unless artifact
|
|
74
|
+
|
|
75
|
+
db.execute("DELETE FROM artifacts WHERE id = ?", [id])
|
|
76
|
+
now = Time.now.utc.iso8601
|
|
77
|
+
db.execute(<<~SQL, [artifact["workspace_session_id"], id, now])
|
|
78
|
+
INSERT INTO workspace_events (
|
|
79
|
+
workspace_session_id, event_type, entity_type, entity_id, payload, created_at
|
|
80
|
+
) VALUES (?, 'artifact_removed', 'artifact', ?, '{}', ?)
|
|
81
|
+
SQL
|
|
82
|
+
true
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
private
|
|
87
|
+
|
|
88
|
+
def append_workspace_event(db, artifact)
|
|
89
|
+
payload = { artifact_id: artifact.id, revision: artifact.revision }
|
|
90
|
+
db.execute(<<~SQL, [artifact.workspace_session_id, artifact.id, JSON.generate(payload), Time.now.utc.iso8601])
|
|
91
|
+
INSERT INTO workspace_events (
|
|
92
|
+
workspace_session_id, event_type, entity_type, entity_id, payload, created_at
|
|
93
|
+
) VALUES (?, 'artifact_upserted', 'artifact', ?, ?, ?)
|
|
94
|
+
SQL
|
|
95
|
+
db.last_insert_row_id
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def parse(row)
|
|
99
|
+
Domain::Artifact.new(
|
|
100
|
+
id: row["id"], workspace_session_id: row["workspace_session_id"],
|
|
101
|
+
owner_po: row["owner_po"], owner_thread_id: row["owner_thread_id"],
|
|
102
|
+
producing_run_id: row["producing_run_id"], title: row["title"], html: row["html"],
|
|
103
|
+
revision: row["revision"], mode: row["mode"], created_at: timestamp(row["created_at"]),
|
|
104
|
+
updated_at: timestamp(row["updated_at"]), metadata: json(row["metadata"])
|
|
105
|
+
)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PromptObjects
|
|
4
|
+
module Repositories
|
|
5
|
+
class BaseRepository
|
|
6
|
+
def initialize(store)
|
|
7
|
+
@store = store
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def read(&block)
|
|
13
|
+
@store.with_connection(&block)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def transaction(&block)
|
|
17
|
+
@store.transaction(&block)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def json(value, default: {})
|
|
21
|
+
return default if value.nil?
|
|
22
|
+
|
|
23
|
+
JSON.parse(value, symbolize_names: true)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def json_array(value)
|
|
27
|
+
return [] if value.nil?
|
|
28
|
+
|
|
29
|
+
JSON.parse(value)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def timestamp(value)
|
|
33
|
+
value ? Time.parse(value) : nil
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PromptObjects
|
|
4
|
+
module Repositories
|
|
5
|
+
# Persists the exact Prompt Object definition used by a run.
|
|
6
|
+
class DefinitionRepository < BaseRepository
|
|
7
|
+
def attach(run_id:, definition:)
|
|
8
|
+
transaction do |db|
|
|
9
|
+
params = [
|
|
10
|
+
run_id, definition.po_name, definition.version, definition.prompt,
|
|
11
|
+
JSON.generate(definition.config), definition.provider, definition.model,
|
|
12
|
+
definition.capability_policy_version, Time.now.utc.iso8601
|
|
13
|
+
]
|
|
14
|
+
db.execute(<<~SQL, params)
|
|
15
|
+
INSERT INTO run_definitions (
|
|
16
|
+
run_id, po_name, version, prompt, config, provider, model,
|
|
17
|
+
capability_policy_version, created_at
|
|
18
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
19
|
+
SQL
|
|
20
|
+
end
|
|
21
|
+
get(run_id)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def get(run_id)
|
|
25
|
+
row = read { |db| db.get_first_row("SELECT * FROM run_definitions WHERE run_id = ?", [run_id]) }
|
|
26
|
+
return nil unless row
|
|
27
|
+
|
|
28
|
+
Domain::PromptObjectDefinition.new(
|
|
29
|
+
po_name: row["po_name"], version: row["version"], prompt: row["prompt"],
|
|
30
|
+
config: JSON.parse(row["config"]), provider: row["provider"], model: row["model"],
|
|
31
|
+
capability_policy_version: row["capability_policy_version"]
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PromptObjects
|
|
4
|
+
module Repositories
|
|
5
|
+
class EnvDataRepository < BaseRepository
|
|
6
|
+
Mutation = Data.define(:entry, :cursor)
|
|
7
|
+
Removal = Data.define(:deleted, :cursor)
|
|
8
|
+
|
|
9
|
+
def set(**attributes)
|
|
10
|
+
set_with_cursor(**attributes).entry
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def set_with_cursor(workspace_session_id:, key:, short_description:, value:, stored_by:)
|
|
14
|
+
now = Time.now.utc.iso8601
|
|
15
|
+
transaction do |db|
|
|
16
|
+
params = [
|
|
17
|
+
workspace_session_id, workspace_session_id, workspace_session_id,
|
|
18
|
+
key, short_description, JSON.generate(value), stored_by, now, now
|
|
19
|
+
]
|
|
20
|
+
db.execute(<<~SQL, params)
|
|
21
|
+
INSERT INTO env_data (
|
|
22
|
+
root_thread_id, session_id, workspace_session_id, key,
|
|
23
|
+
short_description, value, stored_by, created_at, updated_at
|
|
24
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
25
|
+
ON CONFLICT(root_thread_id, key) DO UPDATE SET
|
|
26
|
+
workspace_session_id = excluded.workspace_session_id,
|
|
27
|
+
session_id = excluded.session_id,
|
|
28
|
+
short_description = excluded.short_description,
|
|
29
|
+
value = excluded.value,
|
|
30
|
+
stored_by = excluded.stored_by,
|
|
31
|
+
updated_at = excluded.updated_at
|
|
32
|
+
SQL
|
|
33
|
+
cursor = append_event(db, workspace_session_id, "store", key, stored_by, now)
|
|
34
|
+
entry = parse(db.get_first_row(<<~SQL, [workspace_session_id, key]))
|
|
35
|
+
SELECT * FROM env_data WHERE workspace_session_id = ? AND key = ?
|
|
36
|
+
SQL
|
|
37
|
+
Mutation.new(entry: entry, cursor: cursor)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def get(workspace_session_id:, key:)
|
|
42
|
+
row = read do |db|
|
|
43
|
+
db.get_first_row(
|
|
44
|
+
"SELECT * FROM env_data WHERE workspace_session_id = ? AND key = ?",
|
|
45
|
+
[workspace_session_id, key]
|
|
46
|
+
)
|
|
47
|
+
end
|
|
48
|
+
row && parse(row)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def list(workspace_session_id:)
|
|
52
|
+
read do |db|
|
|
53
|
+
db.execute(
|
|
54
|
+
"SELECT * FROM env_data WHERE workspace_session_id = ? ORDER BY key ASC",
|
|
55
|
+
[workspace_session_id]
|
|
56
|
+
).map { |row| parse(row) }
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def delete(workspace_session_id:, key:, stored_by:)
|
|
61
|
+
delete_with_cursor(
|
|
62
|
+
workspace_session_id: workspace_session_id,
|
|
63
|
+
key: key,
|
|
64
|
+
stored_by: stored_by
|
|
65
|
+
).deleted
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def delete_with_cursor(workspace_session_id:, key:, stored_by:)
|
|
69
|
+
transaction do |db|
|
|
70
|
+
db.execute(
|
|
71
|
+
"DELETE FROM env_data WHERE workspace_session_id = ? AND key = ?",
|
|
72
|
+
[workspace_session_id, key]
|
|
73
|
+
)
|
|
74
|
+
next Removal.new(deleted: false, cursor: nil) unless db.changes.positive?
|
|
75
|
+
|
|
76
|
+
cursor = append_event(db, workspace_session_id, "delete", key, stored_by, Time.now.utc.iso8601)
|
|
77
|
+
Removal.new(deleted: true, cursor: cursor)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
def append_event(db, workspace_session_id, action, key, stored_by, now)
|
|
84
|
+
payload = { action: action, key: key, stored_by: stored_by }
|
|
85
|
+
db.execute(<<~SQL, [workspace_session_id, key, JSON.generate(payload), now])
|
|
86
|
+
INSERT INTO workspace_events (
|
|
87
|
+
workspace_session_id, event_type, entity_type, entity_id, payload, created_at
|
|
88
|
+
) VALUES (?, 'env_data_changed', 'env_data', ?, ?, ?)
|
|
89
|
+
SQL
|
|
90
|
+
db.last_insert_row_id
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def parse(row)
|
|
94
|
+
{
|
|
95
|
+
id: row["id"], workspace_session_id: row["workspace_session_id"],
|
|
96
|
+
key: row["key"], short_description: row["short_description"],
|
|
97
|
+
value: JSON.parse(row["value"], symbolize_names: true), stored_by: row["stored_by"],
|
|
98
|
+
created_at: timestamp(row["created_at"]), updated_at: timestamp(row["updated_at"])
|
|
99
|
+
}.freeze
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PromptObjects
|
|
4
|
+
module Repositories
|
|
5
|
+
class EventRepository < BaseRepository
|
|
6
|
+
def append_run_event(run_id:, kind:, data: {}, timestamp: Time.now.utc)
|
|
7
|
+
validate_kind!(kind)
|
|
8
|
+
transaction do |db|
|
|
9
|
+
run = db.get_first_row("SELECT * FROM runs WHERE id = ?", [run_id])
|
|
10
|
+
raise ArgumentError, "unknown run: #{run_id}" unless run
|
|
11
|
+
|
|
12
|
+
sequence = db.get_first_value(
|
|
13
|
+
"SELECT COALESCE(MAX(sequence), 0) + 1 FROM run_events WHERE run_id = ?",
|
|
14
|
+
[run_id]
|
|
15
|
+
)
|
|
16
|
+
occurred_at = timestamp.iso8601
|
|
17
|
+
workspace_cursor = append_workspace_event(
|
|
18
|
+
db,
|
|
19
|
+
workspace_session_id: run["workspace_session_id"],
|
|
20
|
+
event_type: "run_event",
|
|
21
|
+
entity_type: "run",
|
|
22
|
+
entity_id: run_id,
|
|
23
|
+
payload: { run_id: run_id, sequence: sequence, kind: kind.to_s, data: data },
|
|
24
|
+
created_at: occurred_at
|
|
25
|
+
)
|
|
26
|
+
params = [
|
|
27
|
+
run_id, sequence, workspace_cursor, run["workspace_session_id"],
|
|
28
|
+
run["thread_id"], kind.to_s, occurred_at, JSON.generate(data)
|
|
29
|
+
]
|
|
30
|
+
db.execute(<<~SQL, params)
|
|
31
|
+
INSERT INTO run_events (
|
|
32
|
+
run_id, sequence, workspace_cursor, workspace_session_id,
|
|
33
|
+
thread_id, kind, timestamp, data
|
|
34
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
35
|
+
SQL
|
|
36
|
+
parse_run_event(db.get_first_row("SELECT * FROM run_events WHERE id = last_insert_rowid()"))
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def run_events(run_id:, after_sequence: 0)
|
|
41
|
+
rows = read do |db|
|
|
42
|
+
db.execute(
|
|
43
|
+
"SELECT * FROM run_events WHERE run_id = ? AND sequence > ? ORDER BY sequence ASC",
|
|
44
|
+
[run_id, after_sequence]
|
|
45
|
+
)
|
|
46
|
+
end
|
|
47
|
+
rows.map { |row| parse_run_event(row) }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def workspace_events(workspace_session_id:, after_cursor: 0, limit: 500)
|
|
51
|
+
read do |db|
|
|
52
|
+
rows = db.execute(<<~SQL, [workspace_session_id, after_cursor, limit])
|
|
53
|
+
SELECT * FROM workspace_events
|
|
54
|
+
WHERE workspace_session_id = ? AND id > ?
|
|
55
|
+
ORDER BY id ASC
|
|
56
|
+
LIMIT ?
|
|
57
|
+
SQL
|
|
58
|
+
rows.map do |row|
|
|
59
|
+
{
|
|
60
|
+
cursor: row["id"], workspace_session_id: row["workspace_session_id"],
|
|
61
|
+
event_type: row["event_type"], entity_type: row["entity_type"],
|
|
62
|
+
entity_id: row["entity_id"], payload: json(row["payload"]),
|
|
63
|
+
created_at: timestamp(row["created_at"])
|
|
64
|
+
}.freeze
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def current_cursor(workspace_session_id:)
|
|
70
|
+
read do |db|
|
|
71
|
+
db.get_first_value(
|
|
72
|
+
"SELECT COALESCE(MAX(id), 0) FROM workspace_events WHERE workspace_session_id = ?",
|
|
73
|
+
[workspace_session_id]
|
|
74
|
+
)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
private
|
|
79
|
+
|
|
80
|
+
def validate_kind!(kind)
|
|
81
|
+
return if Execution::Contracts::RUN_EVENT_KINDS.include?(kind.to_s)
|
|
82
|
+
|
|
83
|
+
raise ArgumentError, "unknown run event kind: #{kind}"
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def append_workspace_event(db, workspace_session_id:, event_type:, entity_type:, entity_id:, payload:, created_at:)
|
|
87
|
+
db.execute(<<~SQL, [workspace_session_id, event_type, entity_type, entity_id, JSON.generate(payload), created_at])
|
|
88
|
+
INSERT INTO workspace_events (
|
|
89
|
+
workspace_session_id, event_type, entity_type, entity_id, payload, created_at
|
|
90
|
+
) VALUES (?, ?, ?, ?, ?, ?)
|
|
91
|
+
SQL
|
|
92
|
+
db.last_insert_row_id
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def parse_run_event(row)
|
|
96
|
+
Domain::RunEvent.new(
|
|
97
|
+
id: row["id"], run_id: row["run_id"], sequence: row["sequence"],
|
|
98
|
+
workspace_cursor: row["workspace_cursor"],
|
|
99
|
+
workspace_session_id: row["workspace_session_id"], thread_id: row["thread_id"],
|
|
100
|
+
kind: row["kind"], timestamp: timestamp(row["timestamp"]), data: json(row["data"])
|
|
101
|
+
)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PromptObjects
|
|
4
|
+
module Repositories
|
|
5
|
+
class MessageRepository < BaseRepository
|
|
6
|
+
def append(thread_id:, role:, content: nil, run_id: nil, turn_ordinal: nil,
|
|
7
|
+
position: nil, from_po: nil, tool_calls: nil, tool_results: nil,
|
|
8
|
+
usage: nil, message_uid: SecureRandom.uuid)
|
|
9
|
+
now = Time.now.utc.iso8601
|
|
10
|
+
transaction do |db|
|
|
11
|
+
position ||= next_position(db, thread_id, turn_ordinal)
|
|
12
|
+
params = [
|
|
13
|
+
thread_id, role.to_s, content, from_po, tool_calls && JSON.generate(tool_calls),
|
|
14
|
+
tool_results && JSON.generate(tool_results), usage && JSON.generate(usage), now,
|
|
15
|
+
message_uid, run_id, turn_ordinal, position
|
|
16
|
+
]
|
|
17
|
+
db.execute(<<~SQL, params)
|
|
18
|
+
INSERT INTO messages (
|
|
19
|
+
session_id, role, content, from_po, tool_calls, tool_results, usage,
|
|
20
|
+
created_at, message_uid, run_id, turn_ordinal, position
|
|
21
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
22
|
+
SQL
|
|
23
|
+
db.execute("UPDATE sessions SET updated_at = ?, last_activity_at = ? WHERE id = ?", [now, now, thread_id])
|
|
24
|
+
parse(db.get_first_row("SELECT * FROM messages WHERE id = last_insert_rowid()"))
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def list(thread_id:, through_turn: nil, after_id: 0, limit: 100)
|
|
29
|
+
rows = read do |db|
|
|
30
|
+
if through_turn
|
|
31
|
+
db.execute(<<~SQL, [thread_id, through_turn, after_id, limit])
|
|
32
|
+
SELECT * FROM messages
|
|
33
|
+
WHERE session_id = ? AND (turn_ordinal IS NULL OR turn_ordinal <= ?) AND id > ?
|
|
34
|
+
ORDER BY COALESCE(turn_ordinal, 0), COALESCE(position, id), id
|
|
35
|
+
LIMIT ?
|
|
36
|
+
SQL
|
|
37
|
+
else
|
|
38
|
+
db.execute(<<~SQL, [thread_id, after_id, limit])
|
|
39
|
+
SELECT * FROM messages
|
|
40
|
+
WHERE session_id = ? AND id > ?
|
|
41
|
+
ORDER BY COALESCE(turn_ordinal, 0), COALESCE(position, id), id
|
|
42
|
+
LIMIT ?
|
|
43
|
+
SQL
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
rows.map { |row| parse(row) }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def next_position(db, thread_id, turn_ordinal)
|
|
52
|
+
return nil unless turn_ordinal
|
|
53
|
+
|
|
54
|
+
db.get_first_value(
|
|
55
|
+
"SELECT COALESCE(MAX(position), -1) + 1 FROM messages WHERE session_id = ? AND turn_ordinal = ?",
|
|
56
|
+
[thread_id, turn_ordinal]
|
|
57
|
+
)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def parse(row)
|
|
61
|
+
{
|
|
62
|
+
id: row["id"], message_uid: row["message_uid"], thread_id: row["session_id"],
|
|
63
|
+
run_id: row["run_id"], turn_ordinal: row["turn_ordinal"], position: row["position"],
|
|
64
|
+
role: row["role"].to_sym, content: row["content"], from_po: row["from_po"],
|
|
65
|
+
tool_calls: row["tool_calls"] && JSON.parse(row["tool_calls"], symbolize_names: true),
|
|
66
|
+
tool_results: row["tool_results"] && JSON.parse(row["tool_results"], symbolize_names: true),
|
|
67
|
+
usage: row["usage"] && JSON.parse(row["usage"], symbolize_names: true),
|
|
68
|
+
created_at: timestamp(row["created_at"])
|
|
69
|
+
}.freeze
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|