Skip to content

feat: name Codex threads from ACP session metadata - #425

Closed
Hacktor-Banned wants to merge 2 commits into
agentclientprotocol:mainfrom
Hacktor-Banned:fix/buzz-session-title-from-meta
Closed

feat: name Codex threads from ACP session metadata#425
Hacktor-Banned wants to merge 2 commits into
agentclientprotocol:mainfrom
Hacktor-Banned:fix/buzz-session-title-from-meta

Conversation

@Hacktor-Banned

Copy link
Copy Markdown

Summary

  • Read sessionTitle from session/new _meta and apply it with Codex thread/name/set.
  • Seed the adapter's explicit-title state and publish the title through session_info_update after the session/new response.
  • Sanitize untrusted titles by collapsing whitespace, removing Unicode control/format/surrogate characters, and capping them at 80 code points.
  • Keep title application cosmetic: failures are logged without failing session creation.

Motivation

Buzz already sends a bounded, out-of-band session title in block/buzz#3028. Without the adapter half, Codex still derives the thread title from the first prompt, which can turn a complete orchestrator prompt into the task title. Using ACP metadata keeps the label out of the prompt and avoids spending tokens on title plumbing.

This rebases and supersedes #338 on current main. It preserves the original commits, authorship, and DCO sign-offs from @wpfleger96 while resolving the intervening thread-fork and test-fixture API changes.

Testing

  • npx vitest run --no-file-parallelism src/__tests__/CodexACPAgent/session-title-from-meta.test.ts src/__tests__/CodexACPAgent/session-title-ordering.test.ts (15 passed)
  • npm run typecheck
  • npm test (454 passed, 28 skipped)
  • npm run build
  • npm run codex-test -- -p "Reply with exactly: title-ok" -o summary
  • Live Codex app-server smoke test: created a session with _meta.sessionTitle, read the persisted thread name back, and archived the test thread

Related

ACP clients that run several sessions against one agent had no way to
label them: every thread showed the same derived title. The title is
carried out of band in `_meta` so it never enters the prompt and costs
no tokens.

The applied title is reported back through `SessionMetadata` so the
session's title state is seeded synchronously as "explicit", which stops
a later prompt- or history-derived fallback from overwriting a title the
client asked for. Naming is cosmetic, so a failed `thread/name/set` is
logged and swallowed rather than failing session creation.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
(cherry picked from commit bba8856)
`readMetaSessionTitle` accepted any non-blank string. A client could
persist an unbounded title, or one carrying a BEL, a zero-width space, or
a bidi override, straight into the Codex thread store — `normalize_thread_name`
only trims. This is the ACP boundary for arbitrary clients, so the adapter
sanitizes independently of its callers: whitespace collapses, `Cc`/`Cf`/`Cs`
are dropped, and the result is capped at `SESSION_TITLE_MAX_CHARS` code
points so the cap cannot split a surrogate pair. Scoped to the `_meta` path;
history- and prompt-derived titles are trusted inputs.

Naming the thread also left ACP title state untouched. `thread/name/set`
resolves before any thread notification handler exists, so Codex's
`thread/name/updated` is dropped, and `NewSessionResponse` has no title
field — a client that supplied the title through opaque `_meta` had no way
to see it reflected. The adapter now publishes one `session_info_update`
carrying it.

That publish must land after the `session/new` response: the SDK client
installs its per-session update queue only when `session/new` resolves and
drops updates for sessions with no queue, so an update emitted inside the
create path would be lost. `setImmediate` puts it behind a macrotask
boundary, and the publish re-checks session liveness, generation, and title
identity so a session closed or renamed in the gap is not told about a
title that is no longer its own.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
(cherry picked from commit 37369ba)
@Hacktor-Banned
Hacktor-Banned deleted the fix/buzz-session-title-from-meta branch August 22, 2026 08:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants