Skip to content
Kward Search API index

Class: Kward::Tools::ContextForTask

Inherits:
Base
  • Object
show all
Defined in:
lib/kward/tools/context_for_task.rb

Overview

Builds a compact, task-shaped bundle from likely workspace files.

Constant Summary collapse

DEFAULT_BUDGET =
4_000
MAX_BUDGET =
20_000
MAX_FILES =
8
MAX_MATCHES_PER_FILE =
8
DEFAULT_EXTENSIONS =
%w[.rb .js .jsx .ts .tsx .py .go .rs .java .cs .cpp .c .h .hpp .md .yml .yaml .json .toml].freeze
SKIP_DIRECTORIES =
%w[.git .yardoc _yardoc node_modules vendor tmp log coverage dist build .bundle].freeze

Instance Attribute Summary

Attributes inherited from Base

#name

Instance Method Summary collapse

Methods inherited from Base

#schema

Constructor Details

#initialize(workspace:) ⇒ ContextForTask

Builds the tool schema and stores the execution dependency.



19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/kward/tools/context_for_task.rb', line 19

def initialize(workspace:)
  @workspace = workspace
  super(
    "context_for_task",
    "Build focused workspace context for a task from outlines and matching excerpts within a byte budget.",
    properties: {
      budget: { type: "integer", description: "Approximate byte budget for the returned context. Default 4000, maximum 20000." },
      paths: { type: "array", items: { type: "string" }, description: "Optional workspace-relative files or directories to focus." },
      task: { type: "string", description: "Task or question to gather context for." }
    },
    required: ["task"]
  )
end

Instance Method Details

#call(args, _conversation, cancellation: nil) ⇒ Object

Executes focused context retrieval.



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/kward/tools/context_for_task.rb', line 34

def call(args, _conversation, cancellation: nil)
  cancellation&.raise_if_cancelled!
  task = argument(args, :task, "").to_s.strip
  return "Error: task is required" if task.empty?

  budget = normalized_budget(argument(args, :budget))
  return budget if budget.is_a?(String)

  focus_paths = Array(argument(args, :paths, [])).map(&:to_s).reject(&:empty?)
  files = candidate_files(focus_paths, cancellation: cancellation)
  return "No readable candidate files found for focused context." if files.empty?

  terms = search_terms(task)
  ranked = rank_files(files, terms)
  return "No matching candidate files found for focused context." if ranked.empty?

  render_context(task: task, budget: budget, terms: terms, ranked: ranked, cancellation: cancellation)
rescue SecurityError, Errno::ENOENT => e
  "Error: #{e.message}"
end