ask-decisions 0.1.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 +7 -0
- data/CHANGELOG.md +67 -0
- data/LICENSE +21 -0
- data/README.md +238 -0
- data/lib/ask/decisions/agent_adapter.rb +178 -0
- data/lib/ask/decisions/argument_resolver.rb +136 -0
- data/lib/ask/decisions/batcher.rb +59 -0
- data/lib/ask/decisions/cache.rb +67 -0
- data/lib/ask/decisions/calibration_harness.rb +112 -0
- data/lib/ask/decisions/calibration_report.rb +168 -0
- data/lib/ask/decisions/confidence_policy.rb +119 -0
- data/lib/ask/decisions/decision_state.rb +122 -0
- data/lib/ask/decisions/failure_classifier.rb +87 -0
- data/lib/ask/decisions/gate.rb +147 -0
- data/lib/ask/decisions/lint.rb +83 -0
- data/lib/ask/decisions/loop_detector.rb +142 -0
- data/lib/ask/decisions/mcp_helper.rb +23 -0
- data/lib/ask/decisions/output_judge.rb +135 -0
- data/lib/ask/decisions/quality_judge.rb +107 -0
- data/lib/ask/decisions/reader.rb +96 -0
- data/lib/ask/decisions/reflection_judge.rb +83 -0
- data/lib/ask/decisions/reranker.rb +78 -0
- data/lib/ask/decisions/static.rb +66 -0
- data/lib/ask/decisions/structured_state_loop.rb +137 -0
- data/lib/ask/decisions/tool_repairer.rb +114 -0
- data/lib/ask/decisions/tool_router.rb +137 -0
- data/lib/ask/decisions/triage.rb +161 -0
- data/lib/ask/decisions/typesafe.rb +189 -0
- data/lib/ask/decisions/version.rb +7 -0
- data/lib/ask/tools/decide.rb +130 -0
- data/lib/ask-decisions.rb +165 -0
- metadata +201 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "ask" # ask-core: Ask::Decision, Ask::DecisionResult, Ask::DecisionProvider
|
|
4
|
+
require "json"
|
|
5
|
+
require "net/http"
|
|
6
|
+
require "uri"
|
|
7
|
+
|
|
8
|
+
require_relative "ask/decisions/version"
|
|
9
|
+
require_relative "ask/decisions/typesafe"
|
|
10
|
+
require_relative "ask/decisions/batcher"
|
|
11
|
+
require_relative "ask/decisions/cache"
|
|
12
|
+
require_relative "ask/decisions/static"
|
|
13
|
+
require_relative "ask/decisions/lint"
|
|
14
|
+
require_relative "ask/decisions/gate"
|
|
15
|
+
require_relative "ask/decisions/output_judge"
|
|
16
|
+
require_relative "ask/decisions/reader"
|
|
17
|
+
require_relative "ask/decisions/triage"
|
|
18
|
+
require_relative "ask/decisions/tool_router"
|
|
19
|
+
require_relative "ask/decisions/argument_resolver"
|
|
20
|
+
require_relative "ask/decisions/decision_state"
|
|
21
|
+
require_relative "ask/decisions/failure_classifier"
|
|
22
|
+
require_relative "ask/decisions/loop_detector"
|
|
23
|
+
require_relative "ask/decisions/confidence_policy"
|
|
24
|
+
require_relative "ask/decisions/quality_judge"
|
|
25
|
+
require_relative "ask/decisions/reflection_judge"
|
|
26
|
+
require_relative "ask/decisions/tool_repairer"
|
|
27
|
+
require_relative "ask/decisions/reranker"
|
|
28
|
+
require_relative "ask/decisions/structured_state_loop"
|
|
29
|
+
require_relative "ask/decisions/calibration_report"
|
|
30
|
+
require_relative "ask/decisions/calibration_harness"
|
|
31
|
+
|
|
32
|
+
# The Decide tool requires ask-tools (Ask::Tool base class). Load conditionally
|
|
33
|
+
# so the core gem works without a tools dependency.
|
|
34
|
+
begin
|
|
35
|
+
require "ask-tools"
|
|
36
|
+
require_relative "ask/tools/decide"
|
|
37
|
+
require_relative "ask/decisions/mcp_helper"
|
|
38
|
+
rescue LoadError
|
|
39
|
+
# ask-tools not loaded — Ask::Tools::Decide unavailable
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Load agent adapter when ask-agent is available.
|
|
43
|
+
begin
|
|
44
|
+
require "ask/agent"
|
|
45
|
+
require_relative "ask/decisions/agent_adapter"
|
|
46
|
+
rescue LoadError
|
|
47
|
+
# ask-agent not loaded — AgentAdapter unavailable
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Register built-in providers.
|
|
51
|
+
Ask::DecisionProvider.register(:typesafe, Ask::Decisions::Typesafe)
|
|
52
|
+
Ask::DecisionProvider.register(:static, Ask::Decisions::Static)
|
|
53
|
+
|
|
54
|
+
module Ask
|
|
55
|
+
# Global convenience for making decisions.
|
|
56
|
+
#
|
|
57
|
+
# Ask.decide(state: "...", decisions: { "route" => Ask::Decision::Choice.new(...) })
|
|
58
|
+
#
|
|
59
|
+
# The provider is resolved from +Ask::Decisions.configuration.default_provider+
|
|
60
|
+
# unless overridden per-call.
|
|
61
|
+
def self.decide(state:, decisions:, provider: nil, model: nil, &block)
|
|
62
|
+
Ask::Decisions.decide(state: state, decisions: decisions, provider: provider, model: model, &block)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
module Ask
|
|
67
|
+
module Decisions
|
|
68
|
+
class << self
|
|
69
|
+
# Configuration block.
|
|
70
|
+
#
|
|
71
|
+
# Ask::Decisions.configure do |c|
|
|
72
|
+
# c.default_provider = :typesafe
|
|
73
|
+
# c.api_key = ENV["TYPESAFE_API_KEY"]
|
|
74
|
+
# end
|
|
75
|
+
def configure
|
|
76
|
+
yield configuration
|
|
77
|
+
configuration
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def configuration
|
|
81
|
+
@configuration ||= Configuration.new
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def reset_configuration!
|
|
85
|
+
@configuration = Configuration.new
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Make a decision call using the configured provider.
|
|
89
|
+
#
|
|
90
|
+
# Ask::Decisions.decide(
|
|
91
|
+
# state: { ticket: "..." },
|
|
92
|
+
# decisions: { "route" => Ask::Decision::Choice.new(instructions: "...", criteria: {...}) }
|
|
93
|
+
# )
|
|
94
|
+
#
|
|
95
|
+
def decide(state:, decisions:, provider: nil, model: nil)
|
|
96
|
+
provider_name = provider || configuration.default_provider
|
|
97
|
+
resolved = resolve_provider(provider_name)
|
|
98
|
+
|
|
99
|
+
# If a block is given, yield a Batcher so the caller can batch questions.
|
|
100
|
+
if block_given?
|
|
101
|
+
batcher = Batcher.new(resolved, state: state, model: model || configuration.default_model)
|
|
102
|
+
yield batcher
|
|
103
|
+
return batcher.execute
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
resolved.evaluate(
|
|
107
|
+
state: state,
|
|
108
|
+
decisions: decisions,
|
|
109
|
+
model: model || configuration.default_model
|
|
110
|
+
)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Shorthand for batched decisions. Yields a Batcher.
|
|
114
|
+
#
|
|
115
|
+
# result = Ask::Decisions.batch(state: "...") do |b|
|
|
116
|
+
# b.ask("route", Ask::Decision::Choice.new(...))
|
|
117
|
+
# b.ask("urgent", Ask::Decision::Noul.new(...))
|
|
118
|
+
# end
|
|
119
|
+
def batch(state:, provider: nil, model: nil, &block)
|
|
120
|
+
decide(state: state, decisions: {}, provider: provider, model: model, &block)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Resolve a provider by name, raising on unknown.
|
|
124
|
+
def resolve_provider(name)
|
|
125
|
+
klass = Ask::DecisionProvider.resolve(name)
|
|
126
|
+
|
|
127
|
+
if configuration.provider_options.any?
|
|
128
|
+
klass.new(**configuration.provider_options)
|
|
129
|
+
else
|
|
130
|
+
klass.new
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Global configuration for the Decisions module.
|
|
136
|
+
class Configuration
|
|
137
|
+
# @return [Symbol] the default provider name (:typesafe)
|
|
138
|
+
attr_accessor :default_provider
|
|
139
|
+
|
|
140
|
+
# @return [String, nil] the default model name ("jev-latest")
|
|
141
|
+
attr_accessor :default_model
|
|
142
|
+
|
|
143
|
+
# @return [String, nil] API key (falls back to Ask::Auth or env var)
|
|
144
|
+
attr_accessor :api_key
|
|
145
|
+
|
|
146
|
+
# @return [String, nil] base URL override (for proxies / Vercel AI Gateway)
|
|
147
|
+
attr_accessor :api_base
|
|
148
|
+
|
|
149
|
+
# @return [Hash] extra options passed to the provider constructor
|
|
150
|
+
attr_accessor :provider_options
|
|
151
|
+
|
|
152
|
+
# @return [Float, nil] default timeout in seconds
|
|
153
|
+
attr_accessor :timeout
|
|
154
|
+
|
|
155
|
+
def initialize
|
|
156
|
+
@default_provider = :typesafe
|
|
157
|
+
@default_model = "jev-latest"
|
|
158
|
+
@api_key = nil
|
|
159
|
+
@api_base = nil
|
|
160
|
+
@provider_options = {}
|
|
161
|
+
@timeout = 5.0
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: ask-decisions
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Kaka Ruto
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: ask-core
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: 0.12.0
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: 0.12.0
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: ask-auth
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: faraday
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '2.0'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '2.0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: json
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0'
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: minitest
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '5.25'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '5.25'
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: mocha
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - "~>"
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '3.1'
|
|
89
|
+
type: :development
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - "~>"
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '3.1'
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: rake
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - "~>"
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '13.0'
|
|
103
|
+
type: :development
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - "~>"
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '13.0'
|
|
110
|
+
- !ruby/object:Gem::Dependency
|
|
111
|
+
name: webmock
|
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - "~>"
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: '3.18'
|
|
117
|
+
type: :development
|
|
118
|
+
prerelease: false
|
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - "~>"
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: '3.18'
|
|
124
|
+
- !ruby/object:Gem::Dependency
|
|
125
|
+
name: vcr
|
|
126
|
+
requirement: !ruby/object:Gem::Requirement
|
|
127
|
+
requirements:
|
|
128
|
+
- - "~>"
|
|
129
|
+
- !ruby/object:Gem::Version
|
|
130
|
+
version: '6.0'
|
|
131
|
+
type: :development
|
|
132
|
+
prerelease: false
|
|
133
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
134
|
+
requirements:
|
|
135
|
+
- - "~>"
|
|
136
|
+
- !ruby/object:Gem::Version
|
|
137
|
+
version: '6.0'
|
|
138
|
+
description: Typed questions (Choice, Score, Noul) with calibrated probabilities and
|
|
139
|
+
confidence. Ships with a TypeSafe/Jev provider. Swap providers via the DecisionProvider
|
|
140
|
+
registry.
|
|
141
|
+
email:
|
|
142
|
+
- kaka@myrrlabs.com
|
|
143
|
+
executables: []
|
|
144
|
+
extensions: []
|
|
145
|
+
extra_rdoc_files: []
|
|
146
|
+
files:
|
|
147
|
+
- CHANGELOG.md
|
|
148
|
+
- LICENSE
|
|
149
|
+
- README.md
|
|
150
|
+
- lib/ask-decisions.rb
|
|
151
|
+
- lib/ask/decisions/agent_adapter.rb
|
|
152
|
+
- lib/ask/decisions/argument_resolver.rb
|
|
153
|
+
- lib/ask/decisions/batcher.rb
|
|
154
|
+
- lib/ask/decisions/cache.rb
|
|
155
|
+
- lib/ask/decisions/calibration_harness.rb
|
|
156
|
+
- lib/ask/decisions/calibration_report.rb
|
|
157
|
+
- lib/ask/decisions/confidence_policy.rb
|
|
158
|
+
- lib/ask/decisions/decision_state.rb
|
|
159
|
+
- lib/ask/decisions/failure_classifier.rb
|
|
160
|
+
- lib/ask/decisions/gate.rb
|
|
161
|
+
- lib/ask/decisions/lint.rb
|
|
162
|
+
- lib/ask/decisions/loop_detector.rb
|
|
163
|
+
- lib/ask/decisions/mcp_helper.rb
|
|
164
|
+
- lib/ask/decisions/output_judge.rb
|
|
165
|
+
- lib/ask/decisions/quality_judge.rb
|
|
166
|
+
- lib/ask/decisions/reader.rb
|
|
167
|
+
- lib/ask/decisions/reflection_judge.rb
|
|
168
|
+
- lib/ask/decisions/reranker.rb
|
|
169
|
+
- lib/ask/decisions/static.rb
|
|
170
|
+
- lib/ask/decisions/structured_state_loop.rb
|
|
171
|
+
- lib/ask/decisions/tool_repairer.rb
|
|
172
|
+
- lib/ask/decisions/tool_router.rb
|
|
173
|
+
- lib/ask/decisions/triage.rb
|
|
174
|
+
- lib/ask/decisions/typesafe.rb
|
|
175
|
+
- lib/ask/decisions/version.rb
|
|
176
|
+
- lib/ask/tools/decide.rb
|
|
177
|
+
homepage: https://github.com/ask-rb/ask-decisions
|
|
178
|
+
licenses:
|
|
179
|
+
- MIT
|
|
180
|
+
metadata:
|
|
181
|
+
homepage_uri: https://github.com/ask-rb/ask-decisions
|
|
182
|
+
source_code_uri: https://github.com/ask-rb/ask-decisions
|
|
183
|
+
changelog_uri: https://github.com/ask-rb/ask-decisions/blob/master/CHANGELOG.md
|
|
184
|
+
rdoc_options: []
|
|
185
|
+
require_paths:
|
|
186
|
+
- lib
|
|
187
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
188
|
+
requirements:
|
|
189
|
+
- - ">="
|
|
190
|
+
- !ruby/object:Gem::Version
|
|
191
|
+
version: '3.2'
|
|
192
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
193
|
+
requirements:
|
|
194
|
+
- - ">="
|
|
195
|
+
- !ruby/object:Gem::Version
|
|
196
|
+
version: '0'
|
|
197
|
+
requirements: []
|
|
198
|
+
rubygems_version: 4.0.18
|
|
199
|
+
specification_version: 4
|
|
200
|
+
summary: Decision primitives and providers for the ask-rb ecosystem
|
|
201
|
+
test_files: []
|