turnkit 0.2.10 → 0.4.0

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.
@@ -4,13 +4,7 @@ require_relative "agent"
4
4
 
5
5
  module TurnKit
6
6
  class Workflow
7
- attr_reader :name, :description, :instructions, :tools, :skills, :available_skills
8
- attr_reader :model, :client, :store, :prompt_mode, :thinking, :compaction, :output_schema
9
- attr_reader :on_event
10
- attr_reader :max_iterations, :timeout, :cost_limit, :max_depth, :max_tool_executions, :max_tool_executions_by_name
11
- attr_reader :output_audit, :output_audit_mode, :output_policy, :output_policy_mode, :output_policy_model, :output_policy_thinking
12
-
13
- DEFAULT_INSTRUCTIONS = <<~TEXT.strip
7
+ ORCHESTRATOR_PREAMBLE = <<~TEXT.strip
14
8
  You are an autonomous task orchestrator. Navigate from the application
15
9
  request to a final output without asking the user follow-up questions.
16
10
 
@@ -29,104 +23,36 @@ module TurnKit
29
23
  limits.
30
24
  TEXT
31
25
 
32
- def initialize(name: "workflow", description: "", instructions: nil,
33
- tools: [], skills: [], available_skills: [], model: nil, client: nil,
34
- store: nil, prompt_mode: :task, thinking: nil, compaction: nil, on_event: nil,
35
- output_schema: nil, max_iterations: nil, timeout: nil, max_spend: nil,
36
- cost_limit: nil, max_depth: nil, max_tool_executions: nil, max_tool_executions_by_name: nil,
37
- output_audit: nil, output_audit_mode: nil, output_policy: nil, output_policy_mode: nil, output_policy_model: nil, output_policy_thinking: nil)
26
+ DEFAULT_INSTRUCTIONS = ORCHESTRATOR_PREAMBLE
27
+
28
+ attr_reader :name, :options
38
29
 
30
+ def initialize(name: "workflow", instructions: nil, preamble: true, **options)
39
31
  @name = name.to_s
40
- @description = description.to_s
41
- @instructions = instructions || DEFAULT_INSTRUCTIONS
42
- @tools = Array(tools)
43
- @skills = Array(skills)
44
- @available_skills = Array(available_skills)
45
- @model = model
46
- @client = client
47
- @store = store
48
- @prompt_mode = prompt_mode
49
- @thinking = thinking
50
- @compaction = compaction
51
- @on_event = on_event
52
- @output_schema = output_schema
53
- @max_iterations = max_iterations
54
- @timeout = timeout
55
- @cost_limit = cost_limit || max_spend
56
- @max_depth = max_depth
57
- @max_tool_executions = max_tool_executions
58
- @max_tool_executions_by_name = max_tool_executions_by_name
59
- @output_audit = output_audit
60
- @output_audit_mode = output_audit_mode
61
- @output_policy = output_policy
62
- @output_policy_mode = output_policy_mode
63
- @output_policy_model = output_policy_model
64
- @output_policy_thinking = output_policy_thinking
65
32
  raise ArgumentError, "name is required" if @name.empty?
66
- @agent = build_agent
67
- end
68
-
69
- def run(prompt = nil, task: nil, input: nil, async: false, subject: nil, metadata: {},
70
- max_spend: nil, cost_limit: nil, **options)
71
-
72
- task = task || prompt
73
- raise ArgumentError, "task is required" if task.to_s.empty?
74
-
75
- runtime_agent = if options.empty? && cost_limit.nil? && max_spend.nil?
76
- @agent
77
- else
78
- build_agent(cost_limit: cost_limit || max_spend, **options)
79
- end
80
33
 
81
- runtime_agent.run(
82
- task,
83
- input: input,
84
- async: async,
85
- subject: subject,
86
- metadata: metadata
87
- )
34
+ @options = options.merge(
35
+ name: @name,
36
+ prompt_mode: options.fetch(:prompt_mode, :task),
37
+ instructions: compose_instructions(instructions, preamble: preamble)
38
+ ).freeze
39
+ @agent = Agent.new(**@options)
88
40
  end
89
41
 
90
- def agent(**options)
91
- options.empty? ? @agent : build_agent(**options)
42
+ def run(prompt = nil, task: nil, input: nil, async: false, subject: nil, metadata: {}, **overrides)
43
+ agent(**overrides).run(task || prompt, input: input, async: async, subject: subject, metadata: metadata)
92
44
  end
93
45
 
94
- def max_spend
95
- cost_limit
46
+ def agent(**overrides)
47
+ overrides.empty? ? @agent : Agent.new(**@options.merge(overrides.compact))
96
48
  end
97
49
 
98
50
  private
99
- def build_agent(**overrides)
100
- attrs = {
101
- name: name,
102
- description: description,
103
- instructions: instructions,
104
- tools: tools,
105
- skills: skills,
106
- available_skills: available_skills,
107
- model: model,
108
- client: client,
109
- store: store,
110
- prompt_mode: prompt_mode,
111
- thinking: thinking,
112
- compaction: compaction,
113
- on_event: on_event,
114
- output_schema: output_schema,
115
- max_iterations: max_iterations,
116
- timeout: timeout,
117
- cost_limit: cost_limit,
118
- max_depth: max_depth,
119
- max_tool_executions: max_tool_executions,
120
- max_tool_executions_by_name: max_tool_executions_by_name,
121
- output_audit: output_audit,
122
- output_audit_mode: output_audit_mode,
123
- output_policy: output_policy,
124
- output_policy_mode: output_policy_mode,
125
- output_policy_model: output_policy_model,
126
- output_policy_thinking: output_policy_thinking
127
- }
128
- attrs.merge!(overrides.compact)
129
- Agent.new(**attrs)
51
+ def compose_instructions(instructions, preamble:)
52
+ parts = []
53
+ parts << ORCHESTRATOR_PREAMBLE if preamble
54
+ parts << instructions.to_s.strip unless instructions.to_s.strip.empty?
55
+ parts.join("\n\n")
130
56
  end
