[codex] add ao hooks activity command#113
Conversation
Greptile SummaryThis PR adds the
Confidence Score: 5/5Safe to merge; the change adds a narrow, best-effort callback receiver and a guarded activity endpoint with no side effects on existing session flows. All error paths in the new hook command exit 0 by design, the activity endpoint validates the state enum before touching the lifecycle manager, and the nil-guard on the recorder returns 501 cleanly when the dependency is absent. The omitempty fix on the Codex matcher field is a correctness improvement. No existing behaviour is altered. No files require special attention. Important Files Changed
Sequence DiagramsequenceDiagram
participant Agent as AgentCLI
participant Hook as AoHooksCmd
participant Dispatch as ActivityDispatch
participant Daemon as DaemonRoute
participant LCM as LifecycleMgr
Agent->>Hook: exec with stdin payload and AO_SESSION_ID
Hook->>Hook: read AO_SESSION_ID from env
Hook->>Hook: io.ReadAll stdin
Hook->>Dispatch: Derive(agent, event, payload)
alt event carries activity signal
Dispatch-->>Hook: "state, ok=true"
Hook->>Daemon: "POST /api/v1/sessions/{id}/activity"
Daemon->>Daemon: validate state enum
Daemon->>LCM: ApplyActivitySignal(ctx, id, signal)
LCM-->>Daemon: nil or error
Daemon-->>Hook: 200 SetActivityResponse
Hook-->>Agent: exit 0
else unknown agent or no-signal event
Dispatch-->>Hook: "empty, ok=false"
Hook-->>Agent: exit 0 no-op
end
Note over Hook,Daemon: Any daemon error logs to stderr and exits 0
Reviews (2): Last reviewed commit: "feat: add ao hooks activity command" | Re-trigger Greptile |
313bb17 to
2ee5b21
Compare
There was a problem hiding this comment.
yyovil has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.
7f909d1 to
f5dfb00
Compare
There was a problem hiding this comment.
yyovil has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.
|
Took over to fix CI failures after recent main merges (#103, #108/#114, #115, #101, #106). Root cause was a botched merge commit ( Changes:
Validation (local, after rebase):
Pushed with |
- lcm: sameActivity ignores LastActivityAt so same-state repeats no-op and don't churn UpdatedAt / CDC events. - cli/hooks: surface stdin read errors to stderr for parity with the daemon-error path; still exit 0 so a failed hook can't break the agent. - claudecode: GetAgentHooks docstring covers Notification + SessionEnd (the slice already included them; only the comment was stale).
There was a problem hiding this comment.
yyovil has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.
Summary
This adds the hidden
ao hooks <agent> <event>callback command and wires it to daemon-backed session activity updates.AO already installs workspace-local activity hooks for agents, but the receiving CLI command did not exist yet. That meant native hook callbacks could shell out to
ao hooks ...without a daemon route that translated the event into durable session activity. The user-visible effect is that sessions can remain stale or rely on runtime observation instead of agent-owned activity signals.The root cause is a missing boundary between installed agent hook callbacks and the lifecycle reducer. The CLI needed a small, best-effort callback receiver, and the daemon needed a route that records normalized activity through the existing lifecycle manager.
Changes
ao hooks <agent> <event>Cobra command that reads hook JSON from stdin, usesAO_SESSION_IDto identify the AO session, derives an activity state, and posts to/api/v1/sessions/{id}/activity.activitydispatchplus Claude Code, Codex, and opencode derivers for the hook events currently installed by those adapters.NotificationandSessionEnd, and Codex hooks to reportPermissionRequest.--dangerously-bypass-hook-trustlaunch/restore flag so AO-installed workspace hooks run in fresh per-session worktrees. I verified the option withcodex --help; it runs enabled hooks without requiring persisted hook trust for the invocation.ao hooks.Validation
codex --help | rg -n "hook|trust|bypass|danger" -C 2npm run apigo run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.12.2 run --path-mode=absgo test ./internal/adapters/agent/claudecode ./internal/adapters/agent/codex ./internal/adapters/agent/opencode ./internal/cli ./internal/httpd/controllers ./internal/httpd/apispecgo test ./internal/terminal -run 'TestNilLoggerFallsBackToDefault|TestCreackPTYCloseIsIdempotent|TestRingBuffer|TestClientMsgRoundTrip|TestServerMsg|TestServe|TestEnqueueOverflowCancelsConn|TestSessionFansOutLiveOutputToSubscribers|TestSessionReplaysRingBufferOnSubscribe|TestSessionWriteAndResizeReachPTY|TestSessionSkipsReattachOnCleanExit|TestSessionReattachesWhileSessionAlive|TestSessionFailsWhenAttachCommandErrors'go test ./... -skip TestSessionStreamsRealZellijPaneNotes
A plain
go test ./...fails inbackend/internal/terminalon this machine becauseTestSessionStreamsRealZellijPaneconstructs a zellij IPC socket path longer than zellij's 103-byte limit. EvenTMPDIR=/tmpleaves the generated path at 118 bytes because the test name is repeated in the socket path.npm run frontend:typecheckalso fails on pre-existing frontend dependency/type issues unrelated to this schema change: missingfumadocs-*and.sourcemodules, plus a Next-specificfetch({ next: ... })option not present in the currentRequestInittype.