@gaberrb/polypus 0.4.3 → 0.4.4

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.
package/dist/index.js CHANGED
@@ -109,6 +109,7 @@ var en = {
109
109
  "cli.opt.agent": "which configured agent to use",
110
110
  "cli.opt.mode": "plan | review | bypass (overrides config)",
111
111
  "cli.opt.maxSteps": "maximum agent steps",
112
+ "cli.opt.json": "headless mode: emit a single JSON object (steps, tool calls, files changed, usage) instead of the TUI \u2014 use with --mode bypass",
112
113
  "cli.arg.swarmTask": "high-level task to split across agents",
113
114
  "cli.opt.agents": "comma-separated agent names (default: all configured)",
114
115
  "cli.opt.maxSubtasks": "maximum number of parallel subtasks",
@@ -135,6 +136,7 @@ var en = {
135
136
  "run.reprompt": "\u21BB no tool call \u2014 reinforcing instructions (attempt {attempt})",
136
137
  "run.autocorrect": "\u21BB tool failed \u2014 auto-correcting with extra context",
137
138
  "run.cancelled": "\u25A0 cancelled",
139
+ "run.jsonNeedsTask": "--json requires a task argument (headless mode has no interactive REPL).",
138
140
  // repl
139
141
  "repl.welcome": "Polypus interactive session.",
140
142
  "repl.welcomeHint": " Type /help for commands, /exit to quit.",
@@ -334,6 +336,7 @@ var ptBR = {
334
336
  "cli.opt.agent": "qual agente configurado usar",
335
337
  "cli.opt.mode": "plan | review | bypass (sobrescreve a config)",
336
338
  "cli.opt.maxSteps": "n\xFAmero m\xE1ximo de passos do agente",
339
+ "cli.opt.json": "modo headless: emite um \xFAnico objeto JSON (passos, tool calls, arquivos alterados, uso) em vez da TUI \u2014 use com --mode bypass",
337
340
  "cli.arg.swarmTask": "tarefa de alto n\xEDvel para dividir entre os agentes",
338
341
  "cli.opt.agents": "nomes de agentes separados por v\xEDrgula (padr\xE3o: todos)",
339
342
  "cli.opt.maxSubtasks": "n\xFAmero m\xE1ximo de subtarefas paralelas",
@@ -358,6 +361,7 @@ var ptBR = {
358
361
  "run.reprompt": "\u21BB nenhuma chamada de tool \u2014 refor\xE7ando instru\xE7\xF5es (tentativa {attempt})",
359
362
  "run.autocorrect": "\u21BB tool falhou \u2014 autocorrigindo com contexto extra",
360
363
  "run.cancelled": "\u25A0 cancelado",
364
+ "run.jsonNeedsTask": "--json exige um argumento de tarefa (o modo headless n\xE3o tem REPL interativo).",
361
365
  "repl.welcome": "Sess\xE3o interativa do Polypus.",
362
366
  "repl.welcomeHint": " Digite /help para comandos, /exit para sair.",
363
367
  "repl.modeChanged": "modo \u2192 {mode}",
@@ -2032,6 +2036,60 @@ ${blocks.join("\n\n")}`;
2032
2036
  return { task: augmented, injected };
2033
2037
  }
2034
2038
 
2039
+ // src/cli/commands/json-output.ts
2040
+ var OUTPUT_PREVIEW = 500;
2041
+ function createJsonCollector() {
2042
+ const log = [];
2043
+ const filesChanged = /* @__PURE__ */ new Set();
2044
+ const events = {
2045
+ onStep(step) {
2046
+ log.push({ type: "step", step });
2047
+ },
2048
+ onAssistantText(text2) {
2049
+ if (text2.trim()) log.push({ type: "assistant", text: text2 });
2050
+ },
2051
+ onToolCall(call) {
2052
+ log.push({ type: "tool_call", name: call.name, arguments: call.arguments });
2053
+ },
2054
+ onToolResult(call, result) {
2055
+ log.push({
2056
+ type: "tool_result",
2057
+ name: call.name,
2058
+ ok: result.ok,
2059
+ output: result.output.slice(0, OUTPUT_PREVIEW)
2060
+ });
2061
+ if (result.ok && (call.name === "write_file" || call.name === "edit_file")) {
2062
+ const path = call.arguments.path;
2063
+ if (typeof path === "string") filesChanged.add(path);
2064
+ }
2065
+ },
2066
+ onCorrection(call) {
2067
+ log.push({ type: "correction", name: call.name });
2068
+ },
2069
+ onReprompt(attempt) {
2070
+ log.push({ type: "reprompt", attempt });
2071
+ },
2072
+ onUsage() {
2073
+ }
2074
+ };
2075
+ return {
2076
+ events,
2077
+ build(result) {
2078
+ return {
2079
+ result: {
2080
+ reason: result.reason,
2081
+ finished: result.finished,
2082
+ steps: result.steps,
2083
+ summary: result.summary,
2084
+ filesChanged: [...filesChanged],
2085
+ usage: result.usage
2086
+ },
2087
+ events: log
2088
+ };
2089
+ }
2090
+ };
2091
+ }
2092
+
2035
2093
  // src/ui/repl.ts
2036
2094
  import pc6 from "picocolors";
2037
2095
 
@@ -3285,20 +3343,23 @@ async function run(task, opts) {
3285
3343
  const resolved2 = createProvider(active);
3286
3344
  await executeTask(taskText, resolved2, workspace, session);
3287
3345
  };
3346
+ if (opts.json && !task) throw new Error(t("run.jsonNeedsTask"));
3288
3347
  if (task) {
3289
3348
  const resolved2 = createProvider(agentConfig);
3290
- console.log(
3291
- pc8.dim(
3292
- t("run.status", {
3293
- name: resolved2.config.name,
3294
- provider: resolved2.config.provider,
3295
- model: resolved2.config.model,
3296
- toolMode: resolved2.toolMode,
3297
- mode: session.mode
3298
- })
3299
- )
3300
- );
3301
- await executeTask(task, resolved2, workspace, session);
3349
+ if (!opts.json) {
3350
+ console.log(
3351
+ pc8.dim(
3352
+ t("run.status", {
3353
+ name: resolved2.config.name,
3354
+ provider: resolved2.config.provider,
3355
+ model: resolved2.config.model,
3356
+ toolMode: resolved2.toolMode,
3357
+ mode: session.mode
3358
+ })
3359
+ )
3360
+ );
3361
+ }
3362
+ await executeTask(task, resolved2, workspace, session, opts.json ?? false);
3302
3363
  return;
3303
3364
  }
3304
3365
  const resolved = createProvider(agentConfig);
@@ -3321,7 +3382,7 @@ async function run(task, opts) {
3321
3382
  };
3322
3383
  await startRepl(ctx);
3323
3384
  }
3324
- async function executeTask(task, resolved, workspace, session) {
3385
+ async function executeTask(task, resolved, workspace, session, json = false) {
3325
3386
  const mention = await resolveMentions(task, {
3326
3387
  workspace,
3327
3388
  allow: session.allow,
@@ -3329,16 +3390,18 @@ async function executeTask(task, resolved, workspace, session) {
3329
3390
  });
3330
3391
  if (mention.injected.length > 0) {
3331
3392
  task = mention.task;
3332
- console.log(pc8.dim(`\u21B3 @ ${mention.injected.join(", ")}`));
3393
+ if (!json) console.log(pc8.dim(`\u21B3 @ ${mention.injected.join(", ")}`));
3333
3394
  }
3334
3395
  const spinner3 = new Spinner();
3335
3396
  const controller = new AbortController();
3336
3397
  const cancel2 = listenForCancel(controller);
3398
+ const collector = json ? createJsonCollector() : void 0;
3337
3399
  const permissions = new PermissionEngine({
3338
3400
  mode: session.mode,
3339
3401
  policy: { workspace, allow: session.allow, deny: session.deny },
3340
3402
  allowedCommands: session.allowedCommands,
3341
- confirm: async (req) => {
3403
+ // Headless runs have no TTY for confirmations — use --mode bypass instead.
3404
+ confirm: json ? async () => false : async (req) => {
3342
3405
  spinner3.stop();
3343
3406
  cancel2.pause();
3344
3407
  const ok = await confirmAction(req);
@@ -3346,7 +3409,7 @@ async function executeTask(task, resolved, workspace, session) {
3346
3409
  return ok;
3347
3410
  }
3348
3411
  });
3349
- spinner3.start(t("ui.thinking"));
3412
+ if (!json) spinner3.start(t("ui.thinking"));
3350
3413
  let result;
3351
3414
  try {
3352
3415
  result = await runAgent({
@@ -3358,13 +3421,17 @@ async function executeTask(task, resolved, workspace, session) {
3358
3421
  history: session.history,
3359
3422
  maxSteps: session.maxSteps,
3360
3423
  signal: controller.signal,
3361
- events: renderEvents(spinner3)
3424
+ events: collector ? collector.events : renderEvents(spinner3)
3362
3425
  });
3363
3426
  } finally {
3364
3427
  spinner3.stop();
3365
3428
  cancel2.dispose();
3366
3429
  }
3367
3430
  session.history = result.messages;
3431
+ if (collector) {
3432
+ process.stdout.write(JSON.stringify(collector.build(result)) + "\n");
3433
+ return;
3434
+ }
3368
3435
  if (result.reason === "finished") {
3369
3436
  console.log(pc8.green("\n" + t("run.done", { steps: result.steps })) + (result.summary ? ` ${result.summary}` : ""));
3370
3437
  } else if (result.reason === "cancelled") {
@@ -4115,7 +4182,7 @@ function buildProgram() {
4115
4182
  program.command("add-agent").argument("<name>", t("cli.arg.addAgentName")).requiredOption("--provider <provider>", t("cli.opt.provider")).requiredOption("--model <model>", t("cli.opt.model")).option("--api-key <key>", t("cli.opt.apiKey")).option("--base-url <url>", t("cli.opt.baseUrl")).option("--tool-mode <mode>", t("cli.opt.toolMode"), "auto").option("--set-default", t("cli.opt.setDefault")).description(t("cli.cmd.addAgent")).action((name, opts) => addAgent(name, opts));
4116
4183
  program.command("remove-agent").argument("<name>", t("cli.arg.removeAgentName")).description(t("cli.cmd.removeAgent")).action((name) => removeAgent(name));
4117
4184
  program.command("list-agents").alias("agents").description(t("cli.cmd.listAgents")).action(() => listAgents());
4118
- program.command("run").argument("[task]", t("cli.arg.runTask")).option("--agent <name>", t("cli.opt.agent")).option("--mode <mode>", t("cli.opt.mode")).option("--max-steps <n>", t("cli.opt.maxSteps")).description(t("cli.cmd.run")).action((task, opts) => run(task, opts));
4185
+ program.command("run").argument("[task]", t("cli.arg.runTask")).option("--agent <name>", t("cli.opt.agent")).option("--mode <mode>", t("cli.opt.mode")).option("--max-steps <n>", t("cli.opt.maxSteps")).option("--json", t("cli.opt.json")).description(t("cli.cmd.run")).action((task, opts) => run(task, opts));
4119
4186
  program.command("swarm").argument("<task>", t("cli.arg.swarmTask")).option("--agents <names>", t("cli.opt.agents")).option("--max-subtasks <n>", t("cli.opt.maxSubtasks")).description(t("cli.cmd.swarm")).action((task, opts) => swarm(task, opts));
4120
4187
  program.command("models").option("--search <text>", t("cli.opt.search")).option("--tools", t("cli.opt.toolsOnly")).option("--free", t("cli.opt.free")).option("--max-price <usd>", t("cli.opt.maxPrice")).option("--sort <order>", t("cli.opt.sort")).option("--limit <n>", t("cli.opt.limit")).description(t("cli.cmd.models")).action((opts) => models(opts));
4121
4188
  program.command("prd").argument("<issue>", t("cli.arg.prdIssue")).option("--out <file>", t("cli.opt.out")).option("--model <model>", t("cli.opt.model")).option("--input <file>", t("cli.opt.input")).description(t("cli.cmd.prd")).action((issue, opts) => prd(issue, opts));