Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: docker/docker-agent
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 6c79176
Choose a base ref
...
head repository: docker/docker-agent
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 514714b
Choose a head ref
  • 19 commits
  • 48 files changed
  • 5 contributors

Commits on Apr 23, 2026

  1. Configuration menu
    Copy the full SHA
    a53b8e1 View commit details
    Browse the repository at this point in the history

Commits on Apr 25, 2026

  1. fix(tui): make user_prompt elicitation dialog scrollable

    Fixes #2495.
    
    When `user_prompt` opens an elicitation pop-up with many enum items
    (or many fields, or a long message) the dialog overflowed the bottom
    of the terminal with no way to access the clipped content — neither
    visually nor for keyboard navigation.
    
    The body region (message + fields, or message + free-form input) is
    now rendered inside a scrollview, capped at 80% of the terminal
    height (max 40 rows). Title/separator stay fixed at the top, the help
    line stays fixed at the bottom.
    
    - The scrollview consumes mouse wheel, scrollbar drag, and
      PgUp/PgDn/Home/End. Up/Down keep their existing role of cycling
      enum/boolean selections.
    - Auto-scroll keeps the focused field's active line visible: Tab /
      Shift-Tab brings the new field into view, and Up/Down inside an
      enum/boolean keeps the selected option in view even when the field
      itself is taller than the viewport. Submit-with-error focuses and
      scrolls to the offending field.
    - Mouse clicks translate the absolute Y through the current scroll
      offset before mapping to a field/option, so clicks on visible
      options still work when the dialog is scrolled.
    - The help line gains a "pgup/pgdn scroll" hint when scrolling is
      active.
    - A single layout() method computes geometry (dialog width, viewport,
      body lines, per-field line offsets) shared by View() and
      Position(), so layout math lives in exactly one place.
    - buildBody tracks line offsets incrementally to stay O(N) in the
      number of fields.
    
    Tests cover long enums (30 options on a 20-row terminal), many
    fields below the fold (15 fields on an 18-row terminal), and small
    content that should not show a scrollbar.
    
    Assisted-By: docker-agent
    dgageot committed Apr 25, 2026
    Configuration menu
    Copy the full SHA
    ec5ce4b View commit details
    Browse the repository at this point in the history

