Commit Graph
1423 Commits
Author SHA1 Message Date
Dark-Alex-17 3254fe9f3c feat: Fixed graph agents with new agent variable passing functionality 2026-09-12 01:37:20 -06:00
Dark-Alex-17 a7528d6e1a feat(graph): warn when a declared variable is shadowed by an initial_state key 2026-09-12 01:37:20 -06:00
Dark-Alex-17 442953ef7d style: applied different styling to agent functions 2026-09-12 01:37:20 -06:00
Dark-Alex-17 1ec7916816 feat(agents): advertise declared agent variables in agent__list_available 2026-09-12 01:37:20 -06:00
Dark-Alex-17 eb7d1421da fix(tests): collision-proof parser test temp files to deflake macOS CI 2026-09-12 01:37:20 -06:00
Dark-Alex-17 f97a83f165 feat(agents): allow passing agent variables to agent__spawn and agent__task_create
- agent__spawn accepts an optional variables object (string->string);
  values overlay the parent-inherited agent variables per key, with
  inheritance preserved as the fallback layer
- unknown variable names, non-string values, and non-object shapes
  return self-correcting status:error JSON listing the agent's
  declared variables
- spawned children can no longer trigger the interactive variable
  prompt: a new interactive gate in Agent::init_agent_variables routes
  missing required variables to the existing bail path while leaving
  CLI/REPL prompting and --info skip semantics unchanged
- agent__task_create persists variables on the task, agent__task_list
  echoes them, and task auto-dispatch threads them into the spawn
- tool schemas and built-in spawn docs updated; unit tests extended
  in agents.rs and taskqueue.rs
2026-09-12 01:37:20 -06:00
Dark-Alex-17 3599b0a861 Merge branch 'main' of github.com:Dark-Alex-17/coyote 2026-09-11 22:42:20 -06:00
Dark-Alex-17 2e7cd6581e feat: seed variables into initial graph state 2026-09-11 22:42:07 -06:00
github-actions[bot] 406a850bdb chore: refresh generated model catalog [skip ci] 2026-09-12 00:48:47 +00:00
Dark-Alex-17 99e592565a feat: Significant code review suite rewrite with improved graph agent features 2026-09-11 15:33:21 -06:00
Dark-Alex-17 838335f84d feat: let install commands remove files that have been removed from bundles, both internal and external 2026-09-11 15:28:42 -06:00
Dark-Alex-17 b50ec42868 fix: Don't infinitely compress a session once it passes a threshold when the threshold is close to the max token count 2026-09-11 14:02:28 -06:00
Dark-Alex-17 e744da8870 feat: update the web_search_coyote tool to attempt to use the current model first then fallback to the configured model for web searches 2026-09-11 13:47:44 -06:00
Dark-Alex-17 eb78a0e32b feat: expose the current coyote model to tools 2026-09-11 13:47:20 -06:00
Alex Clarke e8237bd924 Merge pull request #24 from Dark-Alex-17/feat/map-subgraph-branches
feat(graph): map branches as per-item subgraph chains + templated max_concurrency
2026-09-11 13:12:09 -06:00
Dark-Alex-17 2f85462e2a fix: fix spinner ctrl-c early exit not clearing message and restoring cursor 2026-09-11 13:01:27 -06:00
Dark-Alex-17 3e91813cff feat: removed temperature specification in deep-research and finding-verifier agents to make them more univerally usable 2026-09-11 11:22:06 -06:00
Dark-Alex-17 99fb6e24f1 fmt: applied formatting 2026-09-11 10:56:28 -06:00
Dark-Alex-17 24b5504e21 fix(graph): build peer retirement guards before spawning their tasks
A task aborted before its first poll never runs its body, so a guard
constructed inside the future did not exist yet and the pre-provisioned
teammate identity stayed messageable. Built outside and moved in, the
guard drops with the unpolled future on both the frontier and map items.

