Class: Mistri::Spawner

Inherits:
Object
  • Object
show all
Defined in:
lib/mistri/spawner.rb

Overview

Host policy for spawning workers, as one object: the tool pool children may draw from, the curated types, the model allowlist, the headcount cap, and the dispatcher that makes background mode real. #tool builds the spawn_agent tool the top-level agent holds; SubAgent.spawner and SubAgent.pack are the front doors.

Every policy violation answers the model in band (unknown type, missing instructions, over capacity, workspace sharing in background mode); only host configuration mistakes raise, and they raise at construction.

Instance Method Summary collapse

Constructor Details

#initialize(provider:, tools: [], types: {}, models: [], max_children: 4, dispatcher: nil, needs_approval: false, **agent_options) ⇒ Spawner

Returns a new instance of Spawner.



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/mistri/spawner.rb', line 14

def initialize(provider:, tools: [], types: {}, models: [], max_children: 4,
               dispatcher: nil, needs_approval: false, **agent_options)
  SubAgent.forbid_gated!(tools)
  if tools.any? { |tool| tool.name == "spawn_agent" }
    raise ConfigurationError, "the spawn tool never goes in its own pool"
  end

  @provider = provider
  @pool = tools
  # Symbol keys are natural Ruby; the wire speaks strings. One
  # normalization here and lookup, schema, and menu all agree.
  @types = types.transform_keys(&:to_s)
  @models = models
  @max_children = max_children
  @dispatcher = dispatcher
  @needs_approval = needs_approval
  @agent_options = agent_options
  validate_types!
end

Instance Method Details

#spawn(args, context) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/mistri/spawner.rb', line 42

def spawn(args, context)
  crowded = over_capacity(context.session)
  return crowded if crowded

  worker = resolve_worker(args)
  return worker if worker.is_a?(String)

  if args["mode"] == "background" && @dispatcher
    if args["workspace"] == "parent"
      return "A worker sharing your workspace must run inline: a blocked parent " \
             "cannot write concurrently, a working one can. Drop workspace or " \
             "drop background."
    end

    return dispatch(args, worker, context)
  end

  SubAgent.run_child(label: label_for(args), provider: worker[:provider],
                     system: worker[:system], tools: worker[:tools],
                     task: args.fetch("task"), context: context, **@agent_options)
end

#toolObject



34
35
36
37
38
39
40
# File 'lib/mistri/spawner.rb', line 34

def tool
  spawner = self
  Tool.define("spawn_agent", description, needs_approval: @needs_approval,
                                          schema: schema) do |args, context|
    spawner.spawn(args, context)
  end
end