Skip to content

'\"copilot\"' is not recognized as an internal or external command, operable program or batch file. #51

@doggy8088

Description

@doggy8088

I always produce this error on Windows.

[CLI subprocess] '\"copilot\"' is not recognized as an internal or external command,
[CLI subprocess] operable program or batch file.
Image

Here is my code:

import { CopilotClient } from "@github/copilot-sdk";
import { promises as fs } from "node:fs";
import path from "node:path";

const IMAGE_EXTENSIONS = new Set([
  ".jpg",
  ".jpeg",
  ".png",
  ".gif",
  ".webp",
  ".bmp",
  ".tiff",
  ".tif",
  ".heic",
  ".heif",
]);

const SKIP_DIRS = new Set(["node_modules", ".git", "dist"]);

type WalkOptions = {
  root: string;
  recursive: boolean;
};

async function walkDir({ root, recursive }: WalkOptions): Promise<string[]> {
  const entries = await fs.readdir(root, { withFileTypes: true });
  const files: string[] = [];

  for (const entry of entries) {
    const entryPath = path.join(root, entry.name);
    if (entry.isDirectory()) {
      if (SKIP_DIRS.has(entry.name)) {
        continue;
      }
      if (recursive) {
        files.push(...(await walkDir({ root: entryPath, recursive })));
      }
      continue;
    }

    if (entry.isFile()) {
      files.push(entryPath);
    }
  }

  return files;
}

function isImageFile(filePath: string): boolean {
  return IMAGE_EXTENSIONS.has(path.extname(filePath).toLowerCase());
}

function buildPrompt(fileName: string): string {
  return [
    "Describe this photo in concise, factual terms.",
    "Focus on visible objects, scene, lighting, and any notable details.",
    "Return plain text only, no markdown, no bullet points.",
    `File name: ${fileName}`,
  ].join(" ");
}

async function writeDescription(filePath: string, description: string) {
  const dirName = path.dirname(filePath);
  const baseName = path.basename(filePath, path.extname(filePath));
  const txtPath = path.join(dirName, `${baseName}.txt`);
  await fs.writeFile(txtPath, description.trim() + "\n", "utf8");
}

function printHelp() {
  console.log(`Usage: photo-agent [options]

Options:
  -r, --recursive     Recurse into subdirectories
  -C, --working-dir   Working directory (default: current)
  --model=<name>      Model name (default: gpt-5)
  -h, --help          Show help
`);
}

function readWorkingDir(args: string[]): string | undefined {
  const longPrefix = "--working-dir=";
  const shortPrefix = "-C=";
  for (let i = 0; i < args.length; i += 1) {
    const arg = args[i];
    if (arg.startsWith(longPrefix)) {
      return arg.slice(longPrefix.length);
    }
    if (arg.startsWith(shortPrefix)) {
      return arg.slice(shortPrefix.length);
    }
    if (arg === "--working-dir" || arg === "-C") {
      const next = args[i + 1];
      if (!next || next.startsWith("-")) {
        throw new Error("Missing value for --working-dir/-C.");
      }
      return next;
    }
  }
  return undefined;
}

async function main() {
  const argv = process.argv.slice(2);
  const args = new Set(argv);
  if (args.has("--help") || args.has("-h")) {
    printHelp();
    return;
  }
  const recursive = args.has("--recursive") || args.has("-r");
  const modelArg = argv.find((arg) => arg.startsWith("--model="));
  const model = modelArg ? modelArg.split("=")[1] : "gpt-5";
  let cwd = process.cwd();
  try {
    const workingDir = readWorkingDir(argv);
    if (workingDir) {
      cwd = path.resolve(workingDir);
    }
  } catch (error) {
    console.error(error instanceof Error ? error.message : error);
    process.exitCode = 1;
    return;
  }

  const allFiles = await walkDir({ root: cwd, recursive });
  const images = allFiles.filter(isImageFile);

  if (images.length === 0) {
    console.log("No image files found.");
    return;
  }

  const client = new CopilotClient();
  await client.start();
  const session = await client.createSession({ model });

  try {
    for (const imagePath of images) {
      const fileName = path.basename(imagePath);
      console.log(`Describing ${fileName}...`);

      const event = await session.sendAndWait({
        prompt: buildPrompt(fileName),
        attachments: [
          {
            type: "file",
            path: imagePath,
            displayName: fileName,
          },
        ],
      });

      const content = event?.data?.content?.trim();
      if (!content) {
        console.warn(`No description returned for ${fileName}. Skipping.`);
        continue;
      }

      await writeDescription(imagePath, content);
    }
  } finally {
    await session.destroy();
    await client.stop();
  }
}

main().catch((error) => {
  console.error("Failed to run photo agent:", error);
  process.exitCode = 1;
});

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions