mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-12 06:06:37 +03:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd78be5630 |
@@ -470,12 +470,11 @@ function runClaude(prompt, { cwd, env, resultPath, logPath, timeoutMs = DEFAULT_
|
|||||||
if (env.IMPECCABLE_LIVE_COPY_AGENT_MODEL) {
|
if (env.IMPECCABLE_LIVE_COPY_AGENT_MODEL) {
|
||||||
args.push('--model', env.IMPECCABLE_LIVE_COPY_AGENT_MODEL);
|
args.push('--model', env.IMPECCABLE_LIVE_COPY_AGENT_MODEL);
|
||||||
}
|
}
|
||||||
args.push(prompt);
|
|
||||||
// Forward env as-is so CLAUDE_CODE_OAUTH_TOKEN and ANTHROPIC_API_KEY flow
|
// Forward env as-is so CLAUDE_CODE_OAUTH_TOKEN and ANTHROPIC_API_KEY flow
|
||||||
// through. On macOS, `claude /login` stores creds in the Keychain, which a
|
// through. On macOS, `claude /login` stores creds in the Keychain, which a
|
||||||
// non-TTY subprocess cannot read; setting CLAUDE_CODE_OAUTH_TOKEN (via
|
// non-TTY subprocess cannot read; setting CLAUDE_CODE_OAUTH_TOKEN (via
|
||||||
// `claude setup-token`) is the supported headless auth path.
|
// `claude setup-token`) is the supported headless auth path.
|
||||||
return runAgentProcess('claude', args, '', { cwd, env, logPath, timeoutMs, mirrorOutputPath: resultPath });
|
return runAgentProcess('claude', args, prompt, { cwd, env, logPath, timeoutMs, mirrorOutputPath: resultPath });
|
||||||
}
|
}
|
||||||
|
|
||||||
function runAgentProcess(command, args, stdin, { cwd, env, logPath, timeoutMs, mirrorOutputPath }) {
|
function runAgentProcess(command, args, stdin, { cwd, env, logPath, timeoutMs, mirrorOutputPath }) {
|
||||||
|
|||||||
@@ -305,6 +305,48 @@ describe('live-copy-edit-agent', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('passes large Claude prompts on stdin instead of argv', async () => {
|
||||||
|
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'copy-agent-claude-stdin-'));
|
||||||
|
try {
|
||||||
|
const fakeClaude = path.join(tmp, 'claude');
|
||||||
|
fs.writeFileSync(fakeClaude, [
|
||||||
|
'#!/usr/bin/env node',
|
||||||
|
"let input = '';",
|
||||||
|
"process.stdin.setEncoding('utf8');",
|
||||||
|
"process.stdin.on('data', (chunk) => { input += chunk; });",
|
||||||
|
"process.stdin.on('end', () => {",
|
||||||
|
" const promptLeakedToArgv = process.argv.slice(2).some((arg) => arg.includes('large-prompt-sentinel'));",
|
||||||
|
" if (!input.includes('large-prompt-sentinel') || promptLeakedToArgv) process.exit(2);",
|
||||||
|
" process.stdout.write(JSON.stringify({ status: 'done', appliedEntryIds: ['large'], files: [], notes: [] }));",
|
||||||
|
'});',
|
||||||
|
'',
|
||||||
|
].join('\n'));
|
||||||
|
fs.chmodSync(fakeClaude, 0o755);
|
||||||
|
|
||||||
|
const result = await runCopyEditBatchAgent({
|
||||||
|
pageUrl: '/',
|
||||||
|
entries: [{
|
||||||
|
id: 'large',
|
||||||
|
pageUrl: '/',
|
||||||
|
ops: [{ originalText: 'Old', newText: `large-prompt-sentinel${'x'.repeat(1_100_000)}` }],
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
provider: 'claude',
|
||||||
|
outDir: path.join(tmp, 'out'),
|
||||||
|
timeoutMs: 5_000,
|
||||||
|
env: {
|
||||||
|
...process.env,
|
||||||
|
PATH: `${tmp}${path.delimiter}${process.env.PATH || ''}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(result.status, 'done');
|
||||||
|
assert.deepEqual(result.appliedEntryIds, ['large']);
|
||||||
|
} finally {
|
||||||
|
fs.rmSync(tmp, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it('describeNoProviderError mentions starting impeccable live when chat is the missing piece', () => {
|
it('describeNoProviderError mentions starting impeccable live when chat is the missing piece', () => {
|
||||||
const noChatPolling = describeNoProviderError({
|
const noChatPolling = describeNoProviderError({
|
||||||
exists: () => false,
|
exists: () => false,
|
||||||
|
|||||||
Reference in New Issue
Block a user