automata-cli 0.3.0-develop.59 → 0.3.0-develop.66

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +156 -22
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { Command as Command4 } from "commander";
4
+ import { Command as Command5 } from "commander";
5
5
 
6
6
  // src/version.ts
7
7
  import { readFileSync } from "fs";
@@ -876,9 +876,6 @@ var gitCommand = new Command2("git").description("Git workflow commands (some re
876
876
 
877
877
  // src/commands/getReady.ts
878
878
  import { Command as Command3 } from "commander";
879
- import { spawnSync as spawnSync4 } from "child_process";
880
- import { existsSync } from "fs";
881
- import { delimiter, join as join2 } from "path";
882
879
 
883
880
  // src/config/githubService.ts
884
881
  import { spawnSync as spawnSync3 } from "child_process";
@@ -937,7 +934,11 @@ function postComment(issueNumber, body) {
937
934
  }
938
935
  }
939
936
 
940
- // src/commands/getReady.ts
937
+ // src/claude/claudeService.ts
938
+ import { spawn, spawnSync as spawnSync4 } from "child_process";
939
+ import { createInterface } from "readline";
940
+ import { existsSync } from "fs";
941
+ import { delimiter, join as join2 } from "path";
941
942
  function resolveCommand(name) {
942
943
  const pathDirs = (process.env["PATH"] ?? "").split(delimiter);
943
944
  for (const dir of pathDirs) {
@@ -946,30 +947,150 @@ function resolveCommand(name) {
946
947
  }
947
948
  return name;
948
949
  }
949
- function invokeClaudeCode(issue, systemPrompt, yolo) {
950
- const prompt = systemPrompt ? `${systemPrompt}
951
-
952
- ${issue.body}` : issue.body;
950
+ var MODEL_IDS = {
951
+ opus: "claude-opus-4-6",
952
+ sonnet: "claude-sonnet-4-6",
953
+ haiku: "claude-haiku-4-5-20251001"
954
+ };
955
+ function resolveModelOption(opts) {
956
+ const selected = ["opus", "sonnet", "haiku"].filter((m) => opts[m]);
957
+ if (selected.length > 1) {
958
+ process.stderr.write(`Error: --${selected[0]} and --${selected[1]} are mutually exclusive.
959
+ `);
960
+ process.exit(1);
961
+ }
962
+ return selected.length === 1 ? MODEL_IDS[selected[0]] : void 0;
963
+ }
964
+ function invokeClaudeCode(prompt, options = {}) {
965
+ if (options.verbose) {
966
+ return invokeClaudeCodeVerbose(prompt, options.yolo ?? false, options.model);
967
+ }
968
+ invokeClaudeCodeSync(prompt, options.yolo ?? false, options.model);
969
+ }
970
+ function invokeClaudeCodeSync(prompt, yolo, model) {
953
971
  const claudeBin = resolveCommand("claude");
954
- const args = yolo ? ["--dangerously-skip-permissions", "-p", prompt] : ["-p", prompt];
972
+ const args = [];
973
+ if (yolo) args.push("--dangerously-skip-permissions");
974
+ if (model) args.push("--model", model);
975
+ args.push("-p", prompt);
955
976
  const result = spawnSync4(claudeBin, args, { encoding: "utf8", stdio: "inherit" });
956
- if (result.error) {
957
- const err = result.error;
958
- if (err.code === "ENOENT") {
959
- process.stderr.write("Error: `claude` CLI is not installed or not on PATH.\n");
960
- process.exit(1);
977
+ handleSpawnError(result.error);
978
+ handleExitCode(result.status);
979
+ }
980
+ function invokeClaudeCodeVerbose(prompt, yolo, model) {
981
+ return new Promise((resolve2) => {
982
+ const claudeBin = resolveCommand("claude");
983
+ const args = [];
984
+ if (yolo) args.push("--dangerously-skip-permissions");
985
+ if (model) args.push("--model", model);
986
+ args.push("--verbose", "--output-format", "stream-json", "-p", prompt);
987
+ const child = spawn(claudeBin, args, { stdio: ["inherit", "pipe", "inherit"] });
988
+ const rl = createInterface({ input: child.stdout });
989
+ let turnCount = 0;
990
+ child.on("error", (err) => {
991
+ handleSpawnError(err);
992
+ });
993
+ rl.on("line", (line) => {
994
+ try {
995
+ const event = JSON.parse(line);
996
+ formatEvent(event, turnCount);
997
+ if (event["type"] === "assistant") turnCount++;
998
+ } catch {
999
+ }
1000
+ });
1001
+ child.on("close", (code) => {
1002
+ handleExitCode(code);
1003
+ resolve2();
1004
+ });
1005
+ });
1006
+ }
1007
+ function formatEvent(event, turnCount) {
1008
+ const type = event["type"];
1009
+ if (type === "assistant") {
1010
+ const message = event["message"];
1011
+ const content = message?.["content"];
1012
+ if (!content) return;
1013
+ for (const block of content) {
1014
+ if (block["type"] === "tool_use") {
1015
+ const toolName = block["name"];
1016
+ const input = block["input"];
1017
+ const summary = summarizeTool(toolName, input);
1018
+ process.stderr.write(` [step ${turnCount + 1}] ${summary}
1019
+ `);
1020
+ } else if (block["type"] === "text") {
1021
+ const text = block["text"] ?? "";
1022
+ if (text.length > 0) {
1023
+ const preview = text.length > 120 ? text.slice(0, 120) + "..." : text;
1024
+ const firstLine = preview.split("\n")[0];
1025
+ process.stderr.write(` [step ${turnCount + 1}] ${firstLine}
1026
+ `);
1027
+ }
1028
+ }
961
1029
  }
962
- process.stderr.write(`Error: ${err.message}
1030
+ } else if (type === "result") {
1031
+ const result = event["result"];
1032
+ const cost = event["cost_usd"];
1033
+ const duration = event["duration_ms"];
1034
+ const turns = event["num_turns"];
1035
+ process.stderr.write("\n--- Result ---\n");
1036
+ if (cost !== void 0 || duration !== void 0 || turns !== void 0) {
1037
+ const parts = [];
1038
+ if (turns !== void 0) parts.push(`${turns} turns`);
1039
+ if (duration !== void 0) parts.push(`${(duration / 1e3).toFixed(1)}s`);
1040
+ if (cost !== void 0) parts.push(`$${cost.toFixed(4)}`);
1041
+ process.stderr.write(` [info] ${parts.join(" | ")}
963
1042
  `);
1043
+ }
1044
+ if (result) {
1045
+ process.stdout.write(result + "\n");
1046
+ }
1047
+ }
1048
+ }
1049
+ function summarizeTool(name, input) {
1050
+ if (!input) return `tool: ${name}`;
1051
+ switch (name) {
1052
+ case "Read":
1053
+ return `reading ${input["file_path"] ?? "file"}`;
1054
+ case "Write":
1055
+ return `writing ${input["file_path"] ?? "file"}`;
1056
+ case "Edit":
1057
+ return `editing ${input["file_path"] ?? "file"}`;
1058
+ case "Bash":
1059
+ return `running: ${truncate(String(input["command"] ?? ""), 80)}`;
1060
+ case "Glob":
1061
+ return `searching files: ${input["pattern"] ?? ""}`;
1062
+ case "Grep":
1063
+ return `searching content: ${truncate(String(input["pattern"] ?? ""), 60)}`;
1064
+ case "Agent":
1065
+ return `spawning agent: ${input["description"] ?? name}`;
1066
+ default:
1067
+ return `tool: ${name}`;
1068
+ }
1069
+ }
1070
+ function truncate(str, max) {
1071
+ return str.length > max ? str.slice(0, max) + "..." : str;
1072
+ }
1073
+ function handleSpawnError(error) {
1074
+ if (!error) return;
1075
+ const err = error;
1076
+ if (err.code === "ENOENT") {
1077
+ process.stderr.write("Error: `claude` CLI is not installed or not on PATH.\n");
964
1078
  process.exit(1);
965
1079
  }
966
- if (result.status !== 0) {
967
- process.stderr.write(`Error: Claude Code exited with code ${result.status ?? "unknown"}.
1080
+ process.stderr.write(`Error: ${err.message}
1081
+ `);
1082
+ process.exit(1);
1083
+ }
1084
+ function handleExitCode(status) {
1085
+ if (status !== null && status !== 0) {
1086
+ process.stderr.write(`Error: Claude Code exited with code ${status}.
968
1087
  `);
969
- process.exit(result.status ?? 1);
1088
+ process.exit(status);
970
1089
  }
971
1090
  }
972
- var implementNextCommand = new Command3("implement-next").description("Find the next open GitHub issue matching the configured filter, claim it, and invoke Claude Code").option("--json", "Output issue details as JSON").option("--no-claude", "Skip Claude Code invocation after claiming the issue").option("--query-only", "Print issue content and exit without claiming or invoking Claude").option("--yolo", "Launch Claude Code with --dangerously-skip-permissions").action((options) => {
1091
+
1092
+ // src/commands/getReady.ts
1093
+ var implementNextCommand = new Command3("implement-next").description("Find the next open GitHub issue matching the configured filter, claim it, and invoke Claude Code").option("--json", "Output issue details as JSON").option("--no-claude", "Skip Claude Code invocation after claiming the issue").option("--query-only", "Print issue content and exit without claiming or invoking Claude").option("--yolo", "Launch Claude Code with --dangerously-skip-permissions").option("--verbose", "Show step-by-step progress summary and final result").option("--opus", "Use claude-opus-4-6").option("--sonnet", "Use claude-sonnet-4-6").option("--haiku", "Use claude-haiku-4-5-20251001").action(async (options) => {
973
1094
  const config = readConfig();
974
1095
  if (config.remoteType !== "gh") {
975
1096
  process.stderr.write(
@@ -1022,16 +1143,29 @@ ${issue.body}
1022
1143
  process.exit(1);
1023
1144
  }
1024
1145
  if (options.claude !== false) {
1025
- invokeClaudeCode(issue, config.claudeSystemPrompt, options.yolo ?? false);
1146
+ const prompt = config.claudeSystemPrompt ? `${config.claudeSystemPrompt}
1147
+
1148
+ ${issue.body}` : issue.body;
1149
+ const model = resolveModelOption(options);
1150
+ await invokeClaudeCode(prompt, { yolo: options.yolo, verbose: options.verbose, model });
1026
1151
  }
1027
1152
  });
1028
1153
 
1154
+ // src/commands/test.ts
1155
+ import { Command as Command4 } from "commander";
1156
+ var testClaudeCmd = new Command4("claude").description("Test Claude Code invocation with a user-supplied prompt").requiredOption("--prompt <string>", "Prompt to send to Claude Code").option("--yolo", "Launch Claude Code with --dangerously-skip-permissions").option("--verbose", "Show step-by-step progress summary and final result").option("--opus", "Use claude-opus-4-6").option("--sonnet", "Use claude-sonnet-4-6").option("--haiku", "Use claude-haiku-4-5-20251001").action(async (options) => {
1157
+ const model = resolveModelOption(options);
1158
+ await invokeClaudeCode(options.prompt, { yolo: options.yolo, verbose: options.verbose, model });
1159
+ });
1160
+ var testCommand = new Command4("test").description("Test commands for verifying automata integrations").addCommand(testClaudeCmd);
1161
+
1029
1162
  // src/index.ts
1030
- var program = new Command4();
1163
+ var program = new Command5();
1031
1164
  program.name("automata").description("Automata CLI tool").version(version, "-v, --version");
1032
1165
  program.addCommand(configCommand);
1033
1166
  program.addCommand(gitCommand);
1034
1167
  program.addCommand(implementNextCommand);
1168
+ program.addCommand(testCommand);
1035
1169
  program.showHelpAfterError();
1036
1170
  program.parse();
1037
1171
  if (process.argv.length <= 2) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "automata-cli",
3
- "version": "0.3.0-develop.59",
3
+ "version": "0.3.0-develop.66",
4
4
  "description": "Automata CLI tool",
5
5
  "type": "module",
6
6
  "bin": {