silas 0.3.0 → 0.3.1
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 +22 -0
- data/app/views/silas/inbox/invocations/_invocation.html.erb +2 -2
- data/lib/generators/silas/install/templates/ruby_llm.rb +6 -0
- data/lib/silas/ledger.rb +8 -1
- data/lib/silas/version.rb +1 -1
- data/lib/silas.rb +8 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 36bc01dd259d8950ae57b75a3eb94f91065aed62d2b149d705959695bc8f323f
|
|
4
|
+
data.tar.gz: f2aa37ea2d83373d2252b594aaef87894f1da03adda08edfa746baa6e76c2dea
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 43ba5370306adecd0c53f818d655a367748e5b3162559abca5e8eb2a5687410c8d145f8f8b545f98ca265961344378e1c0a474826b46853357f2bce4192aa12b
|
|
7
|
+
data.tar.gz: 3cf07dea2adbe6eb33ec3bf65401c96127c1a066fbb104ea2e945d42f5526e8272aebbf9561a5777d1c6278674b3bc386036d1aa2b01bcb37d99366822ac431b
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.1
|
|
4
|
+
|
|
5
|
+
- **Fixed: only the first scenario in a `silas:eval` run was really tested.**
|
|
6
|
+
`Silas.configure` never invalidated the memoized resolved engine, so a
|
|
7
|
+
second `configure` in the same process kept serving the first one — every
|
|
8
|
+
eval scenario after the first silently ran the *first* scenario's script
|
|
9
|
+
while still reporting pass/fail as though it hadn't. Reconfiguring now
|
|
10
|
+
re-resolves both the engine and the sandbox. The gem's own specs missed this
|
|
11
|
+
because the spec helper resets config between examples; a real multi-scenario
|
|
12
|
+
eval suite — the production path — does not. Found by building
|
|
13
|
+
`examples/playground`.
|
|
14
|
+
- **Automatic approvals are now recorded.** A graded gate that clears a call
|
|
15
|
+
(a lambda under its threshold, an `:once` rule already satisfied) sets
|
|
16
|
+
`approval_state: "approved"` with **no** `approved_by` — so the audit trail
|
|
17
|
+
distinguishes "gate ran and passed automatically" (which the inbox now
|
|
18
|
+
renders as *auto-approved by policy*) from "no gate at all", which stays
|
|
19
|
+
`nil`. Previously both were indistinguishable on a money-moving tool.
|
|
20
|
+
- The generated `ruby_llm.rb` initializer opts into `use_new_acts_as`, silencing
|
|
21
|
+
RubyLLM's legacy-API deprecation warning on every boot — Silas never uses
|
|
22
|
+
`acts_as_*`, so the warning was pure noise. Existing initializers are still
|
|
23
|
+
never touched.
|
|
24
|
+
|
|
3
25
|
## 0.3.0
|
|
4
26
|
|
|
5
27
|
- **`bin/rails silas:doctor`** — every known first-run failure mode as one
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
<code><%= invocation.tool_name %></code>
|
|
4
4
|
<%= status_pill(invocation.awaiting_approval? ? "required" : invocation.status) %>
|
|
5
5
|
<%# The audit line — who held the lever, and why it moved. %>
|
|
6
|
-
<% if invocation.approval_state == "approved"
|
|
7
|
-
<span class="muted"
|
|
6
|
+
<% if invocation.approval_state == "approved" %>
|
|
7
|
+
<span class="muted"><%= invocation.approved_by.present? ? "approved by #{invocation.approved_by}" : "auto-approved by policy" %></span>
|
|
8
8
|
<% elsif invocation.approval_state == "declined" %>
|
|
9
9
|
<span class="muted">declined<%= " by #{invocation.approved_by}" if invocation.approved_by.present? %><%= " — “#{invocation.decline_reason}”" if invocation.decline_reason.present? %></span>
|
|
10
10
|
<% elsif invocation.approval_state == "expired" %>
|
|
@@ -5,6 +5,12 @@
|
|
|
5
5
|
#
|
|
6
6
|
# Any provider RubyLLM supports works the same way (openai_api_key, etc.).
|
|
7
7
|
RubyLLM.configure do |c|
|
|
8
|
+
# Silas never uses RubyLLM's acts_as_* ActiveRecord mixins (it owns its own
|
|
9
|
+
# durable schema), so opt into the new API to silence the legacy deprecation
|
|
10
|
+
# warning on every boot. Remove this line if THIS app uses acts_as_chat and
|
|
11
|
+
# hasn't migrated yet — see https://rubyllm.com/upgrading-to-1-7/
|
|
12
|
+
c.use_new_acts_as = true if c.respond_to?(:use_new_acts_as=)
|
|
13
|
+
|
|
8
14
|
c.anthropic_api_key = ENV["ANTHROPIC_API_KEY"]
|
|
9
15
|
# The per-request timeout (seconds; RubyLLM default 300). Under streaming
|
|
10
16
|
# this is an idle-between-chunks timeout — the hang protection for a stuck
|
data/lib/silas/ledger.rb
CHANGED
|
@@ -92,8 +92,15 @@ module Silas
|
|
|
92
92
|
when Hash # {denied: "reason"} — eve's shape
|
|
93
93
|
invocation.update!(status: "failed", result: { "denied" => verdict[:denied] })
|
|
94
94
|
return :done
|
|
95
|
+
when :approved
|
|
96
|
+
# A gate ran and CLEARED it (a lambda under its threshold, or an
|
|
97
|
+
# :once rule already satisfied). Record that, so the audit trail
|
|
98
|
+
# can tell "gate evaluated, passed automatically" apart from "no
|
|
99
|
+
# gate at all" (which stays nil). approved_by is left nil — that
|
|
100
|
+
# absence is what marks it automatic rather than human.
|
|
101
|
+
invocation.update!(approval_state: "approved")
|
|
95
102
|
end
|
|
96
|
-
# :not_applicable
|
|
103
|
+
# :not_applicable falls through ungated
|
|
97
104
|
end
|
|
98
105
|
|
|
99
106
|
execute!(invocation, tool)
|
data/lib/silas/version.rb
CHANGED
data/lib/silas.rb
CHANGED
|
@@ -51,9 +51,17 @@ module Silas
|
|
|
51
51
|
@config ||= Configuration.new
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
+
# Reconfiguring re-resolves the engine and sandbox. Without this the
|
|
55
|
+
# memos below outlive the config that produced them: a second
|
|
56
|
+
# `Silas.configure { |c| c.engine = ... }` in one process kept serving the
|
|
57
|
+
# FIRST engine. That silently broke multi-scenario `silas:eval` runs —
|
|
58
|
+
# every scenario after the first ran the first one's script and still
|
|
59
|
+
# reported pass/fail as if it hadn't. Re-resolution is cheap (one `.new`).
|
|
54
60
|
def configure
|
|
55
61
|
yield config
|
|
56
62
|
config.validate!
|
|
63
|
+
@resolved_engine = nil
|
|
64
|
+
@resolved_sandbox = nil
|
|
57
65
|
config
|
|
58
66
|
end
|
|
59
67
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: silas
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Daniel St Paul
|
|
@@ -103,7 +103,7 @@ description: 'An agent framework where your Rails app is the chassis: app/agent/
|
|
|
103
103
|
convention, durable runs on Active Job Continuations, exactly-once tool execution
|
|
104
104
|
via a transactional ledger, approvals that park at zero compute.'
|
|
105
105
|
email:
|
|
106
|
-
-
|
|
106
|
+
- danielstpaul@hotmail.com
|
|
107
107
|
executables: []
|
|
108
108
|
extensions: []
|
|
109
109
|
extra_rdoc_files: []
|