Skip to content

Releases: anima-research/agent-framework

v0.3.0

23 Apr 10:04

Choose a tag to compare

Highlights

Batch of conhost-driven improvements to MCPL plumbing, channel/typing semantics, the workspace watcher, and framework surface area.

MCPL

  • Per-server tool allow/deny policyenabledTools / disabledTools on McplServerConfig, bare names with * substring wildcards. Dual-gated: tools are filtered both at tools/list time (model never sees them) and at dispatch time (calls rejected with a tool-result error). The dual gate is deliberate — schema omission alone doesn't stop a model from imitating a denied call it's already seen in its own prior message history. Deny wins over allow on overlap. Regex metacharacters in patterns are escaped; only * is special. (#26, 0452663)
  • Subprocess stderr forwarded as mcpl:server-stderr trace events — child stderr was previously silently dropped. Every line becomes a trace event keyed on serverId, with pre-handshake lines buffered and drained once the instance exists; rebindable for the reconnect probe → persistent swap. (#26, 7225364)
  • Opaque routing metadata on channels/typingsendChannelsTyping / ChannelRegistry.startTyping accept an optional Record<string, unknown> that travels with the notification. Intentionally untyped per-server: Zulip reads topic, others pick their own keys. The registry caches per-channel metadata so the 7s refresh stays on the same thread. (#26, af4b679)
  • Explicit op: 'start' | 'stop' on typingChannelRegistry.stopTyping dispatches one final stop before clearing the interval, so servers that support explicit stop (Zulip) clear immediately instead of waiting for auto-expire. Metadata carries on the stop too. Single-channel stopTyping and global stopTyping() have symmetric semantics: both dispatch stop only for channels that had an active interval. (#26, 7be4c71, 32cb10c)
  • Immediate refresh on mid-typing metadata changestartTyping(ch, newMetadata) on an already-typing channel now dispatches an immediate notification when the metadata differs from the cached one, instead of waiting up to 7s for the next refresh tick. This is the Zulip topic-switch case — newer incoming message moves the relevant topic, caller bumps startTyping, server sees the new routing within the current request. (32cb10c)

Framework

  • AgentFramework.channels getterChannelRegistry was a private field; modules that need channel-level ops (typing indicators, default-publish channel selection) had no way in. Returns null when no MCPL servers are configured; ChannelRegistry is re-exported from the package entry so consumers can type against it. (#26, f521991)

Workspace

  • Public WorkspaceModule.resolveAbsolutePath — turns a mount-prefixed path (mount/sub/file.md) into an absolute FS path without peer modules reaching into private parsePath state. Honors the same CWE-22 traversal guard. (#26, cf882e1)
  • chokidar silent-failure mitigations — reproducibly on Linux/WSL (and consistent with macOS), chokidar 4's fs.watch backend silently drops events when the watched path — or any parent directory — doesn't exist at subscribe time, and surfaces no error unless an error handler is attached. Post-failure state is indistinguishable from watching an empty directory. Three canonical-chokidar mitigations: (#26, 8961a7f)
    • MountWatcher.start() mkdir -p's the watch path for read-write mounts before attach. Read-only mounts are left alone.
    • WatcherLifecycle callbacks (onReady, onError) give the workspace module observability into the watcher's attach state. Errors forward as workspace:watcher-error events.
    • Mount state now carries watcherReadyAt + watcherError, persisted via snapshot. A null watcherReadyAt on a live mount means watcher never attached; a set timestamp with an empty tree means attached-but-empty. watcherReadyAt is intentionally not restored across restarts — a stale timestamp would mask a fresh attach failure.
    • Does not address the inode-replace failure mode (dir rm'd + recreated post-subscribe); chokidar can't recover from that without re-attach logic, and @parcel/watcher is the better fix when that's prioritized.

Tests

Adds test/channel-registry-typing.test.ts (6 cases) and test/tool-policy.test.ts (8 cases); extends test/workspace-watcher.test.ts. Full suite: 88 tests across 7 files.

Full changelog

v0.2.0…v0.3.0: v0.2.0...v0.3.0