Add native Codex hooks integration (#2319)
* Add native Codex hooks integration * Address Codex review feedback * Use durable Codex marketplace root * Address Codex file context review feedback * Harden Codex installer review paths * Report Codex legacy cleanup failures * fix: keep MCP manifests in marketplace sync * fix: bundle zod in MCP server * fix: warn on Codex legacy cleanup failure * Fix hook observation readiness timeouts * Address Codex hook review notes * Tighten Codex MCP file context matching * Resolve final Codex review nits * Add Codex marketplace version guidance * Reset worker failure counter on API fallback * Fix Codex cat flag file extraction
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
|
||||
import { describe, it, expect, beforeEach, afterEach, spyOn, mock } from 'bun:test';
|
||||
import { mkdtempSync, writeFileSync, utimesSync, rmSync } from 'fs';
|
||||
import { mkdirSync, mkdtempSync, writeFileSync, utimesSync, rmSync } from 'fs';
|
||||
import { tmpdir, homedir } from 'os';
|
||||
import { join } from 'path';
|
||||
|
||||
@@ -181,4 +181,74 @@ describe('fileContextHandler — #2094 (no Read mutation)', () => {
|
||||
expect(ctx).not.toContain('Only line 1 was read');
|
||||
expect(ctx).toContain('full requested section');
|
||||
});
|
||||
|
||||
it('accepts a Codex filePaths array and joins per-file context blocks', async () => {
|
||||
const otherFile = join(tmpDir, 'other.md');
|
||||
writeFileSync(otherFile, PADDING);
|
||||
|
||||
const future = Date.now() + 60_000;
|
||||
fetchSpy = spyOn(globalThis, 'fetch').mockImplementation((url: string | URL | Request) => {
|
||||
const text = String(url);
|
||||
if (text.includes('other.md')) {
|
||||
return Promise.resolve(makeObservationsResponse([{ id: 2, created_at_epoch: future, title: 'Other file context' }]));
|
||||
}
|
||||
return Promise.resolve(makeObservationsResponse([{ id: 1, created_at_epoch: future, title: 'Main file context' }]));
|
||||
});
|
||||
|
||||
const result = await fileContextHandler.execute({
|
||||
sessionId: 'sess',
|
||||
cwd: tmpDir,
|
||||
toolName: 'Bash',
|
||||
toolInput: { filePaths: [testFile, otherFile] },
|
||||
});
|
||||
|
||||
const ctx = result.hookSpecificOutput!.additionalContext as string;
|
||||
expect(ctx).toContain('Main file context');
|
||||
expect(ctx).toContain('Other file context');
|
||||
expect(ctx).toContain('\n\n---\n\n');
|
||||
});
|
||||
|
||||
it('keeps successful timelines when one file lookup fails', async () => {
|
||||
const otherFile = join(tmpDir, 'other.md');
|
||||
writeFileSync(otherFile, PADDING);
|
||||
|
||||
const future = Date.now() + 60_000;
|
||||
fetchSpy = spyOn(globalThis, 'fetch').mockImplementation((url: string | URL | Request) => {
|
||||
const text = String(url);
|
||||
if (text.includes('other.md')) {
|
||||
return Promise.reject(new Error('worker unavailable'));
|
||||
}
|
||||
return Promise.resolve(makeObservationsResponse([{ id: 1, created_at_epoch: future, title: 'Main file context' }]));
|
||||
});
|
||||
|
||||
const result = await fileContextHandler.execute({
|
||||
sessionId: 'sess',
|
||||
cwd: tmpDir,
|
||||
toolName: 'Bash',
|
||||
toolInput: { filePaths: [testFile, otherFile] },
|
||||
});
|
||||
|
||||
const ctx = result.hookSpecificOutput!.additionalContext as string;
|
||||
expect(ctx).toContain('Main file context');
|
||||
expect(ctx).not.toContain('worker unavailable');
|
||||
});
|
||||
|
||||
it('skips directories before querying file history', async () => {
|
||||
const directoryPath = join(tmpDir, 'large-dir');
|
||||
mkdirSync(directoryPath);
|
||||
fetchSpy = spyOn(globalThis, 'fetch').mockResolvedValue(
|
||||
makeObservationsResponse([{ id: 1, created_at_epoch: Date.now() + 60_000 }])
|
||||
);
|
||||
|
||||
const result = await fileContextHandler.execute({
|
||||
sessionId: 'sess',
|
||||
cwd: tmpDir,
|
||||
toolName: 'Bash',
|
||||
toolInput: { filePaths: [directoryPath] },
|
||||
});
|
||||
|
||||
expect(result.continue).toBe(true);
|
||||
expect(result.hookSpecificOutput).toBeUndefined();
|
||||
expect(fetchSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user