protege 0.1.0.alpha.7 → 0.1.0.alpha.8
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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 435fd074ac0f41e0e1e5bf859d394ac23b6e3d46dae7e079ec0080650a54d505
|
|
4
|
+
data.tar.gz: b7cbd48b85e705c1da2d935dcbbb7ce167535e9485b657439d53587d231e790b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e9d4bf8c6d7c28383f4584cd28bba77e3ba940e470cac6dce21fbc6f171ce87db5b7cae2a62623c7074406d1d074af3d6e260e6ed4982decd63f6ae6792298e6
|
|
7
|
+
data.tar.gz: 686d8e8842a41b551a0d47509f48768f00d07b18edb96512453f9c5bd6a165d43779d28fed12c0f4dc27b659a58b4e6d0e5ca042e03199f3741b67d162e40981
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails/generators'
|
|
4
|
+
|
|
5
|
+
module Protege
|
|
6
|
+
# One-command development bootstrap — the service behind `bin/rails protege:setup:dev`. Provisions
|
|
7
|
+
# everything a fresh host app needs to start chatting locally, except the provider API key:
|
|
8
|
+
#
|
|
9
|
+
# * the system toolkits (via +SystemToolkits.sync!+, run first so Default Tools exists to auto-attach),
|
|
10
|
+
# * the +protege.local+ email domain (DKIM keypair minted on create),
|
|
11
|
+
# * the +ExecutiveAgent+ class itself when the host doesn't have one — generated through the same
|
|
12
|
+
# +protege:agent+ generator the installer uses, never guessed at or resolved from configuration,
|
|
13
|
+
# * **Phoenix**, an +ExecutiveAgent+ record at +phoenix@protege.local+ with starter instructions,
|
|
14
|
+
# * a proactive, open-gated All Tools grant, so every registered tool is exercisable in development.
|
|
15
|
+
#
|
|
16
|
+
# Idempotent throughout — records are found-or-created, so re-running never duplicates or clobbers.
|
|
17
|
+
# Environment gating (this seeds play data) is the rake task's concern, not this service's.
|
|
18
|
+
class DevSetup
|
|
19
|
+
# The development email domain. Registering it is what routes inbound mail; sharing a domain with the
|
|
20
|
+
# default +console_address+ (+console@protege.local+) is safe — console-local delivery is decided by
|
|
21
|
+
# address match, not domain registration.
|
|
22
|
+
DOMAIN = 'protege.local'
|
|
23
|
+
|
|
24
|
+
# The development agent's identity.
|
|
25
|
+
AGENT_NAME = 'Phoenix'
|
|
26
|
+
AGENT_EMAIL = "phoenix@#{DOMAIN}".freeze
|
|
27
|
+
|
|
28
|
+
# The starter system prompt — enough personality to be pleasant and enough direction to exercise
|
|
29
|
+
# tools, while staying generic (Phoenix knows nothing about any particular host app).
|
|
30
|
+
INSTRUCTIONS = <<~TEXT.strip
|
|
31
|
+
You are Phoenix, a general-purpose agent running in a development environment. You communicate by
|
|
32
|
+
email: read what you receive, use your tools whenever they help you act or answer accurately, and
|
|
33
|
+
reply with send_email. Keep replies short, concrete, and friendly. When asked to demonstrate a
|
|
34
|
+
capability, actually exercise the tool and report what happened.
|
|
35
|
+
TEXT
|
|
36
|
+
|
|
37
|
+
class << self
|
|
38
|
+
# Provision the full development setup.
|
|
39
|
+
#
|
|
40
|
+
# @return [Protege::Agent] the Phoenix agent record
|
|
41
|
+
def run!
|
|
42
|
+
new.run!
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Provision the full development setup.
|
|
47
|
+
#
|
|
48
|
+
# @return [Protege::Agent] the Phoenix agent record
|
|
49
|
+
def run!
|
|
50
|
+
SystemToolkits.sync!
|
|
51
|
+
ensure_domain
|
|
52
|
+
|
|
53
|
+
agent = ensure_phoenix
|
|
54
|
+
ensure_all_tools_grant(agent:)
|
|
55
|
+
|
|
56
|
+
agent
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
# Register the development email domain (a no-op when it already exists).
|
|
62
|
+
#
|
|
63
|
+
# @return [void]
|
|
64
|
+
def ensure_domain
|
|
65
|
+
EmailDomain.find_or_create_by!(domain: DOMAIN)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Find or create Phoenix. Creation auto-attaches the Default Tools toolkit (see +Toolable+), which
|
|
69
|
+
# is why the toolkit sync runs first.
|
|
70
|
+
#
|
|
71
|
+
# @return [Protege::Agent] the Phoenix record
|
|
72
|
+
def ensure_phoenix
|
|
73
|
+
agent_class.find_or_create_by!(name: AGENT_NAME) do |agent|
|
|
74
|
+
agent.email_address = AGENT_EMAIL
|
|
75
|
+
agent.instructions = INSTRUCTIONS
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# The host's +ExecutiveAgent+ class — generated on the spot when absent, through the same
|
|
80
|
+
# +protege:agent+ generator the installer invokes, then loaded so the constant is live in this
|
|
81
|
+
# process. Deterministic by design: no constant guessing, no environment-variable overrides.
|
|
82
|
+
#
|
|
83
|
+
# @return [Class] the ExecutiveAgent class
|
|
84
|
+
def agent_class
|
|
85
|
+
return ::ExecutiveAgent if defined?(::ExecutiveAgent)
|
|
86
|
+
|
|
87
|
+
generate_executive_agent
|
|
88
|
+
load Rails.root.join(Protege.configuration.agents_path, 'executive_agent.rb')
|
|
89
|
+
::ExecutiveAgent
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Scaffold +app/agents/executive_agent.rb+ into the host app.
|
|
93
|
+
#
|
|
94
|
+
# @return [void]
|
|
95
|
+
def generate_executive_agent
|
|
96
|
+
Rails::Generators.invoke('protege:agent', ['Executive'], destination_root: Rails.root.to_s)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Attach the All Tools system toolkit to the agent — open gate (no rules), proactive use enabled —
|
|
100
|
+
# so the whole catalogue, host tools included, is exercisable in development, reactively and on
|
|
101
|
+
# scheduled runs alike.
|
|
102
|
+
#
|
|
103
|
+
# @param agent [Protege::Agent] the agent to equip
|
|
104
|
+
# @return [void]
|
|
105
|
+
def ensure_all_tools_grant(agent:)
|
|
106
|
+
grant = AgentToolkit.find_or_initialize_by(agent:, toolkit: Toolkit.all_tools)
|
|
107
|
+
grant.update!(allow_proactive: true)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
@@ -8,8 +8,9 @@ module Protege
|
|
|
8
8
|
# each sync rewrites it to the live tool manifest, so a tool added in code shows up automatically and
|
|
9
9
|
# an operator's edits don't stick.
|
|
10
10
|
# * **Default Tools** (+default_tools+) — auto-attached to every new agent (see +Toolable+). The engine
|
|
11
|
-
# only *seeds* it
|
|
12
|
-
#
|
|
11
|
+
# only *seeds* it on first creation — with every engine built-in tool, so a fresh agent starts with
|
|
12
|
+
# the full generic baseline (reply, search, web, files) — and thereafter its membership is the
|
|
13
|
+
# operator's to curate, so later syncs leave it alone.
|
|
13
14
|
#
|
|
14
15
|
# Sync is idempotent and safe to run repeatedly. It runs like any other seed data — not at boot (writing
|
|
15
16
|
# to the DB from an initializer is an anti-pattern): the +protege:toolkits:sync+ rake task on deploy and
|
|
@@ -49,8 +50,10 @@ module Protege
|
|
|
49
50
|
toolkit.save!
|
|
50
51
|
end
|
|
51
52
|
|
|
52
|
-
# Ensure the Default Tools toolkit exists. On first creation it is seeded with
|
|
53
|
-
#
|
|
53
|
+
# Ensure the Default Tools toolkit exists. On first creation it is seeded with every engine built-in
|
|
54
|
+
# tool — the generic baseline (reply, search, web, files) that makes a new agent immediately useful,
|
|
55
|
+
# deliberately overlapping All Tools — while host-defined tools stay out of the seed (granting your
|
|
56
|
+
# own tools is an explicit act). On later syncs its membership is left untouched (operator-owned).
|
|
54
57
|
#
|
|
55
58
|
# @return [void]
|
|
56
59
|
def ensure_default_tools
|
|
@@ -60,8 +63,18 @@ module Protege
|
|
|
60
63
|
toolkit.name = 'Default Tools'
|
|
61
64
|
toolkit.description = 'Attached to every new agent automatically. Curate its members to set the ' \
|
|
62
65
|
'baseline tools an agent starts with.'
|
|
63
|
-
toolkit.member_tool_ids =
|
|
66
|
+
toolkit.member_tool_ids = engine_tool_ids
|
|
64
67
|
toolkit.save!
|
|
65
68
|
end
|
|
69
|
+
|
|
70
|
+
# The ids of the tools the engine itself ships — manifest entries whose class lives under the
|
|
71
|
+
# +Protege::+ namespace, distinguishing built-ins from host-defined tools.
|
|
72
|
+
#
|
|
73
|
+
# @return [Array<String>] the engine built-in tool ids
|
|
74
|
+
def engine_tool_ids
|
|
75
|
+
Manifest.registered(:tool)
|
|
76
|
+
.select { |entry| entry.klass.module_parent == Protege }
|
|
77
|
+
.map { |entry| entry.id.to_s }
|
|
78
|
+
end
|
|
66
79
|
end
|
|
67
80
|
end
|
|
@@ -114,6 +114,9 @@ module Protege
|
|
|
114
114
|
|
|
115
115
|
6. Create your first agent + email domain (dashboard, or a db/seeds.rb bootstrap) so
|
|
116
116
|
inbound mail has somewhere to route. Then boot and open /protege.
|
|
117
|
+
|
|
118
|
+
Or, for a ready-to-chat development setup in one command (covers steps 2 and 6):
|
|
119
|
+
bin/rails protege:setup:dev
|
|
117
120
|
STEPS
|
|
118
121
|
end
|
|
119
122
|
|
data/lib/protege/version.rb
CHANGED
|
@@ -13,6 +13,34 @@ namespace :protege do
|
|
|
13
13
|
end
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
namespace :setup do
|
|
17
|
+
desc 'Provision a ready-to-chat development environment: the protege.local domain, the Phoenix ' \
|
|
18
|
+
'agent (generating ExecutiveAgent if absent), and the system toolkits. Idempotent; dev only.'
|
|
19
|
+
task dev: :environment do
|
|
20
|
+
abort 'protege:setup:dev seeds development play data — refusing to run outside development.' unless
|
|
21
|
+
Rails.env.development?
|
|
22
|
+
|
|
23
|
+
# Rake tasks don't eager-load by default, so the tool manifest would be incomplete; force it so
|
|
24
|
+
# the toolkits capture every registered tool.
|
|
25
|
+
Rails.application.eager_load!
|
|
26
|
+
|
|
27
|
+
agent = Protege::DevSetup.run!
|
|
28
|
+
|
|
29
|
+
puts <<~DONE
|
|
30
|
+
Development environment ready.
|
|
31
|
+
|
|
32
|
+
Domain #{Protege::DevSetup::DOMAIN} (DKIM keypair minted; DNS only matters in production)
|
|
33
|
+
Agent #{agent.name} <#{agent.email_address}> — #{agent.class.name}
|
|
34
|
+
Toolkits Default Tools (auto-attached, all engine built-ins) + All Tools (open gate, proactive)
|
|
35
|
+
|
|
36
|
+
To start chatting:
|
|
37
|
+
1. export OPENROUTER_API_KEY=sk-... (the one thing this task can't do for you)
|
|
38
|
+
2. bin/dev
|
|
39
|
+
3. open http://localhost:3000/protege — Inbox -> Compose -> #{agent.name}
|
|
40
|
+
DONE
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
16
44
|
namespace :css do
|
|
17
45
|
desc "Build the Protege engine's compiled Tailwind CSS. " \
|
|
18
46
|
'Run this after changing engine views. Requires tailwindcss-rails in the host app.'
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: protege
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.0.alpha.
|
|
4
|
+
version: 0.1.0.alpha.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sebastian Scholl
|
|
@@ -205,7 +205,7 @@ dependencies:
|
|
|
205
205
|
- - "~>"
|
|
206
206
|
- !ruby/object:Gem::Version
|
|
207
207
|
version: '3.0'
|
|
208
|
-
description: 'Protege gives your Rails app AI
|
|
208
|
+
description: 'Protege gives your Rails app AI agents: inbound mail via Action Mailbox,
|
|
209
209
|
replies over SMTP, tools that act on your own models, cron-scheduled responsibilities
|
|
210
210
|
dispatched through Active Job, and a built-in dashboard to manage and observe it
|
|
211
211
|
all — in process, no separate service.'
|
|
@@ -308,6 +308,7 @@ files:
|
|
|
308
308
|
- app/resolvers/protege/load_record_resolver.rb
|
|
309
309
|
- app/resolvers/protege/load_text_resolver.rb
|
|
310
310
|
- app/resolvers/protege/thread_history_resolver.rb
|
|
311
|
+
- app/services/protege/dev_setup.rb
|
|
311
312
|
- app/services/protege/introspection_tool_call_presentation.rb
|
|
312
313
|
- app/services/protege/message_search.rb
|
|
313
314
|
- app/services/protege/system_toolkits.rb
|