@aiaiai-pt/martha-cli 0.27.0 → 0.27.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 +100 -2
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -11081,7 +11081,7 @@ init_config();
11081
11081
  init_errors();
11082
11082
 
11083
11083
  // src/version.ts
11084
- var CLI_VERSION = "0.27.0";
11084
+ var CLI_VERSION = "0.27.1";
11085
11085
 
11086
11086
  // src/commands/sessions.ts
11087
11087
  function relativeTime(iso) {
@@ -16630,7 +16630,7 @@ ${items.length} task(s)`));
16630
16630
  }
16631
16631
  console.log(`Open: ${source_default.yellow(data.open ?? 0)} ` + `Running: ${source_default.blue(data.running ?? 0)} ` + `Claimed: ${source_default.magenta(data.claimed ?? 0)} ` + `Completed: ${source_default.green(data.completed ?? 0)} ` + `Failed: ${source_default.red(data.failed ?? 0)} ` + `Cancelled: ${source_default.dim(data.cancelled ?? 0)}`);
16632
16632
  });
16633
- cmd.command("create").description("Create a new task").requiredOption("--agent <name-or-id>", "Agent definition ID").requiredOption("--goal <text>", "Goal / instruction for the agent").option("--title <text>", "Short title for the task").option("--priority <priority>", "Priority (low, medium, high, urgent)", "medium").option("--context <json>", "Structured context as JSON string").option("--team <team-id>", "Assign task to a team").option("--assigned-agent <agent-id>", "Assign task to a specific agent").option("--sticky", "Keep assignment even if agent goes offline").action(async (opts) => {
16633
+ cmd.command("create").description("Create a new task").requiredOption("--agent <name-or-id>", "Agent definition ID").requiredOption("--goal <text>", "Goal / instruction for the agent").option("--title <text>", "Short title for the task").option("--priority <priority>", "Priority (low, medium, high, urgent)", "medium").option("--context <json>", "Structured context as JSON string").option("--team <team-id>", "Assign task to a team").option("--assigned-agent <agent-id>", "Assign task to a specific agent").option("--sticky", "Keep assignment even if agent goes offline").option("--no-auto-execute", "Create the task as claimable (open) for an external runner to pull, instead of auto-running it via the cloud workflow").action(async (opts) => {
16634
16634
  const ctx = getCtx();
16635
16635
  const body = {
16636
16636
  agent_definition_id: opts.agent,
@@ -16652,6 +16652,8 @@ ${items.length} task(s)`));
16652
16652
  body.assigned_agent_id = opts.assignedAgent;
16653
16653
  if (opts.sticky)
16654
16654
  body.sticky_assignment = true;
16655
+ if (opts.autoExecute === false)
16656
+ body.auto_execute = false;
16655
16657
  const result = await ctx.api.post("/api/admin/tasks", body);
