Skip to content

Latest commit

 

History

History
223 lines (182 loc) · 15.2 KB

File metadata and controls

223 lines (182 loc) · 15.2 KB

Changelog

All notable changes to @oni.bot/core are documented here.

Format follows Keep a Changelog. This project uses Semantic Versioning.

[1.2.0] — 2026-03-16

Automated bug pipeline sweep: 90 bugs found, fixed, and independently verified (BUG-0024 through BUG-0182). Primarily security hardening and reliability improvements across the entire codebase.

Security — Injection & Traversal

  • Path traversal prevention: persistSemantic(), persistEpisodic(), persistInternal(), safeSkillPath(), and GitHub API calls now validate/sanitize paths (BUG-0064, 0075, 0100, 0101, 0106, 0163, 0166)
  • Null-byte injection: Stripped from sessionId, domain, and topic fields before filesystem operations (BUG-0163, 0166)
  • Command injection: execSync replaced with execFileSync (array args) in CLI commands; shell:true removed from spawn (BUG-0063, 0104)
  • Prototype pollution: deepMerge filters __proto__/constructor/prototype keys; recursive strip in modifiedInput (BUG-0062, 0144)
  • Mermaid injection: Bracket characters escaped in node labels to prevent diagram injection (BUG-0174)
  • Role string sanitization: LLM message interpolation sites in supervisor sanitized (BUG-0173)
  • LLM-generated skill validation: Content validated before writing to disk (BUG-0157)
  • ReDoS prevention: Replaced vulnerable rm -rf regex with O(n) token-based check (BUG-0180)

Security — SSRF & Exfiltration

  • URL scheme validation: All model factories (anthropic, openai, openrouter, google, ollama) and A2AClient now reject non-HTTP(S) baseUrl schemes to prevent API key exfiltration (BUG-0105, 0141, 0142, 0143, 0170, 0179)
  • API key validation: All model factories throw at construction time if API key is missing (BUG-0098, 0099, 0159)

Security — Information Disclosure

  • Error message sanitization: Raw API response bodies replaced with generic status messages across all model adapters, GitHub, Firecrawl, web-search, and A2A handlers (BUG-0076, 0102, 0111, 0155, 0161, 0164, 0165, 0167)

Security — Access Control & DoS

  • TOCTOU race fix: checkAllowedPath() returns resolved path; all 6 filesystem handlers use it for I/O (BUG-0065, 0181)
  • Fail-closed semantics: Empty allowedPaths now throws instead of allowing all access; hook timeouts fail-closed for security-critical events (BUG-0149, 0168, 0169)
  • Default-deny permissions: Missing agent entries in permission config now deny by default (BUG-0172)
  • Safety gate strictness: approved field checked with strict boolean equality (BUG-0162)
  • Body size limits: A2A server enforces 1MB max body; requestHandler() enforces MAX_BODY_SIZE for Fetch-API callers (BUG-0077, 0145)
  • Buffer overflow guards: MCP StdioTransport enforces MAX_BUFFER_SIZE; LSP client caps buffer at 64MB (BUG-0068, 0182)
  • Unbounded growth caps: ExperimentLog capped at 1000 records; DeadLetterQueue at 100 per thread (BUG-0129, 0130)
  • CORS enforcement: A2A server adds preflight handling and Content-Type enforcement (BUG-0171)

Security — Cryptographic

  • PRNG hardening: Math.random replaced with crypto.randomUUID for HITL resume IDs, broker IDs, and generateId() (BUG-0095, 0103, 0122)

Fixed — Reliability

  • Shared mutable state: 6 module-level counters/maps moved to per-instance scope to prevent cross-tenant interference (BUG-0070, 0082, 0083, 0092, 0123, 0134)
  • Race conditions: refreshTools() coalescing lock prevents concurrent races; fileVersions re-read at increment point; race timeout properly cleared (BUG-0124, 0125, 0127)
  • Resource leaks: ReadableStream reader released in finally block; onAny() returns unsubscribe function (BUG-0079, 0128)
  • Lifecycle events: SessionEnd fires on all loop exit paths including HITL interrupt; telemetry span closes on interrupt (BUG-0080, 0086)
  • Redis atomicity: SET+ZADD combined into single Lua script for put(); DEL+ZREM wrapped in MULTI/EXEC (BUG-0073, 0096, 0126)
  • ESM compatibility: require() calls replaced with static ESM imports in SkillLoader and safeSkillPath (BUG-0078, 0081)
  • Stream resilience: OpenRouter adapter handles usage-only SSE chunks and guards choices dereference; SafetyGate.check() handles non-string/non-array content (BUG-0153, 0178)
  • Error handling: JSON-RPC handler catches sync throws; spawn processes get error event handlers; JSONL parsing skips malformed lines (BUG-0029, 0114, 0115, 0150)
  • Input validation: fromJSON validates input shape; nested object schemas enforce required fields; validate callback invoked on resumed user input; Object.freeze no longer blocks VM result write-back (BUG-0024, 0112, 0151, 0152)
  • Minor fixes: Empty CSV guard, PII regex /g flag removal, Slack username/iconEmoji passthrough, round-robin over full slot list, structuredClone fallback, dotless path guard in getLoader, null-safe refreshTools, unknown channel key filtering, state method signature alignment, E2B timeout cleanup, off-by-one in fireSessionEnd turn count, fallback truncation continue fix (BUG-0025, 0026, 0027, 0028, 0030, 0067, 0090, 0093, 0107, 0120, 0121, 0133, 0136, 0137, 0154, 0175)

