ask-agent 0.4.5 → 0.4.6

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: 84cfe80b10d8495e3d0c1235f63767064b9615a740991b734652cccd0a112abe
4
- data.tar.gz: 95042e3fd3530a683b81259445afc524674808278e48fe7f90a7a89bb8e7f22c
3
+ metadata.gz: 56dc1b3abe92b66b571ee60669c0b95b9a6b00f5ae0b83d8a2777b2d10bb53dc
4
+ data.tar.gz: ea70a273c33e7c04dc9e8dc0e32117e8be60bf780106f8bf36a0f83b7897a73e
5
5
  SHA512:
6
- metadata.gz: af3eaf7b48c3ecb516977f4182df9ec19ae640d14c94cee2173cb53cb78d8cafc8d654a8a4b8c99065413e664e0a7ec73ec35bc63ba1c803093b3cce6bf15de9
7
- data.tar.gz: 2a59313a60550a171b60e1c6a95da02d049f72f6aacabd6cc0bb86385f120bcdb8401bd82011098b6b162ae72bdb2cfda5543b1776ed02f0ee2bb0ca432ba8f9
6
+ metadata.gz: 43298ab2aa83f7e16c86498d6e3f15d1b01821d81794cd2023574e1553446755913982d9323e8f5ff4fc603982570a21734a9b8947ab2c8d34982a45676cd2ad
7
+ data.tar.gz: f95818107b8b50b612944a7e2acb6fde05ef72becc8752866106f1de495e93ddf05b88695c7dc29af1e253bf603f6da0b0cf1cbaf7d3308e62da006201d6c04b
data/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ ## [0.4.5] — 2026-07-18
2
+
3
+ ### Fixed
4
+
5
+ - **`ToolExecutor#try_call` now respects `Ask::Result#ok?` for error detection** — Previously the method always set `is_error: false`, treating all Ask::Result returns as successful even when `ok?` was false. Tool failures returned via `Ask::Result.failure(...)` are now properly detected as errors, preventing the agent from silently ignoring failed tool executions and looping.
6
+
7
+ ## [0.4.4] — 2026-07-18
8
+
9
+ ### Added
10
+
11
+ - **`ToolExecutor` detects `halted: true` from tool results and stops execution** — When a tool returns `Ask::Result.ok(metadata: { halted: true })`, the executor now detects this flag, aborts sibling tools in parallel mode, and stops sequential execution. Previously the `halted` metadata was set but never checked by the executor, causing the agent loop to continue calling tools after a tool signaled completion.
12
+
13
+ ## [0.4.3] — 2026-07-18
14
+
15
+ ### Added
16
+
17
+ - **`Chat#provider_config` passes multiple credential names and path segments to `Ask::Auth.resolve`** — For compound provider slugs like `opencode_go`, the method now tries flat key names (`:opencode_go_api_key`, `:opencode_api_key`) and path segments (`[:opencode, :go, :api_key]`, `[:opencode, :api_key]`) as fallbacks. This lets `Ask::Auth.resolve` find credentials stored under various naming conventions.
18
+
1
19
  ## [0.4.0] — 2026-07-17
2
20
 
3
21
  ### Added
@@ -273,9 +273,15 @@ module Ask
273
273
  end
274
274
 
275
275
  def resolve_tools(tools)
276
- tools.map do |tool|
276
+ resolved = tools.map do |tool|
277
277
  tool.is_a?(Class) ? tool.new : tool
278
278
  end
279
+ # Always include the load_skill tool for progressive skill disclosure,
280
+ # unless the test framework is loaded (test mode keeps tools deterministic)
281
+ unless defined?(Ask::Agent::Test) && Ask::Agent::Test
282
+ resolved << Skills::LoadSkillTool.new(registry: @skills_registry) unless resolved.any? { |t| t.name == "load_skill" }
283
+ end
284
+ resolved
279
285
  end
280
286
 
281
287
  def build_compactor(config)
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ask
4
+ module Agent
5
+ module Skills
6
+ # Built-in tool that lets the LLM load a discovered skill's full
7
+ # instructions on demand. Skills are listed by name and description
8
+ # via progressive disclosure — the LLM decides which to load.
9
+ #
10
+ # Usage by the LLM: call load_skill with the skill name.
11
+ class LoadSkillTool < Ask::Tool
12
+ description "Load the full instructions for a skill by name. Use this when a listed skill seems relevant to the current task."
13
+
14
+ param :name, type: :string, desc: "Name of the skill to load (e.g., writing-guide)", required: true
15
+
16
+ def initialize(registry:)
17
+ @registry = registry
18
+ super()
19
+ end
20
+
21
+ def execute(name:)
22
+ skill = @registry&.[](name)
23
+ unless skill
24
+ available = @registry&.names&.join(", ") || "none"
25
+ return Ask::Result.failure(message: "Skill '#{name}' not found. Available skills: #{available}")
26
+ end
27
+
28
+ # Return the full skill content so it can be injected into conversation
29
+ content = "## Skill: #{skill.name}\n#{skill.description}\n\n#{skill.instructions}"
30
+ Ask::Result.ok(data: { name: skill.name, content: content })
31
+ end
32
+
33
+ def name
34
+ "load_skill"
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Ask
4
4
  module Agent
5
- VERSION = "0.4.5"
5
+ VERSION = "0.4.6"
6
6
  end
7
7
  end
data/lib/ask/agent.rb CHANGED
@@ -56,6 +56,7 @@ require_relative "agent/configuration"
56
56
  require_relative "agent/meta_agent"
57
57
  require_relative "agent/persistence/base"
58
58
  require_relative "agent/persistence/in_memory"
59
+ require_relative "agent/skills/load_skill_tool"
59
60
 
60
61
  # Test helpers (loaded on demand)
61
62
  autoload :Test, "ask/agent/test"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ask-agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ version: 0.4.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kaka Ruto
@@ -148,6 +148,7 @@ files:
148
148
  - lib/ask/agent/persistence/in_memory.rb
149
149
  - lib/ask/agent/reflector.rb
150
150
  - lib/ask/agent/session.rb
151
+ - lib/ask/agent/skills/load_skill_tool.rb
151
152
  - lib/ask/agent/telemetry.rb
152
153
  - lib/ask/agent/test.rb
153
154
  - lib/ask/agent/tool_abort_controller.rb