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: d413f57504bbdb848d33fd0afd7fdc616a409de2b5d3107c38a2d169bd1e1c6f
4
- data.tar.gz: a80f880c36d5b1add111ca5176abfb27416fcb18ae63d2bf4504fd97d61e0912
3
+ metadata.gz: 435fd074ac0f41e0e1e5bf859d394ac23b6e3d46dae7e079ec0080650a54d505
4
+ data.tar.gz: b7cbd48b85e705c1da2d935dcbbb7ce167535e9485b657439d53587d231e790b
5
5
  SHA512:
6
- metadata.gz: 0f9ebf231169742d602abad8f806793599636a6e15ec196d19672128e9ac123fb9db72ba4738e33cc86fd1bcf546dfb9f69ae0aebc9f935400a4a24347b584a0
7
- data.tar.gz: 211573228c71e00cd37ea479419fe13cf7260bcc303443ed3720a7c991f9c2634e6fb1628958c3cb23f9e77121055e2d81a479a44d33eebf3ff7444964a6ff65
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 (with +send_email+, so a fresh agent can at least reply) on first creation;
12
- # thereafter its membership is the operator's to curate, so later syncs leave it alone.
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 +send_email+ so a new
53
- # agent is immediately able to reply; on later syncs its membership is left untouched (operator-owned).
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 = ['send_email']
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
 
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Protege
4
4
  # Current gem version, following Semantic Versioning.
5
- VERSION = '0.1.0.alpha.7'
5
+ VERSION = '0.1.0.alpha.8'
6
6
  end
@@ -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.7
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 teammates: inbound mail via Action Mailbox,
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