Commits on Apr 27, 2026

  1. docs: update CHANGELOG.md for v1.51.0

    Automated changelog update for release v1.51.0
    
    Assisted-By: Docker Agent
    github-actions[bot] committed Apr 27, 2026
    Configuration menu
    Copy the full SHA
    34eed3f View commit details
    Browse the repository at this point in the history
  2. Merge pull request #2514 from docker/changelog/v1.51.0

    docs: update CHANGELOG.md for v1.51.0
    dgageot authored Apr 27, 2026
    Configuration menu
    Copy the full SHA
    aabb4c2 View commit details
    Browse the repository at this point in the history
  3. Merge pull request #2509 from dgageot/board/fix-docker-agent-github-i…

    …ssue-2495-35d25358
    
    fix(tui): make user_prompt elicitation dialog scrollable
    dgageot authored Apr 27, 2026
    Configuration menu
    Copy the full SHA
    d84a8a6 View commit details
    Browse the repository at this point in the history
  4. Merge pull request #2501 from joshbarrington/file-picker-toggle-hidde…

    …n-ignored
    
    hotkeys to toggle filepicker hidden/ignored files
    dgageot authored Apr 27, 2026
    Configuration menu
    Copy the full SHA
    a3b9d61 View commit details
    Browse the repository at this point in the history
  5. fix: normalize message trimming behavior across all model providers

    Ensure strings.TrimSpace() is used only as a skip guard, never to mutate
    the content that reaches the provider API. Fixes inconsistencies across
    Anthropic, OpenAI, Bedrock, Gemini, and oaistream-based providers.
    
    Changes:
    - Anthropic (standard + Beta): single-part user messages, multi-part text
      parts, and tool-result content now send the original untrimmed value.
      Tool-result blocks are normalized to empty string (not skipped) when
      whitespace-only, because every tool_use must have a corresponding
      tool_result.
    - OpenAI oaistream / Chat Completions: ConvertMultiContent switched from
      pre-allocated slice to append-based; adds TrimSpace guard on text parts
      so whitespace-only and empty parts are not forwarded. Same guard added
      to tool-role multi-content text parts.
    - OpenAI Responses API: adds TrimSpace guard on multi-part user message
      text parts in convertMessagesToResponseInput.
    - Gemini: strengthens single-part guard from != "" to TrimSpace != "";
      adds TrimSpace guard in convertMultiContent for multi-part text parts.
    - Test: updates the oaistream ConvertMultiContent test to assert the
      corrected behavior (nil-URL image part produces no output part, not a
      zero-value entry); adds whitespace-only text part test case.
    
    Fixes #2515
    
    Assisted-By: docker-agent
    simonferquel-clanker committed Apr 27, 2026
    Configuration menu
    Copy the full SHA
    d41a406 View commit details
    Browse the repository at this point in the history
  6. fix: collapse else+if into else-if to satisfy gocritic lint

    Assisted-By: docker-agent
    simonferquel-clanker committed Apr 27, 2026
    Configuration menu
    Copy the full SHA
    8620bea View commit details
    Browse the repository at this point in the history
  7. test: update e2e cassettes to reflect untrimmed content sent to Anthr…

    …opic API
    
    The previous Anthropic provider code trimmed trailing whitespace before
    sending content to the API. Now that the original untrimmed content is sent,
    cassettes need to reflect the actual bodies:
    
    - TestDebug_Title/Anthropic*: sessiontitle generator builds prompts with
      fmt.Fprintf('%d. %s\n', ...) + a trailing '\n\n' in the format string,
      producing three trailing newlines. The old TrimSpace stripped these; the
      new code sends them as-is.
    
    - TestExec_Anthropic_ToolCall: list_directory tool output ends with '\n'
      (from fmt.Fprintf 'FILE %s\n'). The old TrimSpace on tool results stripped
      this; the new code sends the original content.
    
    Assisted-By: docker-agent
    simonferquel-clanker committed Apr 27, 2026
    Configuration menu
    Copy the full SHA
    b0c1f93 View commit details
    Browse the repository at this point in the history
  8. runtime: append newline to non-last steer messages on multi-drain

    When multiple steer messages are drained in one batch they were injected
    back-to-back with no separator, causing some chat templates that
    concatenate consecutive user messages before tokenisation to glue
    adjacent word fragments together.
    
    Fix: introduce drainAndEmitSteered() which appends "\n" to every
    non-last message's content before calling appendSteerAndEmit.
    For multi-content messages the "\n" is appended to the last text part
    (or a new text part is added when none exists). The original
    QueuedMessage slice is never mutated — appendNewlineToQueuedMessage
    works on a shallow copy.
    
    The three inline steerQueue.Drain() + for-loop sites in loop.go are
    replaced by calls to the new helper.
    
    Tests added:
    - TestAppendNewlineToQueuedMessage: unit-tests the pure helper across
      plain-text, multi-content-with-text-part, multi-content-no-text-part,
      and no-mutation cases.
    - TestDrainAndEmitSteered_MultipleMessages: verifies three plain-text
      messages are kept as separate session messages with \n on non-last ones.
    - TestDrainAndEmitSteered_MultiContent: verifies the same for
      multi-content messages.
    
    Fixes #2517
    
    Assisted-By: docker-agent
    simonferquel-clanker committed Apr 27, 2026
    Configuration menu
    Copy the full SHA
    17b5d85 View commit details
    Browse the repository at this point in the history
  9. runtime: fix makezero lint in appendNewlineToQueuedMessage

    Replace make([]T, len)+copy with append(nil, src...) to avoid appending
    to a non-zero-initialized slice, which triggers the makezero linter.
    
    Assisted-By: docker-agent
    simonferquel-clanker committed Apr 27, 2026
    Configuration menu
    Copy the full SHA
    961d3ab View commit details
    Browse the repository at this point in the history
  10. feat(hooks): refactor for extensibility, add 5 events and 3 builtins

    Reshape pkg/hooks from "7 hard-coded events with bespoke per-event
    boilerplate" into a generic Dispatch/Has surface backed by a pluggable
    Registry. Add 5 new lifecycle events and 3 in-process builtin hooks
    that extract previously-inline runtime concerns. Strictly additive at
    the YAML layer: every existing hooks YAML keeps parsing untouched.
    
    Architecture:
    
    - Handler/Registry seam: Executor resolves each Hook's HookType
      against a Registry of HandlerFactory values. The default registry
      ships HookTypeCommand (the long-standing shell-out behavior, lifted
      into a Handler) and HookTypeBuiltin (a new handler kind that
      dispatches by name to an in-process Go function). Adding a new
      handler kind is one Register call; extending Hook with `args: []`
      lets builtins receive per-hook parameters.
    - Dispatch/Has API: collapse 7 ExecuteXxx + 7 HasXxxHooks methods
      into Dispatch(ctx, event, input) and Has(event), backed by an
      eventTable built once at construction. Adding a new event becomes
      a one-line entry; the executor needs no per-event methods or fields.
    - Builtin lookup is per-Registry, not global: NewLocalRuntime builds
      a private hooks.Registry, registers the three runtime-owned
      builtins on it, and threads it into every executor. No init()
      functions, no shared mutable state, no cross-runtime pollution.
    
    New events (5):
    
      turn_start         fires per model call, AFTER the persisted
                         messages are read. AdditionalContext is appended
                         transiently and never persisted, so per-turn
                         signals refresh every turn.
      before_llm_call    just before each model invocation. Observational.
      after_llm_call     just after a successful model call. Carries the
                         assistant text via stop_response.
      on_error           structured handler for runtime errors (model
                         failures, tool-call loops). Fires alongside the
                         generic notification event.
      on_max_iterations  structured handler for hitting max_iterations.
                         Fires alongside the generic notification event.
    
    Extracted runtime concerns (3 builtins):
    
      add_date              turn_start, "Today's date: YYYY-MM-DD"
      add_environment_info  session_start, working dir / OS / arch / git
      add_prompt_files      turn_start, reads files via Hook.Args
    
    The runtime auto-injects them based on the existing AddDate /
    AddEnvironmentInfo / AddPromptFiles agent flags, so YAMLs with those
    flags keep working with identical effective behavior. Users can also
    write the builtins explicitly in YAML now that the schema exposes
    type=builtin.
    
    Schema additions in pkg/config/latest:
    
    - HooksConfig gains turn_start, before_llm_call, after_llm_call,
      on_error, on_max_iterations top-level keys.
    - HookDefinition gains args: [string], used by builtin handlers to
      receive per-hook parameters.
    - HookDefinition.type accepts "builtin" alongside "command".
    - agent-schema.json updated to match.
    
    User-facing surface:
    
    - examples/hooks.yaml is a single canonical example covering all
      twelve events and both handler kinds (replaces five separate
      hooks_*.yaml files).
    - The legacy ExecuteXxx / HasXxxHooks shims on Executor are gone;
      every caller migrated to Dispatch / Has.
    
    Bug fixes uncovered along the way:
    
    - Default LocalRuntime.workingDir to os.Getwd() when no caller passed
      WithWorkingDir, matching the session's default. Fixes
      add_prompt_files reading an empty Cwd in CLI invocations.
    - Restore cache_control marker on the last extra in
      Session.GetMessages so AddPromptFiles content keeps participating
      in Anthropic prompt caching.
    - Route plain stdout from turn_start command hooks into
      AdditionalContext (was silently dropped, while session_start did
      surface it).
    - Extend hook deduplication from (type, command) to (type, command,
      args) so two add_prompt_files hooks with different file lists fire
      as distinct invocations.
    - Fix MergeHooks to also merge Stop, Notification, and the new event
      slices (previously dropped Stop / Notification when both base and
      CLI were non-empty).
    - Align hook helpers' log levels to Warn
      (executeSessionEndHooks was the odd Error out).
    
    Validated with go vet ./..., golangci-lint run ./... (0 issues), and
    go test -race across pkg/hooks, pkg/runtime, pkg/session, pkg/config
    (all versions), and e2e.
    
    Assisted-By: docker-agent
    dgageot committed Apr 27, 2026
    Configuration menu
    Copy the full SHA
    97bf594 View commit details
    Browse the repository at this point in the history
  11. runtime: address platform reviewer suggestions on PR #2518

    S1: add NOTE comment in drainAndEmitSteered documenting that the
        appended \n is persisted in session messages and UserMessageEvent.
    S2: appendNewlineToQueuedMessage now returns sm unchanged when
        MultiContent has no text part (e.g. image-only) instead of
        appending a synthetic whitespace text part. Non-text parts carry
        their own envelope that acts as a separator, and pure whitespace
        parts are skipped downstream anyway.
    S3: drainAndEmitSteered now returns (bool, int) where int is the
        pre-drain message count; callers no longer need a separate
        len(sess.GetAllMessages()) call before draining.
    N3: add plain-text no-mutation subtest in TestAppendNewlineToQueuedMessage.
    N4: reword appendNewlineToQueuedMessage doc comment.
    
    Assisted-By: docker-agent
    simonferquel-clanker committed Apr 27, 2026
    Configuration menu
    Copy the full SHA
    0bf91cf View commit details
    Browse the repository at this point in the history
  12. refactor: centralise whitespace-only message filtering in session.Get…

    …Messages
    
    Addresses reviewer feedback: 'Is it possible to normalise the behaviour in only
    one place? In the place where we make the slice of messages of the session?'
    
    Add normalizeMessageContent() to session.GetMessages as the single, authoritative
    place where whitespace-only content is pruned before any provider converter sees
    it. This replaces the patchwork of per-provider TrimSpace skip-guards.
    
    Rules applied by normalizeMessageContent:
    - Tool-result messages (Role=tool) are always forwarded, even when empty, because
      every tool_use block must have a corresponding tool_result.
    - Assistant messages with ToolCalls or FunctionCall are always forwarded even when
      Content is empty — the content field is optional when tool calls are present.
    - Any other message whose Content is whitespace-only (and has no MultiContent) is
      dropped.
    - Within MultiContent, text parts whose Text is whitespace-only are stripped;
      non-text parts (images, files) are preserved as-is. If all parts are stripped the
      whole message is dropped.
    
    Provider-converter changes:
    - All per-converter TrimSpace skip-guards for user/assistant/system messages
      removed (they are now redundant): Anthropic std+Beta convertMessages,
      oaistream ConvertMultiContent + tool-role multi-content, OpenAI Responses API
      user multi-content, Gemini convertMessagesToGemini + convertMultiContent.
    - Pre-existing assistant empty-skip guards in oaistream and openai/client.go are
      kept: they handle streaming artifacts (max_tokens assistant deltas) that are
      produced outside of GetMessages and may not pass through normalizeMessageContent.
    - Anthropic system blocks (extractSystemBlocks / extractBetaSystemBlocks) continue
      to TrimSpace because YAML literal-block instructions (instruction: |) always
      append a trailing newline, and the system-block builder is the right place to
      normalise that for the Anthropic API payload.
    - The Anthropic send-original correctness fix (tool_result and conversation-message
      content: send original string, not trimmed value) is unchanged.
    
    Tests updated throughout to document the new 'converter passes through, session
    layer filters' contract.
    
    Assisted-By: docker-agent
    simonferquel-clanker committed Apr 27, 2026
    Configuration menu
    Copy the full SHA
    7a8ce07 View commit details
    Browse the repository at this point in the history
  13. runtime: simplify appendNewlineToQueuedMessage to check only last part

    Instead of iterating to find the last text part, only inspect
    sm.MultiContent[last]: if it is a text part, append \n; otherwise
    return sm unchanged. Non-text parts carry their own provider envelope
    that acts as a separator, so no \n is needed regardless of what
    precedes them.
    
    Update tests to match: replace the 3-part (text/image/text) subtest
    with explicit last-part-text and last-part-non-text cases.
    
    Assisted-By: docker-agent
    simonferquel-clanker committed Apr 27, 2026
    Configuration menu
    Copy the full SHA
    e2c2552 View commit details
    Browse the repository at this point in the history
  14. fix: replace tab with space before inline comment to satisfy gci form…

    …atter
    
    Assisted-By: docker-agent
    simonferquel-clanker committed Apr 27, 2026
    Configuration menu
    Copy the full SHA
    a854cbd View commit details
    Browse the repository at this point in the history
  15. Merge pull request #2518 from simonferquel-clanker/fix/steer-queue-ne…

    …wline-separator
    
    runtime: append newline to non-last steer messages on multi-drain
    simonferquel authored Apr 27, 2026
    Configuration menu
    Copy the full SHA
    fa3ac9e View commit details
    Browse the repository at this point in the history
  16. Merge pull request #2516 from simonferquel-clanker/fix/message-trimmi…

    …ng-consistency
    
    fix: normalize message trimming behavior across all model providers
    simonferquel authored Apr 27, 2026
    Configuration menu
    Copy the full SHA
    04ee63f View commit details
    Browse the repository at this point in the history
  17. Merge pull request #2519 from dgageot/board/improving-hooks-design-fo…

    …r-extensibility-76cf250c
    
    feat(hooks): refactor for extensibility, add 5 events and 3 builtins
    dgageot authored Apr 27, 2026
    Configuration menu
    Copy the full SHA
    514714b View commit details
    Browse the repository at this point in the history
Loading