From 873e811aeb14c413cef6aba7b472ead25866a750 Mon Sep 17 00:00:00 2001 From: Si Hyeong Lee Date: Tue, 20 Oct 2026 20:32:49 -0700 Subject: [PATCH 1/6] feat(host): session turns for a timeline, documents received for a session, stored quick replies Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_016NLGwiBY5uEivJqERQzcoY --- src/main/api/deckApi.surface.test.ts | 49 ++++++++++++++++++- src/main/api/deckApi.ts | 35 +++++++++++++- src/main/sessionImages.test.ts | 33 ++++++++++++- src/main/sessionImages.ts | 12 ++++- src/main/store.ts | 6 ++- src/main/tempClean.test.ts | 15 ++++++ src/main/tempClean.ts | 6 ++- src/preload/preload.ts | 5 ++ src/renderer/global.d.ts | 7 ++- src/renderer/machineDeck.ts | 5 ++ src/shared/quickReplies.test.ts | 34 +++++++++++++ src/shared/quickReplies.ts | 35 ++++++++++++++ src/shared/sentFiles.test.ts | 37 +++++++++++++++ src/shared/sentFiles.ts | 40 ++++++++++++++++ src/shared/sessionImages.ts | 51 +++++++++++++++++++- src/shared/timeline.test.ts | 44 +++++++++++++++++ src/shared/timeline.ts | 71 ++++++++++++++++++++++++++++ 17 files changed, 475 insertions(+), 10 deletions(-) create mode 100644 src/shared/quickReplies.test.ts create mode 100644 src/shared/quickReplies.ts create mode 100644 src/shared/sentFiles.test.ts create mode 100644 src/shared/sentFiles.ts create mode 100644 src/shared/timeline.test.ts create mode 100644 src/shared/timeline.ts diff --git a/src/main/api/deckApi.surface.test.ts b/src/main/api/deckApi.surface.test.ts index c9ae341..67a80d9 100644 --- a/src/main/api/deckApi.surface.test.ts +++ b/src/main/api/deckApi.surface.test.ts @@ -1,5 +1,7 @@ import { describe, it, expect, vi, beforeAll } from 'vitest'; -import { join } from 'node:path'; +import { basename, dirname, join } from 'node:path'; +import { readFileSync, rmSync } from 'node:fs'; +import { tmpdir } from 'node:os'; // deckApi reaches Electron for dialogs/clipboard/app info; none of that is exercised here — this file // is about the SHAPE of the capability table, not its handlers' behavior (ipc.guard/ipc.cockpit cover those). @@ -291,6 +293,51 @@ describe('receiving a pasted image from another machine', () => { }); }); +describe('receiving a document from another machine', () => { + const b64 = (s: string | Buffer) => Buffer.from(s).toString('base64'); + const receive = (name: unknown, data: unknown) => api['cockpit:receiveFile'].handler(name, data) as string | null; + + it('needs control, like an image', () => { + expect(mayCallRemotely(api['cockpit:receiveFile'], ['observe'])).toBe(false); + expect(mayCallRemotely(api['cockpit:receiveFile'], ['control'])).toBe(true); + }); + + it('writes a text file into the temp directory under its own name, never a path the caller picked', () => { + const written = receive('..\\..\\Windows\\build.log', b64('line 1\nline 2\n')); + expect(written).not.toBeNull(); + expect(dirname(written!)).toBe(tmpdir()); + expect(basename(written!)).toMatch(/^devdeck-file-[0-9a-f-]{36}-build\.log$/); + expect(readFileSync(written!, 'utf8')).toBe('line 1\nline 2\n'); + rmSync(written!); + }); + + it('refuses kinds that could run, and bytes that are not what the name says', () => { + expect(receive('setup.exe', b64('MZ'))).toBeNull(); + expect(receive('run.ps1', b64('Remove-Item'))).toBeNull(); + expect(receive('page.html', b64('