From 8072306a896abaf37839962a74eb8dc7c13d41f6 Mon Sep 17 00:00:00 2001 From: Chris Lettieri Date: Wed, 25 Feb 2026 17:34:31 -0500 Subject: [PATCH] user prompt --- src/services/task-dispatch-service.ts | 11 +---- tests/task-dispatch-service.test.ts | 58 ++++----------------------- 2 files changed, 10 insertions(+), 59 deletions(-) diff --git a/src/services/task-dispatch-service.ts b/src/services/task-dispatch-service.ts index f8eadfa..d5838b8 100644 --- a/src/services/task-dispatch-service.ts +++ b/src/services/task-dispatch-service.ts @@ -355,15 +355,8 @@ export class TaskDispatchService { // Without this, send-keys can fire before the shell is ready and characters get lost. await this.waitForShellReady(tmux, sessionName); - // If the flag expects a file path (e.g. --append-system-prompt-file), pass the path directly. - // Otherwise (e.g. --append-system-prompt), expand the file content inline via $(cat ...). - const contextArg = agentConfig.contextFlag.endsWith('-file') - ? this.shellEscape(contextFilePath) - : `"$(cat ${this.shellEscape(contextFilePath)})"`; - // Explicit cd ensures Claude picks up the correct workspace, even if the - // user's shell profile overrides the tmux -c starting directory. - const prompt = 'Read your system prompt carefully. Summarize the task, outline your approach, then begin working.'; - const agentCmd = `cd ${this.shellEscape(workingDir)} && ${agentConfig.command} ${agentConfig.contextFlag} ${contextArg} "${prompt}"`; + // Pass the context file contents as the initial user prompt via $(cat ...). + const agentCmd = `cd ${this.shellEscape(workingDir)} && ${agentConfig.command} "$(cat ${this.shellEscape(contextFilePath)})"`; await execAsync( `${tmux} send-keys -t ${this.shellEscape(sessionName)} ${this.shellEscape(agentCmd)} Enter` ); diff --git a/tests/task-dispatch-service.test.ts b/tests/task-dispatch-service.test.ts index b8895e1..e724426 100644 --- a/tests/task-dispatch-service.test.ts +++ b/tests/task-dispatch-service.test.ts @@ -415,7 +415,7 @@ describe('TaskDispatchService', () => { vi.restoreAllMocks(); }); - it('creates tmux session then sends agent command', async () => { + it('creates tmux session then sends agent command with context as user prompt', async () => { // new-session mockExecAsync.mockResolvedValueOnce({ stdout: '', stderr: '' }); // capture-pane for waitForShellReady @@ -434,61 +434,19 @@ describe('TaskDispatchService', () => { '/usr/bin/tmux', 'task-test', agentConfig, '/tmp/ctx.md', '/home/user/project' ); - // Verify new-session was called const calls = mockExecAsync.mock.calls.map((c: any[]) => c[0] as string); + + // Verify new-session was called expect(calls.some(c => c.includes('new-session -d -s'))).toBe(true); - // Verify send-keys was called with the agent command + // Verify send-keys passes context file via $(cat ...) as user prompt const sendKeysCmd = calls.find(c => c.includes('send-keys')); expect(sendKeysCmd).toBeTruthy(); + expect(sendKeysCmd).toContain('$(cat'); + expect(sendKeysCmd).toContain('/tmp/ctx.md'); expect(sendKeysCmd).toContain('Enter'); - }); - - it('uses contextFlag -file variant to pass path directly', async () => { - mockExecAsync.mockResolvedValueOnce({ stdout: '', stderr: '' }); - mockExecAsync.mockResolvedValueOnce({ stdout: '$ ', stderr: '' }); - mockExecAsync.mockResolvedValueOnce({ stdout: '', stderr: '' }); - - const agentConfig = { - id: 'claude-code', - name: 'Claude Code', - command: 'claude', - contextFlag: '--append-system-prompt-file', - }; - - await (service as any).createTmuxSession( - '/usr/bin/tmux', 'task-test', agentConfig, '/tmp/ctx.md', '/home/user/project' - ); - - // The send-keys call should contain the file path directly (not $(cat ...)) - const sendKeysCall = mockExecAsync.mock.calls.find( - (c: any[]) => typeof c[0] === 'string' && c[0].includes('send-keys') - ); - const cmd = sendKeysCall![0] as string; - expect(cmd).not.toContain('$(cat'); - }); - - it('uses $(cat ...) for non-file context flag', async () => { - mockExecAsync.mockResolvedValueOnce({ stdout: '', stderr: '' }); - mockExecAsync.mockResolvedValueOnce({ stdout: '$ ', stderr: '' }); - mockExecAsync.mockResolvedValueOnce({ stdout: '', stderr: '' }); - - const agentConfig = { - id: 'test', - name: 'Test', - command: 'agent', - contextFlag: '--system-prompt', - }; - - await (service as any).createTmuxSession( - '/usr/bin/tmux', 'task-test', agentConfig, '/tmp/ctx.md', '/home/user/project' - ); - - const sendKeysCall = mockExecAsync.mock.calls.find( - (c: any[]) => typeof c[0] === 'string' && c[0].includes('send-keys') - ); - const cmd = sendKeysCall![0] as string; - expect(cmd).toContain('$(cat'); + // Should NOT contain the contextFlag — context is the user prompt now + expect(sendKeysCmd).not.toContain('--append-system-prompt'); }); });