Skip to content

v0.10.0

Choose a tag to compare

@devoidfury devoidfury released this 19 Sep 14:55
· 158 commits to main since this release
  • [BRK] removed the profile-level role field. The only "role" concepts that remain are the message-format wire encoding (Message.role, role-mapping) and plain prose in user-supplied context files.

    • Profile files with role: frontmatter still parse -- the key is dropped and can never reach prompt assembly (covered by tests asserting a profile role can never leak into the system prompt).
    • Config keys role and taskDefaultRole and the --role flag are gone; the {{ role }} placeholder was removed from the default system prompt template. If you had a role line, fold it into the profile body.
  • [BRK] internals / hooks - pipeline handlers now patch the payload. Whatever a handler returns is written onto the payload, field by field, so every later handler and core read one thing: the payload. This replaces reading "the last handler's whole return value" at each call site, which silently dropped earlier patches — a provider:request handler returning { modelConfig } followed by one returning { messages } used to lose the model. Same rule now covers context ({ messages }), provider:request, provider:response, tool:result, tool:call, input, and command:dispatch. Non-object returns (a bare array, a string) are not patches and are ignored. runHookPipeline() no longer returns a lastResult field; results (every return, in order) and stopped remain. The now-dead type-guard helpers (isGateActionBlock/Modify/Continue/Handled, isInputTransform, isInputHandled) are removed: call sites directly read the payload's action.

  • extensions - new opt-in tier: @experimental in extension_paths loads src/experimental/ (the setting replaces the default, so use ["@extensions", "@experimental"] to keep the built-ins). First entry: file-watch, cooperative-editing awareness for a shared working tree — it tracks the files a session reads and writes, notices when the bytes on disk stop matching what the session believes, rides that onto each request as a harness system-notice, and blocks an overwrite onto a file that changed underneath the session.

  • fix - duplicate message delivery in the core agent loop: a UI host calling run() after SessionManager had already started the loop spawned a second consumer on the same queue, so one queued message could drive two agent.run() calls (the loser threw AlreadyRunning). run()/runUntilCancelled() are now idempotent -- a later call joins the active loop instead of racing it.

  • tools - a batch of core-tool and extension fixes found by auditing src/extensions/:

    • project_info: the non-git file listing was computed relative to the process CWD instead of the requested directory, so listing a directory from another launch dir produced absolute/../ paths.
    • web_search: the results count entry reported the number of output lines instead of the number of results (e.g. 3 results with descriptions read as 9).
    • find: max_results: 0 was accepted and silently returned "No files found" even when matches exist; it now falls back to the default like any other sub-minimum value. The file_type tool schema now documents the empty-file filter ("e") the code already supported.
    • read: files above 1MB are now read with a single streaming pass (the whole-file read is kept for small files), so paginating a multi-GB log no longer materializes the entire file in memory per call.
  • config - removed two dead config keys: coreTools.maxDiffSize and handoffTool.systemPrompt (declared in schema and docs, read by no code). Added the missing layers block to the loop config schema, which had left loop.* settings outside the config resolution pipeline.

  • question tool: the schema no longer marks key as required — it was always auto-generated from the prompt when omitted.

  • hooks - notifyHooks() is now awaitable: handlers start immediately in registration order (async ones run in parallel). Core call sites now await it where later code depends on the effect: the tool pipeline (TOOL_BEFORE_EXECUTE, AGENT_TOOL_CONTEXT, TOOL_AFTER_EXECUTE, TOOL_METRICS), turn boundaries (TURN_START/TURN_END), session create/swap, the bootstrap registration hooks, and SHUTDOWN_CLEANUP. Previously an async AGENT_TOOL_CONTEXT handler could complete its tool-context mount after the TOOL_CALL gate (e.g. the user-gate approval seam) had already run. Signature note: notifyHooks() returns Promise<void> (was void); unawaited call sites keep the old behavior.

Full Changelog: v0.9.2...v0.10.0