Class: Silas::AgentSdk::Cli

Inherits:
Object
  • Object
show all
Defined in:
lib/silas/agent_sdk/cli.rb

Overview

Builds the verified claude -p argv and manages the subprocess. --bare is the API-key-only auth guard (never subscription OAuth); alwaysLoad + a non-zero MCP_TIMEOUT are BOTH mandatory or the single-shot -p turn races ahead of the MCP handshake and never sees the tools (spike trap #1).

Instance Method Summary collapse

Constructor Details

#initialize(bin:, prompt:, system:, model:, mcp_url:, allowed:, resume_session_id: nil) ⇒ Cli

Returns a new instance of Cli.



10
11
12
13
14
15
16
17
18
# File 'lib/silas/agent_sdk/cli.rb', line 10

def initialize(bin:, prompt:, system:, model:, mcp_url:, allowed:, resume_session_id: nil)
  @bin = bin
  @prompt = prompt
  @system = system
  @model = model
  @mcp_url = mcp_url
  @allowed = allowed
  @resume_session_id = resume_session_id
end

Instance Method Details

#argvObject



38
39
40
41
42
43
44
45
46
47
# File 'lib/silas/agent_sdk/cli.rb', line 38

def argv
  args = [ @bin, "-p", @prompt,
           "--output-format", "stream-json", "--verbose", "--bare",
           "--mcp-config", mcp_config_json,
           "--allowedTools", @allowed.join(","),
           "--model", @model ]
  args += [ "--append-system-prompt", @system ] if @system.present?
  args += [ "--resume", @resume_session_id ] if @resume_session_id.present?
  args
end

#envObject



53
54
55
56
# File 'lib/silas/agent_sdk/cli.rb', line 53

def env
  { "ANTHROPIC_API_KEY" => ENV["ANTHROPIC_API_KEY"],
    "MCP_TIMEOUT" => Silas.config.agent_sdk_mcp_timeout_ms.to_s }
end

#mcp_config_jsonObject



49
50
51
# File 'lib/silas/agent_sdk/cli.rb', line 49

def mcp_config_json
  JSON.generate("mcpServers" => { "silas" => { "type" => "http", "url" => @mcp_url, "alwaysLoad" => true } })
end

#streamObject

Spawns claude, yields each stdout line, returns the exit status integer.



21
22
23
24
25
26
27
# File 'lib/silas/agent_sdk/cli.rb', line 21

def stream
  @io = IO.popen(env, argv, err: %i[child out], pgroup: true)
  @pid = @io.pid
  @io.each_line { |line| yield line }
  @io.close
  $?.exitstatus
end

#terminateObject



29
30
31
32
33
34
35
36
# File 'lib/silas/agent_sdk/cli.rb', line 29

def terminate
  return unless @pid

  Process.kill("-TERM", @pid)
  Process.kill("-KILL", @pid)
rescue Errno::ESRCH, Errno::EPERM
  # already gone
end