Class: OllamaAgent::Agent

Inherits:
Object
  • Object
show all
Includes:
ClientWiring, PromptWiring, SessionWiring, SandboxedTools
Defined in:
lib/ollama_agent/agent.rb,
lib/ollama_agent/agent/turn_loop.rb,
lib/ollama_agent/agent/agent_config.rb,
lib/ollama_agent/agent/client_wiring.rb,
lib/ollama_agent/agent/prompt_wiring.rb,
lib/ollama_agent/agent/session_wiring.rb,
lib/ollama_agent/agent/chat_coordinator.rb

Overview

Runs a tool-calling loop against Ollama: read files, search, apply unified diffs. Public entry: #run. Other instance methods are internal to the agent loop. rubocop:disable Metrics/ClassLength – facade coordinates includes, config, and chat helpers

Defined Under Namespace

Modules: ClientWiring, PromptWiring, SessionWiring Classes: AgentConfig, ChatCoordinator, TurnLoop

Constant Summary collapse

MAX_TURNS =
64
DEFAULT_HTTP_TIMEOUT =
120

Constants included from SandboxedTools

SandboxedTools::DEFAULT_MAX_READ_FILE_BYTES

Constants included from RepoList

RepoList::MAX_LIST_FILES

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client: nil, config: nil, model: nil, root: nil, confirm_patches: true, http_timeout: nil, think: nil, read_only: false, patch_policy: nil, system_prompt: nil, skill_paths: nil, skills_enabled: nil, skills_include: nil, skills_exclude: nil, external_skills_enabled: nil, orchestrator: false, confirm_delegation: nil, max_retries: nil, audit: nil, session_id: nil, resume: false, max_tokens: nil, context_summarize: nil, stdin: $stdin, stdout: $stdout, provider: nil, provider_name: nil, budget: nil, permissions: nil, policies: nil, memory_manager: nil, trace_logger: nil, approval_gate: nil, user_prompt: nil, logger: nil) ⇒ Agent

rubocop:disable Metrics/ParameterLists rubocop:disable Metrics/MethodLength

Parameters:



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/ollama_agent/agent.rb', line 54

def initialize(client: nil, config: nil, model: nil, root: nil, confirm_patches: true, http_timeout: nil,
               think: nil,
               read_only: false, patch_policy: nil,
               system_prompt: nil,
               skill_paths: nil, skills_enabled: nil, skills_include: nil, skills_exclude: nil,
               external_skills_enabled: nil,
               orchestrator: false, confirm_delegation: nil,
               max_retries: nil, audit: nil,
               session_id: nil, resume: false,
               max_tokens: nil, context_summarize: nil,
               stdin: $stdin, stdout: $stdout,
               provider: nil, provider_name: nil, budget: nil,
               permissions: nil, policies: nil,
               memory_manager: nil, trace_logger: nil, approval_gate: nil, user_prompt: nil,
               logger: nil)
  cfg = config || AgentConfig.new(
    model: model, root: root, confirm_patches: confirm_patches, http_timeout: http_timeout, think: think,
    read_only: read_only, patch_policy: patch_policy,
    system_prompt: system_prompt,
    skill_paths: skill_paths, skills_enabled: skills_enabled, skills_include: skills_include,
    skills_exclude: skills_exclude, external_skills_enabled: external_skills_enabled,
    orchestrator: orchestrator, confirm_delegation: confirm_delegation,
    max_retries: max_retries, audit: audit, session_id: session_id, resume: resume,
    max_tokens: max_tokens, context_summarize: context_summarize, stdin: stdin, stdout: stdout,
    provider: provider, provider_name: provider_name, budget: budget,
    permissions: permissions, policies: policies,
    memory_manager: memory_manager, trace_logger: trace_logger, approval_gate: approval_gate,
    user_prompt: user_prompt,
    logger: logger
  )
  apply_agent_config(cfg)
  @user_prompt = cfg.user_prompt || UserPrompt.new(stdin: cfg.stdin, stdout: cfg.stdout)
  @context_manager = Context::Manager.new(max_tokens: @max_tokens, context_summarize: @context_summarize)
  @hooks = Streaming::Hooks.new
  attach_audit_logger if resolved_audit_enabled
  @client = client || build_default_client
end

Instance Attribute Details

#clientObject

Returns the value of attribute client.



47
48
49
# File 'lib/ollama_agent/agent.rb', line 47

def client
  @client
end

#hooksObject (readonly)

Returns the value of attribute hooks.



48
49
50
# File 'lib/ollama_agent/agent.rb', line 48