Added

  • 8 new test files covering prototype pollution, hooks eval bypass, PII regex safety, skill evolver ESM paths, DAG unsatisfiable deps, supervisor routing errors, wrap-agent loop errors, and A2A handler subscribe errors

[1.1.1] — 2026-03-15

Fixed

  • Deep equal cycle guard: Two separate WeakSets for independent object tracking prevents false equality on cyclic structures
  • Direction-aware improvement check: ExperimentalExecutor now correctly evaluates optimization direction
  • ESM error code: Postgres store uses ERR_MODULE_NOT_FOUND (correct ESM code) instead of MODULE_NOT_FOUND
  • Streaming tool-call ID collisions: Counter-based IDs prevent duplicates in parallel tool calls
  • SSE error propagation: Nested try/catch with controller.error for proper stream error handling
  • Fallback truncation: continue instead of break so oversized messages don't halt truncation
  • Silent parse failures: console.warn surfaced across all 5 model adapters and responseFormat parsers
  • Postgres checkpoint deserialization: Runtime validation on restored checkpoint data
  • PubSub subscriber errors: Errors in subscriber callbacks are now logged instead of silently swallowed
  • Bridge tracer cleanup: startTimes map entries removed on unsubscribe to prevent memory leaks
  • MCP client error propagation: .catch() reordered so callback errors propagate correctly
  • Mermaid graph rendering: Router-to-target edges now render correctly in toMermaid()
  • contentLength() accounting: Tool call tokens included in content length calculation
  • interruptAfter parallel safety: Moved to post-loop pass to avoid interrupting mid-superstep
  • executeTools parallel safety: parallelSafe check now matches defineAgent pattern
  • EventBus dispose: waitFor promises correctly reject on bus disposal
  • Harness hooks engine: Error isolation between hook handlers
  • OpenAI adapter streaming: Robust chunk parsing for partial SSE frames
  • Skill evolver: Pattern learner and evolver state management fixes
  • Redis store: Connection lifecycle and error handling improvements

Changed

  • Removed internal planning documents from repository (architecture docs, bug trackers, sprint plans)
  • Moved developer guide to root level (GUIDE.md)

[1.0.2] — 2026-03-13

Fixed

  • Budget guardrails: BudgetTracker.record() is now called from defineAgent after each model.chat() via a RunContext callback; throws BudgetExceededError when maxTokensPerRun/maxTokensPerAgent/maxCostPerRun is exceeded.
  • defineAgent ToolContext: store and stream emit now read from the live RunContext instead of being hard-coded to null/noop, so tools receive the real store and can emit custom stream events.
  • parallelSafe enforcement: parallelSafe: false is now preserved through ToolDefinition and respected by defineAgent — when any tool in a batch has parallelSafe: false all calls in that step execute sequentially.
  • pathMap compile-time validation: StateGraph.compile() now validates conditional edge pathMap targets at compile time, throwing NodeNotFoundError instead of failing silently at runtime.
  • spawnAgent in unsupervised swarms: spawnAgent() now throws a clear error when called on a swarm without a supervisor, rather than silently adding an agent that never executes.
  • removeAgent edge cleanup: removeAgent() now removes stale static edges pointing to the removed node from _edgesBySource, preventing NodeNotFoundError when Pregel tries to route to a removed agent.
  • Lifecycle events from defineAgent: llm.request, llm.response, tool.call, and tool.result events are now emitted and audit entries written for every model call and tool execution inside defineAgent.
  • toolPermissions enforcement: checkToolPermission() is called before each tool execution in defineAgent, outside the tool's try/catch, so ToolPermissionError propagates as a real graph failure.

[1.0.1] — 2026-03-13

Fixed

  • Token streaming (parallel nodes): Replaced module-level _tokenHandler global with AsyncLocalStorage — each node in a parallel fan-out now gets its own token handler, preventing tokens from being silently dropped or misrouted to the wrong node.
  • HITL resume: resume() now looks up the session by resumeId (not just the first pending interrupt) and calls markResumed() so sessions transition from "pending" to "resumed" after being handled.
  • Subgraph checkpointer restore: The child runner's original checkpointer is saved before being overwritten with a NamespacedCheckpointer and restored after the subgraph completes, preventing the child's checkpointer from leaking across invocations.
  • Circuit breaker fallback: The user-supplied fallback(state, error) is now called with the real node state and the CircuitBreakerOpenError instance rather than (undefined, undefined).

[1.0.0] — 2026-03-13

Breaking Changes

  • oni-code AI coding assistant extracted to @oni.bot/code (separate package)
  • sentinel code analysis engine extracted to @oni.bot/sentinel (separate package)
  • oni and oni-code CLI binaries removed from this package (install @oni.bot/code for the CLI)

