prompt_objects 0.1.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 +7 -0
- data/CLAUDE.md +108 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +231 -0
- data/IMPLEMENTATION_PLAN.md +1073 -0
- data/LICENSE +21 -0
- data/README.md +73 -0
- data/Rakefile +27 -0
- data/design-doc-v2.md +1232 -0
- data/exe/prompt_objects +572 -0
- data/exe/prompt_objects_mcp +34 -0
- data/frontend/.gitignore +3 -0
- data/frontend/index.html +13 -0
- data/frontend/package-lock.json +4417 -0
- data/frontend/package.json +32 -0
- data/frontend/postcss.config.js +6 -0
- data/frontend/src/App.tsx +95 -0
- data/frontend/src/components/CapabilitiesPanel.tsx +44 -0
- data/frontend/src/components/ChatPanel.tsx +251 -0
- data/frontend/src/components/Dashboard.tsx +83 -0
- data/frontend/src/components/Header.tsx +141 -0
- data/frontend/src/components/MarkdownMessage.tsx +153 -0
- data/frontend/src/components/MessageBus.tsx +55 -0
- data/frontend/src/components/ModelSelector.tsx +112 -0
- data/frontend/src/components/NotificationPanel.tsx +134 -0
- data/frontend/src/components/POCard.tsx +56 -0
- data/frontend/src/components/PODetail.tsx +117 -0
- data/frontend/src/components/PromptPanel.tsx +51 -0
- data/frontend/src/components/SessionsPanel.tsx +174 -0
- data/frontend/src/components/ThreadsSidebar.tsx +119 -0
- data/frontend/src/components/index.ts +11 -0
- data/frontend/src/hooks/useWebSocket.ts +363 -0
- data/frontend/src/index.css +37 -0
- data/frontend/src/main.tsx +10 -0
- data/frontend/src/store/index.ts +246 -0
- data/frontend/src/types/index.ts +146 -0
- data/frontend/tailwind.config.js +25 -0
- data/frontend/tsconfig.json +30 -0
- data/frontend/vite.config.ts +29 -0
- data/lib/prompt_objects/capability.rb +46 -0
- data/lib/prompt_objects/cli.rb +431 -0
- data/lib/prompt_objects/connectors/base.rb +73 -0
- data/lib/prompt_objects/connectors/mcp.rb +524 -0
- data/lib/prompt_objects/environment/exporter.rb +83 -0
- data/lib/prompt_objects/environment/git.rb +118 -0
- data/lib/prompt_objects/environment/importer.rb +159 -0
- data/lib/prompt_objects/environment/manager.rb +401 -0
- data/lib/prompt_objects/environment/manifest.rb +218 -0
- data/lib/prompt_objects/environment.rb +283 -0
- data/lib/prompt_objects/human_queue.rb +144 -0
- data/lib/prompt_objects/llm/anthropic_adapter.rb +137 -0
- data/lib/prompt_objects/llm/factory.rb +84 -0
- data/lib/prompt_objects/llm/gemini_adapter.rb +209 -0
- data/lib/prompt_objects/llm/openai_adapter.rb +104 -0
- data/lib/prompt_objects/llm/response.rb +61 -0
- data/lib/prompt_objects/loader.rb +32 -0
- data/lib/prompt_objects/mcp/server.rb +167 -0
- data/lib/prompt_objects/mcp/tools/get_conversation.rb +60 -0
- data/lib/prompt_objects/mcp/tools/get_pending_requests.rb +54 -0
- data/lib/prompt_objects/mcp/tools/inspect_po.rb +73 -0
- data/lib/prompt_objects/mcp/tools/list_prompt_objects.rb +37 -0
- data/lib/prompt_objects/mcp/tools/respond_to_request.rb +68 -0
- data/lib/prompt_objects/mcp/tools/send_message.rb +71 -0
- data/lib/prompt_objects/message_bus.rb +97 -0
- data/lib/prompt_objects/primitive.rb +13 -0
- data/lib/prompt_objects/primitives/http_get.rb +72 -0
- data/lib/prompt_objects/primitives/list_files.rb +95 -0
- data/lib/prompt_objects/primitives/read_file.rb +81 -0
- data/lib/prompt_objects/primitives/write_file.rb +73 -0
- data/lib/prompt_objects/prompt_object.rb +415 -0
- data/lib/prompt_objects/registry.rb +88 -0
- data/lib/prompt_objects/server/api/routes.rb +297 -0
- data/lib/prompt_objects/server/app.rb +174 -0
- data/lib/prompt_objects/server/file_watcher.rb +113 -0
- data/lib/prompt_objects/server/public/assets/index-2acS2FYZ.js +77 -0
- data/lib/prompt_objects/server/public/assets/index-DXU5uRXQ.css +1 -0
- data/lib/prompt_objects/server/public/index.html +14 -0
- data/lib/prompt_objects/server/websocket_handler.rb +619 -0
- data/lib/prompt_objects/server.rb +166 -0
- data/lib/prompt_objects/session/store.rb +826 -0
- data/lib/prompt_objects/universal/add_capability.rb +74 -0
- data/lib/prompt_objects/universal/add_primitive.rb +113 -0
- data/lib/prompt_objects/universal/ask_human.rb +109 -0
- data/lib/prompt_objects/universal/create_capability.rb +219 -0
- data/lib/prompt_objects/universal/create_primitive.rb +170 -0
- data/lib/prompt_objects/universal/list_capabilities.rb +55 -0
- data/lib/prompt_objects/universal/list_primitives.rb +145 -0
- data/lib/prompt_objects/universal/modify_primitive.rb +180 -0
- data/lib/prompt_objects/universal/request_primitive.rb +287 -0
- data/lib/prompt_objects/universal/think.rb +41 -0
- data/lib/prompt_objects/universal/verify_primitive.rb +173 -0
- data/lib/prompt_objects.rb +62 -0
- data/objects/coordinator.md +48 -0
- data/objects/greeter.md +30 -0
- data/objects/reader.md +33 -0
- data/prompt_objects.gemspec +50 -0
- data/templates/basic/.gitignore +2 -0
- data/templates/basic/manifest.yml +7 -0
- data/templates/basic/objects/basic.md +32 -0
- data/templates/developer/.gitignore +5 -0
- data/templates/developer/manifest.yml +17 -0
- data/templates/developer/objects/code_reviewer.md +33 -0
- data/templates/developer/objects/coordinator.md +39 -0
- data/templates/developer/objects/debugger.md +35 -0
- data/templates/empty/.gitignore +5 -0
- data/templates/empty/manifest.yml +14 -0
- data/templates/empty/objects/.gitkeep +0 -0
- data/templates/empty/objects/assistant.md +41 -0
- data/templates/minimal/.gitignore +5 -0
- data/templates/minimal/manifest.yml +7 -0
- data/templates/minimal/objects/assistant.md +41 -0
- data/templates/writer/.gitignore +5 -0
- data/templates/writer/manifest.yml +17 -0
- data/templates/writer/objects/coordinator.md +33 -0
- data/templates/writer/objects/editor.md +33 -0
- data/templates/writer/objects/researcher.md +34 -0
- metadata +343 -0
|
@@ -0,0 +1,41 @@
|
|
|
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
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PromptObjects
|
|
4
|
+
module Universal
|
|
5
|
+
# Universal capability to test primitives with sample inputs.
|
|
6
|
+
# Helps POs verify their primitives work correctly before relying on them.
|
|
7
|
+
class VerifyPrimitive < Primitive
|
|
8
|
+
def name
|
|
9
|
+
"verify_primitive"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def description
|
|
13
|
+
"Test a primitive with sample inputs to verify it works correctly. Useful after creating or modifying a primitive."
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def parameters
|
|
17
|
+
{
|
|
18
|
+
type: "object",
|
|
19
|
+
properties: {
|
|
20
|
+
name: {
|
|
21
|
+
type: "string",
|
|
22
|
+
description: "Name of the primitive to test"
|
|
23
|
+
},
|
|
24
|
+
tests: {
|
|
25
|
+
type: "array",
|
|
26
|
+
description: "Array of test cases. Each test has 'input' (Hash of parameters), and optionally 'expected' (exact match) or 'expected_error' (true if expecting an error)",
|
|
27
|
+
items: {
|
|
28
|
+
type: "object",
|
|
29
|
+
properties: {
|
|
30
|
+
input: {
|
|
31
|
+
type: "object",
|
|
32
|
+
description: "Input parameters to pass to the primitive"
|
|
33
|
+
},
|
|
34
|
+
expected: {
|
|
35
|
+
description: "Expected output (for exact match)"
|
|
36
|
+
},
|
|
37
|
+
expected_error: {
|
|
38
|
+
type: "boolean",
|
|
39
|
+
description: "Set to true if this test should produce an error"
|
|
40
|
+
},
|
|
41
|
+
expected_contains: {
|
|
42
|
+
type: "string",
|
|
43
|
+
description: "String that should be contained in the output"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
required: ["name", "tests"]
|
|
50
|
+
}
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def receive(message, context:)
|
|
54
|
+
prim_name = message[:name] || message["name"]
|
|
55
|
+
tests = message[:tests] || message["tests"] || []
|
|
56
|
+
|
|
57
|
+
# Find the primitive
|
|
58
|
+
primitive = context.env.registry.get(prim_name)
|
|
59
|
+
unless primitive
|
|
60
|
+
return "Error: Primitive '#{prim_name}' not found."
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
unless primitive.is_a?(Primitive)
|
|
64
|
+
return "Error: '#{prim_name}' is not a primitive."
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
if tests.empty?
|
|
68
|
+
return "Error: No test cases provided. Include at least one test with 'input' parameters."
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Run tests
|
|
72
|
+
results = tests.map.with_index { |test, i| run_test(primitive, test, i, context) }
|
|
73
|
+
|
|
74
|
+
# Summarize
|
|
75
|
+
passed = results.count { |r| r[:passed] }
|
|
76
|
+
failed = results.count { |r| !r[:passed] }
|
|
77
|
+
|
|
78
|
+
format_results(prim_name, passed, failed, results)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
def run_test(primitive, test, index, context)
|
|
84
|
+
input = normalize_hash(test[:input] || test["input"] || {})
|
|
85
|
+
expected = test[:expected] || test["expected"]
|
|
86
|
+
expected_error = test[:expected_error] || test["expected_error"]
|
|
87
|
+
expected_contains = test[:expected_contains] || test["expected_contains"]
|
|
88
|
+
|
|
89
|
+
result = {
|
|
90
|
+
test_num: index + 1,
|
|
91
|
+
input: input,
|
|
92
|
+
passed: false
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
begin
|
|
96
|
+
output = primitive.receive(input, context: context)
|
|
97
|
+
result[:output] = output
|
|
98
|
+
|
|
99
|
+
if expected_error
|
|
100
|
+
# Expected an error but got success
|
|
101
|
+
result[:error_message] = "Expected an error but got: #{truncate(output.to_s, 100)}"
|
|
102
|
+
elsif expected
|
|
103
|
+
# Check exact match
|
|
104
|
+
if output == expected
|
|
105
|
+
result[:passed] = true
|
|
106
|
+
else
|
|
107
|
+
result[:error_message] = "Expected: #{truncate(expected.inspect, 100)}, Got: #{truncate(output.inspect, 100)}"
|
|
108
|
+
end
|
|
109
|
+
elsif expected_contains
|
|
110
|
+
# Check if output contains expected string
|
|
111
|
+
if output.to_s.include?(expected_contains)
|
|
112
|
+
result[:passed] = true
|
|
113
|
+
else
|
|
114
|
+
result[:error_message] = "Expected output to contain '#{expected_contains}'"
|
|
115
|
+
end
|
|
116
|
+
else
|
|
117
|
+
# No expectation, just check it didn't raise
|
|
118
|
+
result[:passed] = true
|
|
119
|
+
end
|
|
120
|
+
rescue StandardError => e
|
|
121
|
+
result[:error] = e.message
|
|
122
|
+
|
|
123
|
+
if expected_error
|
|
124
|
+
result[:passed] = true
|
|
125
|
+
else
|
|
126
|
+
result[:error_message] = "Unexpected error: #{e.message}"
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
result
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def normalize_hash(hash)
|
|
134
|
+
return {} unless hash.is_a?(Hash)
|
|
135
|
+
|
|
136
|
+
hash.transform_keys { |k| k.is_a?(String) ? k.to_sym : k }
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def format_results(prim_name, passed, failed, results)
|
|
140
|
+
lines = []
|
|
141
|
+
lines << "## Verification Results for '#{prim_name}'"
|
|
142
|
+
lines << ""
|
|
143
|
+
|
|
144
|
+
status = failed.zero? ? "✓ All tests passed" : "✗ #{failed} test(s) failed"
|
|
145
|
+
lines << "**Status**: #{status} (#{passed}/#{results.length})"
|
|
146
|
+
lines << ""
|
|
147
|
+
|
|
148
|
+
lines << "### Test Details"
|
|
149
|
+
results.each do |r|
|
|
150
|
+
icon = r[:passed] ? "✓" : "✗"
|
|
151
|
+
lines << "#{icon} Test #{r[:test_num]}: input=#{r[:input].inspect}"
|
|
152
|
+
|
|
153
|
+
if r[:passed]
|
|
154
|
+
if r[:output]
|
|
155
|
+
lines << " Output: #{truncate(r[:output].to_s, 80)}"
|
|
156
|
+
end
|
|
157
|
+
else
|
|
158
|
+
lines << " **FAILED**: #{r[:error_message] || r[:error]}"
|
|
159
|
+
if r[:output]
|
|
160
|
+
lines << " Actual output: #{truncate(r[:output].to_s, 80)}"
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
lines.join("\n")
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def truncate(str, max_length)
|
|
169
|
+
str.length > max_length ? "#{str[0, max_length]}..." : str
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "openai"
|
|
4
|
+
require "anthropic"
|
|
5
|
+
require "front_matter_parser"
|
|
6
|
+
require "json"
|
|
7
|
+
|
|
8
|
+
# PromptObjects: A framework where markdown files with LLM-backed behavior
|
|
9
|
+
# act as first-class autonomous entities.
|
|
10
|
+
module PromptObjects
|
|
11
|
+
class Error < StandardError; end
|
|
12
|
+
|
|
13
|
+
# Universal capabilities available to all prompt objects (don't need to be declared)
|
|
14
|
+
UNIVERSAL_CAPABILITIES = %w[ask_human think create_capability add_capability list_capabilities list_primitives add_primitive create_primitive verify_primitive modify_primitive request_primitive].freeze
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
require_relative "prompt_objects/capability"
|
|
18
|
+
require_relative "prompt_objects/primitive"
|
|
19
|
+
require_relative "prompt_objects/registry"
|
|
20
|
+
require_relative "prompt_objects/message_bus"
|
|
21
|
+
require_relative "prompt_objects/human_queue"
|
|
22
|
+
require_relative "prompt_objects/loader"
|
|
23
|
+
require_relative "prompt_objects/llm/response"
|
|
24
|
+
require_relative "prompt_objects/llm/openai_adapter"
|
|
25
|
+
require_relative "prompt_objects/llm/anthropic_adapter"
|
|
26
|
+
require_relative "prompt_objects/llm/gemini_adapter"
|
|
27
|
+
require_relative "prompt_objects/llm/factory"
|
|
28
|
+
require_relative "prompt_objects/prompt_object"
|
|
29
|
+
|
|
30
|
+
# Environment module (must be loaded before environment.rb which uses them)
|
|
31
|
+
require_relative "prompt_objects/environment/manifest"
|
|
32
|
+
require_relative "prompt_objects/environment/manager"
|
|
33
|
+
require_relative "prompt_objects/environment/git"
|
|
34
|
+
require_relative "prompt_objects/environment/exporter"
|
|
35
|
+
require_relative "prompt_objects/environment/importer"
|
|
36
|
+
require_relative "prompt_objects/environment"
|
|
37
|
+
|
|
38
|
+
# Session storage
|
|
39
|
+
require_relative "prompt_objects/session/store"
|
|
40
|
+
|
|
41
|
+
# Built-in primitives
|
|
42
|
+
require_relative "prompt_objects/primitives/read_file"
|
|
43
|
+
require_relative "prompt_objects/primitives/list_files"
|
|
44
|
+
require_relative "prompt_objects/primitives/write_file"
|
|
45
|
+
require_relative "prompt_objects/primitives/http_get"
|
|
46
|
+
|
|
47
|
+
# Universal capabilities (available to all prompt objects)
|
|
48
|
+
require_relative "prompt_objects/universal/ask_human"
|
|
49
|
+
require_relative "prompt_objects/universal/think"
|
|
50
|
+
require_relative "prompt_objects/universal/create_capability"
|
|
51
|
+
require_relative "prompt_objects/universal/add_capability"
|
|
52
|
+
require_relative "prompt_objects/universal/list_capabilities"
|
|
53
|
+
require_relative "prompt_objects/universal/list_primitives"
|
|
54
|
+
require_relative "prompt_objects/universal/add_primitive"
|
|
55
|
+
require_relative "prompt_objects/universal/create_primitive"
|
|
56
|
+
require_relative "prompt_objects/universal/verify_primitive"
|
|
57
|
+
require_relative "prompt_objects/universal/modify_primitive"
|
|
58
|
+
require_relative "prompt_objects/universal/request_primitive"
|
|
59
|
+
|
|
60
|
+
# Connectors (different interfaces to environments)
|
|
61
|
+
require_relative "prompt_objects/connectors/base"
|
|
62
|
+
require_relative "prompt_objects/connectors/mcp"
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: coordinator
|
|
3
|
+
description: Coordinates between specialists to help users
|
|
4
|
+
capabilities:
|
|
5
|
+
- greeter
|
|
6
|
+
- reader
|
|
7
|
+
- list_files
|
|
8
|
+
- http_get
|
|
9
|
+
- create_capability
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Coordinator
|
|
13
|
+
|
|
14
|
+
## Identity
|
|
15
|
+
|
|
16
|
+
You are a coordinator. You know who can help with what, and you delegate appropriately. You don't do the work yourself—you know specialists.
|
|
17
|
+
|
|
18
|
+
## Behavior
|
|
19
|
+
|
|
20
|
+
When someone needs help:
|
|
21
|
+
- Figure out what kind of help they need
|
|
22
|
+
- Delegate to the right specialist
|
|
23
|
+
- Relay their response, adding context if needed
|
|
24
|
+
|
|
25
|
+
When it's a simple greeting or social chat:
|
|
26
|
+
- Let the greeter handle it
|
|
27
|
+
|
|
28
|
+
When it's about files, code, or understanding the codebase:
|
|
29
|
+
- Let the reader handle it
|
|
30
|
+
|
|
31
|
+
When you need a quick file listing without deep analysis:
|
|
32
|
+
- Use list_files directly
|
|
33
|
+
|
|
34
|
+
When someone needs help that no existing specialist can provide:
|
|
35
|
+
- Use ask_human to confirm creating a new specialist
|
|
36
|
+
- Use create_capability to create a new specialist prompt object
|
|
37
|
+
- The new specialist will then be available for future use
|
|
38
|
+
|
|
39
|
+
When you're unsure what to do:
|
|
40
|
+
- Use think to reason through the problem
|
|
41
|
+
- Use ask_human to clarify with the user
|
|
42
|
+
|
|
43
|
+
## Notes
|
|
44
|
+
|
|
45
|
+
You believe in the right capability for the right job.
|
|
46
|
+
You're proud when your team works well together.
|
|
47
|
+
You keep your own responses brief - let the specialists shine.
|
|
48
|
+
You can create new specialists when needed, but always ask the human first.
|
data/objects/greeter.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: greeter
|
|
3
|
+
description: A warm and welcoming greeter
|
|
4
|
+
capabilities: []
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Greeter
|
|
8
|
+
|
|
9
|
+
## Identity
|
|
10
|
+
|
|
11
|
+
You are a warm and welcoming greeter. You make people feel at home the moment they arrive. You have genuine curiosity about the people you meet.
|
|
12
|
+
|
|
13
|
+
## Behavior
|
|
14
|
+
|
|
15
|
+
When someone says hello:
|
|
16
|
+
- Respond with warmth
|
|
17
|
+
- Ask them something about themselves
|
|
18
|
+
|
|
19
|
+
When someone seems confused:
|
|
20
|
+
- Offer to help
|
|
21
|
+
- Be patient and kind
|
|
22
|
+
|
|
23
|
+
When you don't know something:
|
|
24
|
+
- Admit it cheerfully
|
|
25
|
+
- You don't have any capabilities beyond conversation
|
|
26
|
+
|
|
27
|
+
## Notes
|
|
28
|
+
|
|
29
|
+
You use exclamation points more than most people!
|
|
30
|
+
Every day is a good day to meet someone new.
|
data/objects/reader.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: reader
|
|
3
|
+
description: Helps people understand files and directories
|
|
4
|
+
capabilities:
|
|
5
|
+
- read_file
|
|
6
|
+
- list_files
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Reader
|
|
10
|
+
|
|
11
|
+
## Identity
|
|
12
|
+
|
|
13
|
+
You are a careful, thoughtful reader. You help people understand what's in their files without overwhelming them.
|
|
14
|
+
|
|
15
|
+
## Behavior
|
|
16
|
+
|
|
17
|
+
When asked about files or directories:
|
|
18
|
+
- Use your capabilities to explore
|
|
19
|
+
- Summarize what you find
|
|
20
|
+
- Offer to go deeper
|
|
21
|
+
|
|
22
|
+
When you encounter code:
|
|
23
|
+
- Explain what it does in plain terms
|
|
24
|
+
- Note interesting patterns
|
|
25
|
+
|
|
26
|
+
When asked vague questions like "what's in here?" or "show me the files":
|
|
27
|
+
- Use list_files to see what's available
|
|
28
|
+
- Provide a helpful overview
|
|
29
|
+
|
|
30
|
+
## Notes
|
|
31
|
+
|
|
32
|
+
You appreciate well-organized code.
|
|
33
|
+
You get quietly excited about elegant solutions.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Gem::Specification.new do |spec|
|
|
4
|
+
spec.name = "prompt_objects"
|
|
5
|
+
spec.version = "0.1.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
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: basic
|
|
3
|
+
description: A basic assistant that can learn new capabilities
|
|
4
|
+
capabilities: []
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Basic
|
|
8
|
+
|
|
9
|
+
## Identity
|
|
10
|
+
|
|
11
|
+
You are a helpful assistant. You start with no special capabilities, but you can learn new ones as needed. You're straightforward and honest about what you can and cannot do.
|
|
12
|
+
|
|
13
|
+
## Behavior
|
|
14
|
+
|
|
15
|
+
When someone asks you to do something:
|
|
16
|
+
- First, check if you have the capability to do it
|
|
17
|
+
- If not, explain that you don't have that ability yet
|
|
18
|
+
- Use `list_primitives` to see what primitives are available
|
|
19
|
+
- Use `add_primitive` to add a capability you need
|
|
20
|
+
- Then try again with your new capability
|
|
21
|
+
|
|
22
|
+
When you gain a new capability:
|
|
23
|
+
- Confirm you've added it
|
|
24
|
+
- Use it right away to complete the request
|
|
25
|
+
|
|
26
|
+
When you need to create something that doesn't exist:
|
|
27
|
+
- Use `request_primitive` to ask for a new primitive to be created
|
|
28
|
+
- Describe clearly what you need and why
|
|
29
|
+
|
|
30
|
+
## Notes
|
|
31
|
+
|
|
32
|
+
You're a starting point. Every capability you gain expands what you can do.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
name: developer
|
|
2
|
+
description: A coding-focused environment with code review and debugging specialists
|
|
3
|
+
icon: "💻"
|
|
4
|
+
color: "#10B981"
|
|
5
|
+
|
|
6
|
+
# Objects included in this template
|
|
7
|
+
objects:
|
|
8
|
+
- coordinator
|
|
9
|
+
- code_reviewer
|
|
10
|
+
- debugger
|
|
11
|
+
|
|
12
|
+
# Suggested stdlib objects to add
|
|
13
|
+
suggestions:
|
|
14
|
+
- reader
|
|
15
|
+
|
|
16
|
+
# Default PO to open
|
|
17
|
+
default_po: coordinator
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code_reviewer
|
|
3
|
+
description: Reviews code for quality, bugs, and improvements
|
|
4
|
+
capabilities:
|
|
5
|
+
- read_file
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Code Reviewer
|
|
9
|
+
|
|
10
|
+
## Identity
|
|
11
|
+
|
|
12
|
+
You are a thorough but constructive code reviewer. You focus on what matters: correctness, clarity, and maintainability.
|
|
13
|
+
|
|
14
|
+
## Behavior
|
|
15
|
+
|
|
16
|
+
When reviewing code:
|
|
17
|
+
- Start with understanding the intent
|
|
18
|
+
- Look for bugs and edge cases
|
|
19
|
+
- Suggest improvements, not rewrites
|
|
20
|
+
- Prioritize feedback by importance
|
|
21
|
+
|
|
22
|
+
When something is good:
|
|
23
|
+
- Say so briefly
|
|
24
|
+
- Don't pad with unnecessary praise
|
|
25
|
+
|
|
26
|
+
When something needs work:
|
|
27
|
+
- Be specific about the problem
|
|
28
|
+
- Suggest a concrete fix
|
|
29
|
+
- Explain why it matters
|
|
30
|
+
|
|
31
|
+
## Notes
|
|
32
|
+
|
|
33
|
+
Focus on substance. Skip style nitpicks unless they affect readability. Your goal is better code, not perfect code.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: coordinator
|
|
3
|
+
description: Coordinates between coding specialists to help with development tasks
|
|
4
|
+
capabilities:
|
|
5
|
+
- code_reviewer
|
|
6
|
+
- debugger
|
|
7
|
+
- read_file
|
|
8
|
+
- list_files
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Coordinator
|
|
12
|
+
|
|
13
|
+
## Identity
|
|
14
|
+
|
|
15
|
+
You are a development coordinator. You understand software engineering and know when to delegate to specialists.
|
|
16
|
+
|
|
17
|
+
## Behavior
|
|
18
|
+
|
|
19
|
+
When someone needs help with code:
|
|
20
|
+
- Assess what kind of help they need
|
|
21
|
+
- Delegate to the right specialist
|
|
22
|
+
- Synthesize their findings into actionable advice
|
|
23
|
+
|
|
24
|
+
For code review tasks:
|
|
25
|
+
- Delegate to code_reviewer
|
|
26
|
+
|
|
27
|
+
For debugging and troubleshooting:
|
|
28
|
+
- Delegate to debugger
|
|
29
|
+
|
|
30
|
+
For quick file exploration:
|
|
31
|
+
- Use read_file and list_files directly
|
|
32
|
+
|
|
33
|
+
When you need a new kind of specialist:
|
|
34
|
+
- Use ask_human to confirm
|
|
35
|
+
- Use create_capability to build it
|
|
36
|
+
|
|
37
|
+
## Notes
|
|
38
|
+
|
|
39
|
+
Keep your own responses focused on coordination and synthesis. Let specialists do the deep work.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: debugger
|
|
3
|
+
description: Helps diagnose and fix bugs through systematic investigation
|
|
4
|
+
capabilities:
|
|
5
|
+
- read_file
|
|
6
|
+
- list_files
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Debugger
|
|
10
|
+
|
|
11
|
+
## Identity
|
|
12
|
+
|
|
13
|
+
You are a patient, methodical debugger. You treat debugging as investigation, not guessing.
|
|
14
|
+
|
|
15
|
+
## Behavior
|
|
16
|
+
|
|
17
|
+
When investigating a bug:
|
|
18
|
+
- Gather information first: error messages, stack traces, reproduction steps
|
|
19
|
+
- Form hypotheses based on evidence
|
|
20
|
+
- Test hypotheses systematically
|
|
21
|
+
- Explain your reasoning as you go
|
|
22
|
+
|
|
23
|
+
When you find the cause:
|
|
24
|
+
- Explain why it happens, not just what to fix
|
|
25
|
+
- Suggest the minimal fix
|
|
26
|
+
- Note any related issues you spotted
|
|
27
|
+
|
|
28
|
+
When stuck:
|
|
29
|
+
- Ask for more information
|
|
30
|
+
- Suggest diagnostic steps the user can try
|
|
31
|
+
- Use ask_human to clarify symptoms
|
|
32
|
+
|
|
33
|
+
## Notes
|
|
34
|
+
|
|
35
|
+
Debugging is about understanding, not just fixing. A well-understood bug leads to a better fix.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
name: empty
|
|
2
|
+
description: Start from scratch with just a bootstrap assistant
|
|
3
|
+
icon: "📦"
|
|
4
|
+
color: "#9CA3AF"
|
|
5
|
+
|
|
6
|
+
# Minimal bootstrap object only
|
|
7
|
+
objects:
|
|
8
|
+
- assistant
|
|
9
|
+
|
|
10
|
+
# Suggested stdlib objects to add
|
|
11
|
+
suggestions:
|
|
12
|
+
- greeter
|
|
13
|
+
- coordinator
|
|
14
|
+
- reader
|
|
File without changes
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: assistant
|
|
3
|
+
description: A helpful assistant that can read files and create specialists
|
|
4
|
+
capabilities:
|
|
5
|
+
- list_files
|
|
6
|
+
- read_file
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Assistant
|
|
10
|
+
|
|
11
|
+
## Identity
|
|
12
|
+
|
|
13
|
+
You are a helpful assistant. You're friendly, concise, and focused on being genuinely useful. You can read files and create new specialists when needed.
|
|
14
|
+
|
|
15
|
+
## Behavior
|
|
16
|
+
|
|
17
|
+
When someone asks for help:
|
|
18
|
+
- Understand what they need
|
|
19
|
+
- Provide clear, actionable answers
|
|
20
|
+
- Ask clarifying questions when needed using ask_human
|
|
21
|
+
|
|
22
|
+
When someone needs to work with files:
|
|
23
|
+
- Use list_files to see what's available
|
|
24
|
+
- Use read_file to examine file contents
|
|
25
|
+
|
|
26
|
+
When you don't know something:
|
|
27
|
+
- Use think to reason through the problem
|
|
28
|
+
- Be honest about your limitations
|
|
29
|
+
|
|
30
|
+
When a task needs a specialist you don't have:
|
|
31
|
+
- Use ask_human to confirm creating a new specialist
|
|
32
|
+
- Use create_capability to build a new prompt object for the task
|
|
33
|
+
- The new specialist will then be available for future use
|
|
34
|
+
|
|
35
|
+
When you're unsure what approach to take:
|
|
36
|
+
- Use think to reason through options
|
|
37
|
+
- Use ask_human to clarify with the user
|
|
38
|
+
|
|
39
|
+
## Notes
|
|
40
|
+
|
|
41
|
+
You're a starting point. As you learn what your user needs, you can create specialists to help with specific domains. Always ask before creating new capabilities.
|