mirror of
https://github.com/JimLiu/baoyu-skills.git
synced 2026-07-12 05:51:44 +08:00
feat(codex-imagegen): cwd-drift immunity (path resolve + skip-git-repo-check)
Two improvements so the wrapper works the same regardless of caller cwd or whether cwd is a git repo: 1. main.ts: resolve all filesystem path args (--prompt-file, --ref, --cache-dir, --log-file) to absolute paths up front. Previously only --image was resolved. Agents passing relative paths from arbitrary working directories (e.g. when SKILL.md is interpreted from a plugin install dir) now produce correct file lookups. 2. spawn.ts: pass --skip-git-repo-check to 'codex exec'. Without it, codex refuses to run outside a trusted directory: 'Not inside a trusted directory and --skip-git-repo-check was not specified.' This made the wrapper fail when invoked from /tmp or from a non-git project tree. 3. baoyu-cover-image/SKILL.md: explicit path resolution note — scripts/codex-imagegen.sh lives at plugin/repo root (not shell cwd-relative). From the skill base directory it is at '../../scripts/codex-imagegen.sh'. Agents should resolve to an absolute path before invoking. Verified: - 16 unit tests pass - e2e from /tmp (non-git, relative-path args) → 45s, 1.6MB PNG, status:ok Composes with the existing cover-image wiring (commit e3932e4).
This commit is contained in:
@@ -71,13 +71,22 @@ function parseArgs(argv: string[]): CliOptions {
|
|||||||
}
|
}
|
||||||
if (!opts.outputPath) throw new GenError("invalid_args", "--image is required", false);
|
if (!opts.outputPath) throw new GenError("invalid_args", "--image is required", false);
|
||||||
if (!opts.prompt && !promptFile) throw new GenError("invalid_args", "--prompt or --prompt-file required", false);
|
if (!opts.prompt && !promptFile) throw new GenError("invalid_args", "--prompt or --prompt-file required", false);
|
||||||
|
|
||||||
|
// Resolve every filesystem path to absolute up front, so behavior is
|
||||||
|
// independent of the caller's cwd. This matters when the wrapper is
|
||||||
|
// invoked from a skill running in an arbitrary working directory.
|
||||||
|
const cwd = process.cwd();
|
||||||
|
const toAbs = (p: string) => (path.isAbsolute(p) ? p : path.resolve(cwd, p));
|
||||||
|
|
||||||
|
opts.outputPath = toAbs(opts.outputPath);
|
||||||
if (promptFile) {
|
if (promptFile) {
|
||||||
opts.prompt = ""; // will be loaded later
|
opts.prompt = ""; // will be loaded later
|
||||||
(opts as any).__promptFile = promptFile;
|
(opts as any).__promptFile = toAbs(promptFile);
|
||||||
}
|
|
||||||
if (!path.isAbsolute(opts.outputPath)) {
|
|
||||||
opts.outputPath = path.resolve(process.cwd(), opts.outputPath);
|
|
||||||
}
|
}
|
||||||
|
opts.refImages = opts.refImages.map(toAbs);
|
||||||
|
if (opts.cacheDir) opts.cacheDir = toAbs(opts.cacheDir);
|
||||||
|
if (opts.logFile) opts.logFile = toAbs(opts.logFile);
|
||||||
|
|
||||||
return opts;
|
return opts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,16 @@ export async function runCodexExec(input: SpawnInput): Promise<CodexRunResult> {
|
|||||||
const logDir = await mkdtemp(path.join(tmpdir(), "codex-imggen-"));
|
const logDir = await mkdtemp(path.join(tmpdir(), "codex-imggen-"));
|
||||||
const rawLogPath = path.join(logDir, "stream.jsonl");
|
const rawLogPath = path.join(logDir, "stream.jsonl");
|
||||||
|
|
||||||
const args = ["exec", "--json", "--sandbox", "danger-full-access"];
|
// --skip-git-repo-check: lets the wrapper run from non-git cwds
|
||||||
|
// (e.g. /tmp, or a skill installed under ~/.claude/plugins/...).
|
||||||
|
// Without it, codex refuses with "Not inside a trusted directory".
|
||||||
|
const args = [
|
||||||
|
"exec",
|
||||||
|
"--json",
|
||||||
|
"--sandbox",
|
||||||
|
"danger-full-access",
|
||||||
|
"--skip-git-repo-check",
|
||||||
|
];
|
||||||
for (const img of input.refImages ?? []) {
|
for (const img of input.refImages ?? []) {
|
||||||
args.push("--image", img);
|
args.push("--image", img);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,17 +29,17 @@ When this skill needs to render an image, resolve the backend in this order:
|
|||||||
2. **Saved preference** — if `EXTEND.md` sets `preferred_image_backend` to a backend available right now, use it.
|
2. **Saved preference** — if `EXTEND.md` sets `preferred_image_backend` to a backend available right now, use it.
|
||||||
3. **Auto-select** (when the preference is `auto`, unset, or the pinned backend isn't available):
|
3. **Auto-select** (when the preference is `auto`, unset, or the pinned backend isn't available):
|
||||||
- **Codex (`imagegen`)** — first, inspect your available-skills / tool inventory. If a skill named `imagegen` is listed, you are running inside Codex and MUST use it: invoke via the `Skill` tool with `skill: "imagegen"`, passing the saved prompt file's content (plus output path and aspect ratio per Codex `imagegen`'s own args). Codex `imagegen` is the official raster backend in that runtime and outranks any non-native skill (e.g., `baoyu-imagine`) unless the user has explicitly pinned a different `preferred_image_backend`.
|
- **Codex (`imagegen`)** — first, inspect your available-skills / tool inventory. If a skill named `imagegen` is listed, you are running inside Codex and MUST use it: invoke via the `Skill` tool with `skill: "imagegen"`, passing the saved prompt file's content (plus output path and aspect ratio per Codex `imagegen`'s own args). Codex `imagegen` is the official raster backend in that runtime and outranks any non-native skill (e.g., `baoyu-imagine`) unless the user has explicitly pinned a different `preferred_image_backend`.
|
||||||
- **Codex via `codex exec` (`codex-imagegen`)** — if the current runtime does NOT expose a native `imagegen` skill but the `codex` CLI is on `PATH` and `codex login` is active (e.g., Claude Code with Codex CLI installed), invoke the `codex-imagegen` wrapper. Command shape:
|
- **Codex via `codex exec` (`codex-imagegen`)** — if the current runtime does NOT expose a native `imagegen` skill but the `codex` CLI is on `PATH` and `codex login` is active (e.g., Claude Code with Codex CLI installed), invoke the `codex-imagegen` wrapper. **Path resolution**: `scripts/codex-imagegen.sh` lives at the plugin/repo root, NOT relative to your shell cwd. From this `SKILL.md`'s base directory, the wrapper is at `../../scripts/codex-imagegen.sh` — resolve to an absolute path before invoking. Command shape:
|
||||||
```bash
|
```bash
|
||||||
./scripts/codex-imagegen.sh \
|
<ABSOLUTE_PLUGIN_ROOT>/scripts/codex-imagegen.sh \
|
||||||
--image <absolute_output_path> \
|
--image <absolute_output_path> \
|
||||||
--prompt-file <prompts/NN-cover-[slug].md> \
|
--prompt-file <absolute_path_to_prompts/NN-cover-[slug].md> \
|
||||||
--aspect <ratio> \
|
--aspect <ratio> \
|
||||||
[--ref <file>]... \
|
[--ref <absolute_file>]... \
|
||||||
[--cache-dir ~/.cache/baoyu-codex-imagegen] \
|
[--cache-dir ~/.cache/baoyu-codex-imagegen] \
|
||||||
[--log-file <jsonl_log_path>]
|
[--log-file <absolute_jsonl_log_path>]
|
||||||
```
|
```
|
||||||
Parse the single-line JSON on stdout. On `{"status":"ok",...}` proceed to Step 5. On `{"status":"error","error_kind":...}` report the `error_kind` to the user and (if retryable) ask whether to retry or fall back to another backend. The wrapper uses the user's Codex subscription — no `OPENAI_API_KEY` needed.
|
All input paths to the wrapper are auto-resolved against the wrapper's `process.cwd()` if you pass relative ones, but agents should pass absolute paths to be robust against cwd drift. Parse the single-line JSON on stdout. On `{"status":"ok",...}` proceed to Step 5. On `{"status":"error","error_kind":...}` report the `error_kind` to the user and (if retryable) ask whether to retry or fall back to another backend. The wrapper uses the user's Codex subscription — no `OPENAI_API_KEY` needed.
|
||||||
- **Other runtime-native tools** — if the runtime exposes a different native image tool (e.g., Hermes `image_generate`), use it the same way.
|
- **Other runtime-native tools** — if the runtime exposes a different native image tool (e.g., Hermes `image_generate`), use it the same way.
|
||||||
- Otherwise, if exactly one non-native backend is installed (e.g., `baoyu-imagine`), use it.
|
- Otherwise, if exactly one non-native backend is installed (e.g., `baoyu-imagine`), use it.
|
||||||
- Otherwise (multiple non-native backends with no runtime-native tool), ask the user once — batch with any other initial questions.
|
- Otherwise (multiple non-native backends with no runtime-native tool), ask the user once — batch with any other initial questions.
|
||||||
@@ -226,7 +226,7 @@ Save to `prompts/cover.md`. Template: [references/workflow/prompt-template.md](r
|
|||||||
- `direct` usage → pass via `--ref` (use ref-capable backend)
|
- `direct` usage → pass via `--ref` (use ref-capable backend)
|
||||||
- `style`/`palette` → extract traits, append to prompt
|
- `style`/`palette` → extract traits, append to prompt
|
||||||
5. **Generate**: Call the chosen backend with the prompt file, output path, aspect ratio.
|
5. **Generate**: Call the chosen backend with the prompt file, output path, aspect ratio.
|
||||||
- **`codex-imagegen`**: run `./scripts/codex-imagegen.sh --image <output> --prompt-file prompts/01-cover-[slug].md --aspect <ratio>` (add `--ref <file>` per reference, `--cache-dir ~/.cache/baoyu-codex-imagegen` to enable the idempotency cache). Read the stdout JSON; act on `status` and `error_kind`.
|
- **`codex-imagegen`**: invoke `<ABSOLUTE_PLUGIN_ROOT>/scripts/codex-imagegen.sh` (NOT a cwd-relative `./scripts/...` — resolve the absolute path from this skill's base directory: `../../scripts/codex-imagegen.sh`) with `--image <ABSOLUTE_output>` `--prompt-file <ABSOLUTE_prompts/01-cover-[slug].md>` `--aspect <ratio>` (add `--ref <ABSOLUTE_file>` per reference, `--cache-dir ~/.cache/baoyu-codex-imagegen` to enable the idempotency cache). All input paths to the wrapper are auto-resolved against its `process.cwd()` if relative, but passing absolutes is more robust. Read the stdout JSON; act on `status` and `error_kind`.
|
||||||
- **Codex `imagegen` (native)** or other runtime-native tools / `baoyu-imagine` skill: per the rule in `## Image Generation Tools` above.
|
- **Codex `imagegen` (native)** or other runtime-native tools / `baoyu-imagine` skill: per the rule in `## Image Generation Tools` above.
|
||||||
6. On failure: auto-retry once
|
6. On failure: auto-retry once
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user