Added

  • ./config sub-module export (@oni.bot/core/config) — JSONC config loader with env var substitution and hierarchical merge
  • "sideEffects": false — enables full tree shaking in bundlers

Framework

  • 5 model adapters (anthropic, openai, openrouter, google, ollama) — zero runtime dependencies
  • 21 total exports: root + 20 named subpaths

[0.7.0] - 2026-03-08

Added

  • Structured error codes with ONI_<CATEGORY>_<NAME> taxonomy — every error carries code, category, recoverable flag, suggestion, and context
  • Per-node timeouts via addNode(name, fn, { timeout: ms }) with NodeTimeoutError
  • Global default timeout via compile({ defaults: { nodeTimeout: ms } })
  • Circuit breaker pattern: addNode(name, fn, { circuitBreaker: { threshold, resetAfter, fallback? } })
  • Dead letter queue: compile({ deadLetterQueue: true }) captures failed node inputs for recovery
  • OpenTelemetry tracing adapter (ONITracer) — zero-dep, user brings own tracer
  • Backpressure streaming with BoundedBuffer (drop-oldest and error strategies)
  • Testing utilities: mockModel(), assertGraph(), createTestHarness() via @oni.bot/core/testing
  • oni init CLI command for project scaffolding
  • 7 new error types: NodeTimeoutError, CircuitBreakerOpenError, SwarmDeadlockError, ModelRateLimitError, ModelContextLengthError, CheckpointCorruptError, StoreKeyNotFoundError

Changed

  • ONIError now accepts optional ONIErrorOptions as second constructor parameter
  • All existing error classes enhanced with structured codes (backward compatible)

[0.6.3] - 2026-03-05

Added

  • set() alias for put() on InMemoryStore and NamespacedStore

[0.6.2] - 2026-03-05

Fixed

  • createReactAgent now accepts ONIModel (auto-adapts chat to invoke)

Changed

  • Package renamed from @oni-bot/core to @oni.bot/core

[0.6.1] - 2026-03-05

Changed

  • Removed all external framework references from codebase and documentation

Fixed

  • Resolved TypeScript strict errors in swarm template Send casts

[0.6.0] - 2026-03-04

Added

  • SwarmGraph builder for multi-agent orchestration
  • SwarmGraph.hierarchical() template — supervisor-workers pattern
  • SwarmGraph.fanOut() template — parallel agent execution with reducer
  • SwarmGraph.pipeline() template — linear chain with conditional transitions
  • SwarmGraph.peerNetwork() template — decentralized agent handoffs
  • SwarmGraph.mapReduce() template — parallel map with reducer
  • SwarmGraph.debate() template — multi-round parallel debate with judge
  • SwarmGraph.hierarchicalMesh() template — nested team coordination
  • Lazy coordination auto-wiring (broker and pubsub) on SwarmGraph
  • Handoff execution — agent Handoff returns converted to Command routing
  • Retry-then-fallback — agents retry on failure, fall back to supervisor

Changed

  • Replaced SwarmLLM with ONIModel in supervisor routing

[0.5.0] - 2026-03-04

Added

  • ONIModel interface and core LLM types
  • Anthropic LLM adapter
  • OpenAI LLM adapter
  • Ollama LLM adapter
  • Google Gemini LLM adapter
  • Models export path and re-exports
  • Tool framework with defineTool() and ToolContext
  • AgentContext and agent types
  • defineAgent() declarative agent factory
  • agent() functional agent factory
  • addAgent() on StateGraph to wire agent nodes
  • Request/response and pub/sub coordination patterns
  • Tool permission guardrails
  • Budget tracking and cost control guardrails
  • Content filtering guardrails
  • Audit trail and guardrails exports
  • EventBus for structured lifecycle events
  • Guardrails and event bus wired into compile/execution pipeline
  • Integration tests for agents, tools, and guardrails

Removed

  • Direct openai dependency (adapters are now bring-your-own-client)

[0.4.0] - 2026-03-04

Added

  • StateGraph builder with addNode(), addEdge(), addConditionalEdges()
  • Pregel execution engine (ONIPregelRunner) with parallel superstep execution
  • Command and Send primitives for dynamic routing
  • Subgraph support via addSubgraph()
  • Functional API (entrypoint, task)
  • MemoryCheckpointer and NoopCheckpointer
  • InMemoryStore and NamespacedStore for shared key-value state
  • Human-in-the-loop via interrupt() and getUserInput()
  • Token streaming with emitToken() and TokenStreamWriter
  • Stream modes: values, updates, events, messages, custom
  • Graph inspection via getGraphDef()
  • createReactAgent prebuilt for tool-calling loops
  • ToolNode prebuilt for automatic tool dispatch
  • Messages reducer (messagesReducer, addMessages, removeMessages)
  • Retry policies with configurable backoff
  • Swarm primitives: AgentRegistry, AgentPool, Mailbox, Supervisor
  • Ephemeral channel support
  • Map-reduce parallel fan-out pattern