From 0d6eac76f3a2f05fe21575134f3a3f741a431d4e Mon Sep 17 00:00:00 2001
From: Evgeny Shurakov
Date: Tue, 1 Sep 2026 21:04:46 +0200
Subject: [PATCH] feat(cloud-agent): show workspace commits in chat
---
.../CloudAgentWorkspaceTabs.test.ts | 11 +
.../cloud-agent-next/CloudChatPage.tsx | 13 +-
.../cloud-agent-next/CommitCard.tsx | 99 ++++
.../ConversationMessages.test.ts | 177 ++++++-
.../cloud-agent-next/ConversationMessages.tsx | 27 +-
.../message-presentation.test.ts | 103 ++++-
.../cloud-agent-next/message-presentation.ts | 67 ++-
.../cloud-agent-next/terminal-tabs.test.ts | 99 +++-
packages/cloud-agent-sdk/src/index.ts | 1 +
packages/cloud-agent-sdk/src/normalizer.ts | 16 +-
packages/cloud-agent-sdk/src/schemas.ts | 20 +
.../cloud-agent-sdk/src/service-state.test.ts | 98 +++-
packages/cloud-agent-sdk/src/service-state.ts | 38 +-
.../src/session-manager.test.ts | 2 +
.../cloud-agent-sdk/src/session-manager.ts | 22 +-
packages/cloud-agent-sdk/src/session.test.ts | 82 ++++
packages/cloud-agent-sdk/src/types.ts | 14 +-
packages/worker-utils/package.json | 1 +
.../src/cloud-agent-commits.test.ts | 67 +++
.../worker-utils/src/cloud-agent-commits.ts | 22 +
packages/worker-utils/src/index.ts | 7 +
.../src/sandbox-session/SandboxSession.ts | 27 +-
.../sandbox-control-event.test.ts | 82 +++-
.../sandbox-session/sandbox-control-event.ts | 39 ++
.../cloud-agent-next/src/shared/protocol.ts | 4 +
.../test/e2e/sandbox-control.ts | 6 +-
.../test/integration/sandbox-control.test.ts | 320 ++++++++++++-
.../test/unit/wrapper/auto-commit.test.ts | 432 +++++++++++++++++-
.../wrapper/src/auto-commit.ts | 155 ++++---
.../wrapper/src/commit-objects.test.ts | 97 ++++
.../wrapper/src/commit-objects.ts | 87 ++++
.../control/sandbox-control-handlers.test.ts | 48 +-
.../src/control/sandbox-control-handlers.ts | 1 +
33 files changed, 2161 insertions(+), 123 deletions(-)
create mode 100644 apps/web/src/components/cloud-agent-next/CommitCard.tsx
create mode 100644 packages/worker-utils/src/cloud-agent-commits.test.ts
create mode 100644 packages/worker-utils/src/cloud-agent-commits.ts
create mode 100644 services/cloud-agent-next/wrapper/src/commit-objects.test.ts
create mode 100644 services/cloud-agent-next/wrapper/src/commit-objects.ts
diff --git a/apps/web/src/components/cloud-agent-next/CloudAgentWorkspaceTabs.test.ts b/apps/web/src/components/cloud-agent-next/CloudAgentWorkspaceTabs.test.ts
index b314f22143..ce030b6565 100644
--- a/apps/web/src/components/cloud-agent-next/CloudAgentWorkspaceTabs.test.ts
+++ b/apps/web/src/components/cloud-agent-next/CloudAgentWorkspaceTabs.test.ts
@@ -152,6 +152,17 @@ describe('CloudAgentWorkspaceTabs', () => {
expect(html).toContain('Selected workspace panel');
}
});
+
+ it('keeps workspace navigation limited to chats, terminals, and saved files', () => {
+ const html = renderWorkspaceTabs({
+ terminals: [{ id: 'pty', title: 'Terminal 1', cloudAgentSessionId: 'workspace-one' }],
+ files: [{ path: 'src/file.ts' }],
+ });
+ expect((html.match(/
');
+ expect(html).toContain('Keep the complete body accessible.');
+ expect(html).toContain(commit.commitHash);
+ expect(html).toContain(`dateTime="${commit.committedAt}"`);
+ expect(html.includes('>Not pushed<')).toBe(showsNotPushed);
+ expect(html).not.toContain('Workspace commit');
+ expect(html).not.toContain('Push status');
+ expect(html).not.toContain('>Pushed<');
+ expect(html).not.toContain('may include changes from other chats');
+ expect(html).not.toContain('text-destructive');
+ expect(html).not.toContain('View diff');
+ }
+ );
+
+ it('keeps long commit messages as plain text in details without embedding them in the trigger name', () => {
+ const longCommit = {
+ ...commit,
+ commitMessage: `${'Long subject '.repeat(100)}\n\n\n${'Body '.repeat(1000)}`,
+ };
+ const html = renderConversation(
+ [assistantMessage('assistant-1', [textPart('answer', 'Answer')])],
+ { commits: [longCommit] }
+ );
+ expect(html).toContain('aria-label="Commit aaaaaaa details"');
+ expect(html).not.toContain('Body ');
+ const details = renderToStaticMarkup(
+ React.createElement(CommitDetails, { commit: longCommit })
+ );
+ expect(details).toContain('Body '.repeat(1000));
+ expect(details).toContain('<script>not markup</script>');
+ expect(details).not.toContain('