🌐 US-Proxy
class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
Skip to content

feat: add chat suffix messages, idle failure, and content update support - #27428

Merged
ibetitsmike merged 8 commits into
mainfrom
mike/chat-hooks/chatstate
Jul 29, 2026
Merged

feat: add chat suffix messages, idle failure, and content update support#27428
ibetitsmike merged 8 commits into
mainfrom
mike/chat-hooks/chatstate

Conversation

@ibetitsmike

@ibetitsmike ibetitsmike commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

Adds generic chat state and query capabilities that the lifecycle hooks integration (#27429) builds on. Part of the lifecycle hooks stack (#27401, #27429, #27430).

  • chatstate: EditMessage accepts caller-provided suffix messages inserted after the replacement in the same transaction, transitions can carry a typed error kind, and FinishError is also allowed from waiting chats so admission-time failures can park an idle chat in error.
  • chatstate: ValidateToolResults holds the submitted-tool-result rules (duplicate, invalid JSON, missing, unexpected) in one place, so CompleteRequiresAction and API-level prechecks reject the same payloads with the same typed causes.
  • database: InsertChat accepts an optional caller-provided ID.

No hook-specific state or behavior is introduced here; these primitives are usable by any caller.

An earlier revision added a message-content rewrite primitive so a pre_tool_use override could update an already-committed tool call. Message content is immutable by design, and @hugodutka pushed back on changing that. The rewrite is gone: #27429 now dispatches the hook before the assistant message is stored, so the stored input is the one that runs and nothing needs updating.

This PR was written by Mux, an AI coding agent, on Mike's behalf.

ibetitsmike commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator Author

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9fefafe6dc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread coderd/x/chatd/chatstate/transitions.go Outdated
Comment thread coderd/x/chatd/chatstate/transition.go Outdated
@ibetitsmike
ibetitsmike force-pushed the mike/chat-hooks/backend branch from fb591a8 to cdabebf Compare July 22, 2026 19:59
@ibetitsmike
ibetitsmike requested a review from Emyrk as a code owner July 22, 2026 19:59
@ibetitsmike
ibetitsmike force-pushed the mike/chat-hooks/chatstate branch from 9fefafe to e0b7344 Compare July 22, 2026 19:59
@ibetitsmike ibetitsmike changed the title feat(coderd/x/chatd/chatstate): add hook transitions and end-chat family orchestration feat(coderd/x/chatd/chatstate): add hook-aware transitions and queued policy Jul 22, 2026
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e0b7344a0f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread coderd/x/chatd/chatstate/transition.go Outdated
@ibetitsmike
ibetitsmike force-pushed the mike/chat-hooks/chatstate branch from e0b7344 to a05cf3c Compare July 22, 2026 20:12
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a05cf3ceb6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread coderd/x/chatd/chatstate/transitions.go Outdated
@ibetitsmike
ibetitsmike force-pushed the mike/chat-hooks/backend branch from cdabebf to fb7db50 Compare July 22, 2026 20:24
@ibetitsmike
ibetitsmike force-pushed the mike/chat-hooks/chatstate branch from a05cf3c to 841eefb Compare July 22, 2026 20:24
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 841eefb780

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread coderd/x/chatd/chatstate/transitions.go Outdated
@ibetitsmike
ibetitsmike force-pushed the mike/chat-hooks/chatstate branch from 841eefb to e08f7af Compare July 22, 2026 20:51
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e08f7affcd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread coderd/x/chatd/chatstate/transitions.go Outdated
Comment thread coderd/x/chatd/ARCHITECTURE.md Outdated
@ibetitsmike
ibetitsmike force-pushed the mike/chat-hooks/backend branch from fb7db50 to a2f6d68 Compare July 22, 2026 22:00
@ibetitsmike
ibetitsmike force-pushed the mike/chat-hooks/chatstate branch from e08f7af to c6e5dff Compare July 22, 2026 22:00
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@ibetitsmike ibetitsmike changed the title feat(coderd/x/chatd/chatstate): add hook-aware transitions and queued policy feat(coderd): add hook-aware chat transitions and queued policy Jul 22, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c6e5dff779

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread coderd/x/chatd/chatstate/transitions.go Outdated
@ibetitsmike
ibetitsmike force-pushed the mike/chat-hooks/chatstate branch from c6e5dff to bc056cc Compare July 22, 2026 22:20
@ibetitsmike
ibetitsmike force-pushed the mike/chat-hooks/chatstate branch from 45387e5 to 98f4fbb Compare July 27, 2026 16:41
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

Reviewed commit: 98f4fbbd0f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Swish!

Reviewed commit: c0617e5750

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@hugodutka hugodutka left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. Please resolve the comments before merging.

if len(insertedReplacement) == 1 {
replacementRow = insertedReplacement[0]
}
insertedSuffix, err := tx.insertMessages(input.SuffixMessages)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure this shouldn't be addressed right now? What should the ordering be? I'd expect the messages to be ordered in the message history in the same order that they were in the SuffixMessages array. Will breaking by id ensure that?

Comment thread coderd/x/chatd/ARCHITECTURE.md Outdated
Comment thread coderd/x/chatd/chatstate/transitions.go Outdated
ibetitsmike added a commit that referenced this pull request Jul 28, 2026
Adds the chat lifecycle hook wire contract and dispatch plumbing, first
PR of the lifecycle hooks stack (followed by #27428, #27429, #27430).

- `codersdk/x/agenthooks`: event and response wire types, JWT creation
and verification with the shared secret (HS256, request body digest,
expiry and not-before freshness checks), and an HTTP handler helper so
consumers only implement the events they use. The `codersdk/x` location
marks the consumer SDK as experimental.
- `coderd/x/agenthooks/dispatch`: a stateless dispatcher that signs and
posts hook events, enforces a concurrency cap under one configured
timeout that bounds both the capacity wait and both post attempts,
retries one connection failure with the same JWT, sends a distinctive
`coderd-agenthooks/<version>` User-Agent, and records Prometheus
metrics. Delivery is at least once; consumers own durable decision
state, audit records, and deduplication keyed by the stable payload
identifiers. Nothing is persisted by Coder.
- Response bodies decode strictly: unknown fields, duplicate JSON keys
(including inside `input_override`), and trailing data fail the dispatch
closed as protocol errors instead of silently reading as allow.
- `coderd/util/xnet`: shared timeout and connection error classification
used by the dispatcher retry logic. Transient HTTP/2 stream aborts count
as connection errors, so the documented single retry also applies to h2
consumers, which is the shape Go's default transport negotiates against
any TLS consumer. Deterministic protocol failures stay terminal. Only
the struct form of a stream error is matched, because `net/http` bundles
its own HTTP/2 types and `h2_error.go` bridges only that shape.
- `scripts/agenthooks-server`: a reference consumer that logs events and
demonstrates consumer-owned pre-tool decision deduplication. It requires
an explicitly configured JWT audience rather than deriving one from the
request, and its startup output names the mode it is running in so an
operator can see that the example policy flags need `-log-only=false`.
- `scripts/apitypings`: generate TypeScript types for the hook wire
contract.

Dispatch failures log without the error's stack frames, since a failed
dispatch is an expected, operator-visible condition.

Nothing dispatches these events yet; chatd wiring lands in #27429.

> This PR was written by Mux, an AI coding agent, on Mike's behalf.
Base automatically changed from mike/chat-hooks/backend to main July 28, 2026 11:59
@ibetitsmike
ibetitsmike requested a review from a team as a code owner July 28, 2026 11:59
mafredri pushed a commit that referenced this pull request Jul 28, 2026
Adds the chat lifecycle hook wire contract and dispatch plumbing, first
PR of the lifecycle hooks stack (followed by #27428, #27429, #27430).

- `codersdk/x/agenthooks`: event and response wire types, JWT creation
and verification with the shared secret (HS256, request body digest,
expiry and not-before freshness checks), and an HTTP handler helper so
consumers only implement the events they use. The `codersdk/x` location
marks the consumer SDK as experimental.
- `coderd/x/agenthooks/dispatch`: a stateless dispatcher that signs and
posts hook events, enforces a concurrency cap under one configured
timeout that bounds both the capacity wait and both post attempts,
retries one connection failure with the same JWT, sends a distinctive
`coderd-agenthooks/<version>` User-Agent, and records Prometheus
metrics. Delivery is at least once; consumers own durable decision
state, audit records, and deduplication keyed by the stable payload
identifiers. Nothing is persisted by Coder.
- Response bodies decode strictly: unknown fields, duplicate JSON keys
(including inside `input_override`), and trailing data fail the dispatch
closed as protocol errors instead of silently reading as allow.
- `coderd/util/xnet`: shared timeout and connection error classification
used by the dispatcher retry logic. Transient HTTP/2 stream aborts count
as connection errors, so the documented single retry also applies to h2
consumers, which is the shape Go's default transport negotiates against
any TLS consumer. Deterministic protocol failures stay terminal. Only
the struct form of a stream error is matched, because `net/http` bundles
its own HTTP/2 types and `h2_error.go` bridges only that shape.
- `scripts/agenthooks-server`: a reference consumer that logs events and
demonstrates consumer-owned pre-tool decision deduplication. It requires
an explicitly configured JWT audience rather than deriving one from the
request, and its startup output names the mode it is running in so an
operator can see that the example policy flags need `-log-only=false`.
- `scripts/apitypings`: generate TypeScript types for the hook wire
contract.

Dispatch failures log without the error's stack frames, since a failed
dispatch is an expected, operator-visible condition.

Nothing dispatches these events yet; chatd wiring lands in #27429.

> This PR was written by Mux, an AI coding agent, on Mike's behalf.
@ibetitsmike ibetitsmike changed the title feat(coderd): add chat suffix messages, idle failure, and content update support feat: add chat suffix messages, idle failure, and content update support Jul 28, 2026
@github-actions

Copy link
Copy Markdown

Docs preview

Check off each page once it's been reviewed. If a page changes in a later push, its checkbox clears automatically so it gets a fresh look. Pages not yet wired into the docs navigation aren't listed here.

@ibetitsmike
ibetitsmike force-pushed the mike/chat-hooks/chatstate branch from 89900f4 to 2104035 Compare July 28, 2026 16:53
…ed IDs

Add generic chat state and query capabilities used by lifecycle hook
integration:

- chatstate: EditMessage accepts caller-provided suffix messages that
  insert after the replacement in the same transaction, transitions
  can carry a typed error kind, and FailIdle moves an idle chat to the
  error state.
- database: InsertChat accepts an optional caller-provided ID.
Allow FinishError from a waiting chat instead of adding a separate
transition. Callers encode the error payload, matching the existing
FinishError contract.
No transition requires runner ownership, so saying FinishError does not
need it implied a distinction that does not exist. Ownership is enforced
by worker-side fences, not by the transition matrix.

State the actual precondition instead: the transition matrix allows
FinishError from an unarchived chat that is waiting or running.
The test used a single suffix message and only checked the returned
slice, so it could not detect a batch whose rows came back reordered or
a history read that returned the suffix before its replacement.

Use two distinguishable suffix messages, assert their IDs ascend with
the input array, and reload through GetChatMessagesByChatID to check the
active tail is the replacement followed by both notices in order.
@ibetitsmike
ibetitsmike force-pushed the mike/chat-hooks/chatstate branch from 2104035 to b8bc5f4 Compare July 29, 2026 09:11
@ibetitsmike
ibetitsmike merged commit 91c7232 into main Jul 29, 2026
29 checks passed
@ibetitsmike
ibetitsmike deleted the mike/chat-hooks/chatstate branch July 29, 2026 11:16
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 29, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants