feat(agent): add AgentGUI live event protocol#1634
Conversation
Signed-off-by: liying <422107224@qq.com>
Signed-off-by: liying <422107224@qq.com>
Signed-off-by: liying <422107224@qq.com>
Signed-off-by: liying <422107224@qq.com>
Signed-off-by: liying <422107224@qq.com>
| func (n *acpTurnNormalizer) AppendToolOutputDelta( | ||
| session Session, | ||
| turnID string, | ||
| rawToolCallID string, | ||
| delta string, | ||
| ) []activityshared.Event { |
There was a problem hiding this comment.
🟡 Provider normalizer source file grows past the mandated size limit
New streaming/tool-output logic is added to the provider normalizer file (AppendToolOutputDelta at packages/agent/daemon/runtime/acp_turn_normalizer.go:500), pushing it from 786 lines to 930 lines, past the repository's 800-line limit for business-code files.
Impact: The file becomes harder to maintain and violates an explicit repository size rule that signals decomposition is required.
Why this violates the repository rule
AGENTS.md and CONTRIBUTING.md state: "Business-code files should stay at or below 800 lines. Prefer decomposition before adding more logic." The base file (b7053fb) was 786 lines and under the limit; this PR adds AppendToolOutputDelta, attachTextLiveOperation, attachToolOutputLiveOperation, and related logic, crossing 800 (now 930). Per the rule, the new logic should be introduced together with a decomposition of the file.
Prompt for agents
packages/agent/daemon/runtime/acp_turn_normalizer.go crossed the repository's 800-line business-file limit (786 -> 930) after adding tool-output delta and live-operation attachment helpers. The AGENTS.md/CONTRIBUTING.md rule requires decomposing an oversized business file before adding more logic. Consider extracting the live-operation attachment helpers (attachTextLiveOperation, attachToolOutputLiveOperation, and the metadata-key constants) and/or the tool-output delta handling into a separate file within the same package (for example acp_turn_normalizer_live.go) so each file stays at or below 800 lines.
Was this helpful? React with 👍 or 👎 to provide feedback.
| protected reconcileOptimisticMessages( | ||
| workspaceId: string, | ||
| agentSessionId: string | ||
| ): void { | ||
| const normalizedWorkspaceId = normalizeWorkspaceId(workspaceId); | ||
| const normalizedAgentSessionId = agentSessionId.trim(); | ||
| if (!normalizedAgentSessionId) return; | ||
| const canonicalMessages = | ||
| this.entry(normalizedWorkspaceId).engine.getSnapshot().sessionMessages | ||
| .messagesBySessionId[normalizedAgentSessionId] ?? []; | ||
| this.optimisticProjection.reconcile( | ||
| normalizedWorkspaceId, | ||
| normalizedAgentSessionId, | ||
| canonicalMessages | ||
| ); |
There was a problem hiding this comment.
🟡 Reconcile bridge source file remains well over the mandated size limit and grows further
New optimistic-projection wiring is added to the reconcile bridge file (reconcileOptimisticMessages at packages/agent/desktop reconcile bridge, apps/desktop/src/renderer/src/features/workspace-agent/services/internal/workspaceAgentActivityReconcileBridge.ts:132), enlarging an already over-limit file from 893 to 993 lines instead of decomposing it first.
Impact: The file drifts further past the repository's 800-line business-file limit, compounding a maintenance hotspot the rule is meant to prevent.
Why this violates the repository rule
AGENTS.md and CONTRIBUTING.md state: "Business-code files should stay at or below 800 lines. Prefer decomposition before adding more logic." The file was already 893 lines at the merge base and this PR adds the optimistic projection methods (subscribeActivitySnapshot, reconcileOptimisticMessages, message_delta handling) rather than decomposing before adding logic.
Prompt for agents
apps/desktop/src/renderer/src/features/workspace-agent/services/internal/workspaceAgentActivityReconcileBridge.ts is already above the repository's 800-line business-file limit (893 at base, 993 after this PR). The AGENTS.md/CONTRIBUTING.md rule requires decomposition before adding more logic. Consider extracting the optimistic-projection bridging responsibilities (activitySnapshot projection wiring, subscribeActivitySnapshot, reconcileOptimisticMessages, and the message_delta observation branch) into a dedicated collaborator module so the reconcile bridge returns to or below 800 lines.
Was this helpful? React with 👍 or 👎 to provide feedback.
What changed
json.RawMessage, including file paths and large JSON integers; only closed workspace, Session, and Turn identities are projected.message_delta.turnIdrequired, close Turn terminal/nonterminal invariants, and coalesce only pure adjacentappend_textdeltas.set, a strict prefix extension emits only the suffix asappend_text, duplicates are dropped, and real rewrites/backtracks useset. This applies to Claude SDK assistant and reasoning streams as well as existing ACP/Codex deltas.agent.activity.updatedv2 contract so normalized local provider text/reasoning deltas are published over the existing/v1/events/wsbusiness-event WebSocket.message_updatefor terminal confirmation, tools, audits, imports, and any message that was not represented by a delta. Suppress only redundant nonterminal runtime text/reasoning snapshots.Why
Shared and local Agent streaming need a lossy optimistic fast lane without making peer or WebSocket data authoritative and without teaching renderers separate transport protocols. The runtime already produces normalized AgentGUI deltas, so both the device-link adapter and the local business-event bridge now carry that same semantic event. Canonical local/cloud reads remain the source of truth.
This removes repeated full
message_updatepayloads from high-frequency text/reasoning streaming. Cumulative provider snapshots are reduced at the provider normalizer boundary, so monotonic text growth is linear in transmitted text size instead of repeatedly sending the full accumulated message.Impact and risk
reconcile,project, andresetrequire an explicit workspace/Session scope.message_delta; renderer UI remains unaware of whether the source was local or shared.delivery_too_largediscontinuity with reconcile keys so the final oversized event cannot disappear silently.Validation
pnpm check:changed -- --push-ready— 32 lanes passed in the pre-push gatepnpm --filter @tutti-os/desktop buildgo test ./packages/agent/daemon/runtime ./services/tuttid/service/eventstream ./services/tuttid/service/agent ./services/tuttidcd services/tuttid && go build ./...Exploratory full-package
go test -race ./runtime -count=1still reports the existingCodexAppServerAdapter.setSessionActiveTurnIDrace. The same race reproduces on the untouched baseline; the modified runtime tests pass repeatedly under the race detector.