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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions