silas 0.1.1 → 0.1.3
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 +21 -0
- data/lib/generators/silas/install/templates/channel_email.rb +13 -2
- data/lib/silas/ledger.rb +10 -3
- data/lib/silas/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 35e622a6b7c17416ebe71717f1d072bd07c8a075f901c5b477177aa9bfccfa29
|
|
4
|
+
data.tar.gz: 59a87acd719063f275926852e255507d3c6159c16892907f70c8a77180dd61f8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 608b8bc79c926eadf04b74360e62832413580986c8ef5c6899b5acdc9371695db555799d9dd26d76b3aea77d2deafee13f32236cf8564c3cc6ad47692c58be80
|
|
7
|
+
data.tar.gz: f992423e27b802ae2efb6e7cf1c366f584ff703bd2210b9388b68abb9730616f2d16ded6b0da6e4b0a62c4c9fefd5becc8e8a85c6a17763d47dfd72bfef6d9ab
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.3
|
|
4
|
+
|
|
5
|
+
- **Ledger: parallel graded gates.** When the model emits several tool calls in
|
|
6
|
+
one step, `settle!` now settles every invocation instead of stopping at the
|
|
7
|
+
first one that needs approval. An ungated call (e.g. a low-risk write) runs
|
|
8
|
+
immediately even when a gated sibling (e.g. a money move) parks for a human —
|
|
9
|
+
it is no longer stranded behind the approval. This changes only *timing*, not
|
|
10
|
+
safety: an unsettled sibling already executed on resume regardless of the
|
|
11
|
+
human's approve/decline, so stopping early only delayed independent work.
|
|
12
|
+
Regression test in `spec/silas/parallel_tool_calls_spec.rb`.
|
|
13
|
+
|
|
14
|
+
## 0.1.2
|
|
15
|
+
|
|
16
|
+
- **Security (email channel scaffold): approvals no longer go to the session
|
|
17
|
+
initiator.** The generated `Agent::Channels::Email#deliver_approval` mailed the
|
|
18
|
+
approve link to `email["from"]` — the address that started the session, which
|
|
19
|
+
for a support agent is the customer, letting them approve their own gated
|
|
20
|
+
request. It now routes to a configured operator (`SILAS_APPROVER_EMAIL`) and
|
|
21
|
+
fails closed (sends nothing) if unset. The Slack scaffold was unaffected (its
|
|
22
|
+
card posts to the team channel/thread, not the initiator).
|
|
23
|
+
|
|
3
24
|
## 0.1.1
|
|
4
25
|
|
|
5
26
|
- **Fix: parallel tool calls.** When the model emitted several tool_use blocks
|
|
@@ -10,9 +10,20 @@ class Agent::Channels::Email < Silas::Channel
|
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def deliver_approval(session:, invocation:)
|
|
13
|
-
|
|
13
|
+
# SECURITY: an approval must go to an OPERATOR, never to whoever started the
|
|
14
|
+
# session. For an email-driven agent, session.metadata["email"]["from"] is
|
|
15
|
+
# the person who emailed in — often the customer — so mailing THEM the
|
|
16
|
+
# approve link lets them approve their own request. Route approvals to your
|
|
17
|
+
# ops/approver inbox instead, and fail closed if it isn't configured.
|
|
18
|
+
approver = ENV["SILAS_APPROVER_EMAIL"] # e.g. "approvals@yourcompany.com"
|
|
19
|
+
if approver.blank?
|
|
20
|
+
Rails.logger.warn("[Silas] SILAS_APPROVER_EMAIL unset — approval for " \
|
|
21
|
+
"invocation #{invocation.id} not emailed (won't send to the sender).")
|
|
22
|
+
return
|
|
23
|
+
end
|
|
24
|
+
|
|
14
25
|
Silas::ChannelMailer.approval(
|
|
15
|
-
to:
|
|
26
|
+
to: approver, subject: "Approval needed: #{invocation.tool_name}", invocation: invocation
|
|
16
27
|
).deliver_later
|
|
17
28
|
end
|
|
18
29
|
end
|
data/lib/silas/ledger.rb
CHANGED
|
@@ -34,12 +34,19 @@ module Silas
|
|
|
34
34
|
"the continuation believes are committed."
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
+
# Settle EVERY invocation in the step, then report whether the turn must
|
|
38
|
+
# park. When the model emits parallel tool calls, an ungated one must not
|
|
39
|
+
# be blocked by a gated sibling's approval — and it wouldn't be protected
|
|
40
|
+
# anyway: an unsettled sibling executes on resume regardless of whether the
|
|
41
|
+
# human approves or declines the gated call, so stopping at the first park
|
|
42
|
+
# only delays independent work. Execute what can proceed; park if any
|
|
43
|
+
# invocation is awaiting a human.
|
|
37
44
|
def settle!(step, resolver:)
|
|
45
|
+
parked = false
|
|
38
46
|
step.tool_invocations.order(:id).each do |invocation|
|
|
39
|
-
|
|
40
|
-
return :parked if outcome == :parked
|
|
47
|
+
parked = true if settle_invocation!(invocation, resolver) == :parked
|
|
41
48
|
end
|
|
42
|
-
:completed
|
|
49
|
+
parked ? :parked : :completed
|
|
43
50
|
end
|
|
44
51
|
|
|
45
52
|
# Drive a SINGLE freshly-created invocation to a terminal state — the
|
data/lib/silas/version.rb
CHANGED