Also rewords the two timeout: 0 validator warnings: the graph-level one
no longer claims max_loop_iterations always applies (it may be 0 too),
and the node-level one names the enclosing bounds that still end the
node instead of saying it runs until it returns.
2026-09-11 10:56:28 -06:00
Dark-Alex-17 02e2227aa0 fix(graph): reject agents that ship both config.yaml and graph.yaml at load
Agent::init refuses that layout, so any agent node pointing at such a
directory failed at run time while validation passed it as graph-capable.
2026-09-11 10:56:28 -06:00
Dark-Alex-17 778aa6449c fix(graph): bound concurrency caps by the semaphore permit limit
Semaphore::new panics above tokio's MAX_PERMITS, so a fixed or templated
map cap (or settings.max_concurrency) that large crashed the run instead
of erroring. The validator rejects both at load, resolve_max_concurrency
rejects every arm at run time, and the executor checks the graph setting
before building its own semaphore, so validation mode makes no difference.

Also corrects run_child_agent_with_graph_inputs' contract comment: inputs
for a config-only agent are rejected, not ignored.
2026-09-11 10:56:28 -06:00
Dark-Alex-17 a9f89f0414 test(graph): wait for the dispatcher before aborting the retirement test
On slow runners bash start-up alone can exceed the fixed 300 ms delay, so
the abort landed before the worker tasks (and their retirement guards)
existed and the observer saw nothing. The dispatcher now leaves a marker
and the trigger waits for it.
2026-09-11 10:56:28 -06:00
Dark-Alex-17 f072aa1b2c docs(graph): drop the output-null gotcha from the example graph 2026-09-11 10:56:28 -06:00
Dark-Alex-17 32f4adb71f fix(graph): make turn-cap and template checks consistent across validation modes 2026-09-11 10:56:28 -06:00
Dark-Alex-17 b4c01e0f28 chore(agents): drop the inert output reducers from librarian and finding-verifier 2026-09-11 10:56:28 -06:00
Dark-Alex-17 1a5824ce4f fix(graph): leave output absent after state_updates when it was absent before 2026-09-11 10:56:28 -06:00
Dark-Alex-17 324dd3397a docs(graph): document abort semantics and map binding rules in the example graph
Comment-only: settings.timeout notes that Ctrl-C ends a run promptly from
anywhere; the map node's as:/output_key: comments state that the two must
differ, and max_concurrency describes the template form as exactly one
{{key}} with nothing around it.
2026-09-11 10:56:28 -06:00
Dark-Alex-17 727cab11ff fix(graph): validate the whole max_concurrency template string
A string max_concurrency passed the load-time check whenever it merely
contained a {{...}} pair, so forms like "n={{k}}" or "{{ key }}" that
can never resolve at runtime were only caught after the map's inputs had
been computed. The check now requires the trimmed string to be exactly
one template reference, matching what interpolate_raw resolves as a pure
reference; padded forms like " {{budget}} " stay valid.

Also: the bash tool build-failure context names the source file instead
of the destination path, and the map-subgraph validator no longer
shadows its member id list with the resolved member nodes.
2026-09-11 10:56:28 -06:00
Dark-Alex-17 ccec38c5b9 fix(graph): reject as == output_key on map nodes
A map node whose item binding shares its name with output_key would have
the binding collected as the chain's result whenever the chain never
wrote it, while the missing-writer warning stayed silent. The collision
is now a validator error attributed to the map node and, with validation
off, a runtime error in run_map before any item forks.
2026-09-11 10:56:28 -06:00
Dark-Alex-17 cce8381962 feat(graph): thread the graph abort into llm nodes and tool execution
LlmNodeExecutor::execute now takes the graph's abort signal and threads
it through run -> run_with_retries -> run_chat_loop, replacing the
loop-private signal, so an in-flight model call is interrupted and every
turn starts with an abort check that bails 'llm node aborted' before any
client is created.

