* feat: expose custom MemoryStore via TeamConfig.sharedMemoryStore (#156)
The MemoryStore interface was already public, and SharedMemory / TeamInfo
already used the interface internally. This adds the final user-config wire
so integrators can attach custom backends (Redis, Postgres, Engram, etc.)
without hacking SharedMemory private fields.
Priority: sharedMemoryStore > sharedMemory: true > no memory.
Fully backward-compatible: existing sharedMemory: true users see no change.
SDK-only: the CLI cannot pass runtime objects through JSON config.
Closes#156.
* fix: validate sharedMemoryStore shape and reject from CLI JSON
Addresses Codex P2 review on #157. Plain objects from untrusted JSON could
previously reach `new SharedMemory(plainObject)` and crash later on the first
`.set`/`.list` call with a cryptic TypeError.
Defense-in-depth:
- SharedMemory constructor performs a runtime shape check and throws a clear
TypeError if the provided store does not implement get/set/list/delete/clear.
- CLI `asTeamConfig` explicitly rejects `sharedMemoryStore` in JSON with a
message pointing to the SDK path, since this field is documented SDK-only.
Adds 4 tests covering malformed stores (plain object, partial interface,
null, Team constructor path).
* fix: route falsy-but-present sharedMemoryStore through shape check
Addresses Codex finding 2 on #157. The truthy gate silently skipped falsy
values (null, 0, ''), letting config bugs downgrade to the default in-memory
store or no memory instead of failing fast.
Switched to `!== undefined` so any present value reaches SharedMemory's
runtime shape check and throws a clear TypeError. Adds 2 tests: null as a
bogus store throws; omitting the field still honors `sharedMemory: true`.
* docs: restructure Ecosystem section, add Engram integration
Merge Used by and Integrations into one ## Ecosystem section with three
tiers (In production, Integrations free, Featured Partner $3,000/yr).
Drop Philosophy section (covered in DECISIONS.md). Add Engram to free
tier with maintainer's original tagline verbatim. Mirror in README_zh.md.
* chore: add repository, homepage, and bugs npm metadata
Standard fields so npm and GitHub surface source links.
* docs: README consistency pass
- Architecture diagram: add AzureOpenAIAdapter (missed when #143 landed).
- Quick Start: promote CLI (oma) to ### subheading for discoverability.
- Ecosystem: drop hardcoded "5,500+ stars"; shield badge is the live source.
- Intro: bump "Opus 4.6" example to "Opus 4.7" (prose only; code defaults
unchanged, to revisit separately).
- Supported providers: drop the "Gemma 4" sentence that contradicted the
5-model list below it.
- Stats images: bump cache-buster to 20260423 for contrib.rocks and
star-history so GitHub camo refetches.
Mirror in README_zh.md.
- New AzureOpenAIAdapter using AzureOpenAI client from openai SDK
- Registered 'azure-openai' in SupportedProvider and createAdapter()
- model field is primary deployment name; AZURE_OPENAI_DEPLOYMENT as fallback
- Default api-version: 2024-10-21
- Example in examples/providers/azure-openai.ts
- 14 tests covering chat, stream, tool_use, deployment fallback, error path
- Updated README.md, README_zh.md, examples/README.md, src/cli/oma.ts
Adds `oma run --dashboard` to write a static post-execution DAG HTML to `oma-dashboards/runTeam-<timestamp>.html`.
- Pure `renderTeamRunDashboard(result: TeamRunResult)` in `src/dashboard/`, no FS/network I/O in the library
- `TeamRunResult` gains `goal` + `tasks: TaskExecutionRecord[]` (with `TaskExecutionMetrics`)
- `layoutTasks()` extracted as pure function with cycle detection
- XSS mitigations: `application/json` payload, `</script>` escape, `textContent`-only node rendering
- CLI awaits write before exit (no race with `process.exit`)
Closes#4
Co-authored-by: Ibrahim Kazimov <74775400+ibrahimkzmv@users.noreply.github.com>
patterns/ is for orchestration primitives (fan-out, handoff, retry, etc.).
Use-case-driven examples like meeting-summarizer fit better in a new
cookbook/ bucket, positioned between patterns/ and production/ in
acceptance bar. meeting-summarizer.ts relocated; paths stay valid since
directory depth is unchanged.
Adds examples/patterns/meeting-summarizer.ts — fan-out pattern
tailored for meeting transcripts. Three specialists run in parallel
on the same transcript:
- summary: three-paragraph prose summary
- action-items: Zod-validated { task, owner, due_date? }[] schema
- sentiment: Zod-validated per-participant tone + evidence
Each specialist's wall duration is recorded, and the script asserts
parallel wall time < 70% of the sum of per-agent durations to prove
fan-out gives a real speedup. An aggregator then merges the three
outputs into a single Markdown report with four H2 sections
(Summary, Action Items, Sentiment, Next Steps).
Ships with examples/fixtures/meeting-transcript.txt — a 350-word
engineering standup transcript designed so the three schemas exercise
cleanly (concrete owners + due dates for action items, a mixed-tone
on-call engineer for sentiment).
Lint and test pass on upstream/main.
Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Codecov bot posts a coverage summary on every PR, plus an "install the
Codecov app" nudge. The badge in the README is enough signal; the PR
comments are noise for contributors. Add minimal codecov.yml with
comment: false to disable them.
Coverage upload from CI still works. Only the PR commenting is off.
Install size (14MB) muddles the "lightweight" story even though it's a
typical size for projects with LLM SDK deps. Runtime dep count (3) is
the actual architectural commitment being promised.
Static badge is acceptable here because the number is a deliberate
design constraint documented in DECISIONS.md, not a naturally-drifting
metric. If it ever changes, the README body text ("3 runtime
dependencies") has to change too.
Bundlephobia's shields.io proxy frequently hits upstream rate limits
and shows an error state. Packagephobia is more reliable and its
install-size number is on-message for the "3 deps, lightweight" story.
- Replace the static fake coverage badge with codecov.
- Add npm version and bundlephobia bundle-size badges.
- Add test:coverage script and lcov reporter so CI can upload.
- Add a coverage job in CI that uploads to codecov on Node 20.
Requires CODECOV_TOKEN secret to be set in the repo for the badge to
populate; until then the badge will display "unknown".
* chore: trim README of stale facts and tighten examples section
- Drop the "41 source files" tagline. The count drifts every time we
add a file, and lower-bound trivia is not what someone reading the
README needs in the first 10 lines.
- Update the coverage badge to 85% to match the actual `vitest run
--coverage` output (was 88%, written by hand and stale).
- Rebalance the Examples highlights from 8 lines to 7. The previous
list listed three providers individually (`minimax`, `deepseek`,
`groq`) which read like a wall, replaced with one umbrella bullet
pointing at `examples/providers/`. The standalone Ollama bullet
is now covered by the same umbrella.
- Replaced "Examples" in the Contributing section with a more
specific "Production examples" pointer to the new
`examples/production/README.md` acceptance criteria, so the new
category has a real entry point for would-be contributors.
Both English and Chinese READMEs updated in parallel.
* chore: de-AI README prose and strip em-dashes
Remove em-dashes from both READMEs and rewrite the Chinese version's
translation-ese sections (vs. comparisons, philosophy paragraph, bold
feature-benefit bullets) with more natural phrasing.
Examples grew to 19 flat files mixing basics, provider demos, orchestration
patterns, and integrations, with two files colliding on the number 16.
Reorganized into category folders so the structure scales as new providers
and patterns get added.
Layout:
examples/basics/ core execution modes (4 files)
examples/providers/ one example per supported model provider (8 files)
examples/patterns/ reusable orchestration patterns (6 files)
examples/integrations/ MCP, observability, AI SDK (3 entries)
examples/production/ placeholder for end-to-end use cases
Notable changes:
- Dropped numeric prefixes; folder + filename now signal category and intent.
- Rewrote former smoke-test scripts (copilot, gemini) into proper three-agent
team examples matching the deepseek/grok/minimax/groq template. Adapter
unit tests in tests/ already cover correctness, so this only improves
documentation quality.
- Added examples/README.md as the categorized index plus maintenance rules
for new submissions.
- Added examples/production/README.md with acceptance criteria for the new
production category.
- Updated all internal npx tsx paths and import paths (../src/ to ../../src/).
- Updated README.md and README_zh.md links.
- Fixed stale cd paths inside examples/integrations/with-vercel-ai-sdk/README.md.
Implements `delegate_to_agent` built-in tool (closes#63). Opt-in registration via `includeDelegateTool`; only wired up by `runTeam` / `runTasks` for pool workers. Guards: self-delegation, unknown target, cycle detection via `delegationChain`, depth cap (`maxDelegationDepth`, default 3), pool deadlock.
Delegation runs on ephemeral Agent instances via `AgentPool.runEphemeral` (pool semaphore only, no per-agent lock) so mutual delegation (A→B while B→A) can't deadlock. Delegated run `tokenUsage` surfaces via `ToolResult.metadata` and rolls into the parent runner's total before the next budget check; delegation tool_result blocks are exempt from `compressToolResults` and the `compact` strategy. Best-effort SharedMemory audit writes at `{caller}/delegation:{target}:{ts}-{rand}`.
Picks up @NamelessNATM's work from #84 and adds cycle detection, token aggregation, compression exemption, mutual-delegation deadlock fix (Codex P1), and tool_result-preservation on budget-exceeded (Codex P2).
Co-authored-by: NamelessNATM <hamzarstar@gmail.com>
- Document AgentConfig.customTools alongside agent.addTool()
- Add Tool Output Control section (maxToolOutputChars, maxOutputChars, compressToolResults)
- Add Context Management section covering all four strategies (sliding-window, summarize, compact, custom)
- Bump examples count 18 to 19 and add example 16 (MCP) and example 19 (Groq) to curated list
- Sync README_zh with README: add CLI (oma) note, full MCP Tools section, Groq row in providers table
- Drop stale rentech-quant-platform entry from Used by
* feat: add rule-based compact context strategy (#111)
Add `contextStrategy: 'compact'` as a zero-LLM-cost alternative to `summarize`.
Instead of making an LLM call to compress everything into prose, it selectively
compresses old turns using structural rules:
- Preserve tool_use blocks (agent decisions) and error tool_results
- Replace long tool_result content with compact markers including tool name
- Truncate long assistant text blocks with head excerpts
- Keep recent turns (configurable via preserveRecentTurns) fully intact
- Detect already-compressed markers from compressToolResults to avoid double-processing
Closes#111
* fix: remove redundant length guard and fix compact type indentation
When minChars is set low, compressed markers could be re-compressed
with incorrect char counts. Skip blocks whose content already starts
with the compression prefix.
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
* 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
* 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.
Previously runtime-added tools bypassed all filtering including
disallowedTools, contradicting the documented behavior. Now custom
tools still bypass preset/allowlist but respect the denylist.
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
Helps maintainers triage by requiring contributors to indicate where
the idea originated (real use case, competitive reference, systematic
gap, or external discussion).
- #99: pass per-call effectiveAbortSignal to buildToolContext() so tools
receive the correct signal instead of the static runner-level one
- #100: replace manual pending-task loop with queue.skipRemaining() on
abort, fixing blocked tasks left non-terminal and missing events
- #101: forward abortSignal in Gemini adapter's buildConfig() so the
SDK can cancel in-flight API calls
- Add 8 targeted tests for all three fixes
run() only handled 'done' events from stream(), silently dropping
'error' events. This caused failed LLM calls to return an empty
RunResult that the caller treated as successful.