@mutagent/cli 0.2.214 → 0.2.216

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/README.md CHANGED
@@ -85,8 +85,8 @@ To run Helix on your own machine instead, install the Helix binary with `mutagen
85
85
  belong here.
86
86
  - **Helix session**: a cloud run of Helix, addressed by a reference (`hs1_...`) that is printed
87
87
  when the run starts. `mutagent helix session` lists sessions, attaches to them, sends input,
88
- stops, checkpoints and restores them. A sandbox idle for 15 minutes is stopped, and an
89
- interactive session in it is checkpointed first.
88
+ answers their questions, stops, checkpoints and restores them. A sandbox idle for 15 minutes is
89
+ stopped, and an interactive session in it is checkpointed first.
90
90
  - **Managed agent**: a folder whose entry file is `agent.md` (YAML frontmatter, then the standing
91
91
  prompt). `mutagent agent deploy` stores each change as a new revision. A slot is the agent in one
92
92
  Environment (`--env`).
@@ -201,6 +201,8 @@ mutagent helix session list
201
201
  mutagent helix session attach <reference> # Watch it (--since <n> replays)
202
202
  mutagent helix session send <reference> "and now the tests"
203
203
  mutagent helix session send <reference> --type steer "stop and re-read the spec"
204
+ mutagent helix session approvals <reference> # What it is waiting on (a question it asked)
205
+ mutagent helix session answer <reference> <id> --value 'an option' # Answer it (--cancel denies)
204
206
  mutagent helix session signal <reference> --force # Stop it; the sandbox stays up
205
207
  mutagent helix session close-input <reference>
206
208
  mutagent helix session checkpoint <reference>
package/dist/bin/cli.js CHANGED
@@ -28750,6 +28750,16 @@ async function restoreSession(routes, reference, body) {
28750
28750
  async function endSession(routes, reference) {
28751
28751
  return onRoute(routes, (base) => requestJson(referencePath(base, reference) + "/end", { method: "POST", body: "{}" }));
28752
28752
  }
28753
+ async function listSessionApprovals(routes, reference, signal) {
28754
+ return onRoute(routes, (base) => requestJson(referencePath(base, reference) + "/approvals", { signal }));
28755
+ }
28756
+ async function answerSessionApproval(routes, reference, id, answer, signal) {
28757
+ await onRoute(routes, (base) => requestJson(`${referencePath(base, reference)}/approvals/${encodeURIComponent(id)}`, {
28758
+ method: "POST",
28759
+ body: JSON.stringify({ decision: answer.decision, ...answer.value === undefined ? {} : { value: answer.value } }),
28760
+ signal
28761
+ }));
28762
+ }
28753
28763
  async function onSessionRoute(routes, call) {
28754
28764
  return onRoute(routes, (base) => call(base));
28755
28765
  }
@@ -28762,6 +28772,215 @@ init_errors();
28762
28772
  import { createInterface as createInterface2 } from "node:readline";
28763
28773
  init_known_secrets();
28764
28774
 
28775
+ // src/lib/session-questions.ts
28776
+ var QUESTION_KINDS = ["select", "confirm", "input", "editor"];
28777
+ var isQuestionKind = (method) => typeof method === "string" && QUESTION_KINDS.includes(method);
28778
+ var str = (value) => typeof value === "string" ? value : null;
28779
+ function questionOfFrame(frameText) {
28780
+ let frame;
28781
+ try {
28782
+ frame = JSON.parse(frameText);
28783
+ } catch {
28784
+ return null;
28785
+ }
28786
+ if (frame === null || typeof frame !== "object" || Array.isArray(frame))
28787
+ return null;
28788
+ const record = frame;
28789
+ if (record.type !== "extension_ui_request")
28790
+ return null;
28791
+ const method = record.method;
28792
+ if (!isQuestionKind(method))
28793
+ return null;
28794
+ const id = str(record.id);
28795
+ if (id === null || id === "")
28796
+ return null;
28797
+ return {
28798
+ id,
28799
+ kind: method,
28800
+ title: str(record.title) ?? "",
28801
+ message: method === "confirm" ? str(record.message) : null,
28802
+ options: method === "select" && Array.isArray(record.options) ? record.options.filter((option) => typeof option === "string") : null,
28803
+ placeholder: method === "input" ? str(record.placeholder) : null
28804
+ };
28805
+ }
28806
+ function shellQuote2(value) {
28807
+ if (value !== "" && /^[A-Za-z0-9_@%+=:,./-]+$/.test(value))
28808
+ return value;
28809
+ return `'${value.replace(/'/g, `'\\''`)}'`;
28810
+ }
28811
+ function answerCommand(cli, reference, question) {
28812
+ if (question.kind === "confirm")
28813
+ return `${cli} session answer ${reference} ${question.id}`;
28814
+ const example = question.options !== null && question.options.length > 0 ? question.options[0] ?? "<text>" : "<text>";
28815
+ return `${cli} session answer ${reference} ${question.id} --value ${shellQuote2(example)}`;
28816
+ }
28817
+ function cancelCommand(cli, reference, id) {
28818
+ return `${cli} session answer ${reference} ${id} --cancel`;
28819
+ }
28820
+ function questionDetail(question) {
28821
+ if (question.kind === "select") {
28822
+ return question.options === null || question.options.length === 0 ? "" : `options: ${question.options.join(" | ")}`;
28823
+ }
28824
+ if (question.kind === "confirm")
28825
+ return question.message === null ? "" : `message: ${question.message}`;
28826
+ if (question.kind === "input")
28827
+ return question.placeholder === null ? "" : `placeholder: ${question.placeholder}`;
28828
+ return "";
28829
+ }
28830
+ function questionLines(question, cli, reference) {
28831
+ const lines = [`The session asks (${question.kind}, id ${question.id}): ${question.title === "" ? "(no title)" : question.title}`];
28832
+ if (question.kind === "select" && question.options !== null && question.options.length > 0) {
28833
+ lines.push(` Options: ${question.options.join(" | ")}`);
28834
+ }
28835
+ if (question.kind === "confirm" && question.message !== null && question.message !== "") {
28836
+ lines.push(` Message: ${question.message}`);
28837
+ }
28838
+ if (question.kind === "input" && question.placeholder !== null && question.placeholder !== "") {
28839
+ lines.push(` Placeholder: ${question.placeholder}`);
28840
+ }
28841
+ lines.push(` Answer: ${answerCommand(cli, reference, question)}`);
28842
+ lines.push(` Deny: ${cancelCommand(cli, reference, question.id)}`);
28843
+ return lines;
28844
+ }
28845
+ function pendingQuestionLines(approvals, cli, reference) {
28846
+ if (approvals.length === 0)
28847
+ return [];
28848
+ const count = `${String(approvals.length)} question${approvals.length === 1 ? "" : "s"}`;
28849
+ return [
28850
+ `The session is waiting on ${count} asked before this attach — answer from any terminal:`,
28851
+ ...approvals.flatMap((approval) => questionLines(approval, cli, reference))
28852
+ ];
28853
+ }
28854
+ var TURN_ENDS = new Set(["turn_end", "agent_end"]);
28855
+ function questionSignalOfFrame(frameText) {
28856
+ const question = questionOfFrame(frameText);
28857
+ if (question !== null)
28858
+ return { type: "ask", question };
28859
+ if (!/(?:extension_ui_response|turn_end|agent_end)/.test(frameText))
28860
+ return null;
28861
+ let frame;
28862
+ try {
28863
+ frame = JSON.parse(frameText);
28864
+ } catch {
28865
+ return null;
28866
+ }
28867
+ if (frame === null || typeof frame !== "object" || Array.isArray(frame))
28868
+ return null;
28869
+ const record = frame;
28870
+ if (record.type === "extension_ui_response") {
28871
+ const id = str(record.id);
28872
+ return id === null ? null : { type: "answer", id };
28873
+ }
28874
+ return typeof record.type === "string" && TURN_ENDS.has(record.type) ? { type: "turn-end" } : null;
28875
+ }
28876
+
28877
+ class SessionQuestions {
28878
+ #notice;
28879
+ #cli;
28880
+ #reference;
28881
+ #fetchOpen;
28882
+ #known = false;
28883
+ #started = new Set;
28884
+ #open = new Set;
28885
+ #closed = new Set;
28886
+ #printed = new Set;
28887
+ #waiting = [];
28888
+ #inFlight = null;
28889
+ constructor(options) {
28890
+ this.#notice = options.notice;
28891
+ this.#cli = options.cli;
28892
+ this.#reference = options.reference;
28893
+ this.#fetchOpen = options.fetchOpen;
28894
+ }
28895
+ async start() {
28896
+ if (this.#fetchOpen === undefined)
28897
+ return;
28898
+ let open;
28899
+ try {
28900
+ open = await this.#fetchOpen();
28901
+ } catch {
28902
+ return;
28903
+ }
28904
+ this.#known = true;
28905
+ for (const approval of open) {
28906
+ this.#started.add(approval.id);
28907
+ this.#open.add(approval.id);
28908
+ }
28909
+ for (const line of pendingQuestionLines(open, this.#cli, this.#reference))
28910
+ this.#notice(line);
28911
+ }
28912
+ frame(frameText) {
28913
+ const signal = questionSignalOfFrame(frameText);
28914
+ if (signal === null)
28915
+ return;
28916
+ if (signal.type === "answer") {
28917
+ this.#closed.add(signal.id);
28918
+ this.#open.delete(signal.id);
28919
+ return;
28920
+ }
28921
+ if (signal.type === "turn-end") {
28922
+ for (const id of this.#open)
28923
+ this.#closed.add(id);
28924
+ for (const question of this.#waiting)
28925
+ this.#closed.add(question.id);
28926
+ this.#open.clear();
28927
+ this.#waiting = [];
28928
+ return;
28929
+ }
28930
+ const question = signal.question;
28931
+ if (this.#printed.has(question.id) || this.#closed.has(question.id))
28932
+ return;
28933
+ if (this.#started.has(question.id)) {
28934
+ this.#printed.add(question.id);
28935
+ return;
28936
+ }
28937
+ if (this.#fetchOpen === undefined || !this.#known) {
28938
+ this.#render(question);
28939
+ return;
28940
+ }
28941
+ this.#waiting.push(question);
28942
+ this.#inFlight ??= this.#verify();
28943
+ }
28944
+ async settle() {
28945
+ while (this.#inFlight !== null)
28946
+ await this.#inFlight;
28947
+ }
28948
+ async#verify() {
28949
+ try {
28950
+ const open = await this.#fetchOpen?.() ?? [];
28951
+ const openIds = new Set(open.map((approval) => approval.id));
28952
+ for (const question of this.#drain()) {
28953
+ if (openIds.has(question.id))
28954
+ this.#render(question);
28955
+ else {
28956
+ this.#closed.add(question.id);
28957
+ this.#open.delete(question.id);
28958
+ }
28959
+ }
28960
+ } catch {
28961
+ for (const question of this.#drain())
28962
+ this.#render(question);
28963
+ } finally {
28964
+ this.#inFlight = null;
28965
+ if (this.#waiting.length > 0)
28966
+ this.#inFlight = this.#verify();
28967
+ }
28968
+ }
28969
+ #drain() {
28970
+ const waiting = this.#waiting;
28971
+ this.#waiting = [];
28972
+ return waiting;
28973
+ }
28974
+ #render(question) {
28975
+ if (this.#closed.has(question.id))
28976
+ return;
28977
+ this.#printed.add(question.id);
28978
+ this.#open.add(question.id);
28979
+ for (const line of questionLines(question, this.#cli, this.#reference))
28980
+ this.#notice(line);
28981
+ }
28982
+ }
28983
+
28765
28984
  // src/lib/sse.ts
28766
28985
  var DEFAULT_EVENT_NAME = "message";
28767
28986
 
@@ -29303,9 +29522,22 @@ async function runNativeSession(options) {
29303
29522
  notice("Session " + options.reference + (options.interrupt === undefined ? ". Ctrl-C detaches." : ". Ctrl-C stops the session (SIGINT)."));
29304
29523
  if (options.interruptRequested)
29305
29524
  onSigint();
29525
+ const questions = new SessionQuestions({
29526
+ notice,
29527
+ cli: activeProduct().cli,
29528
+ reference: options.reference,
29529
+ ...options.openQuestions === undefined ? {} : { fetchOpen: options.openQuestions }
29530
+ });
29531
+ let attached = false;
29306
29532
  const result = await runStreamSession({
29307
29533
  open: async (request) => {
29308
29534
  const stream = await options.open(request);
29535
+ if (!attached) {
29536
+ attached = true;
29537
+ try {
29538
+ await questions.start();
29539
+ } catch {}
29540
+ }
29309
29541
  if (options.rpc && !startedInput && !inputController.signal.aborted) {
29310
29542
  startedInput = true;
29311
29543
  inputTask = pump().catch((error) => {
@@ -29328,6 +29560,7 @@ async function runNativeSession(options) {
29328
29560
  stdout(text.endsWith(`
29329
29561
  `) ? text : text + `
29330
29562
  `);
29563
+ questions.frame(text);
29331
29564
  },
29332
29565
  banner: (text) => {
29333
29566
  stdout(text.endsWith(`
@@ -29347,6 +29580,9 @@ async function runNativeSession(options) {
29347
29580
  signal: controller.signal
29348
29581
  });
29349
29582
  finished = true;
29583
+ try {
29584
+ await questions.settle();
29585
+ } catch {}
29350
29586
  const woke = result.session;
29351
29587
  if (woke?.reference !== undefined && (woke.status === "woken" || woke.status === "exited")) {
29352
29588
  stderr("[mutagent] " + JSON.stringify({ event: "woken", reference: woke.reference }) + `
@@ -31042,6 +31278,12 @@ Send does not wait for the reply. The reply arrives on the session's stream as a
31042
31278
  'response' event carrying the command id (in --json output). Watch it with:
31043
31279
  ${chalk29.dim("$")} mutagent helix session attach <reference>
31044
31280
 
31281
+ Questions are not sent to, they are answered: when the session asks (its ask tool —
31282
+ a select, confirm, input or editor dialog), 'mutagent helix session approvals
31283
+ <reference>' lists what is open and 'mutagent helix session answer <reference> <id>
31284
+ --value <text>' (or --cancel) answers it. Attach prints the same command when the
31285
+ question appears.
31286
+
31045
31287
  AI Agent Directive:
31046
31288
  --json returns ONE object: { success, reference, type, id, line, accepted,
31047
31289
  _links }. 'accepted' means delivered, not answered: the answer is a 'response'
@@ -31049,7 +31291,10 @@ AI Agent Directive:
31049
31291
  command does not wait for it. wake.state 'waking' means queued: the session is
31050
31292
  being restored and the message is not delivered yet; the stream reports the
31051
31293
  delivery, or the failed restore and the message it lost. Use --type and a message; use --line only for a
31052
- command the four types cannot express.
31294
+ command the four types cannot express. A question the session asks is never
31295
+ answered by send: poll 'mutagent helix session approvals <reference> --json'
31296
+ and answer with 'mutagent helix session answer <reference> <id> --value <text>'
31297
+ (or --cancel).
31053
31298
  `)).action(async (id, messageParts, options) => {
31054
31299
  const isJson = getJsonFlag(jsonSource);
31055
31300
  const output = new OutputFormatter(isJson ? "json" : "table");
@@ -31285,8 +31530,10 @@ Examples:
31285
31530
  ${chalk31.dim("$")} mutagent helix session checkpoint <reference>
31286
31531
 
31287
31532
  A session reference (hs1_...) is printed when a run starts and listed by 'session list'.
31288
- attach, send, signal, close-input, checkpoint, checkpoints and restore take it.
31289
- checkpoint saves a session's conversation; restore continues it in a rebuilt sandbox.
31533
+ attach, send, signal, close-input, checkpoint, checkpoints, approvals, answer and
31534
+ restore take it. checkpoint saves a session's conversation; restore continues it in
31535
+ a rebuilt sandbox. approvals lists the questions the session is waiting on a human
31536
+ for, and answer answers one — a session that asked blocks until it is answered.
31290
31537
  A sandbox idle for 15 minutes is stopped; an interactive session in it is checkpointed first.
31291
31538
  A send to that session wakes it from its last checkpoint; restore is the manual option.
31292
31539
 
@@ -31294,7 +31541,7 @@ AI Agent Directive:
31294
31541
  Start a steerable session with mutagent helix --mode rpc (or -p for one-shot)
31295
31542
  and keep the session reference it prints; 'mutagent helix session list --json'
31296
31543
  lists references too. Use the reference for attach, send, signal, close-input,
31297
- checkpoint, checkpoints and restore; never guess one. Only an interactive
31544
+ checkpoint, checkpoints, approvals, answer and restore; never guess one. Only an interactive
31298
31545
  (--mode rpc) session accepts send. restore starts a NEW session and returns its
31299
31546
  reference. A managed agent's session cannot be restored yet (409).
31300
31547
  `));
@@ -31303,6 +31550,8 @@ AI Agent Directive:
31303
31550
  registerSessionList(session, parent, p);
31304
31551
  registerSessionAttach(session, p);
31305
31552
  registerSendCommand(session, { jsonSource: parent, product: p });
31553
+ registerApprovals(session, parent, p);
31554
+ registerAnswer(session, parent, p);
31306
31555
  registerSignalCommand(session, { jsonSource: parent, product: p });
31307
31556
  registerCloseInput(session, parent, p);
31308
31557
  registerCheckpoint(session, parent, p);
@@ -31470,7 +31719,10 @@ function registerSessionAttach(session, p) {
31470
31719
  " A dropped stream reconnects at its cursor for up to 5 minutes; if it gives up, it prints the seq to resume from.",
31471
31720
  " A reference names one session; after a restore, take the new reference from session list.",
31472
31721
  ' When a send wakes the session, stderr carries [mutagent] {"event":"woken","reference":"hs1_..."}:',
31473
- " this stream ends there; attach to that reference with --since 0."
31722
+ " this stream ends there; attach to that reference with --since 0.",
31723
+ " A question the session asks (its ask tool: a select, confirm, input or editor dialog)",
31724
+ " prints on stderr with the command that answers it; a question replayed from",
31725
+ " history that has since closed prints nothing. session approvals lists what is open."
31474
31726
  ].join(`
31475
31727
  `))).action(async (reference, options) => {
31476
31728
  try {
@@ -31482,13 +31734,110 @@ function registerSessionAttach(session, p) {
31482
31734
  check: () => checkSession(reference, findRow),
31483
31735
  ...since === undefined ? {} : { since },
31484
31736
  open: (request) => openSessionStream(p, reference, request),
31485
- send: (line, signal) => sendSessionInput(p, reference, line, signal)
31737
+ send: (line, signal) => sendSessionInput(p, reference, line, signal),
31738
+ openQuestions: async () => {
31739
+ const { approvals } = await listSessionApprovals(p, reference, AbortSignal.timeout(1e4));
31740
+ return Array.isArray(approvals) ? approvals : [];
31741
+ }
31486
31742
  });
31487
31743
  } catch (error) {
31488
31744
  handleError(sessionGoneGuidance(error, "stream", reference), false);
31489
31745
  }
31490
31746
  });
31491
31747
  }
31748
+ function registerApprovals(session, root, p) {
31749
+ const t = (text) => productText(text, p);
31750
+ session.command("approvals").description(t("List the questions a Helix session is waiting on")).argument("<reference>", t("Session reference (hs1_...) from 'mutagent helix' or 'session list'")).addHelpText("after", t(`
31751
+ Examples:
31752
+ ${chalk31.dim("$")} mutagent helix session approvals <reference>
31753
+ ${chalk31.dim("$")} mutagent helix session approvals <reference> --json
31754
+
31755
+ The questions the session asked and is waiting on a human to answer: a select
31756
+ (its options), a confirm (yes or no), an input or an editor (text). While any
31757
+ is open the session is needs-input and its turn waits; a question whose timeout
31758
+ passes is resolved by the sandbox itself. Each row's id is what an answer
31759
+ names — answer it with 'mutagent helix session answer'; attach prints the same
31760
+ commands the moment a question appears.
31761
+
31762
+ AI Agent Directive:
31763
+ --json returns { success, reference, approvals: [{ id, kind, title, message,
31764
+ options, placeholder, requestedAt, expiresAt }], count, _links }. Poll it to
31765
+ find a session blocked on a person; answer with 'mutagent helix session answer
31766
+ <reference> <id> --value <text>' (or --cancel), never with session send.
31767
+ `)).action(async (reference) => {
31768
+ const isJson = getJsonFlag(root);
31769
+ const output = new OutputFormatter(isJson ? "json" : "table");
31770
+ try {
31771
+ const { approvals } = await listSessionApprovals(p, reference);
31772
+ const open = Array.isArray(approvals) ? approvals : [];
31773
+ if (isJson) {
31774
+ output.output({
31775
+ reference,
31776
+ approvals: open,
31777
+ count: open.length,
31778
+ _links: { api: sessionPath(p, reference) + "/approvals" }
31779
+ });
31780
+ return;
31781
+ }
31782
+ if (open.length === 0) {
31783
+ output.info(t("No open questions: the session is not waiting on anyone."));
31784
+ return;
31785
+ }
31786
+ output.output(open.map((approval) => ({
31787
+ id: approval.id,
31788
+ kind: approval.kind,
31789
+ title: approval.title,
31790
+ detail: questionDetail(approval),
31791
+ asked: new Date(approval.requestedAt).toLocaleString()
31792
+ })));
31793
+ } catch (error) {
31794
+ handleError(withoutSandboxIds(error), isJson);
31795
+ }
31796
+ });
31797
+ }
31798
+ function registerAnswer(session, root, p) {
31799
+ const t = (text) => productText(text, p);
31800
+ session.command("answer").description(t("Answer a question a Helix session is waiting on")).argument("<reference>", t("Session reference (hs1_...) from 'mutagent helix' or 'session list'")).argument("<id>", "The question id, from session approvals or an attach notice").option("--value <text>", "Approve with this answer (a select option, or the text)").option("--cancel", "Deny the question instead of approving it").addHelpText("after", t(`
31801
+ Examples:
31802
+ ${chalk31.dim("$")} mutagent helix session answer <reference> q1 --value 'Deploy to production'
31803
+ ${chalk31.dim("$")} mutagent helix session answer <reference> q2 # approve a confirm
31804
+ ${chalk31.dim("$")} mutagent helix session answer <reference> q2 --cancel # deny it
31805
+
31806
+ Approve answers the question; --cancel denies it. A select takes one of its
31807
+ options as --value, an input or editor takes the text, and a confirm needs no
31808
+ value at all. The id comes from 'session approvals' or from the block attach
31809
+ prints when the question appears; answering from any terminal reaches the
31810
+ session, and the turn continues on its stream, not in this output.
31811
+
31812
+ AI Agent Directive:
31813
+ --json returns { success, reference, id, decision, value?, _links }. Delivery
31814
+ is not the continuation: watch the session's stream for it. APPROVAL_NOT_FOUND
31815
+ means another terminal answered it or its timeout passed — list what is still
31816
+ open with 'mutagent helix session approvals <reference> --json'.
31817
+ `)).action(async (reference, id, options) => {
31818
+ const isJson = getJsonFlag(root);
31819
+ const output = new OutputFormatter(isJson ? "json" : "table");
31820
+ try {
31821
+ if (options.cancel === true && options.value !== undefined) {
31822
+ throw new MutagentError("INVALID_ARGUMENTS", "--cancel denies the question, so --value would be discarded.", "Send --value to approve the question, or --cancel to deny it — one of the two.");
31823
+ }
31824
+ const answer = options.cancel === true ? { decision: "deny" } : options.value === undefined ? { decision: "approve" } : { decision: "approve", value: options.value };
31825
+ await answerSessionApproval(p, reference, id, answer);
31826
+ if (isJson) {
31827
+ output.output({
31828
+ reference,
31829
+ id,
31830
+ ...answer,
31831
+ _links: { api: sessionPath(p, reference) + "/approvals/" + encodeURIComponent(id) }
31832
+ });
31833
+ } else {
31834
+ output.success(`Answered ${id} (${answer.decision}${answer.value === undefined ? "" : `: ${answer.value}`}) on ${reference}; the session continues on its stream.`);
31835
+ }
31836
+ } catch (error) {
31837
+ handleError(withoutSandboxIds(error), isJson);
31838
+ }
31839
+ });
31840
+ }
31492
31841
  function registerCheckpoint(session, root, p) {
31493
31842
  const t = (text) => productText(text, p);
31494
31843
  session.command("checkpoint").description("Save a session's conversation as a checkpoint").argument("<reference>", "Session reference (hs1_...)").addOption(new Option4("--session <id>", "The session id, when the argument is a sandbox id").hideHelp()).addHelpText("after", t(`
@@ -37807,7 +38156,7 @@ function readBody(value) {
37807
38156
  function isInteractive(isJson) {
37808
38157
  return !isJson && process.env.MUTAGENT_NON_INTERACTIVE !== "true" && process.env.CI !== "true" && process.stdin.isTTY && process.stdout.isTTY;
37809
38158
  }
37810
- function shellQuote2(value) {
38159
+ function shellQuote3(value) {
37811
38160
  return /^[\w@%+=:,./-]+$/.test(value) ? value : `'${value.replace(/'/g, `'\\''`)}'`;
37812
38161
  }
37813
38162
  function rerunWithYes(options) {
@@ -37823,7 +38172,7 @@ function rerunWithYes(options) {
37823
38172
  ];
37824
38173
  for (const [flag, value] of flags) {
37825
38174
  if (value !== undefined)
37826
- parts.push(`--${flag}`, shellQuote2(value));
38175
+ parts.push(`--${flag}`, shellQuote3(value));
37827
38176
  }
37828
38177
  parts.push("--yes", "--json");
37829
38178
  return parts.join(" ");
@@ -39206,21 +39555,21 @@ init_sandbox_scope_error();
39206
39555
  // src/commands/integrations/secret-required.ts
39207
39556
  init_output();
39208
39557
  import chalk66 from "chalk";
39209
- function shellQuote3(value) {
39558
+ function shellQuote4(value) {
39210
39559
  return `'${value.replace(/'/g, `'\\''`)}'`;
39211
39560
  }
39212
39561
  function rerunCommand(body) {
39213
- const parts = [`${SOURCES3} add ${shellQuote3(String(body.kind))}`, `--name ${shellQuote3(String(body.name))}`];
39562
+ const parts = [`${SOURCES3} add ${shellQuote4(String(body.kind))}`, `--name ${shellQuote4(String(body.name))}`];
39214
39563
  if (typeof body.host === "string")
39215
- parts.push(`--host ${shellQuote3(body.host)}`);
39564
+ parts.push(`--host ${shellQuote4(body.host)}`);
39216
39565
  if (typeof body.org === "string")
39217
- parts.push(`--openobserve-org ${shellQuote3(body.org)}`);
39566
+ parts.push(`--openobserve-org ${shellQuote4(body.org)}`);
39218
39567
  if (typeof body.stream === "string")
39219
- parts.push(`--stream ${shellQuote3(body.stream)}`);
39568
+ parts.push(`--stream ${shellQuote4(body.stream)}`);
39220
39569
  if (typeof body.signal === "string")
39221
- parts.push(`--signal ${shellQuote3(body.signal)}`);
39570
+ parts.push(`--signal ${shellQuote4(body.signal)}`);
39222
39571
  if (typeof body.dataset === "string")
39223
- parts.push(`--dataset ${shellQuote3(body.dataset)}`);
39572
+ parts.push(`--dataset ${shellQuote4(body.dataset)}`);
39224
39573
  return parts.join(" ");
39225
39574
  }
39226
39575
  function printSecretRequired(isJson, detail, rerun) {
@@ -45170,4 +45519,4 @@ if (process.env.CLI_VERSION) {
45170
45519
  }
45171
45520
  runCli(process.argv.slice(2), cliVersion);
45172
45521
 
45173
- //# debugId=C84BBF9AA9B7837764756E2164756E21
45522
+ //# debugId=3B06A5F83D41F6E764756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutagent/cli",
3
- "version": "0.2.214",
3
+ "version": "0.2.216",
4
4
  "description": "Bun-native CLI for the MutagenT AI platform - auth, provider config, and lifecycle-tool installer for AI-native workflows",
5
5
  "type": "module",
6
6
  "bin": {
@@ -45,7 +45,7 @@
45
45
  },
46
46
  "dependencies": {
47
47
  "@inquirer/prompts": "^8.7.2",
48
- "@mutagent/sdk": "0.12.25",
48
+ "@mutagent/sdk": "0.12.27",
49
49
  "@sinclair/typebox": "^0.34.0",
50
50
  "chalk": "^5.3.0",
51
51
  "commander": "^12.1.0",
@@ -94,5 +94,5 @@
94
94
  "bugs": {
95
95
  "url": "https://docs.mutagent.io/support"
96
96
  },
97
- "gitHead": "485011daa8fbf26044dfa5e3f412222292afe3a4"
97
+ "gitHead": "c32ceb2e6b9127d247bccee7447ee0c9acf0e007"
98
98
  }