def hooks
  @hooks
end

#loggerObject (readonly)

Returns the value of attribute logger.



48
49
50
# File 'lib/ollama_agent/agent.rb', line 48

def logger
  @logger
end

#max_tokensObject (readonly)

Returns the value of attribute max_tokens.



48
49
50
# File 'lib/ollama_agent/agent.rb', line 48

def max_tokens
  @max_tokens
end

#modelObject (readonly)

Returns the value of attribute model.



48
49
50
# File 'lib/ollama_agent/agent.rb', line 48

def model
  @model
end

#orchestratorObject (readonly)

Returns the value of attribute orchestrator.



48
49
50
# File 'lib/ollama_agent/agent.rb', line 48

def orchestrator
  @orchestrator
end

#provider_nameObject (readonly)

Returns the value of attribute provider_name.



48
49
50
# File 'lib/ollama_agent/agent.rb', line 48

def provider_name
  @provider_name
end

#read_onlyObject (readonly)

Returns the value of attribute read_only.



48
49
50
# File 'lib/ollama_agent/agent.rb', line 48

def read_only
  @read_only
end

#rootObject (readonly)

Returns the value of attribute root.



48
49
50
# File 'lib/ollama_agent/agent.rb', line 48

def root
  @root
end

#session_idObject (readonly)

Returns the value of attribute session_id.



48
49
50
# File 'lib/ollama_agent/agent.rb', line 48

def session_id
  @session_id
end

Instance Method Details

#assign_chat_model!(name) ⇒ String

Switch the chat model for subsequent #run calls (same session, same client). Accepts Ollama local tags (e.g. llama3.2) or cloud catalog names (e.g. glm-5.1).

Parameters:

  • name (String)

Returns:

  • (String)

    the normalized model id

Raises:



106
107
108
109
110
111
112
# File 'lib/ollama_agent/agent.rb', line 106

def assign_chat_model!(name)
  n = name.to_s.strip
  raise EmptyModelNameError, "Model name cannot be empty" if n.empty?

  @model = n
  n
end

#list_cloud_model_namesObject



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/ollama_agent/agent.rb', line 142

def list_cloud_model_names
  base_url = nil
  api_key = nil

  if @client.respond_to?(:client) && @client.client.respond_to?(:config)
    config = @client.client.config
    base_url = config.base_url
    api_key = config.api_key
  end

  # Fallback to OLLAMA_BASE_URL if client doesn't expose it
  base_url ||= ENV.fetch("OLLAMA_BASE_URL", nil)

  # If it's a cloud-like URL, we can try to append /api/tags if needed,
  # but OllamaCloudCatalog.list_model_names handles the mapping.
  catalog_host = base_url ? "#{base_url.to_s.chomp("/")}/api/tags" : nil

  OllamaCloudCatalog.list_model_names(base_url: catalog_host, api_key: api_key)
end

#list_local_model_namesArray<String>

Names from the local Ollama daemon (/api/tags on your base_url). Not used by the REPL /models command.

Returns:

  • (Array<String>)


132
133
134
135
136
137
138
139
140
# File 'lib/ollama_agent/agent.rb', line 132

def list_local_model_names
  return [] unless @client.respond_to?(:list_model_names)

  @client.list_model_names
rescue StandardError => e
  logger.warn("list_local_model_names failed (#{e.class}: #{e.message})")
  logger.debug(e.full_message) if ENV["OLLAMA_AGENT_DEBUG"] == "1"
  []
end

#model_accessible?(name = nil) ⇒ Boolean

Performs a pre-flight check to see if the model is accessible. Currently only implemented for Ollama Cloud (checks for 403 Subscription Required).

Parameters:

  • name (String, nil) (defaults to: nil)

    defaults to current @model

Returns:

  • (Boolean)

    true if accessible or check not applicable



119
120
121
122
123
124
125
126
127
# File 'lib/ollama_agent/agent.rb', line 119

def model_accessible?(name = nil)
  n = name || @model
  return true unless @client.respond_to?(:cloud?) && @client.cloud?
  return true unless @client.respond_to?(:subscription_required?)

  !@client.subscription_required?(n)
rescue StandardError
  true # assume accessible if check fails
end

#run(query) ⇒ Object

rubocop:enable Metrics/MethodLength rubocop:enable Metrics/ParameterLists



94
95
96
97
98
# File 'lib/ollama_agent/agent.rb', line 94

def run(query)
  Console.reset_thinking_session!
  messages = build_messages_for_run(query)
  TurnLoop.new(self).run(messages)
end