diff --git a/skills/oracle/SKILL.md b/skills/oracle/SKILL.md index 336dd099a..6dacbf432 100644 --- a/skills/oracle/SKILL.md +++ b/skills/oracle/SKILL.md @@ -39,6 +39,13 @@ Recommended defaults: - Browser run (main path; long-running is normal): - `npx -y @steipete/oracle --engine browser --model gpt-5.4-pro -p "" --file "src/**"` +- Whole-repo browser upload (tracked archive; preferred when you want ChatGPT to inspect an entire repo): + - `cd /path/to/repo && git archive --format=zip --output /tmp/repo-tracked.zip HEAD` + - `npx -y @steipete/oracle --engine browser --browser-attachments always -p "" --file /tmp/repo-tracked.zip` + - Notes: + - `git archive HEAD` includes tracked files only, so untracked junk like `node_modules`, `.next`, `dist`, and local logs stay out automatically. + - If you need extra excludes beyond tracked-file filtering, use git pathspecs or a repo-specific archive script; avoid brittle `grep` pipelines. + - Manual paste fallback (assemble bundle, copy to clipboard): - `npx -y @steipete/oracle --render --copy -p "" --file "src/**"` - Note: `--copy` is a hidden alias for `--copy-markdown`. diff --git a/src/browser/prompt.ts b/src/browser/prompt.ts index fe3ea200b..f97ccea57 100644 --- a/src/browser/prompt.ts +++ b/src/browser/prompt.ts @@ -39,6 +39,10 @@ const MEDIA_EXTENSIONS = new Set([ ".heic", ".heif", ".pdf", + ".zip", + ".tar", + ".gz", + ".7z", ]); export function isMediaFile(filePath: string): boolean { diff --git a/tests/browser/prompt.test.ts b/tests/browser/prompt.test.ts index 412693e1e..f6561e4dc 100644 --- a/tests/browser/prompt.test.ts +++ b/tests/browser/prompt.test.ts @@ -1,3 +1,5 @@ +import fs from "node:fs/promises"; +import os from "node:os"; import path from "node:path"; import { describe, expect, test } from "vitest"; import { assembleBrowserPrompt } from "../../src/browser/prompt.js"; @@ -213,4 +215,38 @@ describe("assembleBrowserPrompt", () => { bundlePath: result.attachments[0]?.displayPath, }); }); + + test("treats zip archives as upload attachments", async () => { + const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "oracle-zip-")); + const zipPath = path.join(tempDir, "repo-tracked.zip"); + await fs.writeFile(zipPath, "fake zip payload"); + + try { + const result = await assembleBrowserPrompt( + buildOptions({ + file: [zipPath], + browserAttachments: "always", + }), + { + cwd: "/repo", + readFilesImpl: async (paths) => { + expect(paths).toEqual([]); + return []; + }, + }, + ); + + expect(result.attachmentMode).toBe("upload"); + expect(result.attachments).toEqual([ + expect.objectContaining({ + path: zipPath, + displayPath: path.relative("/repo", zipPath), + }), + ]); + expect(result.composerText).toBe("Explain the bug"); + expect(result.inlineFileCount).toBe(0); + } finally { + await fs.rm(tempDir, { recursive: true, force: true }); + } + }); });