Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions sdk/typescript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ try {
```

`result.findings` contains this scan's findings; `repositoryFindings` also
includes earlier open findings when available. Matching earlier findings can
make one extra model call, even with a cost limit.
includes earlier open findings when available. Matching earlier findings uses
additional model calls, with large inputs split into batches. These calls are
outside the scan's recorded cost and `maxCostUsd` limit.

Keep results outside the repository and restrict access: reports can contain
source code, vulnerability details, and reproduction steps.
Expand Down
1 change: 0 additions & 1 deletion sdk/typescript/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1703,7 +1703,6 @@ export class CodexSecurity {
((input, comparisonOptions) =>
matchScanFindingsInternal(input, comparisonOptions, {
surface: this.#surface,
allowBatching: false,
})),
environment,
model,
Expand Down
7 changes: 3 additions & 4 deletions sdk/typescript/src/scan-comparison.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,15 +174,15 @@ export async function matchScanFindings(
export async function matchScanFindingsInternal(
input: ScanComparisonInput,
options: ScanComparisonOptions = {},
runtimeOptions: { surface: CodexSecuritySurface; allowBatching?: boolean },
runtimeOptions: { surface: CodexSecuritySurface },
): Promise<ScanComparisonResult> {
const comparisons: ScanComparisonResult[] = [];
const allowHistoricalUncertainty =
options.allowHistoricalUncertainty ?? false;
const outputSchema = z.toJSONSchema(comparisonSchema.required(), {
target: "openapi-3.0",
});
for (const batch of comparisonBatches(input, runtimeOptions.allowBatching)) {
for (const batch of comparisonBatches(input)) {
options.signal?.throwIfAborted();
const finalResponse = await runReadOnlyCodex(
batch.prompt,
Expand Down Expand Up @@ -214,10 +214,9 @@ export async function matchScanFindingsInternal(

function* comparisonBatches(
input: ScanComparisonInput,
allowBatching = true,
): Generator<{ input: ScanComparisonInput; prompt: string }> {
const prompt = comparisonPrompt(input);
if (allowBatching && prompt.length > CODEX_MAX_INPUT_CHARACTERS / 2) {
if (prompt.length > CODEX_MAX_INPUT_CHARACTERS / 2) {
// Splitting one side at a time covers every before/after pair exactly once.
const side =
input.before.length > 1 &&
Expand Down
31 changes: 0 additions & 31 deletions sdk/typescript/tests-ts/scan-comparison-batches.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { expect, test } from "bun:test";
import {
matchScanFindings,
matchScanFindingsInternal,
type ScanComparisonInput,
type ScanComparisonOptions,
type ScanComparisonResult,
Expand Down Expand Up @@ -252,36 +251,6 @@ test("uses Codex's full allowance for individual pairs without truncation", asyn
expect(oversized.before[0]!.evidence).toHaveLength(1048576);
});

test.each([200000, 300000])(
"keeps automatic post-scan matching to at most one call (%p characters per finding)",
async (characters) => {
const input = {
before: Array.from({ length: 4 }, (_, index) =>
finding(`before-${index}`, characters),
),
after: [finding("after")],
};
const calls: ScanComparisonInput[] = [];
const comparison = matchScanFindingsInternal(
input,
{
codex: codex((batch) => {
calls.push(batch);
return noMatches;
}),
},
{ surface: "sdk", allowBatching: false },
);
if (characters === 300000) {
await expect(comparison).rejects.toThrow("input limit");
expect(calls).toEqual([]);
} else {
expect(await comparison).toEqual(noMatches);
expect(calls).toEqual([input]);
}
},
);

test("stops between batches when canceled", async () => {
const controller = new AbortController();
let calls = 0;
Expand Down
Loading