run_llm_function gains an optional abort signal: the synchronous tool
wait loop kills the child and returns a 'Tool call ... aborted' error
within one poll interval when it is set. The tool dispatcher passes the
session abort; the agent _instructions runner passes None.
2026-09-11 10:56:28 -06:00
Dark-Alex-17 1ea755e864 feat(graph): abort a graph run on Ctrl-C from anywhere
A graph run now observes user interrupts wherever it is: GraphExecutor::run
spawns a run-scoped bridge that maps SIGINT or the enclosing session abort
onto the graph's own abort flag (only when a session signal exists; a
pre-set session trips a synchronous check). The frontier join selects on
the abort and, like the timeout path, cancels every in-flight branch task,
failing the run with 'Graph ... aborted during super-step'.

Branch and map item tasks are cancellation-owned via TaskCancelGuard, so
dropping a map task's future no longer detaches its item chains. Peer
retirement is a Drop guard (PeerRetireGuard) constructed before the
semaphore acquire and dropped explicitly right after step(), so the
success-path ordering is unchanged while task abort, panic, and the
pre-step abort return all still retire the identity.
2026-09-11 10:56:28 -06:00
Dark-Alex-17 6aad82c6fd fix(graph): inherit the session abort in agent-node children
A child agent spawned from a graph node now carries its parent's session
abort signal, so a user interrupt is observable from every sync wait in
the agent tree. Background agent__spawn children are unchanged.

run_child_agent_with_graph_inputs also guards the child's own supervisor
with a disarmable CancelOnDrop: if the future is dropped mid-flight or
the child fails before its normal cleanup, its spawned subagents are
cancelled instead of running on invisibly.
2026-09-11 10:56:27 -06:00
Dark-Alex-17 aa1287b902 docs(graph): document llm max_iterations: 0 in the example graph 2026-09-11 10:56:27 -06:00
Dark-Alex-17 d7a16363b8 feat(graph): warn when an llm node's turn cap is disabled 2026-09-11 10:56:27 -06:00
Dark-Alex-17 36601d8668 feat(graph): treat llm max_iterations: 0 as no turn cap 2026-09-11 10:56:27 -06:00
Dark-Alex-17 8e9a1f1ee8 docs: removed unnecessary comment on GraphState.history field 2026-09-11 10:56:27 -06:00
Dark-Alex-17 8f9284cb92 refactor(graph): keep the ordered visit log test-only
GraphState.history was pushed to on every node visit and deep-cloned on
every super-step snapshot and map fork, but its only reader is the
cfg(test) current_node accessor. Gate the field, its initializer, and
the push behind cfg(test) so production builds no longer carry an
unbounded Vec<String> that nothing observes.
2026-09-11 10:56:27 -06:00
Dark-Alex-17 69a3d928ee docs(graph): document max_loop_iterations: 0 in the example graph 2026-09-11 10:56:27 -06:00
Dark-Alex-17 4c5aa8d895 feat(graph): warn when the visit cap is disabled
validate_timeouts now also flags settings.max_loop_iterations: 0, ahead
of the settings.timeout: 0 warning so both opt-outs read top-to-bottom
as they appear in settings. (design §3.14 / C22)
2026-09-11 10:56:27 -06:00
Dark-Alex-17 3aa35e1259 feat(graph): treat max_loop_iterations: 0 as no visit cap
Both enforcement sites (frontier loop and map chain step) skip the
comparison when the cap is 0; visits are still counted and logged.
Adds an executor test that loops past the default cap with 0, a test
pinning the frontier cap message for a non-zero value, and a map-chain
twin at 0. (design §3.14 / C22)
2026-09-11 10:56:27 -06:00
Dark-Alex-17 4dee1a6849 docs: Removed unnecessary unicode arrow from example graph config 2026-09-11 10:56:27 -06:00
Dark-Alex-17 f342dd7dd7 docs(graph): document timeout: 0 in the example graph
Comment-only: each of the five timeout fields in graph.example.yaml now
says that 0 disables the bound. Parsed content is unchanged.
2026-09-11 10:56:27 -06:00
Dark-Alex-17 cd0318f384 feat(graph): warn when a timeout is disabled
A timeout: 0 on settings.timeout or on an agent/script/llm/rag node is
the author's explicit opt-out of the wall-clock bound. It stays legal;
the validator now emits one warning per zero so the choice is visible in
--validate output. Non-zero and unset values do not warn (unset already
means no bound for settings.timeout and llm nodes, matching the
explicit-zero-only convention of the orchestration-limit warnings).

