Commit Graph

27 Commits

Author SHA1 Message Date
JackChen a6b5181c74
feat: post-consumption tool result compression (#116) (#117)
Replace consumed tool results with compact markers before each LLM call,
freeing context budget in multi-turn agent runs. A tool result is
"consumed" once the assistant has produced a response after seeing it.

- Add `compressToolResults` option to AgentConfig / RunnerOptions
- Runs before contextStrategy (lightweight, no LLM calls)
- Error results and short results (< minChars, default 500) are skipped
- 9 test cases covering default off, compression, parallel tools,
  4+ turn compounding, error exemption, custom threshold, and
  contextStrategy coexistence
2026-04-16 18:22:42 +08:00
JackChen c3ead26677
feat: add tool output auto-truncation (#110) (#115)
* feat: add tool output auto-truncation at framework level (#110)

Prevent context blowup from large tool outputs by adding opt-in
character-based truncation (head 70% + tail 30% with marker).
Agent-level `maxToolOutputChars` and per-tool `maxOutputChars`
with per-tool taking priority. Marker overhead is budgeted so
the result never exceeds the configured limit.

* fix: truncateToolOutput may exceed maxChars when limit < marker overhead

- Fall back to hard slice when maxChars is too small to fit the marker
- Fix misplaced JSDoc for outputSchema in AgentConfig
- Tighten test assertion to verify length <= maxChars
2026-04-16 17:40:08 +08:00
JackChen 0170e43c4e
feat: add customTools to AgentConfig (#109)
* feat: add customTools support to AgentConfig for orchestrator-level tool injection

Users can now pass custom ToolDefinition objects via AgentConfig.customTools,
which are registered alongside built-in tools in all orchestrator paths
(runAgent, runTeam, runTasks). Custom tools bypass allowlist/preset filtering
but can still be blocked by disallowedTools.

Ref #108

* test: add disallowedTools blocking custom tool test

* fix: apply disallowedTools filtering to runtime-added custom tools

Previously runtime-added tools bypassed all filtering including
disallowedTools, contradicting the documented behavior. Now custom
tools still bypass preset/allowlist but respect the denylist.
2026-04-15 15:14:19 +08:00
JackChen ced1d90a93
Merge pull request #89 from ibrahimkzmv/feat.mcp-tool-integration
feat: add connectMCPTools() to register MCP server tools as standard agent tools
2026-04-12 17:05:31 +08:00
JackChen 0fb8a38284
Merge pull request #88 from ibrahimkzmv/feat.context-strategy
feat: Add contextStrategy to control conversation growth and prevent token explosion in agent runs
2026-04-12 16:54:41 +08:00
Ibrahim Kazimov 167085c3a7
Merge branch 'main' into feat.mcp-tool-integration 2026-04-12 00:03:18 +03:00
MrAvalonApple 12dd802ad8 feat: update MCP GitHub example and added llmInputSchema 2026-04-12 00:01:22 +03:00
Ibrahim Kazimov aa5fab59fa
feat: enforce dependency-scoped agent context (default-deny) (#87)
Co-authored-by: MrAvalonApple <74775400+ibrahimkazimov@users.noreply.github.com>
2026-04-10 03:09:58 +08:00
MrAvalonApple eb484d9bbf feat: add context management strategies (sliding-window, summarize, custom) to prevent unbounded conversation growth 2026-04-09 19:40:15 +03:00
MrAvalonApple 0b57ffe3e9 feat: enhance CoordinatorConfig with toolPreset and disallowedTools options 2026-04-08 12:34:25 +03:00
MrAvalonApple 30369b0597 feat: add customizable coordinator options for runTeam and enhance system prompt 2026-04-07 22:11:27 +03:00
Ibrahim Kazimov 97c39b316c
feat: add tool allowlist, denylist, preset list (#83)
* feat: add allowlist denylist and preset list for tools

* feat: update readme and add AGENT_FRAMEWORK_DISALLOWED

* fix: update filtering logic to allow custom tools

* fix: enhance tool registration and filtering for runtime-added tools

---------

Co-authored-by: MrAvalonApple <74775400+ibrahimkazimov@users.noreply.github.com>
2026-04-08 02:04:40 +08:00
Ibrahim Kazimov 60fb2b142e
feat: implement token budget management in agent and orchestrator (#71)
* feat: implement token budget management in agent and orchestrator

* fix: resolve TypeScript type errors in event and trace handlers

* feat: add budget exceeded event handling in agent and orchestrator

---------

Co-authored-by: MrAvalonApple <74775400+ibrahimkazimov@users.noreply.github.com>
2026-04-06 23:14:08 +08:00
JackChen a86a448fa0
feat(agent): smart loop detection for stuck agents (#49)
* feat(agent): add smart loop detection for stuck agents (#16)

Detect when agents repeat the same tool calls or text outputs in a
sliding window. Three modes: warn (inject nudge, terminate on 2nd hit),
terminate (immediate stop), or custom callback. Fully opt-in via
`loopDetection` on AgentConfig — zero overhead when unconfigured.

* fix(agent): support async onLoopDetected callbacks and prevent orphaned tool_use events

- Await onLoopDetected callback result so async functions work correctly
  instead of silently falling through to 'continue'
- Move loop detection before yielding tool_use events so terminate mode
  never emits tool_use without a matching tool_result

* fix(agent): reset loopWarned on recovery and rename maxRepeatedToolCalls to maxRepetitions

- Reset loopWarned flag when the agent stops repeating, so a future
  loop gets a fresh warning cycle instead of immediate termination
- Rename maxRepeatedToolCalls → maxRepetitions since the threshold
  applies to both tool call and text output repetition detection

* test(agent): add tests for async callback, warn recovery, and injected warning text

- Verify async onLoopDetected callback is awaited correctly
- Verify loopWarned resets after recovery, giving fresh warning cycle
- Verify WARNING TextBlock is injected into user message content
2026-04-05 13:01:53 +08:00
JackChen bc31008f4e feat(llm): add fallback tool-call extraction for local models (#15)
Local models (Ollama, vLLM) sometimes return tool calls as text instead
of using the native tool_calls wire format. This adds a safety-net
extractor that parses tool calls from model text output when native
tool_calls is empty.

- Add text-tool-extractor with support for bare JSON, code fences,
  and Hermes <tool_call> tags
- Wire fallback into OpenAI adapter chat() and stream() paths
- Add onWarning callback when model ignores configured tools
- Add timeoutMs on AgentConfig for per-run abort (local models can
  be slow)
- Add 26 tests for extractor and fallback behavior
- Document local model compatibility in README
2026-04-05 11:49:10 +08:00
JackChen 9a81a13982
feat(llm): add Gemini adapter (#28)
feat: Add support for Gemini model
2026-04-05 11:48:32 +08:00
JackChen 9f5afb10f5
feat(orchestrator): add onApproval callback for human-in-the-loop (#32)
* feat(orchestrator): add onApproval callback for human-in-the-loop (#32)

Add an optional `onApproval` callback to OrchestratorConfig that gates
between task execution rounds. After each batch of parallel tasks
completes, the callback receives the completed tasks and the tasks about
to start, returning true to continue or false to abort gracefully.

Key changes:
- Add 'skipped' to TaskStatus for user-initiated abort (distinct from 'failed')
- Add skip(), skipRemaining(), cascadeSkip() to TaskQueue
- Add 'task_skipped' to OrchestratorEvent for progress monitoring
- Approval gate in executeQueue() with try/catch for callback errors
- Synthesis prompt now includes skipped tasks section
- 17 new tests covering queue skip operations and orchestrator integration

Closes #32

* docs: clarify onApproval contract and add missing test scenarios

- Document skip() cascade semantics, skipRemaining() in-flight constraint,
  and onApproval trigger conditions / mutation warning
- Add concurrency safety comment on completedThisRound
- Note task_skipped as breaking union addition on OrchestratorEvent
- Add 3 test scenarios: single-batch no-callback, mixed success/failure
  batch, and onProgress task_skipped event relay
2026-04-05 02:46:20 +08:00
JackChen a1ccbfea61
feat(agent): add beforeRun / afterRun lifecycle hooks (#45)
* feat(agent): add beforeRun / afterRun lifecycle hooks (#31)

Add optional hook callbacks to AgentConfig for cross-cutting concerns
(guardrails, logging, token budgets) without modifying framework internals.

- beforeRun: receives prompt + agent config, can modify or throw to abort
- afterRun: receives AgentRunResult, can modify or throw to fail
- Works with all three execution modes: run(), prompt(), stream()
- 15 test cases covering modify, throw, async, composition, and history integrity

* fix(agent): preserve non-text content blocks in beforeRun hook

- applyHookContext now replaces only text blocks, keeping images and
  tool results intact (was silently stripping them)
- Use backward loop instead of reverse() + find() for efficiency
- Clarify JSDoc that only `prompt` is applied from hook return value
- Add test for mixed-content user messages

* fix(agent): address review feedback on beforeRun/afterRun hooks

- Normalize stream done event to always yield AgentRunResult
- Move transitionTo('completed') after afterRun to fix state ordering
- Strip hook functions from BeforeRunHookContext.agent to avoid self-references
- Pass originalPrompt to applyHookContext to avoid redundant message scan
- Clarify afterRun JSDoc: not called when the run throws
- Add tests: error-path skip, outputSchema+afterRun, ctx.agent shape, multi-turn hooks
2026-04-05 00:41:21 +08:00
Ibrahim Kazimov 944918d5ae
Merge branch 'main' into main 2026-04-04 13:43:40 +03:00
Marcelo Ceccon 10074c9b7d
feat(llm): add first-class Grok (xAI) support with dedicated GrokAdapter (#44)
feat(llm): add first-class Grok (xAI) support with dedicated GrokAdapter
2026-04-04 18:20:55 +08:00
JackChen 0111876264
feat: add onTrace observability callback (#18)
Add lightweight onTrace callback to OrchestratorConfig that emits
structured span events (llm_call, tool_call, task, agent) with timing,
token usage, and runId correlation. Zero overhead when not subscribed.

Closes #18
2026-04-03 15:28:59 +08:00
JackChen 4d7564b71a
feat: task-level retry with exponential backoff (#37)
* feat: add task-level retry with exponential backoff

Add `maxRetries`, `retryDelayMs`, and `retryBackoff` to task config.
When a task fails and retries remain, the orchestrator waits with
exponential backoff and re-runs the task with a fresh agent conversation.
A `task_retry` event is emitted via `onProgress` for observability.
Cascade failure only occurs after all retries are exhausted.

Closes #30

* fix: address review — extract executeWithRetry, add delay cap, fix tests

- Extract `executeWithRetry()` as a testable exported function
- Add `computeRetryDelay()` with 30s max cap (prevents runaway backoff)
- Remove retry fields from `ParsedTaskSpec` (dead code for runTeam path)
- Deduplicate retry event emission (single code path for both error types)
- Injectable delay function for test determinism
- Rewrite tests to call the real `executeWithRetry`, not a copy
- 15 tests covering: success, retry+success, retry+failure, backoff
  calculation, delay cap, delay function injection, no-retry default

* fix: clamp negative maxRetries/retryBackoff to safe values

- maxRetries clamped to >= 0 (negative values treated as no retry)
- retryBackoff clamped to >= 1 (prevents zero/negative delay oscillation)
- retryDelayMs clamped to >= 0
- Add tests for negative maxRetries and negative backoff

Addresses Codex review P1 on #37

* fix: accumulate token usage across retry attempts

Previously only the final attempt's tokenUsage was returned, causing
under-reporting of actual model consumption when retries occurred.
Now all attempts' token counts are summed in the returned result.

Addresses Codex review P2 (token usage) on #37
2026-04-03 14:08:36 +08:00
JackChen fbc5546fa1
feat: add optional outputSchema (Zod) for structured agent output (#36)
When `outputSchema` is set on AgentConfig, the agent's final text output
is parsed as JSON, validated against the Zod schema, and exposed via
`result.structured`. On validation failure a single retry with error
feedback is attempted automatically.

Closes #29
2026-04-03 13:45:47 +08:00
MrAvalonApple 2bb220fc63 feat: add support for Gemini model 2026-04-02 21:41:56 +03:00
JackChen 62d6fa9e26 feat: add baseURL and apiKey support for OpenAI-compatible APIs
Enable connecting to any OpenAI-compatible API (Ollama, vLLM, LM Studio,
etc.) by adding baseURL and apiKey fields to AgentConfig and
OrchestratorConfig, threaded through to adapter constructors.

- OpenAIAdapter and AnthropicAdapter accept optional baseURL
- createAdapter() forwards baseURL to both adapters, warns if used with copilot
- All execution paths (runAgent, runTeam coordinator, buildPool) merge defaults
- Fully backward compatible — omitting new fields preserves existing behavior
2026-04-02 19:33:10 +08:00
Deathwing eedfeb17a2 feat: add GitHub Copilot as LLM provider
- Add CopilotAdapter with OAuth2 device flow authentication
- Token exchange via /copilot_internal/v2/token with caching
- Premium request multiplier system (getCopilotMultiplier)
- Full model metadata catalog (COPILOT_MODELS)
- Add 'copilot' to SupportedProvider and provider union types
- Add example: examples/05-copilot-test.ts
2026-04-02 01:45:43 +02:00
JackChen a6244cfe64 Initial release: open-multi-agent v0.1.0
Production-grade multi-agent orchestration framework.
Model-agnostic, supports team collaboration, task scheduling
with dependency resolution, and inter-agent communication.
2026-04-01 04:33:15 +08:00