16656
16658
  if (isJson()) {
16657
16659
  console.log(JSON.stringify(result, null, 2));
@@ -16961,6 +16963,101 @@ ${items.length} task(s) available`));
16961
16963
  });
16962
16964
  }
16963
16965
 
16966
+ // src/commands/runner.ts
16967
+ init_errors();
16968
+ function sleep5(ms) {
16969
+ return new Promise((r) => setTimeout(r, ms));
16970
+ }
16971
+ async function runOnce(ctx, opts, handled) {
16972
+ const tasks = await ctx.api.get("/api/tasks/poll", {
16973
+ params: { agent_id: opts.agent, limit: String(opts.pollLimit ?? 5) }
16974
+ });
16975
+ const candidates = Array.isArray(tasks) ? tasks : [];
16976
+ const task = candidates.find((t) => (t.status ?? "open") === "open" && !handled?.has(t.id));
16977
+ if (!task)
16978
+ return { ran: false };
16979
+ if (!opts.autoYes) {
16980
+ process.stderr.write(source_default.yellow(`
16981
+ [runner] refused task ${task.id} — re-run with --yes to allow host execution
16982
+ `));
16983
+ return { ran: false, taskId: task.id, status: "refused" };
16984
+ }
16985
+ handled?.add(task.id);
16986
+ const claimed = await ctx.api.post(`/api/tasks/${encodeURIComponent(task.id)}/claim`, {});
16987
+ const goal = claimed.goal ?? task.goal ?? "";
16988
+ process.stderr.write(source_default.dim(`
16989
+ [runner] claimed ${task.id} — running: ${goal}
16990
+ `));
16991
+ let result;
16992
+ try {
16993
+ result = await runHostCommand(goal, `task-${task.id}`, { cwd: opts.cwd });
16994
+ } catch (e) {
16995
+ result = { stdout: "", stderr: String(e), exit_code: -1 };
16996
+ }
16997
+ const exit_code = result.exit_code;
16998
+ const stdout = result.stdout || result.stderr || "";
16999
+ const status = exit_code === 0 ? "completed" : "failed";
17000
+ await ctx.api.post(`/api/tasks/${encodeURIComponent(task.id)}/complete`, {
17001
+ outcome: { stdout, exit_code },
17002
+ status
17003
+ });
17004
+ process.stderr.write(source_default.dim(`[runner] completed ${task.id} — ${status} (exit ${exit_code})
17005
+ `));
17006
+ return { ran: true, taskId: task.id, status, exitCode: exit_code };
17007
+ }
17008
+ function registerRunnerCommand(program2) {
17009
+ program2.command("runner").description("Run as an external agent's executor: claim tasks and run them on this host.").requiredOption("--agent <id>", "Agent definition id this runner serves").option("--once", "Claim + run a single task, then exit").option("--poll-interval <ms>", "Poll interval when idle (ms)", "3000").option("--cwd <dir>", "Scoped workspace for task execution", process.cwd()).option("--yes", "Consent to run host commands (required to execute)").action(async (opts) => {
17010
+ const ctx = createContext({
17011
+ profileOverride: program2.opts().profile,
17012
+ verbose: program2.opts().verbose
17013
+ });
17014
+ if (program2.opts().apiUrl)
17015
+ ctx.profile.api_url = program2.opts().apiUrl;
17016
+ const pollInterval = parseInt(opts.pollInterval, 10);
17017
+ if (isNaN(pollInterval) || pollInterval < 250) {
17018
+ throw new CLIError("--poll-interval must be >= 250 (ms)", 4 /* Validation */);
17019
+ }
17020
+ const runOpts = {
17021
+ agent: opts.agent,
17022
+ cwd: opts.cwd,
17023
+ autoYes: !!opts.yes
17024
+ };
17025
+ process.stderr.write(source_default.dim(`[runner] serving agent ${opts.agent} (cwd ${opts.cwd})${opts.once ? " — once" : ""}
17026
+ `));
17027
+ if (opts.once) {
17028
+ await runOnce(ctx, runOpts);
17029
+ return;
17030
+ }
17031
+ let stop = false;
17032
+ const onSignal = () => {
17033
+ stop = true;
17034
+ process.stderr.write(`
17035
+ [runner] stopping…
17036
+ `);
17037
+ };
17038
+ process.on("SIGINT", onSignal);
17039
+ process.on("SIGTERM", onSignal);
17040
+ const handled = new Set;
17041
+ try {
17042
+ while (!stop) {
17043
+ let r;
17044
+ try {
17045
+ r = await runOnce(ctx, runOpts, handled);
17046
+ } catch (e) {
17047
+ process.stderr.write(source_default.red(`[runner] error: ${String(e)}
17048
+ `));
17049
+ r = { ran: false };
17050
+ }
17051
+ if (!r.ran)
17052
+ await sleep5(pollInterval);
17053
+ }
17054
+ } finally {
17055
+ process.off("SIGINT", onSignal);
17056
+ process.off("SIGTERM", onSignal);
17057
+ }
17058
+ });
17059
+ }
17060
+
16964
17061
  // src/commands/teams.ts
16965
17062
  init_errors();
16966
17063
  var API_PATH3 = "/api/admin/teams";
@@ -21267,6 +21364,7 @@ registerDocumentSyncCommands(program2);
21267
21364
  registerWikiCommands(program2);
21268
21365
  registerApprovalCommands(program2);
21269
21366
  registerTaskCommands(program2);
21367
+ registerRunnerCommand(program2);
21270
21368
  registerTeamCommands(program2);
21271
21369
  registerIntegrationCommands(program2);
21272
21370
  registerConnectionCommands(program2);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiaiai-pt/martha-cli",
3
- "version": "0.27.0",
3
+ "version": "0.27.1",
4
4
  "description": "Terminal-first client for the Martha AI platform",
5
5
  "homepage": "https://docs.martha.nomadriver.co",
6
6
  "repository": {