131
57
  end
132
58
  end
data/lib/turnkit.rb CHANGED
@@ -15,12 +15,14 @@ require_relative "turnkit/cost"
15
15
  require_relative "turnkit/budget"
16
16
  require_relative "turnkit/event"
17
17
  require_relative "turnkit/model_request"
18
+ require_relative "turnkit/schema_check"
18
19
  require_relative "turnkit/agent"
19
20
  require_relative "turnkit/workflow"
20
21
  require_relative "turnkit/client"
21
22
  require_relative "turnkit/conversation"
22
23
  require_relative "turnkit/message"
23
24
  require_relative "turnkit/record"
25
+ require_relative "turnkit/image_result"
24
26
  require_relative "turnkit/result"
25
27
  require_relative "turnkit/skill"
26
28
  require_relative "turnkit/output_audit"
@@ -33,9 +35,11 @@ require_relative "turnkit/store"
33
35
  require_relative "turnkit/memory_store"
34
36
  require_relative "turnkit/compaction"
35
37
  require_relative "turnkit/tool"
38
+ require_relative "turnkit/image_tool"
36
39
  require_relative "turnkit/tool_call"
37
40
  require_relative "turnkit/tool_execution"
38
41
  require_relative "turnkit/sub_agent_tool"
42
+ require_relative "turnkit/load_skill_tool"
39
43
  require_relative "turnkit/message_projection"
40
44
  require_relative "turnkit/tool_runner"
41
45
  require_relative "turnkit/turn"
@@ -52,7 +56,7 @@ module TurnKit
52
56
  attr_accessor :default_model, :client, :store, :logger
53
57
  attr_accessor :max_iterations, :timeout, :max_depth, :max_tool_executions
54
58
  attr_accessor :max_tool_executions_by_name
55
- attr_accessor :cost_limit, :prompt_cache
59
+ attr_accessor :max_spend, :prompt_cache
56
60
  attr_accessor :compaction
57
61
  attr_accessor :output_policy_model, :output_policy_thinking
58
62
  attr_accessor :cost_rates, :cost_calculator
@@ -72,6 +76,7 @@ module TurnKit
72
76
  self.max_depth = 3
73
77
  self.max_tool_executions = 100
74
78
  self.max_tool_executions_by_name = {}
79
+ self.max_spend = nil
75
80
  self.prompt_cache = :auto
76
81
  self.compaction = true
77
82
  self.cost_rates = {}
@@ -97,21 +102,18 @@ module TurnKit
97
102
  self.default_model = value
98
103
  end
99
104
 
100
- def self.max_spend
101
- cost_limit
102
- end
103
-
104
- def self.max_spend=(value)
105
- self.cost_limit = value
106
- end
107
-
108
105
  def self.reconcile_stale!(before: Clock.now - (timeout || 300))
109
106
  store.find_stale_turns(before: before).each do |turn|
110
107
  store.update_turn(turn.fetch("id"), "status" => "stale", "completed_at" => Clock.now)
111
108
  end
112
109
  end
113
110
 
114
- def self.audit_output(output, constraints: [], context: {})
111
+ def self.check_output_policy(output, constraints: [], context: {})
115
112
  OutputAudit.check(output, constraints: constraints, context: context)
116
113
  end
114
+
115
+ def self.paint(prompt, model:, provider: nil, size: nil, assume_model_exists: nil, input_images: nil, mask: nil, params: {}, metadata: {}, client: nil)
116
+ image_client = client || self.client
117
+ image_client.paint(prompt: prompt, model: model, provider: provider, size: size, assume_model_exists: assume_model_exists, input_images: input_images, mask: mask, params: params, metadata: metadata).images.first
118
+ end
117
119
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: turnkit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.10
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Couch
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-06-10 00:00:00.000000000 Z
11
+ date: 2026-06-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby_llm
@@ -57,6 +57,9 @@ files:
57
57
  - lib/turnkit/generators/turnkit/install/templates/turn.rb
58
58
  - lib/turnkit/generators/turnkit/install_generator.rb
59
59
  - lib/turnkit/id.rb
60
+ - lib/turnkit/image_result.rb
61
+ - lib/turnkit/image_tool.rb
62
+ - lib/turnkit/load_skill_tool.rb
60
63
  - lib/turnkit/memory_store.rb
61
64
  - lib/turnkit/message.rb
62
65
  - lib/turnkit/message_projection.rb
@@ -70,6 +73,7 @@ files:
70
73
  - lib/turnkit/record.rb
71
74
  - lib/turnkit/result.rb
72
75
  - lib/turnkit/run.rb
76
+ - lib/turnkit/schema_check.rb
73
77
  - lib/turnkit/skill.rb
74
78
  - lib/turnkit/store.rb
75
79
  - lib/turnkit/stores/active_record_store.rb