open-agents-ai 0.4.0 → 0.4.1

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 +136 -57
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1116,21 +1116,29 @@ var init_tool_executor = __esm({
1116
1116
  });
1117
1117
 
1118
1118
  // packages/execution/dist/tools/shell.js
1119
- import { execFile } from "node:child_process";
1120
- import { promisify } from "node:util";
1121
- var execFileAsync, ShellTool;
1119
+ import { spawn } from "node:child_process";
1120
+ var ShellTool;
1122
1121
  var init_shell = __esm({
1123
1122
  "packages/execution/dist/tools/shell.js"() {
1124
1123
  "use strict";
1125
- execFileAsync = promisify(execFile);
1126
1124
  ShellTool = class {
1127
1125
  name = "shell";
1128
- description = "Execute a shell command in the project working directory";
1126
+ description = "Execute a shell command in the project working directory. Commands run non-interactively (CI=true). For commands that need input, use the stdin parameter or pass non-interactive flags (--yes, --no-input).";
1129
1127
  parameters = {
1130
1128
  type: "object",
1131
1129
  properties: {
1132
- command: { type: "string", description: "The shell command to execute" },
1133
- timeout: { type: "number", description: "Timeout in milliseconds" }
1130
+ command: {
1131
+ type: "string",
1132
+ description: "The shell command to execute"
1133
+ },
1134
+ timeout: {
1135
+ type: "number",
1136
+ description: "Timeout in milliseconds (default: 30000)"
1137
+ },
1138
+ stdin: {
1139
+ type: "string",
1140
+ description: "Text to write to the command's standard input. Use newlines to separate multiple inputs. For arrow-key prompts, prefer --yes or non-interactive flags instead."
1141
+ }
1134
1142
  },
1135
1143
  required: ["command"]
1136
1144
  };
@@ -1143,29 +1151,89 @@ var init_shell = __esm({
1143
1151
  async execute(args) {
1144
1152
  const command = args["command"];
1145
1153
  const timeout = args["timeout"] ?? this.defaultTimeout;
1154
+ const stdinInput = args["stdin"];
1146
1155
  const start = performance.now();
1147
- try {
1148
- const { stdout, stderr } = await execFileAsync("bash", ["-c", command], {
1156
+ return new Promise((resolve12) => {
1157
+ const child = spawn("bash", ["-c", command], {
1149
1158
  cwd: this.workingDir,
1150
- timeout,
1151
- maxBuffer: 1024 * 1024
1159
+ env: {
1160
+ ...process.env,
1161
+ // Non-interactive mode: libraries like prompts, inquirer,
1162
+ // create-next-app, and many Node CLI tools check CI to skip
1163
+ // interactive prompts and use defaults instead.
1164
+ CI: "true",
1165
+ NONINTERACTIVE: "1",
1166
+ // Disable color in most tools to get clean output
1167
+ NO_COLOR: "1",
1168
+ FORCE_COLOR: "0"
1169
+ },
1170
+ stdio: ["pipe", "pipe", "pipe"]
1152
1171
  });
1153
- return {
1154
- success: true,
1155
- output: stdout + (stderr ? `
1172
+ let stdout = "";
1173
+ let stderr = "";
1174
+ let killed = false;
1175
+ const maxBuf = 1024 * 1024;
1176
+ const timer = setTimeout(() => {
1177
+ killed = true;
1178
+ child.kill("SIGTERM");
1179
+ setTimeout(() => {
1180
+ try {
1181
+ child.kill("SIGKILL");
1182
+ } catch {
1183
+ }
1184
+ }, 5e3);
1185
+ }, timeout);
1186
+ child.stdout.on("data", (data) => {
1187
+ stdout += data.toString();
1188
+ if (stdout.length > maxBuf) {
1189
+ stdout = stdout.slice(0, maxBuf);
1190
+ }
1191
+ });
1192
+ child.stderr.on("data", (data) => {
1193
+ stderr += data.toString();
1194
+ if (stderr.length > maxBuf) {
1195
+ stderr = stderr.slice(0, maxBuf);
1196
+ }
1197
+ });
1198
+ if (stdinInput) {
1199
+ child.stdin.write(stdinInput);
1200
+ }
1201
+ child.stdin.end();
1202
+ child.on("close", (code) => {
1203
+ clearTimeout(timer);
1204
+ const durationMs = performance.now() - start;
1205
+ if (killed) {
1206
+ const combined = stdout + stderr;
1207
+ const looksInteractive = /\? .+[›>]|y\/n|yes\/no|\(Y\/n\)|\[y\/N\]/i.test(combined);
1208
+ const hint = looksInteractive ? " The command appears to be waiting for interactive input. Use non-interactive flags (e.g., --yes, --no-input) or provide input via the stdin parameter." : "";
1209
+ resolve12({
1210
+ success: false,
1211
+ output: stdout,
1212
+ error: `Command timed out after ${timeout}ms.${hint}`,
1213
+ durationMs
1214
+ });
1215
+ return;
1216
+ }
1217
+ const success = code === 0;
1218
+ resolve12({
1219
+ success,
1220
+ output: stdout + (stderr && success ? `
1156
1221
  STDERR:
1157
1222
  ${stderr}` : ""),
1158
- durationMs: performance.now() - start
1159
- };
1160
- } catch (error) {
1161
- const err = error;
1162
- return {
1163
- success: false,
1164
- output: err.stdout ?? "",
1165
- error: err.stderr ?? err.message,
1166
- durationMs: performance.now() - start
1167
- };
1168
- }
1223
+ error: success ? void 0 : stderr || `Exit code ${code}`,
1224
+ durationMs
1225
+ });
1226
+ });
1227
+ child.on("error", (err) => {
1228
+ clearTimeout(timer);
1229
+ resolve12({
1230
+ success: false,
1231
+ output: stdout,
1232
+ error: err.message,
1233
+ durationMs: performance.now() - start
1234
+ });
1235
+ });
1236
+ });
1169
1237
  }
1170
1238
  };
1171
1239
  }
@@ -1275,14 +1343,14 @@ var init_file_write = __esm({
1275
1343
  });
1276
1344
 
1277
1345
  // packages/execution/dist/tools/grep-search.js
1278
- import { execFile as execFile2 } from "node:child_process";
1279
- import { promisify as promisify2 } from "node:util";
1346
+ import { execFile } from "node:child_process";
1347
+ import { promisify } from "node:util";
1280
1348
  import { resolve as resolve3 } from "node:path";
1281
- var execFileAsync2, MAX_OUTPUT_LINES, GrepSearchTool;
1349
+ var execFileAsync, MAX_OUTPUT_LINES, GrepSearchTool;
1282
1350
  var init_grep_search = __esm({
1283
1351
  "packages/execution/dist/tools/grep-search.js"() {
1284
1352
  "use strict";
1285
- execFileAsync2 = promisify2(execFile2);
1353
+ execFileAsync = promisify(execFile);
1286
1354
  MAX_OUTPUT_LINES = 100;
1287
1355
  GrepSearchTool = class {
1288
1356
  name = "grep_search";
@@ -1323,7 +1391,7 @@ var init_grep_search = __esm({
1323
1391
  rgArgs.push("--glob", include);
1324
1392
  }
1325
1393
  rgArgs.push(pattern, searchPath);
1326
- const { stdout } = await execFileAsync2("rg", rgArgs, {
1394
+ const { stdout } = await execFileAsync("rg", rgArgs, {
1327
1395
  cwd: this.workingDir,
1328
1396
  maxBuffer: 1024 * 1024
1329
1397
  });
@@ -1334,7 +1402,7 @@ var init_grep_search = __esm({
1334
1402
  grepArgs.push(`--include=${include}`);
1335
1403
  }
1336
1404
  grepArgs.push(pattern, searchPath);
1337
- const { stdout } = await execFileAsync2("grep", grepArgs, {
1405
+ const { stdout } = await execFileAsync("grep", grepArgs, {
1338
1406
  cwd: this.workingDir,
1339
1407
  maxBuffer: 1024 * 1024
1340
1408
  });
@@ -1369,7 +1437,7 @@ var init_grep_search = __esm({
1369
1437
  }
1370
1438
  async #isRipgrepAvailable() {
1371
1439
  try {
1372
- await execFileAsync2("rg", ["--version"], { timeout: 2e3 });
1440
+ await execFileAsync("rg", ["--version"], { timeout: 2e3 });
1373
1441
  return true;
1374
1442
  } catch {
1375
1443
  return false;
@@ -1380,14 +1448,14 @@ var init_grep_search = __esm({
1380
1448
  });
1381
1449
 
1382
1450
  // packages/execution/dist/tools/glob-find.js
1383
- import { execFile as execFile3 } from "node:child_process";
1384
- import { promisify as promisify3 } from "node:util";
1451
+ import { execFile as execFile2 } from "node:child_process";
1452
+ import { promisify as promisify2 } from "node:util";
1385
1453
  import { resolve as resolve4 } from "node:path";
1386
- var execFileAsync3, MAX_RESULTS, GlobFindTool;
1454
+ var execFileAsync2, MAX_RESULTS, GlobFindTool;
1387
1455
  var init_glob_find = __esm({
1388
1456
  "packages/execution/dist/tools/glob-find.js"() {
1389
1457
  "use strict";
1390
- execFileAsync3 = promisify3(execFile3);
1458
+ execFileAsync2 = promisify2(execFile2);
1391
1459
  MAX_RESULTS = 50;
1392
1460
  GlobFindTool = class {
1393
1461
  name = "find_files";
@@ -1415,7 +1483,7 @@ var init_glob_find = __esm({
1415
1483
  const searchPath = resolve4(this.workingDir, args["path"] ?? ".");
1416
1484
  const start = performance.now();
1417
1485
  try {
1418
- const { stdout } = await execFileAsync3("find", [
1486
+ const { stdout } = await execFileAsync2("find", [
1419
1487
  searchPath,
1420
1488
  "-type",
1421
1489
  "f",
@@ -4087,13 +4155,13 @@ var init_plannerRunner = __esm({
4087
4155
  });
4088
4156
 
4089
4157
  // packages/retrieval/dist/grep-search.js
4090
- import { execFile as execFile4 } from "node:child_process";
4091
- import { promisify as promisify4 } from "node:util";
4092
- var execFileAsync4, GrepSearch;
4158
+ import { execFile as execFile3 } from "node:child_process";
4159
+ import { promisify as promisify3 } from "node:util";
4160
+ var execFileAsync3, GrepSearch;
4093
4161
  var init_grep_search2 = __esm({
4094
4162
  "packages/retrieval/dist/grep-search.js"() {
4095
4163
  "use strict";
4096
- execFileAsync4 = promisify4(execFile4);
4164
+ execFileAsync3 = promisify3(execFile3);
4097
4165
  GrepSearch = class {
4098
4166
  rootDir;
4099
4167
  constructor(rootDir) {
@@ -4115,7 +4183,7 @@ var init_grep_search2 = __esm({
4115
4183
  }
4116
4184
  args.push(pattern, this.rootDir);
4117
4185
  try {
4118
- const { stdout } = await execFileAsync4("rg", args, {
4186
+ const { stdout } = await execFileAsync3("rg", args, {
4119
4187
  maxBuffer: 10 * 1024 * 1024
4120
4188
  });
4121
4189
  return this.parseRipgrepOutput(stdout);
@@ -4190,8 +4258,8 @@ var init_code_retriever = __esm({
4190
4258
  });
4191
4259
 
4192
4260
  // packages/retrieval/dist/lexicalSearch.js
4193
- import { execFile as execFile5 } from "node:child_process";
4194
- import { promisify as promisify5 } from "node:util";
4261
+ import { execFile as execFile4 } from "node:child_process";
4262
+ import { promisify as promisify4 } from "node:util";
4195
4263
  import { readFile as readFile6, readdir, stat } from "node:fs/promises";
4196
4264
  import { join as join10, extname as extname2 } from "node:path";
4197
4265
  async function searchByPath(pathPattern, options) {
@@ -4235,7 +4303,7 @@ async function runSearch(pattern, kind, options) {
4235
4303
  }
4236
4304
  async function isRipgrepAvailable() {
4237
4305
  try {
4238
- await execFileAsync5("rg", ["--version"], { timeout: 2e3 });
4306
+ await execFileAsync4("rg", ["--version"], { timeout: 2e3 });
4239
4307
  return true;
4240
4308
  } catch {
4241
4309
  return false;
@@ -4255,7 +4323,7 @@ async function searchWithRipgrep(pattern, kind, options) {
4255
4323
  args.push(pattern, options.rootDir);
4256
4324
  let stdout;
4257
4325
  try {
4258
- const result = await execFileAsync5("rg", args, {
4326
+ const result = await execFileAsync4("rg", args, {
4259
4327
  maxBuffer: 20 * 1024 * 1024,
4260
4328
  timeout: 1e4
4261
4329
  });
@@ -4365,11 +4433,11 @@ function matchesGlob(filePath, glob2) {
4365
4433
  return false;
4366
4434
  }
4367
4435
  }
4368
- var execFileAsync5, DEFAULT_INCLUDE_GLOBS, DEFAULT_EXCLUDE_GLOBS, DEFAULT_MAX_MATCHES, ALWAYS_SKIP, ALL_CODE_EXTS;
4436
+ var execFileAsync4, DEFAULT_INCLUDE_GLOBS, DEFAULT_EXCLUDE_GLOBS, DEFAULT_MAX_MATCHES, ALWAYS_SKIP, ALL_CODE_EXTS;
4369
4437
  var init_lexicalSearch = __esm({
4370
4438
  "packages/retrieval/dist/lexicalSearch.js"() {
4371
4439
  "use strict";
4372
- execFileAsync5 = promisify5(execFile5);
4440
+ execFileAsync4 = promisify4(execFile4);
4373
4441
  DEFAULT_INCLUDE_GLOBS = ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "**/*.py"];
4374
4442
  DEFAULT_EXCLUDE_GLOBS = ["node_modules", "dist", ".git", "build", "coverage"];
4375
4443
  DEFAULT_MAX_MATCHES = 50;
@@ -5115,9 +5183,9 @@ var init_verifierRunner = __esm({
5115
5183
  async executeTests(patch, repoRoot) {
5116
5184
  if (patch.testsToRun.length === 0)
5117
5185
  return "(no tests specified)";
5118
- const { execFile: execFile6 } = await import("node:child_process");
5119
- const { promisify: promisify6 } = await import("node:util");
5120
- const execFileAsync6 = promisify6(execFile6);
5186
+ const { execFile: execFile5 } = await import("node:child_process");
5187
+ const { promisify: promisify5 } = await import("node:util");
5188
+ const execFileAsync5 = promisify5(execFile5);
5121
5189
  const outputs = [];
5122
5190
  const workDir = this.options.workingDir || repoRoot;
5123
5191
  for (const cmd of patch.testsToRun.slice(0, 3)) {
@@ -5126,7 +5194,7 @@ var init_verifierRunner = __esm({
5126
5194
  const [bin, ...args] = parts;
5127
5195
  if (!bin)
5128
5196
  continue;
5129
- const { stdout, stderr } = await execFileAsync6(bin, args, {
5197
+ const { stdout, stderr } = await execFileAsync5(bin, args, {
5130
5198
  cwd: workDir,
5131
5199
  timeout: 6e4,
5132
5200
  maxBuffer: 1024 * 1024
@@ -5701,7 +5769,7 @@ var init_agenticRunner = __esm({
5701
5769
  - file_edit: Make a precise string replacement in a file (preferred over rewriting). Uses old_string/new_string.
5702
5770
  - find_files: Find files by name pattern (glob). Searches recursively, excludes node_modules/.git.
5703
5771
  - grep_search: Search file contents with regex. Returns matching lines with paths and line numbers.
5704
- - shell: Execute any shell command (tests, builds, git, npm, etc.)
5772
+ - shell: Execute any shell command (tests, builds, git, npm, etc.). Supports stdin parameter for input. Commands run with CI=true for non-interactive mode.
5705
5773
  - list_directory: List files in a directory with types and sizes
5706
5774
  - web_search: Search the web for documentation or solutions
5707
5775
  - web_fetch: Fetch a web page and extract text content (for docs, MDN, w3schools.com, etc.)
@@ -5752,6 +5820,15 @@ When a test or build fails:
5752
5820
  8. If it fails with the SAME error, try a different approach
5753
5821
  9. After 3 failed attempts at the same error, use web_search for solutions
5754
5822
 
5823
+ ## Interactive Commands
5824
+
5825
+ Commands run non-interactively (CI=true). When running scaffolding tools:
5826
+ - ALWAYS add non-interactive flags: --yes, --no-input, --defaults, etc.
5827
+ - For npx create-next-app: use --yes (skips all prompts, uses defaults)
5828
+ - For npm init: use -y
5829
+ - If a command needs specific answers, use the stdin parameter
5830
+ - If a command times out, it likely hit an interactive prompt \u2014 retry with --yes
5831
+
5755
5832
  ## Context Efficiency
5756
5833
 
5757
5834
  - Use grep_search to find specific code instead of reading many files
@@ -6267,8 +6344,10 @@ function formatToolArgs(toolName, args) {
6267
6344
  case "file_write":
6268
6345
  case "file_edit":
6269
6346
  return String(args["path"] ?? "");
6270
- case "shell":
6271
- return truncStr(String(args["command"] ?? ""), 60);
6347
+ case "shell": {
6348
+ const cmd = truncStr(String(args["command"] ?? ""), 60);
6349
+ return args["stdin"] ? `${cmd} ${c2.dim("(with stdin)")}` : cmd;
6350
+ }
6272
6351
  case "grep_search":
6273
6352
  return `${c2.yellow(String(args["pattern"] ?? ""))}${args["path"] ? ` in ${args["path"]}` : ""}`;
6274
6353
  case "find_files":
@@ -7802,7 +7881,7 @@ var serve_exports = {};
7802
7881
  __export(serve_exports, {
7803
7882
  serveCommand: () => serveCommand
7804
7883
  });
7805
- import { spawn } from "node:child_process";
7884
+ import { spawn as spawn2 } from "node:child_process";
7806
7885
  async function serveCommand(opts, config) {
7807
7886
  const backendType = config.backendType;
7808
7887
  if (backendType === "ollama") {
@@ -7895,7 +7974,7 @@ async function serveVllm(opts, config) {
7895
7974
  }
7896
7975
  async function runVllmServer(args, verbose) {
7897
7976
  return new Promise((resolve12, reject) => {
7898
- const child = spawn("python", args, {
7977
+ const child = spawn2("python", args, {
7899
7978
  stdio: verbose ? "inherit" : ["ignore", "pipe", "pipe"],
7900
7979
  env: { ...process.env }
7901
7980
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — Claude Code-style TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",