Design §3.13 / C21.
2026-09-11 10:56:27 -06:00
Dark-Alex-17 d630c7e30b feat(graph): treat timeout: 0 as no wall-clock bound
A zero on any of the five timeout fields (settings.timeout, agent, script,
llm, rag) now disables the bound instead of firing an immediate
"timed out after 0s" or graph bail. Unset values keep their defaults
(agent 300, script 30, rag 120, llm/settings none); non-zero values are
unchanged. One resolution helper, wall_clock(secs) -> Option<Duration>,
feeds all five call sites; the C17 peer-retirement mark and every error
message stay where they were.

The one existing test that relied on timeout: 0 firing
(run_item_chain_marks_identity_finished_when_agent_step_times_out) moves
to timeout: 1 with its 5s hold unchanged.

Design §3.13 / C21.
2026-09-11 10:56:27 -06:00
Dark-Alex-17 b666b7e494 docs(graph): illustrate the inputs map on the example agent node
Comment-only block on deep_dive; the example's parsed YAML is unchanged.
2026-09-11 10:56:27 -06:00
Dark-Alex-17 e26543f21a test(graph): cover agent node inputs end to end and at the runtime guards
Two offline chain tests materialize an echo-inputs graph agent whose
script reports the width it sees: a parent with inputs.width gets the
parent's value back, a parent without inputs gets the child's YAML
default. Two agents.rs tests pin the exact runtime guard texts for a
config-only target and a reserved initial_prompt key.

Task T5 of plans/map-subgraph-branches-design.md §3.12.
2026-09-11 10:56:27 -06:00
Dark-Alex-17 10b8fe5cae feat(graph): validate agent node inputs at load time
Inside validate_agents: an agent node with inputs whose target has a
config.yaml but no graph.yaml is an error, and an inputs key named
initial_prompt is rejected. primary_templated_fields now includes every
inputs value for agent nodes, so validate_parallel_reads treats them as
cross-branch reads with no new pass.

Design: plans/map-subgraph-branches-design.md §3.12 V10a–V10c, task T5.
2026-09-11 10:56:27 -06:00
Dark-Alex-17 3393123baf feat(graph): seed a child graph agent's state from an agent node's inputs map
Agent nodes gain an optional `inputs:` map of templates resolved against
the parent state and overlaid on the child graph agent's initial_state
before its executor starts. A lone {{key}} keeps the state value's JSON
type; mixed text renders to a string; initial_prompt is still owned by the
dispatcher. run_child_agent and run_active_agent_graph keep their
signatures as wrappers over the new *_with_inputs variants, and
run_agent_for_graph rejects inputs aimed at a config-only agent or
containing initial_prompt.

Design: plans/map-subgraph-branches-design.md §3.12 (C18), task T5.
2026-09-11 10:56:27 -06:00
Dark-Alex-17 0bef0f2c39 fix(graph): retire the teammate identity before structured extraction
PR #24 follow-up 10. The identity was only retired by the frontier and
chain-exit safety nets, so a peer stayed messageable during
structured::extract after its agent had already stopped. Mark it
finished the moment the agent future resolves, on success and on both
error paths.
2026-09-11 10:56:27 -06:00
Dark-Alex-17 874ef7f6ec fix(graph): reject a literal max_concurrency of 0 instead of clamping it
Copilot review on PR #24. The validator already rejects 0 and the
template path errors on it, but a literal 0 loaded with
validate_before_run off was silently clamped to 1. Fail with the same
error shape as the template path; only the absent-cap default clamps.
2026-09-11 10:56:27 -06:00