@mutagent/cli 0.2.184 → 0.2.186
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 +18 -0
- package/dist/bin/cli.js +613 -331
- package/package.json +3 -3
package/dist/bin/cli.js
CHANGED
|
@@ -19809,7 +19809,8 @@ function platformError(status, body, ctx) {
|
|
|
19809
19809
|
if (ctx.credential === "sandbox-token" && status === 401) {
|
|
19810
19810
|
return sandboxTokenRefused();
|
|
19811
19811
|
}
|
|
19812
|
-
const
|
|
19812
|
+
const routeMiss = status === 404 && parsed.code === undefined && parsed.message === undefined && parsed.error === "Route not found";
|
|
19813
|
+
const reason = typeof parsed.reason === "string" ? parsed.reason : typeof parsed.message === "string" ? parsed.message : routeMiss ? "Route not found" : undefined;
|
|
19813
19814
|
if (typeof parsed.code === "string" && /^[A-Z][A-Z0-9_]{1,63}$/.test(parsed.code) && reason !== undefined) {
|
|
19814
19815
|
const fix = typeof parsed.fix === "string" && parsed.fix.trim() !== "" ? asSuggestion(parsed.fix) : `Run: ${ctx.help}`;
|
|
19815
19816
|
return new PlatformRefusal(parsed.code, reason, fix, status, Array.isArray(parsed.errors) ? parsed.errors : undefined);
|
|
@@ -22692,6 +22693,12 @@ fill in for you, and which credential it signs in with.
|
|
|
22692
22693
|
|
|
22693
22694
|
\`mutagent helix access --json\` says whether this account may use cloud sandboxes.
|
|
22694
22695
|
|
|
22696
|
+
An Architech cloud session runs through \`mutagent architech\`, the cloud form of the
|
|
22697
|
+
local \`architech\`, never through \`mutagent helix --preset architech\` (refused with
|
|
22698
|
+
\`HARNESS_USE_PRODUCT_COMMAND\`; run the \`mutagent architech …\` line it names). Its
|
|
22699
|
+
\`agent\`, \`session\`, \`models\` and \`access\` verbs work like Helix's and take the same
|
|
22700
|
+
\`hs1_\` references; it has no \`--preset\`.
|
|
22701
|
+
|
|
22695
22702
|
## What defaults from the session
|
|
22696
22703
|
|
|
22697
22704
|
In a cloud sandbox launched for a Factory entry, the platform sets these:
|
|
@@ -26416,7 +26423,40 @@ AI Agent Directive:
|
|
|
26416
26423
|
return install;
|
|
26417
26424
|
}
|
|
26418
26425
|
|
|
26419
|
-
// src/
|
|
26426
|
+
// src/lib/cloud-product.ts
|
|
26427
|
+
var HELIX_PRODUCT = Object.freeze({ command: "helix", cli: "mutagent helix", title: "Helix", harness: "helix", sessions: "/api/helix/sessions" });
|
|
26428
|
+
var ARCHITECH_PRODUCT = Object.freeze({
|
|
26429
|
+
command: "architech",
|
|
26430
|
+
cli: "mutagent architech",
|
|
26431
|
+
title: "Architech",
|
|
26432
|
+
harness: "architech",
|
|
26433
|
+
sessions: "/api/architech/sessions",
|
|
26434
|
+
preset: "architech"
|
|
26435
|
+
});
|
|
26436
|
+
var CLOUD_PRODUCTS = [HELIX_PRODUCT, ARCHITECH_PRODUCT];
|
|
26437
|
+
function productOwningPreset(preset) {
|
|
26438
|
+
if (preset === undefined)
|
|
26439
|
+
return;
|
|
26440
|
+
return CLOUD_PRODUCTS.find((product) => product.preset !== undefined && product.preset === preset.trim());
|
|
26441
|
+
}
|
|
26442
|
+
var active = HELIX_PRODUCT;
|
|
26443
|
+
function productCopy(text, product = active) {
|
|
26444
|
+
return product === HELIX_PRODUCT ? text : text.replace(/mutagent helix(?! (?:version|doctor|smoke|update)\b)/g, product.cli);
|
|
26445
|
+
}
|
|
26446
|
+
function productText(text, product) {
|
|
26447
|
+
if (product === HELIX_PRODUCT)
|
|
26448
|
+
return text;
|
|
26449
|
+
const article = /^[AEIOU]/.test(product.title) ? "an" : "a";
|
|
26450
|
+
return productCopy(text, product).replace(/\b([Aa]) Helix\b(?! binary)/g, (_match, a) => `${a === "A" ? article.charAt(0).toUpperCase() + article.slice(1) : article} ${product.title}`).replace(/\bHelix\b(?! binary)/g, product.title);
|
|
26451
|
+
}
|
|
26452
|
+
function activeProduct() {
|
|
26453
|
+
return active;
|
|
26454
|
+
}
|
|
26455
|
+
function selectProduct(product) {
|
|
26456
|
+
active = product;
|
|
26457
|
+
}
|
|
26458
|
+
|
|
26459
|
+
// src/commands/cloud-session/product-command.ts
|
|
26420
26460
|
import { Command as Command14 } from "commander";
|
|
26421
26461
|
|
|
26422
26462
|
// src/lib/launch-failure.ts
|
|
@@ -26466,10 +26506,10 @@ function handleLaunchFailure(raw, mode) {
|
|
|
26466
26506
|
handleError(error, mode.isJson);
|
|
26467
26507
|
}
|
|
26468
26508
|
|
|
26469
|
-
// src/commands/
|
|
26509
|
+
// src/commands/cloud-session/product-command.ts
|
|
26470
26510
|
init_output();
|
|
26471
26511
|
|
|
26472
|
-
// src/commands/
|
|
26512
|
+
// src/commands/cloud-session/agent.ts
|
|
26473
26513
|
init_output();
|
|
26474
26514
|
init_errors();
|
|
26475
26515
|
import { Option } from "commander";
|
|
@@ -26619,12 +26659,12 @@ function agentRepositoryRefusal(argv, options, runnable) {
|
|
|
26619
26659
|
if (options.rpc === true)
|
|
26620
26660
|
bound.push("--rpc");
|
|
26621
26661
|
const words = [...kept, ...bound].map(shellWord);
|
|
26622
|
-
const line = words.every((word) => word !== undefined) ? [
|
|
26662
|
+
const line = words.every((word) => word !== undefined) ? [`${activeProduct().cli} agent`, ...words].join(" ") : undefined;
|
|
26623
26663
|
return new LaunchRepositoryError("MANAGED_AGENT_REQUEST_INVALID", "A managed agent runs its package; drop --repository or run a native brief.", {
|
|
26624
26664
|
fix: line !== undefined && runnable(line) ? [line] : [],
|
|
26625
26665
|
notes: [
|
|
26626
26666
|
"A managed agent (@slug) runs its deployed package, so the server refuses a repository checkout with it. Run the same command without --repository and --branch.",
|
|
26627
|
-
|
|
26667
|
+
`To run in a repository checkout, use a native brief: ${activeProduct().cli} agent --name <agent> --repository <owner/name> -p "<task>", or the launcher: ${activeProduct().cli} --repository <owner/name> -p "<task>".`
|
|
26628
26668
|
]
|
|
26629
26669
|
});
|
|
26630
26670
|
}
|
|
@@ -26950,13 +26990,13 @@ function renderWorkspaceConfigFix(fix, resource) {
|
|
|
26950
26990
|
return escalate === undefined ? rendered : { ...rendered, escalate };
|
|
26951
26991
|
}
|
|
26952
26992
|
|
|
26953
|
-
// src/commands/
|
|
26993
|
+
// src/commands/cloud-session/agent-argv.ts
|
|
26954
26994
|
init_errors();
|
|
26955
26995
|
import { homedir as homedir5 } from "os";
|
|
26956
26996
|
import { basename as basename6, join as join20, isAbsolute as isAbsolute6, resolve as resolve8 } from "path";
|
|
26957
26997
|
import { accessSync as accessSync3, constants as constants3, existsSync as existsSync11, readFileSync as readFileSync13, statSync as statSync4 } from "fs";
|
|
26958
26998
|
|
|
26959
|
-
// src/commands/
|
|
26999
|
+
// src/commands/cloud-session/argv-transport.ts
|
|
26960
27000
|
var HOST_PATH = "it names a path on THIS machine, and the sandbox is a different machine";
|
|
26961
27001
|
var TRANSPORT_TABLE = [
|
|
26962
27002
|
{
|
|
@@ -26978,7 +27018,9 @@ var TRANSPORT_TABLE = [
|
|
|
26978
27018
|
takesValue: false,
|
|
26979
27019
|
class: "reject",
|
|
26980
27020
|
reason: "the sandbox image already contains Helix",
|
|
26981
|
-
alternative: "The image pins its own Helix build; see `mutagent sandbox presets`."
|
|
27021
|
+
alternative: "The image pins its own Helix build; see `mutagent sandbox presets`.",
|
|
27022
|
+
fixedHarnessReason: "the sandbox image already contains the Architech harness",
|
|
27023
|
+
fixedHarnessAlternative: "The image pins its own Architech harness build; see `mutagent sandbox presets`."
|
|
26982
27024
|
},
|
|
26983
27025
|
{
|
|
26984
27026
|
token: "--prompt",
|
|
@@ -27152,14 +27194,16 @@ var TRANSPORT_TABLE = [
|
|
|
27152
27194
|
takesValue: false,
|
|
27153
27195
|
class: "reject",
|
|
27154
27196
|
reason: "there is no previous session in a new sandbox to continue",
|
|
27155
|
-
alternative: "Run against a sandbox you kept: `mutagent helix agent --sandbox <id> …`, or restore a checkpoint."
|
|
27197
|
+
alternative: "Run against a sandbox you kept: `mutagent helix agent --sandbox <id> …`, or restore a checkpoint.",
|
|
27198
|
+
fixedHarnessAlternative: "Continue the session from its checkpoint in a rebuilt sandbox: `mutagent helix session restore <reference>`."
|
|
27156
27199
|
},
|
|
27157
27200
|
{
|
|
27158
27201
|
token: "-c",
|
|
27159
27202
|
takesValue: false,
|
|
27160
27203
|
class: "reject",
|
|
27161
27204
|
reason: "there is no previous session in a new sandbox to continue",
|
|
27162
|
-
alternative: "Run against a sandbox you kept: `mutagent helix agent --sandbox <id> …`, or restore a checkpoint."
|
|
27205
|
+
alternative: "Run against a sandbox you kept: `mutagent helix agent --sandbox <id> …`, or restore a checkpoint.",
|
|
27206
|
+
fixedHarnessAlternative: "Continue the session from its checkpoint in a rebuilt sandbox: `mutagent helix session restore <reference>`."
|
|
27163
27207
|
},
|
|
27164
27208
|
{
|
|
27165
27209
|
token: "--resume",
|
|
@@ -27229,17 +27273,27 @@ var TRANSPORT_TABLE = [
|
|
|
27229
27273
|
takesValue: false,
|
|
27230
27274
|
class: "reject",
|
|
27231
27275
|
reason: "it would spawn a whole sandbox to print a version string",
|
|
27232
|
-
alternative: "Run `mutagent helix version`, which reports both this CLI and the image’s pinned Helix."
|
|
27276
|
+
alternative: "Run `mutagent helix version`, which reports both this CLI and the image’s pinned Helix.",
|
|
27277
|
+
fixedHarnessAlternative: "Drop it: `mutagent helix --help --json` reports the cloud surface (the pinned harness flag surface) without a sandbox."
|
|
27233
27278
|
},
|
|
27234
27279
|
{
|
|
27235
27280
|
token: "-v",
|
|
27236
27281
|
takesValue: false,
|
|
27237
27282
|
class: "reject",
|
|
27238
27283
|
reason: "it would spawn a whole sandbox to print a version string",
|
|
27239
|
-
alternative: "Run `mutagent helix version`, which reports both this CLI and the image’s pinned Helix."
|
|
27284
|
+
alternative: "Run `mutagent helix version`, which reports both this CLI and the image’s pinned Helix.",
|
|
27285
|
+
fixedHarnessAlternative: "Drop it: `mutagent helix --help --json` reports the cloud surface (the pinned harness flag surface) without a sandbox."
|
|
27240
27286
|
}
|
|
27241
27287
|
];
|
|
27242
27288
|
var BY_TOKEN = new Map(TRANSPORT_TABLE.map((entry) => [entry.token, entry]));
|
|
27289
|
+
function alternativeFor(entry, product = activeProduct()) {
|
|
27290
|
+
const text = product.preset !== undefined && entry.fixedHarnessAlternative !== undefined ? entry.fixedHarnessAlternative : entry.alternative ?? "";
|
|
27291
|
+
return productCopy(text, product);
|
|
27292
|
+
}
|
|
27293
|
+
function reasonFor(entry, product = activeProduct()) {
|
|
27294
|
+
const reason = product.preset !== undefined && entry.fixedHarnessReason !== undefined ? entry.fixedHarnessReason : entry.reason;
|
|
27295
|
+
return reason ?? "it cannot mean the same thing there";
|
|
27296
|
+
}
|
|
27243
27297
|
function transportFor(token) {
|
|
27244
27298
|
return BY_TOKEN.get(token);
|
|
27245
27299
|
}
|
|
@@ -27268,7 +27322,7 @@ function redactCommanderError(text) {
|
|
|
27268
27322
|
return text.replace(/(unknown (?:option|command) ')([^']*)(')/g, (_match, before, token, after) => `${before}${redactToken(token)}${after}`);
|
|
27269
27323
|
}
|
|
27270
27324
|
|
|
27271
|
-
// src/commands/
|
|
27325
|
+
// src/commands/cloud-session/planned-flags.ts
|
|
27272
27326
|
init_errors();
|
|
27273
27327
|
import { basename as basename5, isAbsolute as isAbsolute5, resolve as resolve7 } from "path";
|
|
27274
27328
|
var OWN_FLAGS = {
|
|
@@ -27360,7 +27414,7 @@ function checkSandboxId(value) {
|
|
|
27360
27414
|
}
|
|
27361
27415
|
}
|
|
27362
27416
|
|
|
27363
|
-
// src/commands/
|
|
27417
|
+
// src/commands/cloud-session/agent-argv.ts
|
|
27364
27418
|
function defaultPlanDeps() {
|
|
27365
27419
|
return {
|
|
27366
27420
|
cwd: process.cwd(),
|
|
@@ -27456,7 +27510,7 @@ function planAgentArgv(argv, deps, flags = {}) {
|
|
|
27456
27510
|
continue;
|
|
27457
27511
|
}
|
|
27458
27512
|
if (entry.class === "reject") {
|
|
27459
|
-
throw rejection(token, entry
|
|
27513
|
+
throw rejection(token, reasonFor(entry), alternativeFor(entry));
|
|
27460
27514
|
}
|
|
27461
27515
|
let value = "";
|
|
27462
27516
|
if (entry.takesValue) {
|
|
@@ -27516,7 +27570,7 @@ function planAgentArgv(argv, deps, flags = {}) {
|
|
|
27516
27570
|
};
|
|
27517
27571
|
}
|
|
27518
27572
|
function rejection(token, reason, alternative) {
|
|
27519
|
-
return new MutagentError("INVALID_ARGUMENTS", `${token} is not supported in a cloud run: ${reason}.`, alternative);
|
|
27573
|
+
return new MutagentError("INVALID_ARGUMENTS", `${token} is not supported in a cloud run: ${reason}.`, productCopy(alternative));
|
|
27520
27574
|
}
|
|
27521
27575
|
function resolveDefinition(source, deps) {
|
|
27522
27576
|
if (source === undefined) {
|
|
@@ -27585,7 +27639,7 @@ function stripFrontmatter(raw) {
|
|
|
27585
27639
|
return text.slice(3 + close.index + fence.length).trim();
|
|
27586
27640
|
}
|
|
27587
27641
|
|
|
27588
|
-
// src/commands/
|
|
27642
|
+
// src/commands/cloud-session/native-mode.ts
|
|
27589
27643
|
init_errors();
|
|
27590
27644
|
function hasNativeMode(args) {
|
|
27591
27645
|
return modeSelection(args).explicit;
|
|
@@ -27636,7 +27690,7 @@ function nativeMode(args, print, rpc = false) {
|
|
|
27636
27690
|
return "json";
|
|
27637
27691
|
if (print)
|
|
27638
27692
|
return "text";
|
|
27639
|
-
throw new MutagentError("NOT_SUPPORTED",
|
|
27693
|
+
throw new MutagentError("NOT_SUPPORTED", `${activeProduct().cli} has no terminal chat UI.`, 'Use -p "<task>" for a complete run, --mode json "<task>" for events, or --mode rpc with a JSONL client.');
|
|
27640
27694
|
}
|
|
27641
27695
|
function nativeTaskNotices(mode, messages) {
|
|
27642
27696
|
if (mode === "rpc") {
|
|
@@ -27648,7 +27702,7 @@ function nativeTaskNotices(mode, messages) {
|
|
|
27648
27702
|
return [];
|
|
27649
27703
|
}
|
|
27650
27704
|
|
|
27651
|
-
// src/commands/
|
|
27705
|
+
// src/commands/cloud-session/run-cloud.ts
|
|
27652
27706
|
init_errors();
|
|
27653
27707
|
|
|
27654
27708
|
// src/lib/sandbox-api.ts
|
|
@@ -28183,81 +28237,141 @@ function hostArch() {
|
|
|
28183
28237
|
return null;
|
|
28184
28238
|
}
|
|
28185
28239
|
|
|
28186
|
-
// src/lib/
|
|
28240
|
+
// src/lib/sandbox-session-api.ts
|
|
28187
28241
|
init_errors();
|
|
28188
|
-
var
|
|
28189
|
-
|
|
28190
|
-
|
|
28191
|
-
|
|
28192
|
-
|
|
28193
|
-
|
|
28194
|
-
|
|
28195
|
-
const
|
|
28196
|
-
|
|
28197
|
-
|
|
28198
|
-
|
|
28199
|
-
|
|
28200
|
-
|
|
28201
|
-
|
|
28202
|
-
})
|
|
28203
|
-
|
|
28204
|
-
|
|
28205
|
-
|
|
28206
|
-
}
|
|
28207
|
-
|
|
28208
|
-
|
|
28209
|
-
|
|
28210
|
-
|
|
28211
|
-
retryWhenStopping: true
|
|
28212
|
-
});
|
|
28242
|
+
var LEGACY_SESSIONS = "/api/sandbox/helix/sessions";
|
|
28243
|
+
var chosen = new Map;
|
|
28244
|
+
var ROUTE_NOT_FOUND = "Route not found";
|
|
28245
|
+
function routeMissing(error) {
|
|
28246
|
+
return error instanceof ApiError && error.statusCode === 404 && error.code === "API_404" && error.message === ROUTE_NOT_FOUND;
|
|
28247
|
+
}
|
|
28248
|
+
async function onRoute(routes, call) {
|
|
28249
|
+
const choice = chosen.get(routes.sessions);
|
|
28250
|
+
if (choice === "legacy")
|
|
28251
|
+
return call(LEGACY_SESSIONS, true);
|
|
28252
|
+
try {
|
|
28253
|
+
const result = await call(routes.sessions, false);
|
|
28254
|
+
chosen.set(routes.sessions, "product");
|
|
28255
|
+
return result;
|
|
28256
|
+
} catch (error) {
|
|
28257
|
+
if (choice === undefined && routeMissing(error)) {
|
|
28258
|
+
chosen.set(routes.sessions, "legacy");
|
|
28259
|
+
return call(LEGACY_SESSIONS, true);
|
|
28260
|
+
}
|
|
28261
|
+
if (choice === undefined && error instanceof ApiError)
|
|
28262
|
+
chosen.set(routes.sessions, "product");
|
|
28263
|
+
throw error;
|
|
28264
|
+
}
|
|
28213
28265
|
}
|
|
28214
|
-
function
|
|
28266
|
+
function referencePath(base, reference) {
|
|
28215
28267
|
if (reference.trim() === "") {
|
|
28216
28268
|
throw new MutagentError("INVALID_ARGUMENTS", "A live session reference is required.", "Use the reference returned when the session starts.");
|
|
28217
28269
|
}
|
|
28218
|
-
return
|
|
28270
|
+
return base + "/" + encodeURIComponent(reference);
|
|
28219
28271
|
}
|
|
28220
|
-
|
|
28221
|
-
return
|
|
28272
|
+
function sessionPath(routes, reference) {
|
|
28273
|
+
return referencePath(chosen.get(routes.sessions) === "legacy" ? LEGACY_SESSIONS : routes.sessions, reference);
|
|
28222
28274
|
}
|
|
28223
|
-
|
|
28224
|
-
|
|
28275
|
+
function ownsRow(routes, row) {
|
|
28276
|
+
const harness = row.harness ?? "helix";
|
|
28277
|
+
return harness === routes.harness;
|
|
28278
|
+
}
|
|
28279
|
+
async function listSessionsPage(routes, cursor) {
|
|
28280
|
+
const page = await onRoute(routes, (base, legacy) => {
|
|
28281
|
+
const params = new URLSearchParams;
|
|
28282
|
+
if (cursor !== undefined)
|
|
28283
|
+
params.set("cursor", cursor);
|
|
28284
|
+
if (legacy)
|
|
28285
|
+
params.set("harness", routes.harness);
|
|
28286
|
+
const query = params.toString();
|
|
28287
|
+
return requestJson(base + (query === "" ? "" : `?${query}`));
|
|
28288
|
+
});
|
|
28289
|
+
return { ...page, sessions: page.sessions.filter((row) => ownsRow(routes, row)) };
|
|
28290
|
+
}
|
|
28291
|
+
var SESSION_LIST_PAGE = 100;
|
|
28292
|
+
var SESSION_LIST_MAX_REQUESTS = 20;
|
|
28293
|
+
async function listHarnessSessions(routes) {
|
|
28294
|
+
const sessions = [];
|
|
28295
|
+
let cursor;
|
|
28296
|
+
let workspaceId = "";
|
|
28297
|
+
for (let request = 0;request < SESSION_LIST_MAX_REQUESTS; request++) {
|
|
28298
|
+
const page = await listSessionsPage(routes, cursor).catch((error) => {
|
|
28299
|
+
if (error instanceof MutagentError && error.code === "UNKNOWN_SESSION_HARNESS") {
|
|
28300
|
+
throw new MutagentError(error.code, error.message, `The platform does not list ${routes.harness} sessions yet.`);
|
|
28301
|
+
}
|
|
28302
|
+
throw error;
|
|
28303
|
+
});
|
|
28304
|
+
workspaceId = page.workspaceId;
|
|
28305
|
+
sessions.push(...page.sessions);
|
|
28306
|
+
const next = page.nextCursor;
|
|
28307
|
+
if (next === undefined || next === "" || next === cursor || sessions.length >= SESSION_LIST_PAGE) {
|
|
28308
|
+
return { workspaceId, sessions, ...next === undefined || next === "" || next === cursor ? {} : { nextCursor: next } };
|
|
28309
|
+
}
|
|
28310
|
+
cursor = next;
|
|
28311
|
+
}
|
|
28312
|
+
return { workspaceId, sessions, ...cursor === undefined ? {} : { nextCursor: cursor } };
|
|
28225
28313
|
}
|
|
28226
|
-
async function
|
|
28227
|
-
|
|
28314
|
+
async function launchSession(routes, body) {
|
|
28315
|
+
const sent = JSON.stringify(body);
|
|
28316
|
+
return onRoute(routes, (base) => requestJson(base, { method: "POST", body: sent }));
|
|
28228
28317
|
}
|
|
28229
|
-
async function
|
|
28230
|
-
return requestJson(
|
|
28318
|
+
async function sendSessionInput(routes, reference, line, signal) {
|
|
28319
|
+
return onRoute(routes, (base) => requestJson(referencePath(base, reference) + "/input", {
|
|
28231
28320
|
method: "POST",
|
|
28232
28321
|
body: JSON.stringify({ line }),
|
|
28233
28322
|
signal
|
|
28234
|
-
});
|
|
28323
|
+
}));
|
|
28235
28324
|
}
|
|
28236
|
-
async function
|
|
28237
|
-
return requestJson(
|
|
28325
|
+
async function closeSessionInput(routes, reference, signal) {
|
|
28326
|
+
return onRoute(routes, (base) => requestJson(referencePath(base, reference) + "/close-input", {
|
|
28238
28327
|
method: "POST",
|
|
28239
28328
|
body: "{}",
|
|
28240
28329
|
signal
|
|
28241
|
-
});
|
|
28330
|
+
}));
|
|
28242
28331
|
}
|
|
28243
|
-
async function
|
|
28244
|
-
return requestJson(
|
|
28332
|
+
async function signalSession(routes, reference, signal, abort) {
|
|
28333
|
+
return onRoute(routes, (base) => requestJson(referencePath(base, reference) + "/signal", {
|
|
28245
28334
|
method: "POST",
|
|
28246
28335
|
body: JSON.stringify({ signal }),
|
|
28247
28336
|
signal: abort
|
|
28248
|
-
});
|
|
28337
|
+
}));
|
|
28249
28338
|
}
|
|
28250
|
-
async function
|
|
28339
|
+
async function openSessionStream(routes, reference, options = {}) {
|
|
28251
28340
|
const query = options.since === undefined ? "" : "?since=" + String(options.since);
|
|
28252
|
-
return openStream(
|
|
28253
|
-
retryHint: "Reattach with:
|
|
28254
|
-
}, options);
|
|
28341
|
+
return onRoute(routes, (base) => openStream(referencePath(base, reference) + "/stream" + query, {
|
|
28342
|
+
retryHint: "Reattach with: " + routes.cli + " session attach " + reference
|
|
28343
|
+
}, options));
|
|
28344
|
+
}
|
|
28345
|
+
async function checkpointSession(routes, reference) {
|
|
28346
|
+
return onRoute(routes, (base) => requestJson(referencePath(base, reference) + "/checkpoint", {
|
|
28347
|
+
method: "POST",
|
|
28348
|
+
body: "{}"
|
|
28349
|
+
}));
|
|
28350
|
+
}
|
|
28351
|
+
async function listSessionCheckpoints(routes, reference) {
|
|
28352
|
+
return onRoute(routes, (base) => requestJson(referencePath(base, reference) + "/checkpoints"));
|
|
28353
|
+
}
|
|
28354
|
+
async function restoreSession(routes, reference, body) {
|
|
28355
|
+
return onRoute(routes, (base) => requestJson(referencePath(base, reference) + "/restore", {
|
|
28356
|
+
method: "POST",
|
|
28357
|
+
body: JSON.stringify(body),
|
|
28358
|
+
retryWhenStopping: true
|
|
28359
|
+
}));
|
|
28360
|
+
}
|
|
28361
|
+
async function endSession(routes, reference) {
|
|
28362
|
+
return onRoute(routes, (base) => requestJson(referencePath(base, reference) + "/end", { method: "POST", body: "{}" }));
|
|
28363
|
+
}
|
|
28364
|
+
async function onSessionRoute(routes, call) {
|
|
28365
|
+
return onRoute(routes, (base) => call(base));
|
|
28366
|
+
}
|
|
28367
|
+
async function getCloudAccess() {
|
|
28368
|
+
return requestJson("/api/sandbox/helix/access");
|
|
28255
28369
|
}
|
|
28256
28370
|
|
|
28257
|
-
// src/lib/
|
|
28371
|
+
// src/lib/sandbox-native-session.ts
|
|
28258
28372
|
init_errors();
|
|
28259
|
-
init_known_secrets();
|
|
28260
28373
|
import { createInterface as createInterface2 } from "node:readline";
|
|
28374
|
+
init_known_secrets();
|
|
28261
28375
|
|
|
28262
28376
|
// src/lib/sse.ts
|
|
28263
28377
|
var DEFAULT_EVENT_NAME = "message";
|
|
@@ -28613,7 +28727,7 @@ function delay(ms, signal) {
|
|
|
28613
28727
|
});
|
|
28614
28728
|
}
|
|
28615
28729
|
|
|
28616
|
-
// src/lib/
|
|
28730
|
+
// src/lib/sandbox-native-session.ts
|
|
28617
28731
|
var TEARDOWN_SIGNALS = ["SIGTERM", "SIGHUP"];
|
|
28618
28732
|
var EOF_SETTLE_MS = 100;
|
|
28619
28733
|
async function runNativeSession(options) {
|
|
@@ -28742,7 +28856,7 @@ async function runNativeSession(options) {
|
|
|
28742
28856
|
}
|
|
28743
28857
|
const closed = await closeInput(inputController.signal);
|
|
28744
28858
|
if (!closed.closed) {
|
|
28745
|
-
throw new MutagentError("RPC_INPUT_REJECTED", "The session did not confirm stdin closure.",
|
|
28859
|
+
throw new MutagentError("RPC_INPUT_REJECTED", "The session did not confirm stdin closure.", `Check the session: ${activeProduct().cli} session list. No signal was sent in place of EOF.`);
|
|
28746
28860
|
}
|
|
28747
28861
|
};
|
|
28748
28862
|
try {
|
|
@@ -28807,9 +28921,9 @@ async function runNativeSession(options) {
|
|
|
28807
28921
|
if (interruption.requested && result.end !== "exited")
|
|
28808
28922
|
process.exitCode = 1;
|
|
28809
28923
|
if (result.end === "asleep") {
|
|
28810
|
-
notice("Session " + options.reference + " is asleep: it stopped for idling. Everything it recorded is above. " + "Wake it with:
|
|
28924
|
+
notice("Session " + options.reference + " is asleep: it stopped for idling. Everything it recorded is above. " + "Wake it with: " + activeProduct().cli + " session send " + options.reference + ' "<message>"');
|
|
28811
28925
|
} else if (result.end !== "exited") {
|
|
28812
|
-
notice("Reattach with:
|
|
28926
|
+
notice("Reattach with: " + activeProduct().cli + " session attach " + options.reference + " --since " + String(result.lastSeq));
|
|
28813
28927
|
}
|
|
28814
28928
|
return result;
|
|
28815
28929
|
} finally {
|
|
@@ -28828,7 +28942,7 @@ async function runNativeSession(options) {
|
|
|
28828
28942
|
}
|
|
28829
28943
|
}
|
|
28830
28944
|
|
|
28831
|
-
// src/commands/
|
|
28945
|
+
// src/commands/cloud-session/run-cloud.ts
|
|
28832
28946
|
function repositoryFields(flags) {
|
|
28833
28947
|
return {
|
|
28834
28948
|
...flags.repository === undefined ? {} : { repository: flags.repository },
|
|
@@ -28869,7 +28983,7 @@ async function runCloudLaunch(plan, mode) {
|
|
|
28869
28983
|
};
|
|
28870
28984
|
process.on("SIGINT", queueInterrupt);
|
|
28871
28985
|
try {
|
|
28872
|
-
const session = sandbox ? await startSession(sandbox, body) : await
|
|
28986
|
+
const session = sandbox ? await startSession(sandbox, body) : await launchSession(activeProduct(), {
|
|
28873
28987
|
...body,
|
|
28874
28988
|
...plan.preset === undefined ? {} : { preset: plan.preset },
|
|
28875
28989
|
...plan.sandboxProvider === undefined ? {} : { sandboxProvider: plan.sandboxProvider },
|
|
@@ -28880,10 +28994,10 @@ async function runCloudLaunch(plan, mode) {
|
|
|
28880
28994
|
throw entryRefusal(launchRepositoryRefusal(error));
|
|
28881
28995
|
});
|
|
28882
28996
|
if (!session.reference) {
|
|
28883
|
-
throw new MutagentError("INVALID_RESPONSE", "The server did not return a session reference.", "Run: mutagent helix doctor");
|
|
28997
|
+
throw new MutagentError("INVALID_RESPONSE", "The server did not return a session reference.", activeProduct() === HELIX_PRODUCT ? "Run: mutagent helix doctor" : `Run: ${activeProduct().cli} access`);
|
|
28884
28998
|
}
|
|
28885
28999
|
if (session.arm !== plan.arm || session.mode !== body.mode) {
|
|
28886
|
-
throw new MutagentError("INVALID_RESPONSE", "The server started the session with a different arm or mode than requested.", "Session " + session.reference + " may still be running. Check:
|
|
29000
|
+
throw new MutagentError("INVALID_RESPONSE", "The server started the session with a different arm or mode than requested.", "Session " + session.reference + " may still be running. Check: " + activeProduct().cli + " session list");
|
|
28887
29001
|
}
|
|
28888
29002
|
process.removeListener("SIGINT", queueInterrupt);
|
|
28889
29003
|
await attachLaunched({ reference: session.reference, sessionId: session.sessionId }, mode === "rpc", interruptRequested);
|
|
@@ -28907,7 +29021,7 @@ async function runManagedAgentLaunch(launch, write = (line) => {
|
|
|
28907
29021
|
};
|
|
28908
29022
|
process.on("SIGINT", queueInterrupt);
|
|
28909
29023
|
try {
|
|
28910
|
-
const session = await
|
|
29024
|
+
const session = await launchSession(activeProduct(), {
|
|
28911
29025
|
agent: plan.address,
|
|
28912
29026
|
...plan.mode === undefined ? {} : { mode: plan.mode },
|
|
28913
29027
|
...plan.task === undefined ? {} : { args: ["-p", plan.task] },
|
|
@@ -28919,7 +29033,7 @@ async function runManagedAgentLaunch(launch, write = (line) => {
|
|
|
28919
29033
|
throw new MutagentError("INVALID_RESPONSE", "The server did not return a session reference for the managed agent run.", "Check that the server supports managed agents (mutagent agent --help) before running again.");
|
|
28920
29034
|
}
|
|
28921
29035
|
if (session.arm !== "agent" || plan.mode !== undefined && session.mode !== plan.mode) {
|
|
28922
|
-
throw new MutagentError("INVALID_RESPONSE", "The server started the session with a different arm or mode than requested.", "Session " + session.reference + " may still be running. Check:
|
|
29036
|
+
throw new MutagentError("INVALID_RESPONSE", "The server started the session with a different arm or mode than requested.", "Session " + session.reference + " may still be running. Check: " + activeProduct().cli + " session list");
|
|
28923
29037
|
}
|
|
28924
29038
|
write("[mutagent] " + JSON.stringify({ reference: session.reference, sessionId: session.reference, agent: session.agent, mode: session.mode }) + `
|
|
28925
29039
|
`);
|
|
@@ -28932,21 +29046,22 @@ async function runManagedAgentLaunch(launch, write = (line) => {
|
|
|
28932
29046
|
}
|
|
28933
29047
|
async function attachLaunched(session, rpc, interruptRequested) {
|
|
28934
29048
|
const reference = session.reference;
|
|
29049
|
+
const routes = activeProduct();
|
|
28935
29050
|
await runNativeSession({
|
|
28936
29051
|
reference,
|
|
28937
29052
|
sessionId: session.sessionId,
|
|
28938
29053
|
rpc,
|
|
28939
|
-
open: (options) =>
|
|
28940
|
-
send: (line, signal) =>
|
|
28941
|
-
closeInput: (signal) =>
|
|
28942
|
-
interrupt: (signal) =>
|
|
29054
|
+
open: (options) => openSessionStream(routes, reference, options),
|
|
29055
|
+
send: (line, signal) => sendSessionInput(routes, reference, line, signal),
|
|
29056
|
+
closeInput: (signal) => closeSessionInput(routes, reference, signal),
|
|
29057
|
+
interrupt: (signal) => signalSession(routes, reference, "SIGINT", signal),
|
|
28943
29058
|
interruptRequested
|
|
28944
29059
|
}).catch((error) => {
|
|
28945
29060
|
throw markStreamStarted(error);
|
|
28946
29061
|
});
|
|
28947
29062
|
}
|
|
28948
29063
|
|
|
28949
|
-
// src/commands/
|
|
29064
|
+
// src/commands/cloud-session/managed-agent.ts
|
|
28950
29065
|
init_errors();
|
|
28951
29066
|
var ADDRESS = /^@([a-z][a-z0-9-]{1,49})(?::(?:v([1-9]\d{0,8})|(latest)))?$/;
|
|
28952
29067
|
var MANAGED_AGENT_ARGS_MESSAGE = 'a managed agent takes its prompt, tools, skills and model from its package, so @slug accepts only -p "<task>" or --rpc';
|
|
@@ -28970,7 +29085,7 @@ function usage(message, recovery) {
|
|
|
28970
29085
|
function planManagedAgentRun(argv, flags) {
|
|
28971
29086
|
const [token, ...rest] = argv;
|
|
28972
29087
|
const address = parseManagedAgentAddress(token ?? "");
|
|
28973
|
-
const example =
|
|
29088
|
+
const example = `${activeProduct().cli} agent @${address.slug} -p "<task>"`;
|
|
28974
29089
|
if (flags.sandbox !== undefined) {
|
|
28975
29090
|
throw usage("a managed agent runs in a fresh sandbox the platform stages its package into, so --sandbox is refused", `Run: ${example}`);
|
|
28976
29091
|
}
|
|
@@ -28998,7 +29113,7 @@ function planManagedAgentRun(argv, flags) {
|
|
|
28998
29113
|
throw usage("-p needs the task text", `Run: ${example}`);
|
|
28999
29114
|
}
|
|
29000
29115
|
if (printSeen && flags.rpc === true) {
|
|
29001
|
-
throw usage("-p runs headless and --rpc runs interactive, so pass one of them", `Run: ${example} or
|
|
29116
|
+
throw usage("-p runs headless and --rpc runs interactive, so pass one of them", `Run: ${example} or ${activeProduct().cli} agent @${address.slug} --rpc`);
|
|
29002
29117
|
}
|
|
29003
29118
|
if (task !== undefined)
|
|
29004
29119
|
return { address, mode: "headless", task };
|
|
@@ -29212,11 +29327,93 @@ async function resolveFactoryDefault(name, explicit, usage, conn, env = process.
|
|
|
29212
29327
|
throw new MutagentError("MISSING_ARGUMENTS", why + unreadable + several, `Run: ${usage.command} --help`);
|
|
29213
29328
|
}
|
|
29214
29329
|
|
|
29215
|
-
// src/commands/
|
|
29330
|
+
// src/commands/cloud-session/product-guard.ts
|
|
29331
|
+
init_errors();
|
|
29332
|
+
var HARNESS_USE_PRODUCT_COMMAND = "HARNESS_USE_PRODUCT_COMMAND";
|
|
29333
|
+
var FIXED_HARNESS_REFUSED = {
|
|
29334
|
+
"--preset": (product) => `${product.cli} always runs the ${product.title} harness, so it takes no preset.`,
|
|
29335
|
+
"--sandbox": (product) => `${product.cli} always starts a new sandbox with the ${product.title} harness; an existing sandbox runs the harness it was built with.`
|
|
29336
|
+
};
|
|
29337
|
+
function flagOf(token) {
|
|
29338
|
+
const eq = token.indexOf("=");
|
|
29339
|
+
return eq === -1 ? token : token.slice(0, eq);
|
|
29340
|
+
}
|
|
29341
|
+
function fixedHarnessFlagRefusal(product, verb, argv) {
|
|
29342
|
+
if (product.preset === undefined)
|
|
29343
|
+
return;
|
|
29344
|
+
const token = argv.find((arg) => FIXED_HARNESS_REFUSED[flagOf(arg)] !== undefined);
|
|
29345
|
+
if (token === undefined)
|
|
29346
|
+
return;
|
|
29347
|
+
const flag = flagOf(token);
|
|
29348
|
+
const why = FIXED_HARNESS_REFUSED[flag]?.(product) ?? "";
|
|
29349
|
+
const command = verb === "" ? product.cli : `${product.cli} ${verb}`;
|
|
29350
|
+
return new MutagentError("UNKNOWN_OPTION", `unknown option '${flag}' for '${command}': ${why}`, `Drop ${flag}. See: ${command} --help`);
|
|
29351
|
+
}
|
|
29352
|
+
function splitPresets(argv) {
|
|
29353
|
+
const presets = [];
|
|
29354
|
+
const rest = [];
|
|
29355
|
+
for (let i = 0;i < argv.length; i++) {
|
|
29356
|
+
const token = argv[i] ?? "";
|
|
29357
|
+
if (token === "--preset") {
|
|
29358
|
+
const value = argv[i + 1];
|
|
29359
|
+
if (value !== undefined)
|
|
29360
|
+
presets.push(value);
|
|
29361
|
+
i++;
|
|
29362
|
+
continue;
|
|
29363
|
+
}
|
|
29364
|
+
if (token.startsWith("--preset=")) {
|
|
29365
|
+
presets.push(token.slice("--preset=".length));
|
|
29366
|
+
continue;
|
|
29367
|
+
}
|
|
29368
|
+
rest.push(token);
|
|
29369
|
+
}
|
|
29370
|
+
while (rest.length > 0 && rest[rest.length - 1] === "--")
|
|
29371
|
+
rest.pop();
|
|
29372
|
+
return { presets, rest };
|
|
29373
|
+
}
|
|
29374
|
+
function productPresetRefusal(product, verb, argv, bound = {}) {
|
|
29375
|
+
if (product.preset !== undefined)
|
|
29376
|
+
return;
|
|
29377
|
+
const { presets, rest } = splitPresets(argv);
|
|
29378
|
+
const owner = [bound.preset, ...presets].map(productOwningPreset).find((found) => found !== undefined && found !== product);
|
|
29379
|
+
if (owner === undefined)
|
|
29380
|
+
return;
|
|
29381
|
+
const carried = [];
|
|
29382
|
+
const valued = [
|
|
29383
|
+
[bound.sandboxProvider, "--sandbox-provider"],
|
|
29384
|
+
[bound.env, "--env"],
|
|
29385
|
+
[bound.cwd, "--cwd"],
|
|
29386
|
+
[bound.repository, "--repository"],
|
|
29387
|
+
[bound.branch, "--branch"],
|
|
29388
|
+
[bound.subject, "--subject"],
|
|
29389
|
+
[bound.stage, "--stage"]
|
|
29390
|
+
];
|
|
29391
|
+
for (const [value, flag] of valued)
|
|
29392
|
+
if (value !== undefined)
|
|
29393
|
+
carried.push(flag, value);
|
|
29394
|
+
if (bound.rpc === true)
|
|
29395
|
+
carried.push("--rpc");
|
|
29396
|
+
const words = [...rest, ...carried].map(shellWord);
|
|
29397
|
+
const head = verb === "" ? owner.cli : `${owner.cli} ${verb}`;
|
|
29398
|
+
const line = words.every((word) => word !== undefined) ? [head, ...words].join(" ") : undefined;
|
|
29399
|
+
const sandboxNamed = bound.sandbox !== undefined || rest.some((token) => flagOf(token) === "--sandbox");
|
|
29400
|
+
const runnable = line !== undefined && !sandboxNamed && isRunnableFixCommand(line);
|
|
29401
|
+
const launched = verb === "" ? product.cli : `${product.cli} ${verb}`;
|
|
29402
|
+
return new MutagentError(HARNESS_USE_PRODUCT_COMMAND, `${launched} does not launch the ${owner.title} harness: --preset ${owner.preset ?? ""} belongs to ${head}, which always runs it.`, runnable ? `Run: ${line}` : `Run the same launch with ${head}, without --preset${sandboxNamed ? " and without --sandbox (it always starts a new sandbox)" : ""}.`);
|
|
29403
|
+
}
|
|
29404
|
+
|
|
29405
|
+
// src/commands/cloud-session/agent.ts
|
|
29216
29406
|
var MISSING_TASK_MESSAGE = 'a cloud run needs a task: pass -p "<task>", or --rpc for an interactive session';
|
|
29217
29407
|
function registerAgentCommand(parent, registration, deps = defaultPlanDeps()) {
|
|
29218
29408
|
const jsonSource = registration?.jsonSource ?? parent;
|
|
29219
|
-
|
|
29409
|
+
const p = registration?.product ?? HELIX_PRODUCT;
|
|
29410
|
+
const fixed = p.preset !== undefined;
|
|
29411
|
+
const t = (text) => productText(text, p);
|
|
29412
|
+
const agent = parent.command("agent").description(t("Run a Helix agent in the cloud, or a managed agent by @slug")).argument("[argv...]", t("Agent definition, then the task and Helix flags; or @slug[:vN|:latest] for a managed agent")).allowUnknownOption(true).allowExcessArguments(true);
|
|
29413
|
+
if (!fixed) {
|
|
29414
|
+
agent.addOption(new Option("--sandbox <id>", "Run in an existing sandbox, by sandbox id").hideHelp()).option("--preset <name>", "Sandbox preset (not with --sandbox)");
|
|
29415
|
+
}
|
|
29416
|
+
agent.option("--sandbox-provider <name>", "Run on this configured sandbox provider").option("--env <name>", "Workspace Environment to load for this run (see mutagent env list)").option("--rpc", "Read JSON commands on stdin; write events on stdout").option("--cwd <path>", "Working directory in the sandbox").option("--repository <owner/name>", `Native brief only: run in a checkout of this GitHub repository (not with ${fixed ? "--cwd" : "--sandbox or --cwd"})`).option("--branch <name>", "Branch of --repository to check out (default: its default branch)").option("--subject <id>", "Native brief only: bind the session to this Factory entry (with or without --stage)").option("--stage <stage>", `The platform opens a stage run first (${FACTORY_STAGES.join("|")}); the entry is --subject, else inferred`).addHelpText("after", t([
|
|
29220
29417
|
"",
|
|
29221
29418
|
"Examples:",
|
|
29222
29419
|
' mutagent helix agent @invoice-pricing --env prod -p "Price three widget units."',
|
|
@@ -29271,8 +29468,15 @@ function registerAgentCommand(parent, registration, deps = defaultPlanDeps()) {
|
|
|
29271
29468
|
" --repository <owner/name> [--branch <name>]; the checkout is the working directory. @slug refuses it.",
|
|
29272
29469
|
" On a refusal, show the returned fix: the Run: lines, the notes, and who has to act; do not invent other commands."
|
|
29273
29470
|
].join(`
|
|
29274
|
-
`)).action(async (argv, options) => {
|
|
29471
|
+
`))).action(async (argv, options) => {
|
|
29275
29472
|
const isJson = getJsonFlag(jsonSource);
|
|
29473
|
+
const productRefusal = fixedHarnessFlagRefusal(p, "agent", argv) ?? productPresetRefusal(p, "agent", argv, options);
|
|
29474
|
+
if (productRefusal !== undefined) {
|
|
29475
|
+
handleLaunchFailure(productRefusal, {
|
|
29476
|
+
isJson: isJson && !hasNativeMode(argv) && options.rpc !== true,
|
|
29477
|
+
machine: options.rpc === true || isMachineMode(argv)
|
|
29478
|
+
});
|
|
29479
|
+
}
|
|
29276
29480
|
const factoryRefusal = factoryLaunchRefusal(argv, options);
|
|
29277
29481
|
if (factoryRefusal !== undefined) {
|
|
29278
29482
|
handleLaunchFailure(factoryRefusal, {
|
|
@@ -29293,7 +29497,7 @@ function registerAgentCommand(parent, registration, deps = defaultPlanDeps()) {
|
|
|
29293
29497
|
await runManagedAgentLaunch({
|
|
29294
29498
|
plan,
|
|
29295
29499
|
...options.env === undefined ? {} : { environment: options.env },
|
|
29296
|
-
...
|
|
29500
|
+
...presetOf(p, options.preset),
|
|
29297
29501
|
...options.sandboxProvider === undefined ? {} : { sandboxProvider: options.sandboxProvider }
|
|
29298
29502
|
});
|
|
29299
29503
|
} catch (error) {
|
|
@@ -29302,7 +29506,7 @@ function registerAgentCommand(parent, registration, deps = defaultPlanDeps()) {
|
|
|
29302
29506
|
return;
|
|
29303
29507
|
}
|
|
29304
29508
|
try {
|
|
29305
|
-
const plan = planAgentArgv(argv, deps, { own:
|
|
29509
|
+
const plan = planAgentArgv(argv, deps, { own: agentOwnFlags(p), verb: `\`${p.cli} agent\`` });
|
|
29306
29510
|
const opts = withPlannedFlags(options, plan.own);
|
|
29307
29511
|
if (!plan.print && !hasNativeMode(plan.nativeArgs) && !opts.rpc) {
|
|
29308
29512
|
throw new MutagentError("MISSING_ARGUMENTS", MISSING_TASK_MESSAGE, taskRecovery(plan));
|
|
@@ -29310,14 +29514,14 @@ function registerAgentCommand(parent, registration, deps = defaultPlanDeps()) {
|
|
|
29310
29514
|
const mode = nativeMode(plan.nativeArgs, plan.print, opts.rpc);
|
|
29311
29515
|
const taskNotices = nativeTaskNotices(mode, plan.messages);
|
|
29312
29516
|
checkArgsForRoute(plan.nativeArgs, plan.inlined);
|
|
29313
|
-
const factory = await factoryTarget(opts);
|
|
29517
|
+
const factory = await factoryTarget(opts, p);
|
|
29314
29518
|
for (const notice of [...plan.notices, ...taskNotices])
|
|
29315
29519
|
process.stderr.write("[mutagent] " + notice + `
|
|
29316
29520
|
`);
|
|
29317
29521
|
await runCloudLaunch({
|
|
29318
29522
|
arm: "agent",
|
|
29319
29523
|
...opts.sandbox === undefined ? {} : { sandbox: opts.sandbox },
|
|
29320
|
-
...
|
|
29524
|
+
...presetOf(p, opts.preset),
|
|
29321
29525
|
...opts.sandboxProvider === undefined ? {} : { sandboxProvider: opts.sandboxProvider },
|
|
29322
29526
|
...opts.env === undefined ? {} : { environment: opts.env },
|
|
29323
29527
|
...opts.cwd === undefined ? {} : { cwd: opts.cwd },
|
|
@@ -29338,6 +29542,13 @@ function registerAgentCommand(parent, registration, deps = defaultPlanDeps()) {
|
|
|
29338
29542
|
}
|
|
29339
29543
|
});
|
|
29340
29544
|
}
|
|
29545
|
+
function presetOf(p, requested) {
|
|
29546
|
+
const preset = p.preset ?? requested;
|
|
29547
|
+
return preset === undefined ? {} : { preset };
|
|
29548
|
+
}
|
|
29549
|
+
function agentOwnFlags(p) {
|
|
29550
|
+
return p.preset === undefined ? TRANSPORT_ONLY_FLAGS : TRANSPORT_ONLY_FLAGS.filter((flag) => flag !== "--preset" && flag !== "--sandbox");
|
|
29551
|
+
}
|
|
29341
29552
|
function factoryLaunchRefusal(argv, options) {
|
|
29342
29553
|
const { subject, stage } = options;
|
|
29343
29554
|
if (subject === undefined && stage === undefined)
|
|
@@ -29350,15 +29561,15 @@ function factoryLaunchRefusal(argv, options) {
|
|
|
29350
29561
|
}
|
|
29351
29562
|
return;
|
|
29352
29563
|
}
|
|
29353
|
-
async function factoryTarget(opts) {
|
|
29564
|
+
async function factoryTarget(opts, p) {
|
|
29354
29565
|
if (opts.stage === undefined)
|
|
29355
29566
|
return opts.subject === undefined ? undefined : { subject: opts.subject };
|
|
29356
|
-
const subject = await resolveFactoryDefault("subject", opts.subject, { what: "--subject <id>", command:
|
|
29567
|
+
const subject = await resolveFactoryDefault("subject", opts.subject, { what: "--subject <id>", command: `${p.cli} agent` }, connectPlatform);
|
|
29357
29568
|
return { subject, stage: opts.stage };
|
|
29358
29569
|
}
|
|
29359
29570
|
function taskRecovery(plan) {
|
|
29360
29571
|
if (plan.source === undefined) {
|
|
29361
|
-
return 'Run: mutagent helix agent --prompt "<who the agent is>" -p "<what to do>"\nThe positional is the DEFINITION, not the task — same as the local `helix agent`.';
|
|
29572
|
+
return productCopy('Run: mutagent helix agent --prompt "<who the agent is>" -p "<what to do>"\nThe positional is the DEFINITION, not the task — same as the local `helix agent`.');
|
|
29362
29573
|
}
|
|
29363
29574
|
return `The definition is set (${plan.origin}); the task is not. Add: -p "<what to do>"`;
|
|
29364
29575
|
}
|
|
@@ -29391,13 +29602,16 @@ function withPlannedFlags(options, own) {
|
|
|
29391
29602
|
};
|
|
29392
29603
|
}
|
|
29393
29604
|
|
|
29394
|
-
// src/commands/
|
|
29605
|
+
// src/commands/cloud-session/launcher-argv.ts
|
|
29395
29606
|
init_errors();
|
|
29396
29607
|
var LAUNCHER_OWN_FLAGS = ["--sandbox", "--preset", "--sandbox-provider", "--cwd", "--env", "--rpc", "--repository", "--branch"];
|
|
29608
|
+
function launcherOwnFlags(product) {
|
|
29609
|
+
return product.preset === undefined ? LAUNCHER_OWN_FLAGS : LAUNCHER_OWN_FLAGS.filter((flag) => flag !== "--preset" && flag !== "--sandbox");
|
|
29610
|
+
}
|
|
29397
29611
|
function rejection2(token, reason, alternative) {
|
|
29398
|
-
return new MutagentError("NOT_SUPPORTED", `${token} is not supported in a cloud run: ${reason}`, alternative);
|
|
29612
|
+
return new MutagentError("NOT_SUPPORTED", `${token} is not supported in a cloud run: ${reason}`, productCopy(alternative));
|
|
29399
29613
|
}
|
|
29400
|
-
function planLauncherArgv(argv, deps = defaultPlanDeps()) {
|
|
29614
|
+
function planLauncherArgv(argv, deps = defaultPlanDeps(), ownFlags = LAUNCHER_OWN_FLAGS) {
|
|
29401
29615
|
let arm = "classic";
|
|
29402
29616
|
let task;
|
|
29403
29617
|
let sandbox;
|
|
@@ -29424,7 +29638,7 @@ function planLauncherArgv(argv, deps = defaultPlanDeps()) {
|
|
|
29424
29638
|
continue;
|
|
29425
29639
|
if (token === "--")
|
|
29426
29640
|
continue;
|
|
29427
|
-
const mine = readOwnFlag(argv, i,
|
|
29641
|
+
const mine = readOwnFlag(argv, i, ownFlags, "the classic and prime arms");
|
|
29428
29642
|
if (mine !== undefined) {
|
|
29429
29643
|
if (mine.flag === "--rpc")
|
|
29430
29644
|
rpc = true;
|
|
@@ -29487,7 +29701,7 @@ function planLauncherArgv(argv, deps = defaultPlanDeps()) {
|
|
|
29487
29701
|
}
|
|
29488
29702
|
const cls = entry.launcherClass ?? entry.class;
|
|
29489
29703
|
if (cls === "reject") {
|
|
29490
|
-
throw rejection2(token, entry
|
|
29704
|
+
throw rejection2(token, reasonFor(entry), alternativeFor(entry));
|
|
29491
29705
|
}
|
|
29492
29706
|
let value = "";
|
|
29493
29707
|
if (entry.takesValue) {
|
|
@@ -29513,14 +29727,14 @@ function planLauncherArgv(argv, deps = defaultPlanDeps()) {
|
|
|
29513
29727
|
forwardFlag(token, read.text);
|
|
29514
29728
|
continue;
|
|
29515
29729
|
}
|
|
29516
|
-
throw rejection2(token, "it names an agent definition, and the classic arm has no agent to define", `Use the agent arm instead:
|
|
29730
|
+
throw rejection2(token, "it names an agent definition, and the classic arm has no agent to define", `Use the agent arm instead: ${activeProduct().cli} agent ${token} ${redactToken(value)} -p "<task>"`);
|
|
29517
29731
|
case "cross":
|
|
29518
29732
|
if (token === "--prime") {
|
|
29519
29733
|
arm = "prime";
|
|
29520
29734
|
continue;
|
|
29521
29735
|
}
|
|
29522
29736
|
if (token === "--prompt") {
|
|
29523
|
-
throw rejection2(token, "it supplies an agent definition, and the classic arm has no agent to define",
|
|
29737
|
+
throw rejection2(token, "it supplies an agent definition, and the classic arm has no agent to define", `Use the agent arm instead: ${activeProduct().cli} agent --prompt "<who>" -p "<task>"`);
|
|
29524
29738
|
}
|
|
29525
29739
|
forwardFlag(token);
|
|
29526
29740
|
if (entry.takesValue)
|
|
@@ -29548,7 +29762,7 @@ function planLauncherArgv(argv, deps = defaultPlanDeps()) {
|
|
|
29548
29762
|
};
|
|
29549
29763
|
}
|
|
29550
29764
|
|
|
29551
|
-
// src/commands/
|
|
29765
|
+
// src/commands/cloud-session/session-commands.ts
|
|
29552
29766
|
init_output();
|
|
29553
29767
|
init_errors();
|
|
29554
29768
|
import { Command as Command13, Option as Option4 } from "commander";
|
|
@@ -29971,7 +30185,7 @@ function parseSince(raw) {
|
|
|
29971
30185
|
return value;
|
|
29972
30186
|
}
|
|
29973
30187
|
|
|
29974
|
-
// src/lib/
|
|
30188
|
+
// src/lib/sandbox-session-gone.ts
|
|
29975
30189
|
init_errors();
|
|
29976
30190
|
var GONE_STATUSES = new Set([404, 410]);
|
|
29977
30191
|
var CONSEQUENCE = {
|
|
@@ -29980,19 +30194,21 @@ var CONSEQUENCE = {
|
|
|
29980
30194
|
stream: "it can't be attached to",
|
|
29981
30195
|
input: "it can't take input"
|
|
29982
30196
|
};
|
|
29983
|
-
|
|
30197
|
+
function newSessionCommands(cli = activeProduct().cli) {
|
|
30198
|
+
return [`${cli} -p "<task>"`, `${cli} --mode rpc`];
|
|
30199
|
+
}
|
|
29984
30200
|
|
|
29985
30201
|
class SessionSandboxGoneError extends MutagentError {
|
|
29986
30202
|
serverMessage;
|
|
29987
30203
|
constructor(code, reference, route, serverMessage) {
|
|
29988
|
-
super(code, `The sandbox of ${sessionLabel(reference) === reference ? `session ${reference}` : "this session"} was deleted, so ${CONSEQUENCE[route]}.`, `Start a new session: ${
|
|
30204
|
+
super(code, `The sandbox of ${sessionLabel(reference) === reference ? `session ${reference}` : "this session"} was deleted, so ${CONSEQUENCE[route]}.`, `Start a new session: ${newSessionCommands()[0]} or ${newSessionCommands()[1]}`);
|
|
29989
30205
|
this.serverMessage = serverMessage;
|
|
29990
30206
|
this.name = "SessionSandboxGoneError";
|
|
29991
30207
|
}
|
|
29992
30208
|
toJSON() {
|
|
29993
30209
|
return {
|
|
29994
30210
|
...super.toJSON(),
|
|
29995
|
-
_agentGuidance: { fix: [...
|
|
30211
|
+
_agentGuidance: { fix: [...newSessionCommands()], notes: [`The server answered: ${redactSandboxIds(this.serverMessage)}`] }
|
|
29996
30212
|
};
|
|
29997
30213
|
}
|
|
29998
30214
|
}
|
|
@@ -30002,13 +30218,14 @@ function sessionGoneGuidance(error, route, reference) {
|
|
|
30002
30218
|
return new SessionSandboxGoneError(error.code, reference, route, error.message);
|
|
30003
30219
|
}
|
|
30004
30220
|
|
|
30005
|
-
// src/commands/
|
|
30221
|
+
// src/commands/cloud-session/restore-command.ts
|
|
30006
30222
|
init_output();
|
|
30007
30223
|
init_errors();
|
|
30008
30224
|
import chalk25 from "chalk";
|
|
30009
30225
|
var DRIFT_MODES = ["warn", "refuse", "skip"];
|
|
30010
|
-
function registerRestore(session, root) {
|
|
30011
|
-
|
|
30226
|
+
function registerRestore(session, root, p = HELIX_PRODUCT) {
|
|
30227
|
+
const t = (text) => productText(text, p);
|
|
30228
|
+
session.command("restore").description("Continue a session from a checkpoint in a rebuilt sandbox").argument("<reference>", t("Session reference (hs1_...) from 'mutagent helix' or 'session list'; the session may be stopped")).option("--snapshot <id>", "Checkpoint to use, from 'session checkpoints' (default: the newest complete one from this session's sandbox)").option("--on-drift <mode>", `If files the conversation names are missing: ${DRIFT_MODES.join(" | ")} (default: warn)`).option("--partial", "Also restore turns saved after the checkpoint (may end mid tool call)").addHelpText("after", t(`
|
|
30012
30229
|
Examples:
|
|
30013
30230
|
${chalk25.dim("$")} mutagent helix session restore <reference>
|
|
30014
30231
|
${chalk25.dim("$")} mutagent helix session restore <reference> --snapshot snap_1
|
|
@@ -30037,7 +30254,7 @@ AI Agent Directive:
|
|
|
30037
30254
|
partial, partialBytes, skippedSnapshots }. 'reference' is the NEW session:
|
|
30038
30255
|
use it for attach, send, signal and checkpoint. Read notRestored before
|
|
30039
30256
|
relying on the restored state.
|
|
30040
|
-
`).action(async (reference, options) => {
|
|
30257
|
+
`)).action(async (reference, options) => {
|
|
30041
30258
|
const isJson = getJsonFlag(root);
|
|
30042
30259
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
30043
30260
|
try {
|
|
@@ -30047,17 +30264,17 @@ AI Agent Directive:
|
|
|
30047
30264
|
...options.onDrift === undefined ? {} : { onWorkspaceDrift: parseDriftMode(options.onDrift) },
|
|
30048
30265
|
...options.partial === true ? { partial: true } : {}
|
|
30049
30266
|
};
|
|
30050
|
-
const result = await
|
|
30267
|
+
const result = await restoreSession(p, reference, body);
|
|
30051
30268
|
if (isJson) {
|
|
30052
30269
|
output.output({
|
|
30053
30270
|
success: true,
|
|
30054
30271
|
...result,
|
|
30055
|
-
_links: { api:
|
|
30272
|
+
_links: { api: sessionPath(p, result.reference) },
|
|
30056
30273
|
_directive: {
|
|
30057
30274
|
instruction: "The sandbox has been rebuilt and the agent is continuing the checkpoint’s conversation. Use the NEW reference.",
|
|
30058
30275
|
next: [
|
|
30059
|
-
`mutagent helix session attach ${result.reference} --since ${String(result.seq)}
|
|
30060
|
-
`mutagent helix session send ${result.reference} "<message>" --json`
|
|
30276
|
+
productCopy(`mutagent helix session attach ${result.reference} --since ${String(result.seq)}`),
|
|
30277
|
+
productCopy(`mutagent helix session send ${result.reference} "<message>" --json`)
|
|
30061
30278
|
]
|
|
30062
30279
|
}
|
|
30063
30280
|
});
|
|
@@ -30093,12 +30310,13 @@ function parseDriftMode(raw) {
|
|
|
30093
30310
|
throw new MutagentError("INVALID_ARGUMENTS", `--on-drift must be one of ${DRIFT_MODES.join(", ")}, got "${raw}".`, "warn restores and reports; refuse fails before switching; skip does not probe.");
|
|
30094
30311
|
}
|
|
30095
30312
|
|
|
30096
|
-
// src/commands/
|
|
30313
|
+
// src/commands/cloud-session/reference-commands.ts
|
|
30097
30314
|
init_output();
|
|
30098
30315
|
init_errors();
|
|
30099
30316
|
import chalk26 from "chalk";
|
|
30100
|
-
function registerCheckpoints(session, root) {
|
|
30101
|
-
|
|
30317
|
+
function registerCheckpoints(session, root, p = HELIX_PRODUCT) {
|
|
30318
|
+
const t = (text) => productText(text, p);
|
|
30319
|
+
session.command("checkpoints").description("List the checkpoints of the sandbox a session runs in").argument("<reference>", t("Session reference (hs1_...) from 'mutagent helix' or 'session list'")).addHelpText("after", t(`
|
|
30102
30320
|
Examples:
|
|
30103
30321
|
${chalk26.dim("$")} mutagent helix session checkpoints <reference>
|
|
30104
30322
|
${chalk26.dim("$")} mutagent helix session checkpoints <reference> --json
|
|
@@ -30111,19 +30329,19 @@ Pass an id to 'mutagent helix session restore <reference> --snapshot <id>'.
|
|
|
30111
30329
|
AI Agent Directive:
|
|
30112
30330
|
--json returns { snapshots: [...], count: N, reference }. Read it to find a
|
|
30113
30331
|
'snapshotId' (the row's id) for 'restore'.
|
|
30114
|
-
`).action(async (reference) => {
|
|
30332
|
+
`)).action(async (reference) => {
|
|
30115
30333
|
const isJson = getJsonFlag(root);
|
|
30116
30334
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
30117
30335
|
try {
|
|
30118
|
-
const { snapshots } = await
|
|
30336
|
+
const { snapshots } = await listSessionCheckpoints(p, reference);
|
|
30119
30337
|
if (isJson) {
|
|
30120
|
-
output.output({ snapshots, count: snapshots.length, reference, _links: { api:
|
|
30338
|
+
output.output({ snapshots, count: snapshots.length, reference, _links: { api: sessionPath(p, reference) + "/checkpoints" } });
|
|
30121
30339
|
return;
|
|
30122
30340
|
}
|
|
30123
30341
|
if (snapshots.length === 0) {
|
|
30124
30342
|
console.log(chalk26.gray("No checkpoints captured from this session's sandbox."));
|
|
30125
30343
|
console.log("");
|
|
30126
|
-
console.log(` Capture one: mutagent helix session checkpoint ${reference}`);
|
|
30344
|
+
console.log(productCopy(` Capture one: mutagent helix session checkpoint ${reference}`));
|
|
30127
30345
|
return;
|
|
30128
30346
|
}
|
|
30129
30347
|
output.output(snapshots.map((snapshot) => ({
|
|
@@ -30138,8 +30356,9 @@ AI Agent Directive:
|
|
|
30138
30356
|
}
|
|
30139
30357
|
});
|
|
30140
30358
|
}
|
|
30141
|
-
function registerCloseInput(session, root) {
|
|
30142
|
-
|
|
30359
|
+
function registerCloseInput(session, root, p = HELIX_PRODUCT) {
|
|
30360
|
+
const t = (text) => productText(text, p);
|
|
30361
|
+
session.command("close-input").description("Close a session's input (end of stdin)").argument("<reference>", t("Session reference (hs1_...) from 'mutagent helix' or 'session list'")).addHelpText("after", t(`
|
|
30143
30362
|
Examples:
|
|
30144
30363
|
${chalk26.dim("$")} mutagent helix session close-input <reference>
|
|
30145
30364
|
${chalk26.dim("$")} mutagent helix session close-input <reference> --json
|
|
@@ -30152,11 +30371,11 @@ close-input support answers 422.
|
|
|
30152
30371
|
AI Agent Directive:
|
|
30153
30372
|
--json returns { success, reference, closed }. This is not a signal: use
|
|
30154
30373
|
'mutagent helix session signal <reference> --force' to interrupt a turn.
|
|
30155
|
-
`).action(async (reference) => {
|
|
30374
|
+
`)).action(async (reference) => {
|
|
30156
30375
|
const isJson = getJsonFlag(root);
|
|
30157
30376
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
30158
30377
|
try {
|
|
30159
|
-
const result = await
|
|
30378
|
+
const result = await closeSessionInput(p, reference);
|
|
30160
30379
|
if (isJson)
|
|
30161
30380
|
output.output({ success: true, reference, closed: result.closed });
|
|
30162
30381
|
else
|
|
@@ -30167,9 +30386,8 @@ AI Agent Directive:
|
|
|
30167
30386
|
});
|
|
30168
30387
|
}
|
|
30169
30388
|
|
|
30170
|
-
// src/commands/
|
|
30389
|
+
// src/commands/cloud-session/end-access.ts
|
|
30171
30390
|
import chalk27 from "chalk";
|
|
30172
|
-
import { helixSessionsEndHelixSession } from "@mutagent/sdk/funcs/helix-sessions-end-helix-session.js";
|
|
30173
30391
|
init_errors();
|
|
30174
30392
|
init_output();
|
|
30175
30393
|
var NOT_ENDED_CODES = new Set(["AUTH_EXPIRED", "AUTH_REQUIRED", "WORKSPACE_REQUIRED", "SANDBOX_TOKEN_REFUSED", "TENANCY_DENIED", "WORKSPACE_KEY_MISMATCH", "CONFIRMATION_REQUIRED", "MISSING_ARGUMENTS"]);
|
|
@@ -30183,17 +30401,20 @@ function notEnded(reference, error) {
|
|
|
30183
30401
|
return error;
|
|
30184
30402
|
const label = sessionLabel(reference);
|
|
30185
30403
|
if (label === reference) {
|
|
30186
|
-
return new MutagentError("SESSION_END_FAILED", `${reference} was not ended: ${error.message}`, `Run: mutagent helix session end ${reference} --force`);
|
|
30404
|
+
return new MutagentError("SESSION_END_FAILED", `${reference} was not ended: ${error.message}`, productCopy(`Run: mutagent helix session end ${reference} --force`));
|
|
30187
30405
|
}
|
|
30188
|
-
return new MutagentError("SESSION_END_FAILED", `${label} was not ended: ${error.message}. A session is ended by its hs1_ session id: find it in session list, then run mutagent helix session end <hs1_ref> --force
|
|
30406
|
+
return new MutagentError("SESSION_END_FAILED", productCopy(`${label} was not ended: ${error.message}. A session is ended by its hs1_ session id: find it in session list, then run mutagent helix session end <hs1_ref> --force.`), productCopy("Run: mutagent helix session list --json"));
|
|
30189
30407
|
}
|
|
30190
|
-
async function end(reference) {
|
|
30408
|
+
async function end(p, reference) {
|
|
30191
30409
|
if (resolveCredential().kind !== "sandbox-token")
|
|
30192
|
-
return
|
|
30193
|
-
|
|
30194
|
-
|
|
30195
|
-
|
|
30196
|
-
|
|
30410
|
+
return endSession(p, reference);
|
|
30411
|
+
const conn = await connectPlatform();
|
|
30412
|
+
const help = productCopy("mutagent helix session end --help", p);
|
|
30413
|
+
return onSessionRoute(p, (base) => rawJson(conn, "POST", `${base}/${encodeURIComponent(reference)}/end`, { body: {}, help }));
|
|
30414
|
+
}
|
|
30415
|
+
function registerEnd(session, root, p = HELIX_PRODUCT) {
|
|
30416
|
+
const t = (text) => productText(text, p);
|
|
30417
|
+
session.command("end").description(t("End a Helix session and remove its sandbox, addressed by its hs1_ session id")).argument("[reference]", t("The Helix session id (hs1_…); in a sandbox, its own session")).option("-f, --force", "Confirm the end (required in every mode, --json included): ending removes the sandbox").addHelpText("after", t(`
|
|
30197
30418
|
Examples:
|
|
30198
30419
|
${chalk27.dim("$")} mutagent helix session end hs1_8f2c41d07a --force
|
|
30199
30420
|
${chalk27.dim("$")} mutagent helix session end hs1_8f2c41d07a --force --json
|
|
@@ -30211,16 +30432,16 @@ Errors (code: recovery):
|
|
|
30211
30432
|
AI Agent Directive:
|
|
30212
30433
|
Destructive: the sandbox and its files are removed. Confirm with the user, then pass --force.
|
|
30213
30434
|
--json returns { success, session, ended, sandboxRemoved, checkpointSkipped }.
|
|
30214
|
-
`).action(async (reference, options) => {
|
|
30435
|
+
`)).action(async (reference, options) => {
|
|
30215
30436
|
const isJson = getJsonFlag(root);
|
|
30216
30437
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
30217
30438
|
let ref = reference ?? "<hs1_ref>";
|
|
30218
30439
|
try {
|
|
30219
|
-
requireForce(options, { what: `Ending session ${ref}`, verb: "mutagent helix session end", command: `mutagent helix session end ${ref}` });
|
|
30220
|
-
ref = await resolveFactoryDefault("session", reference, { what: "the hs1_ session id", command: "mutagent helix session end" }, connectPlatform);
|
|
30440
|
+
requireForce(options, { what: `Ending session ${ref}`, verb: productCopy("mutagent helix session end"), command: productCopy(`mutagent helix session end ${ref}`) });
|
|
30441
|
+
ref = await resolveFactoryDefault("session", reference, { what: "the hs1_ session id", command: productCopy("mutagent helix session end") }, connectPlatform);
|
|
30221
30442
|
let result;
|
|
30222
30443
|
try {
|
|
30223
|
-
result = await end(ref);
|
|
30444
|
+
result = await end(p, ref);
|
|
30224
30445
|
} catch (error) {
|
|
30225
30446
|
if (!alreadyGone(error))
|
|
30226
30447
|
throw notEnded(ref, error);
|
|
@@ -30235,8 +30456,9 @@ AI Agent Directive:
|
|
|
30235
30456
|
}
|
|
30236
30457
|
});
|
|
30237
30458
|
}
|
|
30238
|
-
function registerAccess(helix) {
|
|
30239
|
-
|
|
30459
|
+
function registerAccess(helix, p = HELIX_PRODUCT) {
|
|
30460
|
+
const t = (text) => productText(text, p);
|
|
30461
|
+
helix.command("access").description("Whether this account may use cloud sandboxes, and why not").addHelpText("after", t(`
|
|
30240
30462
|
Examples:
|
|
30241
30463
|
${chalk27.dim("$")} mutagent helix access
|
|
30242
30464
|
${chalk27.dim("$")} mutagent helix access --json
|
|
@@ -30249,12 +30471,12 @@ Errors (code: recovery):
|
|
|
30249
30471
|
AI Agent Directive:
|
|
30250
30472
|
A read: run it before a cloud launch. --json returns { success, allowed, reason?, fix? };
|
|
30251
30473
|
allowed false is a successful answer: show the reason and who can fix it.
|
|
30252
|
-
`).action(async () => {
|
|
30474
|
+
`)).action(async () => {
|
|
30253
30475
|
const isJson = getJsonFlag(helix);
|
|
30254
30476
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
30255
30477
|
try {
|
|
30256
30478
|
const inSandbox = runLocation() !== "local" && resolveCredential().kind === "sandbox-token";
|
|
30257
|
-
const allowed = inSandbox ? true : await
|
|
30479
|
+
const allowed = inSandbox ? true : await getCloudAccess().then((a) => a.cloudSandboxes, (error) => {
|
|
30258
30480
|
if (error instanceof ApiError && error.statusCode === 404)
|
|
30259
30481
|
return true;
|
|
30260
30482
|
throw error;
|
|
@@ -30273,7 +30495,7 @@ AI Agent Directive:
|
|
|
30273
30495
|
});
|
|
30274
30496
|
}
|
|
30275
30497
|
|
|
30276
|
-
// src/commands/
|
|
30498
|
+
// src/commands/cloud-session/session-start-argv.ts
|
|
30277
30499
|
var SESSION_START_OWN_FLAGS = ["--rpc", "--cwd", "--env"];
|
|
30278
30500
|
function planSessionStartArgs(argv, deps) {
|
|
30279
30501
|
const plan = planAgentArgv(argv, deps, { own: SESSION_START_OWN_FLAGS, verb: "`mutagent helix session start`" });
|
|
@@ -30287,7 +30509,7 @@ function planSessionStartArgs(argv, deps) {
|
|
|
30287
30509
|
return { args, notices: plan.notices, own: plan.own };
|
|
30288
30510
|
}
|
|
30289
30511
|
|
|
30290
|
-
// src/commands/
|
|
30512
|
+
// src/commands/cloud-session/send.ts
|
|
30291
30513
|
init_output();
|
|
30292
30514
|
init_errors();
|
|
30293
30515
|
import { Option as Option2 } from "commander";
|
|
@@ -30297,7 +30519,9 @@ var COMMAND_TYPES = ["prompt", "steer", "follow_up", "abort"];
|
|
|
30297
30519
|
var NEEDS_MESSAGE = new Set(["prompt", "steer", "follow_up"]);
|
|
30298
30520
|
function registerSendCommand(parent, registration) {
|
|
30299
30521
|
const jsonSource = registration?.jsonSource ?? parent;
|
|
30300
|
-
|
|
30522
|
+
const p = registration?.product ?? HELIX_PRODUCT;
|
|
30523
|
+
const t = (text) => productText(text, p);
|
|
30524
|
+
parent.command("send").description("Send a prompt or command to a session").argument("<reference>", "Session reference (hs1_...)").argument("[message...]", "What to say to the agent").addOption(new Option2("--session <id>", "The session id, when the first argument is a sandbox id").hideHelp()).option("--type <type>", `${COMMAND_TYPES.join(" | ")} (default: prompt)`).option("--line <json>", "Send this exact JSON command instead of building one").option("--message-id <id>", "Use this command id instead of a generated one").addHelpText("after", t(`
|
|
30301
30525
|
Examples:
|
|
30302
30526
|
${chalk28.dim("$")} mutagent helix session send <reference> "also check the refresh path"
|
|
30303
30527
|
${chalk28.dim("$")} mutagent helix session send <reference> --type steer "stop and re-read the spec"
|
|
@@ -30332,22 +30556,22 @@ AI Agent Directive:
|
|
|
30332
30556
|
being restored and the message is not delivered yet; the stream reports the
|
|
30333
30557
|
delivery, or the failed restore and the message it lost. Use --type and a message; use --line only for a
|
|
30334
30558
|
command the four types cannot express.
|
|
30335
|
-
`).action(async (id, messageParts, options) => {
|
|
30559
|
+
`)).action(async (id, messageParts, options) => {
|
|
30336
30560
|
const isJson = getJsonFlag(jsonSource);
|
|
30337
30561
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
30338
30562
|
try {
|
|
30339
30563
|
if (options.session === undefined) {
|
|
30340
30564
|
const built = buildLine(messageParts.join(" ").trim(), options);
|
|
30341
|
-
const result = await
|
|
30565
|
+
const result = await sendSessionInput(p, id, built.line);
|
|
30342
30566
|
if (queuedForWake(result)) {
|
|
30343
|
-
const watch = `mutagent helix session attach ${id}
|
|
30567
|
+
const watch = productCopy(`mutagent helix session attach ${id}`);
|
|
30344
30568
|
if (isJson) {
|
|
30345
30569
|
output.output({
|
|
30346
30570
|
success: true,
|
|
30347
30571
|
reference: id,
|
|
30348
30572
|
...built,
|
|
30349
30573
|
...result,
|
|
30350
|
-
_links: { api:
|
|
30574
|
+
_links: { api: sessionPath(p, id) },
|
|
30351
30575
|
_directive: {
|
|
30352
30576
|
instruction: "Queued, not delivered yet: the session is being restored from its checkpoint. The stream reports the delivery, or a failed restore.",
|
|
30353
30577
|
next: [watch]
|
|
@@ -30360,17 +30584,17 @@ AI Agent Directive:
|
|
|
30360
30584
|
return;
|
|
30361
30585
|
}
|
|
30362
30586
|
if (!result.accepted) {
|
|
30363
|
-
throw new MutagentError("RPC_INPUT_REJECTED", "The session did not accept the command.", "Check the session: mutagent helix session list");
|
|
30587
|
+
throw new MutagentError("RPC_INPUT_REJECTED", "The session did not accept the command.", productCopy("Check the session: mutagent helix session list"));
|
|
30364
30588
|
}
|
|
30365
30589
|
if (isJson)
|
|
30366
|
-
output.output({ success: result.accepted, reference: id, ...built, ...result, _links: { api:
|
|
30590
|
+
output.output({ success: result.accepted, reference: id, ...built, ...result, _links: { api: sessionPath(p, id) } });
|
|
30367
30591
|
else
|
|
30368
30592
|
output.success("Sent " + built.type + " to " + id + "; the reply arrives on the session stream.");
|
|
30369
30593
|
return;
|
|
30370
30594
|
}
|
|
30371
30595
|
const sessionId = options.session.trim();
|
|
30372
30596
|
if (sessionId === "") {
|
|
30373
|
-
throw new MutagentError("MISSING_ARGUMENTS", "--session is required — a sandbox can hold more than one session.", `Run: mutagent helix session send ${id} --session <session-id> "<message>"`);
|
|
30597
|
+
throw new MutagentError("MISSING_ARGUMENTS", "--session is required — a sandbox can hold more than one session.", productCopy(`Run: mutagent helix session send ${id} --session <session-id> "<message>"`));
|
|
30374
30598
|
}
|
|
30375
30599
|
const built = buildLine(messageParts.join(" ").trim(), options);
|
|
30376
30600
|
const result = await postInput(id, { sessionId, line: built.line });
|
|
@@ -30413,7 +30637,7 @@ function buildLine(message, options) {
|
|
|
30413
30637
|
throw new MutagentError("INVALID_ARGUMENTS", `Unknown command type "${options.type ?? ""}".`, `Use one of: ${COMMAND_TYPES.join(", ")}. For anything else, pass the raw JSON with --line.`);
|
|
30414
30638
|
}
|
|
30415
30639
|
if (message === "" && NEEDS_MESSAGE.has(type)) {
|
|
30416
|
-
throw new MutagentError("MISSING_ARGUMENTS", `A "${type}" carries a message — there is nothing to send without one.`, `Run: mutagent helix session send <id> --session <session-id> --type ${type} "<message>"`);
|
|
30640
|
+
throw new MutagentError("MISSING_ARGUMENTS", `A "${type}" carries a message — there is nothing to send without one.`, productCopy(`Run: mutagent helix session send <id> --session <session-id> --type ${type} "<message>"`));
|
|
30417
30641
|
}
|
|
30418
30642
|
if (message !== "" && !NEEDS_MESSAGE.has(type)) {
|
|
30419
30643
|
throw new MutagentError("INVALID_ARGUMENTS", `A "${type}" takes no message, so the text would be silently discarded.`, `Drop the message, or send it separately as a prompt.`);
|
|
@@ -30454,7 +30678,7 @@ function readType(raw) {
|
|
|
30454
30678
|
return "raw";
|
|
30455
30679
|
}
|
|
30456
30680
|
|
|
30457
|
-
// src/commands/
|
|
30681
|
+
// src/commands/cloud-session/signal.ts
|
|
30458
30682
|
init_output();
|
|
30459
30683
|
init_errors();
|
|
30460
30684
|
import { Option as Option3 } from "commander";
|
|
@@ -30463,7 +30687,9 @@ var SIGNAL_TYPES = ["SIGINT", "SIGTERM"];
|
|
|
30463
30687
|
var DEFAULT_SIGNAL = "SIGINT";
|
|
30464
30688
|
function registerSignalCommand(parent, registration) {
|
|
30465
30689
|
const jsonSource = registration?.jsonSource ?? parent;
|
|
30466
|
-
|
|
30690
|
+
const p = registration?.product ?? HELIX_PRODUCT;
|
|
30691
|
+
const t = (text) => productText(text, p);
|
|
30692
|
+
parent.command("signal").description("Stop a session with SIGINT or SIGTERM; its sandbox stays up").argument("<reference>", "Session reference (hs1_...)").addOption(new Option3("--session <id>", "The session id, when the argument is a sandbox id").hideHelp()).option("--type <signal>", `${SIGNAL_TYPES.join(" | ")} (default: ${DEFAULT_SIGNAL})`).option("-f, --force", "Confirm the stop (required in every mode, --json included)").addHelpText("after", t(`
|
|
30467
30693
|
Examples:
|
|
30468
30694
|
${chalk29.dim("$")} mutagent helix session signal <reference> --force
|
|
30469
30695
|
${chalk29.dim("$")} mutagent helix session signal <reference> --type SIGTERM --force
|
|
@@ -30487,7 +30713,7 @@ AI Agent Directive:
|
|
|
30487
30713
|
'signalled' is true only when a running process was stopped. A session that had
|
|
30488
30714
|
already ended exits non-zero; the agent is already stopped, so treat it as
|
|
30489
30715
|
information and do not retry.
|
|
30490
|
-
`).action(async (id, options) => {
|
|
30716
|
+
`)).action(async (id, options) => {
|
|
30491
30717
|
const isJson = getJsonFlag(jsonSource);
|
|
30492
30718
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
30493
30719
|
try {
|
|
@@ -30496,26 +30722,26 @@ AI Agent Directive:
|
|
|
30496
30722
|
const type = options.type === undefined ? "" : ` --type ${options.type}`;
|
|
30497
30723
|
requireForce(options, {
|
|
30498
30724
|
what: `Stopping session ${id}`,
|
|
30499
|
-
verb: "mutagent helix session signal",
|
|
30500
|
-
command: `mutagent helix session signal ${id}${session}${type}`
|
|
30725
|
+
verb: productCopy("mutagent helix session signal"),
|
|
30726
|
+
command: productCopy(`mutagent helix session signal ${id}${session}${type}`)
|
|
30501
30727
|
});
|
|
30502
30728
|
};
|
|
30503
30729
|
if (options.session === undefined) {
|
|
30504
30730
|
const signal = resolveSignal(options.type);
|
|
30505
30731
|
confirm();
|
|
30506
|
-
const result = await
|
|
30732
|
+
const result = await signalSession(p, id, signal);
|
|
30507
30733
|
if (!result.signalled) {
|
|
30508
|
-
throw new MutagentError("SESSION_SIGNAL_REJECTED", "The session was not signalled.", "Check the session: mutagent helix session list");
|
|
30734
|
+
throw new MutagentError("SESSION_SIGNAL_REJECTED", "The session was not signalled.", productCopy("Check the session: mutagent helix session list"));
|
|
30509
30735
|
}
|
|
30510
30736
|
if (isJson)
|
|
30511
|
-
output.output({ success: result.signalled, reference: id, signal, ...result, _links: { api:
|
|
30737
|
+
output.output({ success: result.signalled, reference: id, signal, ...result, _links: { api: sessionPath(p, id) } });
|
|
30512
30738
|
else
|
|
30513
30739
|
output.success("Sent " + signal + " to " + id + ".");
|
|
30514
30740
|
return;
|
|
30515
30741
|
}
|
|
30516
30742
|
const sessionId = options.session.trim();
|
|
30517
30743
|
if (sessionId === "") {
|
|
30518
|
-
throw new MutagentError("MISSING_ARGUMENTS", "--session is required — a sandbox can hold more than one session.", `Run: mutagent helix session signal ${id} --session <session-id>`);
|
|
30744
|
+
throw new MutagentError("MISSING_ARGUMENTS", "--session is required — a sandbox can hold more than one session.", productCopy(`Run: mutagent helix session signal ${id} --session <session-id>`));
|
|
30519
30745
|
}
|
|
30520
30746
|
const signal = resolveSignal(options.type);
|
|
30521
30747
|
confirm();
|
|
@@ -30553,9 +30779,10 @@ function resolveSignal(raw) {
|
|
|
30553
30779
|
return normalised;
|
|
30554
30780
|
}
|
|
30555
30781
|
|
|
30556
|
-
// src/commands/
|
|
30557
|
-
function registerSessionCommand(parent) {
|
|
30558
|
-
const
|
|
30782
|
+
// src/commands/cloud-session/session-commands.ts
|
|
30783
|
+
function registerSessionCommand(parent, p = HELIX_PRODUCT) {
|
|
30784
|
+
const t = (text) => productText(text, p);
|
|
30785
|
+
const session = new Command13("session").description(t("List, watch and control Helix sessions")).addHelpText("after", t(`
|
|
30559
30786
|
Examples:
|
|
30560
30787
|
${chalk30.dim("$")} mutagent helix session list
|
|
30561
30788
|
${chalk30.dim("$")} mutagent helix session attach <reference>
|
|
@@ -30576,17 +30803,18 @@ AI Agent Directive:
|
|
|
30576
30803
|
checkpoint, checkpoints and restore; never guess one. Only an interactive
|
|
30577
30804
|
(--mode rpc) session accepts send. restore starts a NEW session and returns its
|
|
30578
30805
|
reference. A managed agent's session cannot be restored yet (409).
|
|
30579
|
-
`);
|
|
30580
|
-
|
|
30581
|
-
|
|
30582
|
-
|
|
30583
|
-
|
|
30584
|
-
|
|
30585
|
-
|
|
30586
|
-
|
|
30587
|
-
|
|
30588
|
-
|
|
30589
|
-
|
|
30806
|
+
`));
|
|
30807
|
+
if (p.preset === undefined)
|
|
30808
|
+
registerStart(session, parent);
|
|
30809
|
+
registerSessionList(session, parent, p);
|
|
30810
|
+
registerSessionAttach(session, p);
|
|
30811
|
+
registerSendCommand(session, { jsonSource: parent, product: p });
|
|
30812
|
+
registerSignalCommand(session, { jsonSource: parent, product: p });
|
|
30813
|
+
registerCloseInput(session, parent, p);
|
|
30814
|
+
registerCheckpoint(session, parent, p);
|
|
30815
|
+
registerCheckpoints(session, parent, p);
|
|
30816
|
+
registerRestore(session, parent, p);
|
|
30817
|
+
registerEnd(session, parent, p);
|
|
30590
30818
|
parent.addCommand(session);
|
|
30591
30819
|
}
|
|
30592
30820
|
function withSessionFlags(options, own) {
|
|
@@ -30672,13 +30900,15 @@ function requireSessionId(result, sandboxId) {
|
|
|
30672
30900
|
return result.sessionId;
|
|
30673
30901
|
throw new MutagentError("INVALID_RESPONSE", "The server started a session but did not return a session id.", `The session may be running — watch it with: mutagent sandbox attach ${sandboxId}`);
|
|
30674
30902
|
}
|
|
30675
|
-
function registerSessionList(session, root) {
|
|
30676
|
-
|
|
30903
|
+
function registerSessionList(session, root, p) {
|
|
30904
|
+
const t = (text) => productText(text, p);
|
|
30905
|
+
session.command("list").alias("ls").description(t("List this workspace's Helix sessions")).addHelpText("after", t(`
|
|
30677
30906
|
Examples:
|
|
30678
30907
|
${chalk30.dim("$")} mutagent helix session list
|
|
30679
30908
|
${chalk30.dim("$")} mutagent helix session list --json
|
|
30680
30909
|
|
|
30681
|
-
Every session in the workspace, live and ended, newest activity first.
|
|
30910
|
+
Every Helix session in the workspace, live and ended, newest activity first.
|
|
30911
|
+
Sessions of the other cloud product's harness are not listed here: its own session list shows them.
|
|
30682
30912
|
STATUS is live (running now), ended (finished; exitCode in --json), stopped-for-idling
|
|
30683
30913
|
(its sandbox was idle for 15 minutes and was stopped) or restored
|
|
30684
30914
|
(running in a sandbox rebuilt from a checkpoint). AGENT is slug:vN for a session
|
|
@@ -30691,11 +30921,11 @@ AI Agent Directive:
|
|
|
30691
30921
|
sessions: [{ reference, status, agent, arm, mode (interactive or headless), ... }],
|
|
30692
30922
|
count }. reference is the hs1_ session id: find one session by it, and hold it
|
|
30693
30923
|
for attach/send/signal; never guess one. The command takes no argument.
|
|
30694
|
-
`).action(async () => {
|
|
30924
|
+
`)).action(async () => {
|
|
30695
30925
|
const isJson = getJsonFlag(root);
|
|
30696
30926
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
30697
30927
|
try {
|
|
30698
|
-
const { workspaceId, sessions, nextCursor } = await
|
|
30928
|
+
const { workspaceId, sessions, nextCursor } = await listHarnessSessions(p);
|
|
30699
30929
|
if (isJson) {
|
|
30700
30930
|
output.output({
|
|
30701
30931
|
workspaceId,
|
|
@@ -30705,10 +30935,14 @@ AI Agent Directive:
|
|
|
30705
30935
|
});
|
|
30706
30936
|
return;
|
|
30707
30937
|
}
|
|
30708
|
-
if (sessions.length === 0) {
|
|
30709
|
-
console.log(chalk30.gray("No Helix sessions in this workspace yet."));
|
|
30938
|
+
if (sessions.length === 0 && nextCursor === undefined) {
|
|
30939
|
+
console.log(chalk30.gray(t("No Helix sessions in this workspace yet.")));
|
|
30710
30940
|
console.log("");
|
|
30711
|
-
console.log(' Start one: mutagent helix -p "<task>" or mutagent helix --rpc');
|
|
30941
|
+
console.log(t(' Start one: mutagent helix -p "<task>" or mutagent helix --rpc'));
|
|
30942
|
+
return;
|
|
30943
|
+
}
|
|
30944
|
+
if (sessions.length === 0) {
|
|
30945
|
+
console.log(chalk30.gray(t("No Helix sessions in the pages read so far; the listing has more.")));
|
|
30712
30946
|
return;
|
|
30713
30947
|
}
|
|
30714
30948
|
output.output(sessions.map((s) => ({
|
|
@@ -30720,15 +30954,17 @@ AI Agent Directive:
|
|
|
30720
30954
|
"LAST ACTIVITY": s.lastActivityAt
|
|
30721
30955
|
})));
|
|
30722
30956
|
if (nextCursor !== undefined) {
|
|
30723
|
-
console.log(chalk30.gray(
|
|
30957
|
+
console.log(chalk30.gray(t(`
|
|
30958
|
+
More Helix sessions exist than one list reads; these are the newest.`)));
|
|
30724
30959
|
}
|
|
30725
30960
|
} catch (error) {
|
|
30726
30961
|
handleError(withoutSandboxIds(error), isJson);
|
|
30727
30962
|
}
|
|
30728
30963
|
});
|
|
30729
30964
|
}
|
|
30730
|
-
function registerSessionAttach(session) {
|
|
30731
|
-
|
|
30965
|
+
function registerSessionAttach(session, p) {
|
|
30966
|
+
const t = (text) => productText(text, p);
|
|
30967
|
+
session.command("attach").description("Watch a session").argument("<reference>", t("Session reference (hs1_...) from 'mutagent helix' or 'session list'")).option("--since <n>", "Replay from after event number n").addHelpText("after", t([
|
|
30732
30968
|
"",
|
|
30733
30969
|
"Examples:",
|
|
30734
30970
|
" mutagent helix session attach <reference>",
|
|
@@ -30741,23 +30977,24 @@ function registerSessionAttach(session) {
|
|
|
30741
30977
|
' When a send wakes the session, stderr carries [mutagent] {"event":"woken","reference":"hs1_..."}:',
|
|
30742
30978
|
" this stream ends there; attach to that reference with --since 0."
|
|
30743
30979
|
].join(`
|
|
30744
|
-
`)).action(async (reference, options) => {
|
|
30980
|
+
`))).action(async (reference, options) => {
|
|
30745
30981
|
try {
|
|
30746
30982
|
const since = parseSince(options.since);
|
|
30747
30983
|
await runNativeSession({
|
|
30748
30984
|
reference,
|
|
30749
30985
|
rpc: false,
|
|
30750
30986
|
...since === undefined ? {} : { since },
|
|
30751
|
-
open: (request) =>
|
|
30752
|
-
send: (line, signal) =>
|
|
30987
|
+
open: (request) => openSessionStream(p, reference, request),
|
|
30988
|
+
send: (line, signal) => sendSessionInput(p, reference, line, signal)
|
|
30753
30989
|
});
|
|
30754
30990
|
} catch (error) {
|
|
30755
30991
|
handleError(sessionGoneGuidance(error, "stream", reference), false);
|
|
30756
30992
|
}
|
|
30757
30993
|
});
|
|
30758
30994
|
}
|
|
30759
|
-
function registerCheckpoint(session, root) {
|
|
30760
|
-
|
|
30995
|
+
function registerCheckpoint(session, root, p) {
|
|
30996
|
+
const t = (text) => productText(text, p);
|
|
30997
|
+
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(`
|
|
30761
30998
|
Examples:
|
|
30762
30999
|
${chalk30.dim("$")} mutagent helix session checkpoint <reference>
|
|
30763
31000
|
${chalk30.dim("$")} mutagent helix session checkpoint <reference> --json
|
|
@@ -30771,14 +31008,14 @@ AI Agent Directive:
|
|
|
30771
31008
|
--json returns { success, reference, snapshotId, bytes, sha256, harnessSessionId,
|
|
30772
31009
|
messageCount, sourcePath, manifestKey, workspaceBytes, workspaceFiles, notCaptured }.
|
|
30773
31010
|
Keep snapshotId and read notCaptured before relying on a restore.
|
|
30774
|
-
`).action(async (id, options) => {
|
|
31011
|
+
`)).action(async (id, options) => {
|
|
30775
31012
|
const isJson = getJsonFlag(root);
|
|
30776
31013
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
30777
31014
|
try {
|
|
30778
31015
|
if (options.session === undefined) {
|
|
30779
|
-
const result = await
|
|
31016
|
+
const result = await checkpointSession(p, id);
|
|
30780
31017
|
if (isJson)
|
|
30781
|
-
output.output({ success: true, reference: id, ...result, _links: { api:
|
|
31018
|
+
output.output({ success: true, reference: id, ...result, _links: { api: sessionPath(p, id) } });
|
|
30782
31019
|
else {
|
|
30783
31020
|
output.success("Snapshot " + result.snapshotId + " captured from " + id);
|
|
30784
31021
|
if (Array.isArray(result.notCaptured))
|
|
@@ -30787,7 +31024,7 @@ AI Agent Directive:
|
|
|
30787
31024
|
}
|
|
30788
31025
|
return;
|
|
30789
31026
|
}
|
|
30790
|
-
const sessionId = requireSession(options.session, `mutagent helix session checkpoint ${id}`);
|
|
31027
|
+
const sessionId = requireSession(options.session, t(`mutagent helix session checkpoint ${id}`));
|
|
30791
31028
|
const result = await captureCheckpoint(id, sessionId);
|
|
30792
31029
|
if (isJson) {
|
|
30793
31030
|
output.output({
|
|
@@ -30799,7 +31036,7 @@ AI Agent Directive:
|
|
|
30799
31036
|
_directive: {
|
|
30800
31037
|
instruction: "Inspect notCaptured. Restore takes the session's reference: find it with session list, then restore rebuilds the sandbox from this snapshot and returns the new session's reference.",
|
|
30801
31038
|
next: [
|
|
30802
|
-
"mutagent helix session list --json"
|
|
31039
|
+
t("mutagent helix session list --json")
|
|
30803
31040
|
]
|
|
30804
31041
|
}
|
|
30805
31042
|
});
|
|
@@ -30822,13 +31059,13 @@ function requireSession(raw, example) {
|
|
|
30822
31059
|
throw new MutagentError("MISSING_ARGUMENTS", "--session is required — a sandbox can hold more than one session.", `Run: ${example} --session <session-id>`);
|
|
30823
31060
|
}
|
|
30824
31061
|
|
|
30825
|
-
// src/commands/
|
|
31062
|
+
// src/commands/cloud-session/models.ts
|
|
30826
31063
|
init_output();
|
|
30827
31064
|
init_errors();
|
|
30828
31065
|
import chalk31 from "chalk";
|
|
30829
31066
|
function printView(view, output) {
|
|
30830
31067
|
if (view.models.length === 0) {
|
|
30831
|
-
console.log(chalk31.gray("No Helix Cloud models: this workspace has no active LLM provider that Helix can use."));
|
|
31068
|
+
console.log(chalk31.gray(productText("No Helix Cloud models: this workspace has no active LLM provider that Helix can use.", activeProduct())));
|
|
30832
31069
|
console.log("");
|
|
30833
31070
|
console.log(" Add one: mutagent providers add --provider <id> --name <name> --api-key <key>");
|
|
30834
31071
|
} else {
|
|
@@ -30838,14 +31075,15 @@ function printView(view, output) {
|
|
|
30838
31075
|
name: m.displayName
|
|
30839
31076
|
})));
|
|
30840
31077
|
console.log("");
|
|
30841
|
-
console.log(view.default === null ? chalk31.yellow("No default set — a run without --model answers 428. Set one: mutagent helix models default <provider/model>") : `Default: ${view.default}`);
|
|
31078
|
+
console.log(view.default === null ? chalk31.yellow(productCopy("No default set — a run without --model answers 428. Set one: mutagent helix models default <provider/model>")) : `Default: ${view.default}`);
|
|
30842
31079
|
}
|
|
30843
31080
|
if (view.unmapped.length > 0) {
|
|
30844
|
-
console.log(chalk31.yellow(`Not usable by Helix Cloud (Helix cannot load this LLM provider's key): ${view.unmapped.join(", ")}
|
|
31081
|
+
console.log(chalk31.yellow(productText(`Not usable by Helix Cloud (Helix cannot load this LLM provider's key): ${view.unmapped.join(", ")}`, activeProduct())));
|
|
30845
31082
|
}
|
|
30846
31083
|
}
|
|
30847
|
-
function registerModelsCommand(helix) {
|
|
30848
|
-
const
|
|
31084
|
+
function registerModelsCommand(helix, p = HELIX_PRODUCT) {
|
|
31085
|
+
const t = (text) => productText(text, p);
|
|
31086
|
+
const models = helix.command("models").description(t("List the models Helix can use in the cloud, and the workspace default model")).addHelpText("after", t(`
|
|
30849
31087
|
Examples:
|
|
30850
31088
|
${chalk31.dim("$")} mutagent helix models
|
|
30851
31089
|
${chalk31.dim("$")} mutagent helix models --json
|
|
@@ -30863,7 +31101,7 @@ AI Agent Directive:
|
|
|
30863
31101
|
--json returns { workspaceId, models: [{ id, provider, harnessProvider, model,
|
|
30864
31102
|
displayName }], defaults: [...], default: <id|null>, unmapped: [...] }. Pick a
|
|
30865
31103
|
model from models[].id; never invent one — an id outside the list is a 422.
|
|
30866
|
-
`).action(async () => {
|
|
31104
|
+
`)).action(async () => {
|
|
30867
31105
|
const isJson = getJsonFlag(helix);
|
|
30868
31106
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
30869
31107
|
try {
|
|
@@ -30877,7 +31115,7 @@ AI Agent Directive:
|
|
|
30877
31115
|
handleError(error, isJson);
|
|
30878
31116
|
}
|
|
30879
31117
|
});
|
|
30880
|
-
models.command("default").description("Set the workspace default model for Helix in the cloud, and its fallbacks").argument("[models...]", "Model ids from 'mutagent helix models'; the first is the default").option("--clear", "Remove the default model and every fallback").addHelpText("after", `
|
|
31118
|
+
models.command("default").description(t("Set the workspace default model for Helix in the cloud, and its fallbacks")).argument("[models...]", t("Model ids from 'mutagent helix models'; the first is the default")).option("--clear", "Remove the default model and every fallback").addHelpText("after", t(`
|
|
30881
31119
|
Examples:
|
|
30882
31120
|
${chalk31.dim("$")} mutagent helix models default zai-coding-cn/glm-5.3
|
|
30883
31121
|
${chalk31.dim("$")} mutagent helix models default zai-coding-cn/glm-5.3 openai/gpt-5.6-sol
|
|
@@ -30892,15 +31130,15 @@ AI Agent Directive:
|
|
|
30892
31130
|
change. Run it with your own sign-in; it is refused from inside a sandbox
|
|
30893
31131
|
(task credentials). It is the fix when a run without --model answers 428
|
|
30894
31132
|
NO_PROVIDER_CONFIGURED because no default model is set.
|
|
30895
|
-
`).action(async (ids, opts) => {
|
|
31133
|
+
`)).action(async (ids, opts) => {
|
|
30896
31134
|
const isJson = getJsonFlag(helix);
|
|
30897
31135
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
30898
31136
|
try {
|
|
30899
31137
|
if (opts.clear === true && ids.length > 0) {
|
|
30900
|
-
throw new MutagentError("INVALID_ARGUMENTS", "--clear takes no model ids.", "Either: mutagent helix models default --clear or: mutagent helix models default <provider/model>...");
|
|
31138
|
+
throw new MutagentError("INVALID_ARGUMENTS", "--clear takes no model ids.", productCopy("Either: mutagent helix models default --clear or: mutagent helix models default <provider/model>..."));
|
|
30901
31139
|
}
|
|
30902
31140
|
if (opts.clear !== true && ids.length === 0) {
|
|
30903
|
-
throw new MutagentError("INVALID_ARGUMENTS", "Name at least one model, or pass --clear.", "List the choices: mutagent helix models");
|
|
31141
|
+
throw new MutagentError("INVALID_ARGUMENTS", "Name at least one model, or pass --clear.", productCopy("List the choices: mutagent helix models"));
|
|
30904
31142
|
}
|
|
30905
31143
|
const view = await setHelixDefaults(opts.clear === true ? [] : ids);
|
|
30906
31144
|
if (isJson) {
|
|
@@ -30914,6 +31152,85 @@ AI Agent Directive:
|
|
|
30914
31152
|
});
|
|
30915
31153
|
}
|
|
30916
31154
|
|
|
31155
|
+
// src/commands/cloud-session/product-command.ts
|
|
31156
|
+
function launchHelp(p) {
|
|
31157
|
+
const fixed = p.preset !== undefined;
|
|
31158
|
+
return [
|
|
31159
|
+
"",
|
|
31160
|
+
"Run options:",
|
|
31161
|
+
' -p "<task>" Run the task to completion and print the final answer',
|
|
31162
|
+
' --mode json "<task>" Stream events as JSON lines',
|
|
31163
|
+
" --mode rpc, --rpc Read JSON commands on stdin; write events on stdout",
|
|
31164
|
+
" --prime Run the lean Prime agent instead of the full orchestrator",
|
|
31165
|
+
` --model <provider/model> Model to use (default: the workspace default model; see ${p.cli} models)`,
|
|
31166
|
+
" --env <name> Workspace Environment to load (see mutagent env list)",
|
|
31167
|
+
...fixed ? [] : [" --preset <name> Sandbox preset (default: the server's Helix preset)"],
|
|
31168
|
+
" --sandbox-provider <name> Run on this configured sandbox provider",
|
|
31169
|
+
" --cwd <path> Working directory in the sandbox",
|
|
31170
|
+
` --repository <owner/name> Run ${p.title} in a checkout of this GitHub repository (the workspace's GitHub connection);`,
|
|
31171
|
+
" the checkout is the working directory, so --cwd is refused with it",
|
|
31172
|
+
" --branch <name> Branch of --repository to check out (default: its default branch)",
|
|
31173
|
+
"",
|
|
31174
|
+
"Examples:",
|
|
31175
|
+
` ${p.cli} -p "plan the refactor"`,
|
|
31176
|
+
` ${p.cli} --mode json "run the tests"`,
|
|
31177
|
+
` ${p.cli} --prime --mode rpc`,
|
|
31178
|
+
` ${p.cli} --env staging -p "check the deploy"`,
|
|
31179
|
+
` ${p.cli} --repository acme/api --branch feat/login --mode rpc`,
|
|
31180
|
+
` ${p.cli} agent --file reviewer.md --prime --mode rpc`,
|
|
31181
|
+
"",
|
|
31182
|
+
...fixed ? [`Every run starts a new sandbox with the ${p.title} harness; there is no --preset.`, ""] : [],
|
|
31183
|
+
"Each run prints its session reference (hs1_...) on stderr. Use it with",
|
|
31184
|
+
`${p.cli} session attach, send, signal and checkpoint.`,
|
|
31185
|
+
"Ctrl-C sends SIGINT to the session, which stops it; the exit status is reported.",
|
|
31186
|
+
"There is no terminal chat UI: choose -p, --mode json or --mode rpc.",
|
|
31187
|
+
"With --mode rpc, closing stdin ends the session's input; a dropped connection only detaches.",
|
|
31188
|
+
"A sandbox idle for 15 minutes is stopped; an interactive session in it is checkpointed first.",
|
|
31189
|
+
"A send to that session wakes it in a new sandbox from its last checkpoint;",
|
|
31190
|
+
`${p.cli} session restore is the manual option.`,
|
|
31191
|
+
"",
|
|
31192
|
+
"AI Agent Directive:",
|
|
31193
|
+
" Choose -p (one-shot), --mode json or --mode rpc (a steerable session) explicitly.",
|
|
31194
|
+
` Without --prime the full ${p.title} orchestrator runs; --prime runs the lean Prime agent.`,
|
|
31195
|
+
" Keep the session reference (hs1_...) printed on stderr; attach, send, signal and checkpoint take it.",
|
|
31196
|
+
...fixed ? [` This is the cloud form of the local architech command; Helix runs with mutagent helix. Never pass --preset.`] : [" mutagent install helix installs the Helix binary on this machine; this command runs it in the cloud."],
|
|
31197
|
+
" Inside a git checkout, pass the git remote's owner/name to start with it checked out: --repository <owner/name> [--branch <name>].",
|
|
31198
|
+
" On a refusal, show the returned fix: the Run: lines, the notes, and who has to act; do not invent other commands.",
|
|
31199
|
+
" In --mode rpc/json a launch refusal is one JSON line on stderr: {success:false, code, error, suggestedAction,",
|
|
31200
|
+
` _agentGuidance:{fix, notes, escalate?}}; stdout stays the session's. With -p it is text on stderr.`
|
|
31201
|
+
].join(`
|
|
31202
|
+
`);
|
|
31203
|
+
}
|
|
31204
|
+
function createCloudProductCommand(p, own = {}) {
|
|
31205
|
+
const group = new Command14(p.command).description(`Run ${p.title} in the cloud`).allowUnknownOption(true).allowExcessArguments(true).argument("[argv...]", `${p.title} flags and the task, e.g. -p "<task>"`).helpCommand("help [command]", `Print usage for ${p.cli} or one of its subcommands`).addHelpText("after", launchHelp(p)).hook("preAction", () => {
|
|
31206
|
+
selectProduct(p);
|
|
31207
|
+
}).action(async (argv, _options, command) => {
|
|
31208
|
+
try {
|
|
31209
|
+
if (own.reportVersions !== undefined && argv.length === 1 && (argv[0] === "--version" || argv[0] === "-v")) {
|
|
31210
|
+
await own.reportVersions(getJsonFlag(command));
|
|
31211
|
+
return;
|
|
31212
|
+
}
|
|
31213
|
+
const refusal = fixedHarnessFlagRefusal(p, "", argv) ?? productPresetRefusal(p, "", argv);
|
|
31214
|
+
if (refusal !== undefined)
|
|
31215
|
+
throw refusal;
|
|
31216
|
+
const plan = planLauncherArgv(argv, undefined, launcherOwnFlags(p));
|
|
31217
|
+
const mode = nativeMode(plan.nativeArgs, plan.print, plan.rpc);
|
|
31218
|
+
for (const notice of [...plan.notices, ...nativeTaskNotices(mode, plan.messages)])
|
|
31219
|
+
process.stderr.write("[mutagent] " + notice + `
|
|
31220
|
+
`);
|
|
31221
|
+
await runCloudLaunch({ ...plan, ...p.preset === undefined ? {} : { preset: p.preset }, args: plan.nativeArgs }, mode);
|
|
31222
|
+
} catch (error) {
|
|
31223
|
+
handleLaunchFailure(error, { isJson: getJsonFlag(command) && !hasNativeMode(argv), machine: isMachineMode(argv) });
|
|
31224
|
+
}
|
|
31225
|
+
});
|
|
31226
|
+
registerAgentCommand(group, { product: p });
|
|
31227
|
+
registerSessionCommand(group, p);
|
|
31228
|
+
registerModelsCommand(group, p);
|
|
31229
|
+
registerAccess(group, p);
|
|
31230
|
+
own.register?.(group);
|
|
31231
|
+
return group;
|
|
31232
|
+
}
|
|
31233
|
+
|
|
30917
31234
|
// src/commands/helix/doctor.ts
|
|
30918
31235
|
init_output();
|
|
30919
31236
|
init_errors();
|
|
@@ -31104,74 +31421,20 @@ function reportSandboxRun(result, output, isJson, context) {
|
|
|
31104
31421
|
|
|
31105
31422
|
// src/commands/helix/index.ts
|
|
31106
31423
|
function createHelixCommand() {
|
|
31107
|
-
|
|
31108
|
-
|
|
31109
|
-
|
|
31110
|
-
|
|
31111
|
-
|
|
31112
|
-
|
|
31113
|
-
|
|
31114
|
-
" --model <provider/model> Model to use (default: the workspace default model; see mutagent helix models)",
|
|
31115
|
-
" --env <name> Workspace Environment to load (see mutagent env list)",
|
|
31116
|
-
" --preset <name> Sandbox preset (default: the server's Helix preset)",
|
|
31117
|
-
" --sandbox-provider <name> Run on this configured sandbox provider",
|
|
31118
|
-
" --cwd <path> Working directory in the sandbox",
|
|
31119
|
-
" --repository <owner/name> Run Helix in a checkout of this GitHub repository (the workspace's GitHub connection);",
|
|
31120
|
-
" the checkout is the working directory, so --cwd is refused with it",
|
|
31121
|
-
" --branch <name> Branch of --repository to check out (default: its default branch)",
|
|
31122
|
-
"",
|
|
31123
|
-
"Examples:",
|
|
31124
|
-
' mutagent helix -p "plan the refactor"',
|
|
31125
|
-
' mutagent helix --mode json "run the tests"',
|
|
31126
|
-
" mutagent helix --prime --mode rpc",
|
|
31127
|
-
' mutagent helix --env staging -p "check the deploy"',
|
|
31128
|
-
" mutagent helix --repository acme/api --branch feat/login --mode rpc",
|
|
31129
|
-
" mutagent helix agent --file reviewer.md --prime --mode rpc",
|
|
31130
|
-
"",
|
|
31131
|
-
"Each run prints its session reference (hs1_...) on stderr. Use it with",
|
|
31132
|
-
"mutagent helix session attach, send, signal and checkpoint.",
|
|
31133
|
-
"Ctrl-C sends SIGINT to the session, which stops it; the exit status is reported.",
|
|
31134
|
-
"There is no terminal chat UI: choose -p, --mode json or --mode rpc.",
|
|
31135
|
-
"With --mode rpc, closing stdin ends the session's input; a dropped connection only detaches.",
|
|
31136
|
-
"A sandbox idle for 15 minutes is stopped; an interactive session in it is checkpointed first.",
|
|
31137
|
-
"A send to that session wakes it in a new sandbox from its last checkpoint;",
|
|
31138
|
-
"mutagent helix session restore is the manual option.",
|
|
31139
|
-
"",
|
|
31140
|
-
"AI Agent Directive:",
|
|
31141
|
-
" Choose -p (one-shot), --mode json or --mode rpc (a steerable session) explicitly.",
|
|
31142
|
-
" Without --prime the full Helix orchestrator runs; --prime runs the lean Prime agent.",
|
|
31143
|
-
" Keep the session reference (hs1_...) printed on stderr; attach, send, signal and checkpoint take it.",
|
|
31144
|
-
" mutagent install helix installs the Helix binary on this machine; this command runs it in the cloud.",
|
|
31145
|
-
" Inside a git checkout, pass the git remote's owner/name to start with it checked out: --repository <owner/name> [--branch <name>].",
|
|
31146
|
-
" On a refusal, show the returned fix: the Run: lines, the notes, and who has to act; do not invent other commands.",
|
|
31147
|
-
" In --mode rpc/json a launch refusal is one JSON line on stderr: {success:false, code, error, suggestedAction,",
|
|
31148
|
-
" _agentGuidance:{fix, notes, escalate?}}; stdout stays the session's. With -p it is text on stderr."
|
|
31149
|
-
].join(`
|
|
31150
|
-
`)).action(async (argv, _options, command) => {
|
|
31151
|
-
try {
|
|
31152
|
-
if (argv.length === 1 && (argv[0] === "--version" || argv[0] === "-v")) {
|
|
31153
|
-
await reportVersions(getJsonFlag(command));
|
|
31154
|
-
return;
|
|
31155
|
-
}
|
|
31156
|
-
const plan = planLauncherArgv(argv);
|
|
31157
|
-
const mode = nativeMode(plan.nativeArgs, plan.print, plan.rpc);
|
|
31158
|
-
for (const notice of [...plan.notices, ...nativeTaskNotices(mode, plan.messages)])
|
|
31159
|
-
process.stderr.write("[mutagent] " + notice + `
|
|
31160
|
-
`);
|
|
31161
|
-
await runCloudLaunch({ ...plan, args: plan.nativeArgs }, mode);
|
|
31162
|
-
} catch (error) {
|
|
31163
|
-
handleLaunchFailure(error, { isJson: getJsonFlag(command) && !hasNativeMode(argv), machine: isMachineMode(argv) });
|
|
31424
|
+
return createCloudProductCommand(HELIX_PRODUCT, {
|
|
31425
|
+
reportVersions,
|
|
31426
|
+
register: (group) => {
|
|
31427
|
+
registerDoctorCommand(group);
|
|
31428
|
+
registerSmokeCommand(group);
|
|
31429
|
+
registerVersionCommand(group);
|
|
31430
|
+
registerUpdateCommand2(group);
|
|
31164
31431
|
}
|
|
31165
31432
|
});
|
|
31166
|
-
|
|
31167
|
-
|
|
31168
|
-
|
|
31169
|
-
|
|
31170
|
-
|
|
31171
|
-
registerSmokeCommand(helix);
|
|
31172
|
-
registerVersionCommand(helix);
|
|
31173
|
-
registerUpdateCommand2(helix);
|
|
31174
|
-
return helix;
|
|
31433
|
+
}
|
|
31434
|
+
|
|
31435
|
+
// src/commands/architech/index.ts
|
|
31436
|
+
function createArchitechCommand() {
|
|
31437
|
+
return createCloudProductCommand(ARCHITECH_PRODUCT);
|
|
31175
31438
|
}
|
|
31176
31439
|
|
|
31177
31440
|
// src/commands/sandbox/index.ts
|
|
@@ -31571,7 +31834,7 @@ import chalk36 from "chalk";
|
|
|
31571
31834
|
init_errors();
|
|
31572
31835
|
init_config();
|
|
31573
31836
|
init_organization_scope();
|
|
31574
|
-
async function
|
|
31837
|
+
async function getCloudAccess2() {
|
|
31575
31838
|
let body;
|
|
31576
31839
|
try {
|
|
31577
31840
|
body = await requestJson("/api/sandbox/access");
|
|
@@ -31622,7 +31885,7 @@ Requires a workspace: mutagent workspaces use <name> (or --workspace for one com
|
|
|
31622
31885
|
`).action(async () => {
|
|
31623
31886
|
const isJson = getJsonFlag(parent);
|
|
31624
31887
|
try {
|
|
31625
|
-
const access = await
|
|
31888
|
+
const access = await getCloudAccess2();
|
|
31626
31889
|
if (isJson) {
|
|
31627
31890
|
console.log(JSON.stringify(access));
|
|
31628
31891
|
return;
|
|
@@ -33960,9 +34223,14 @@ function assertCreatableKind(kind) {
|
|
|
33960
34223
|
function registerList3(gateway) {
|
|
33961
34224
|
const triggers = new Command17("triggers").description("Event → agent run: create, list, show, update, enable, disable, delete, test");
|
|
33962
34225
|
gateway.addCommand(triggers);
|
|
33963
|
-
|
|
34226
|
+
configureList(triggers, gateway, "mutagent gateway triggers");
|
|
34227
|
+
configureList(triggers.command("list").alias("ls"), gateway, "mutagent gateway triggers list");
|
|
34228
|
+
return triggers;
|
|
34229
|
+
}
|
|
34230
|
+
function configureList(command, gateway, usage) {
|
|
34231
|
+
command.description("List triggers — user-created first, then built-ins").addHelpText("after", `
|
|
33964
34232
|
Examples:
|
|
33965
|
-
${chalk49.dim("$")}
|
|
34233
|
+
${chalk49.dim("$")} ${usage} --json
|
|
33966
34234
|
|
|
33967
34235
|
Built-in triggers (the default @mention behaviour) are listed, marked 'builtin: true',
|
|
33968
34236
|
and are read-only — 'update'/'enable'/'disable'/'delete' on one refuse (409). A built-in
|
|
@@ -33989,7 +34257,6 @@ AI Agent Directive:
|
|
|
33989
34257
|
return;
|
|
33990
34258
|
}, RESOURCE);
|
|
33991
34259
|
});
|
|
33992
|
-
return triggers;
|
|
33993
34260
|
}
|
|
33994
34261
|
function createFilter(options) {
|
|
33995
34262
|
if (options.on === "trace.threshold") {
|
|
@@ -34386,9 +34653,14 @@ function printRoutine(r) {
|
|
|
34386
34653
|
function registerList4(gateway) {
|
|
34387
34654
|
const routines = new Command18("routines").description("Schedule → agent run: create, list, show, update, pause, resume, run-now, delete");
|
|
34388
34655
|
gateway.addCommand(routines);
|
|
34389
|
-
|
|
34656
|
+
configureList2(routines, gateway, "mutagent gateway routines");
|
|
34657
|
+
configureList2(routines.command("list").alias("ls"), gateway, "mutagent gateway routines list");
|
|
34658
|
+
return routines;
|
|
34659
|
+
}
|
|
34660
|
+
function configureList2(command, gateway, usage) {
|
|
34661
|
+
command.description("List routines, with their next three fire times").addHelpText("after", `
|
|
34390
34662
|
Examples:
|
|
34391
|
-
${chalk50.dim("$")}
|
|
34663
|
+
${chalk50.dim("$")} ${usage} --json
|
|
34392
34664
|
|
|
34393
34665
|
AI Agent Directive:
|
|
34394
34666
|
--json returns { success, ok, data: { items: Routine[] } }. schedule.next is 3 ISO-8601
|
|
@@ -34410,7 +34682,6 @@ AI Agent Directive:
|
|
|
34410
34682
|
return;
|
|
34411
34683
|
}, RESOURCE2);
|
|
34412
34684
|
});
|
|
34413
|
-
return routines;
|
|
34414
34685
|
}
|
|
34415
34686
|
function timezoneRequired() {
|
|
34416
34687
|
return new GatewayCliError("TIMEZONE_REQUIRED", "A routine schedule needs a timezone.", {
|
|
@@ -34914,13 +35185,13 @@ function assertUntil(value) {
|
|
|
34914
35185
|
fix: ["mutagent gateway runs --since 24h --until 2h --json"]
|
|
34915
35186
|
});
|
|
34916
35187
|
}
|
|
34917
|
-
function
|
|
34918
|
-
|
|
35188
|
+
function configureRunsList(command, gateway, usage, group) {
|
|
35189
|
+
command.description("Runs from triggers, routines, the test run and emit — newest first").option("--status <s>", "Comma-separated states to filter to").option("--since <duration>", "ISO-8601 timestamp, or a duration like 30m / 24h / 7d").option("--until <when>", "End of the window: ISO-8601, a duration like 30m / 24h / 7d, or now").option("--session <session-id>", "Only the run of this Helix session (its hs1_ reference)").option("--trigger <id>", "Only runs launched by this trigger").option("--routine <id>", "Only runs launched by this routine").addHelpText("after", `
|
|
34919
35190
|
Examples:
|
|
34920
|
-
${chalk51.dim("$")}
|
|
34921
|
-
${chalk51.dim("$")}
|
|
34922
|
-
${chalk51.dim("$")}
|
|
34923
|
-
${chalk51.dim("$")}
|
|
35191
|
+
${chalk51.dim("$")} ${usage} --since 24h --json
|
|
35192
|
+
${chalk51.dim("$")} ${usage} --status failed --json
|
|
35193
|
+
${chalk51.dim("$")} ${usage} --since 24h --until 2h --json
|
|
35194
|
+
${chalk51.dim("$")} ${usage} --session hs1_8f2c41d07a --json
|
|
34924
35195
|
|
|
34925
35196
|
--since and --until bound the window by when a run was created. A window value is
|
|
34926
35197
|
ISO-8601, a duration back from now (30m, 24h, 7d), or, for --until, now. Anything else
|
|
@@ -34930,7 +35201,8 @@ AI Agent Directive:
|
|
|
34930
35201
|
--json returns { success, ok, data: { items: RunSummary[] } }. state is one of queued |
|
|
34931
35202
|
allocating | checkout_ready | grant_ready | running | succeeded | failed |
|
|
34932
35203
|
cancelled | unknown.
|
|
34933
|
-
`).action(async (
|
|
35204
|
+
`).action(async (own) => {
|
|
35205
|
+
const options = { ...group?.opts() ?? {}, ...own };
|
|
34934
35206
|
const isJson = gatewayIsJson(gateway);
|
|
34935
35207
|
await runGatewayAction(isJson, undefined, async () => {
|
|
34936
35208
|
if (options.until !== undefined)
|
|
@@ -35176,7 +35448,8 @@ function registerGatewayRunCommands(gateway) {
|
|
|
35176
35448
|
registerTestRun(gateway);
|
|
35177
35449
|
const runs = new Command19("runs");
|
|
35178
35450
|
gateway.addCommand(runs);
|
|
35179
|
-
|
|
35451
|
+
configureRunsList(runs, gateway, "mutagent gateway runs");
|
|
35452
|
+
configureRunsList(runs.command("list").alias("ls"), gateway, "mutagent gateway runs list", runs);
|
|
35180
35453
|
registerRunsShow(runs, gateway);
|
|
35181
35454
|
registerRunsLogs(runs, gateway);
|
|
35182
35455
|
registerRunsCancel(runs, gateway);
|
|
@@ -41289,13 +41562,15 @@ AI Agent Directive:
|
|
|
41289
41562
|
|
|
41290
41563
|
// src/commands/factory/index.ts
|
|
41291
41564
|
function createFactoryCommand() {
|
|
41292
|
-
const factory = new Command30("factory").description("Manage Factory entries: their specs, builds and stage runs");
|
|
41565
|
+
const factory = new Command30("factory").description("Manage Agent Factory entries: their specs, builds and stage runs");
|
|
41293
41566
|
registerEntryCommands(factory);
|
|
41294
41567
|
factory.addCommand(createSpecCommand());
|
|
41295
41568
|
factory.addCommand(createStageCommand());
|
|
41296
41569
|
factory.addHelpText("after", `
|
|
41297
|
-
A Factory entry is one agent, skill, workflow or
|
|
41298
|
-
wherever it runs. Its id is its agentspec's
|
|
41570
|
+
This is the Agent Factory. A Factory entry is one agent, skill, workflow or
|
|
41571
|
+
multi-agent system you manage, wherever it runs. Its id is its agentspec's
|
|
41572
|
+
metadata.id. The Software Factory (factory.yaml, board-driven runs) is a
|
|
41573
|
+
different product with its own CLI: architech factory.
|
|
41299
41574
|
|
|
41300
41575
|
Register add <agentspec-file|-> (targets come from the spec)
|
|
41301
41576
|
Read list · show <id> · activity <id> · builds <id>
|
|
@@ -43458,6 +43733,7 @@ function registerCommands(program) {
|
|
|
43458
43733
|
program.addCommand(createTracesCommand());
|
|
43459
43734
|
program.addCommand(createArtifactsCommand());
|
|
43460
43735
|
program.addCommand(createHelixCommand());
|
|
43736
|
+
program.addCommand(createArchitechCommand());
|
|
43461
43737
|
program.addCommand(createFeedbackCommand());
|
|
43462
43738
|
program.addCommand(createAgentCommand());
|
|
43463
43739
|
}
|
|
@@ -43488,12 +43764,13 @@ function findRemovedCommand(words) {
|
|
|
43488
43764
|
}
|
|
43489
43765
|
|
|
43490
43766
|
// src/lib/removed-arguments.ts
|
|
43491
|
-
|
|
43492
|
-
|
|
43493
|
-
message:
|
|
43494
|
-
recovery:
|
|
43495
|
-
}
|
|
43496
|
-
}
|
|
43767
|
+
function sessionListTakesNoSandboxId(cli) {
|
|
43768
|
+
return {
|
|
43769
|
+
message: `\`${cli} session list\` takes no sandbox id: filter by hs1_ session id instead. ` + "Every row of the listing names its session by `reference` (hs1_…); " + `\`${cli} session attach <hs1_id>\` opens that one session.`,
|
|
43770
|
+
recovery: `${cli} session list --json`
|
|
43771
|
+
};
|
|
43772
|
+
}
|
|
43773
|
+
var REMOVED_ARGUMENTS = Object.fromEntries(CLOUD_PRODUCTS.map((product) => [`${product.command} session list`, sessionListTakesNoSandboxId(product.cli)]));
|
|
43497
43774
|
function findRemovedArgument(path) {
|
|
43498
43775
|
return REMOVED_ARGUMENTS[path];
|
|
43499
43776
|
}
|
|
@@ -43738,10 +44015,11 @@ function commandPathIndexes(rawArgs, depth) {
|
|
|
43738
44015
|
// src/bin/run-cli.ts
|
|
43739
44016
|
init_errors();
|
|
43740
44017
|
|
|
43741
|
-
// src/commands/
|
|
44018
|
+
// src/commands/cloud-session/api-key-guard.ts
|
|
43742
44019
|
init_errors();
|
|
43743
44020
|
var FORWARDING_VERBS = [
|
|
43744
44021
|
{ path: ["helix"], label: "mutagent helix" },
|
|
44022
|
+
{ path: ["architech"], label: "mutagent architech" },
|
|
43745
44023
|
{ path: ["sandbox", "exec"], label: "mutagent sandbox exec" }
|
|
43746
44024
|
];
|
|
43747
44025
|
function rootValueOption(arg) {
|
|
@@ -43770,10 +44048,10 @@ function forwardedRootOptionRefusal(rawArgs) {
|
|
|
43770
44048
|
continue;
|
|
43771
44049
|
const after = rawArgs.slice((at[at.length - 1] ?? -1) + 1);
|
|
43772
44050
|
const bindable = commanderBindable(after);
|
|
43773
|
-
const
|
|
43774
|
-
const keyScope =
|
|
44051
|
+
const isProduct = verb.path.length === 1;
|
|
44052
|
+
const keyScope = isProduct ? after : bindable;
|
|
43775
44053
|
if (keyScope.some((arg) => rootValueOption(arg) === "--api-key")) {
|
|
43776
|
-
return
|
|
44054
|
+
return isProduct ? productKeyRefusal(verb.label) : sandboxExecKeyRefusal();
|
|
43777
44055
|
}
|
|
43778
44056
|
const other = bindable.map(rootValueOption).find((option) => option !== undefined);
|
|
43779
44057
|
if (other !== undefined)
|
|
@@ -43785,9 +44063,10 @@ function forwardedRootOptionRefusal(rawArgs) {
|
|
|
43785
44063
|
function keyAlternative() {
|
|
43786
44064
|
return transportFor("--api-key")?.alternative ?? "";
|
|
43787
44065
|
}
|
|
43788
|
-
function
|
|
43789
|
-
|
|
43790
|
-
|
|
44066
|
+
function productKeyRefusal(label) {
|
|
44067
|
+
const command = label.replace(/^mutagent /, "");
|
|
44068
|
+
return new MutagentError("NOT_SUPPORTED", `--api-key after '${label}' is refused: locally it is the LLM key for the run, but here the mutagent CLI would read it as its own platform key and send it to the Mutagent platform.`, `${keyAlternative()}
|
|
44069
|
+
To pass the Mutagent platform key instead, put it before the command (mutagent --api-key <mutagent-key> ${command} …) or export MUTAGENT_API_KEY.`);
|
|
43791
44070
|
}
|
|
43792
44071
|
function sandboxExecKeyRefusal() {
|
|
43793
44072
|
return new MutagentError("NOT_SUPPORTED", "--api-key after 'mutagent sandbox exec' and before a -- is refused: it reads as a flag of the command in the sandbox, but the mutagent CLI would take it as its own platform key and send it to the Mutagent platform.", `${keyAlternative()}
|
|
@@ -43829,8 +44108,8 @@ function rescopeProviderApiKeyFlag(rawArgs) {
|
|
|
43829
44108
|
}
|
|
43830
44109
|
return [...rawArgs];
|
|
43831
44110
|
}
|
|
43832
|
-
// src/commands/
|
|
43833
|
-
var
|
|
44111
|
+
// src/commands/cloud-session/harness-surface.json
|
|
44112
|
+
var harness_surface_default = {
|
|
43834
44113
|
helixVersion: "0.4.20",
|
|
43835
44114
|
harnessVersion: "1.0.0",
|
|
43836
44115
|
launcher: {
|
|
@@ -44128,36 +44407,37 @@ var helix_surface_default = {
|
|
|
44128
44407
|
}
|
|
44129
44408
|
};
|
|
44130
44409
|
|
|
44131
|
-
// src/commands/
|
|
44410
|
+
// src/commands/cloud-session/help-json.ts
|
|
44132
44411
|
var HELP_FLAGS = new Set(["--help", "-h"]);
|
|
44133
|
-
function
|
|
44412
|
+
function cloudHelpJsonProduct(rawArgs) {
|
|
44134
44413
|
const at = findSubcommandIndex(rawArgs);
|
|
44135
|
-
|
|
44136
|
-
|
|
44137
|
-
|
|
44138
|
-
return false;
|
|
44414
|
+
const product = at === -1 ? undefined : CLOUD_PRODUCTS.find((candidate) => candidate.command === rawArgs[at]);
|
|
44415
|
+
if (product === undefined || !rawArgs.includes("--json"))
|
|
44416
|
+
return;
|
|
44139
44417
|
const rest = rawArgs.slice(at + 1).filter((arg) => arg !== "--json");
|
|
44140
|
-
return rest.length === 1 && HELP_FLAGS.has(rest[0] ?? "");
|
|
44418
|
+
return rest.length === 1 && HELP_FLAGS.has(rest[0] ?? "") ? product : undefined;
|
|
44141
44419
|
}
|
|
44142
|
-
function helixCloudSurface(cliVersion) {
|
|
44420
|
+
function helixCloudSurface(cliVersion, product = HELIX_PRODUCT) {
|
|
44421
|
+
const fixed = product.preset !== undefined;
|
|
44143
44422
|
return {
|
|
44144
|
-
surface:
|
|
44423
|
+
surface: product.cli,
|
|
44424
|
+
...fixed ? { preset: product.preset } : {},
|
|
44145
44425
|
cli: cliVersion,
|
|
44146
|
-
helixVersion:
|
|
44147
|
-
harnessVersion:
|
|
44148
|
-
manifest:
|
|
44426
|
+
helixVersion: harness_surface_default.helixVersion,
|
|
44427
|
+
harnessVersion: harness_surface_default.harnessVersion,
|
|
44428
|
+
manifest: harness_surface_default,
|
|
44149
44429
|
transport: TRANSPORT_TABLE.map((entry) => ({
|
|
44150
44430
|
flag: entry.token,
|
|
44151
44431
|
class: entry.class,
|
|
44152
44432
|
takesValue: entry.takesValue,
|
|
44153
44433
|
...entry.via === undefined ? {} : { via: entry.via },
|
|
44154
44434
|
...entry.launcherClass === undefined ? {} : { launcherClass: entry.launcherClass },
|
|
44155
|
-
...entry.reason === undefined ? {} : { reason: entry.reason },
|
|
44156
|
-
...entry.alternative === undefined ? {} : { alternative: entry.alternative },
|
|
44435
|
+
...entry.reason === undefined ? {} : { reason: fixed ? reasonFor(entry, product) : entry.reason },
|
|
44436
|
+
...entry.alternative === undefined ? {} : { alternative: fixed ? alternativeFor(entry, product) : entry.alternative },
|
|
44157
44437
|
...entry.notice === undefined ? {} : { notice: entry.notice },
|
|
44158
44438
|
...entry.note === undefined ? {} : { note: entry.note }
|
|
44159
44439
|
})),
|
|
44160
|
-
transportOnlyFlags: [...TRANSPORT_ONLY_FLAGS]
|
|
44440
|
+
transportOnlyFlags: fixed ? TRANSPORT_ONLY_FLAGS.filter((flag) => flag !== "--preset" && flag !== "--sandbox") : [...TRANSPORT_ONLY_FLAGS]
|
|
44161
44441
|
};
|
|
44162
44442
|
}
|
|
44163
44443
|
|
|
@@ -44207,6 +44487,7 @@ async function runCli(argv, cliVersion) {
|
|
|
44207
44487
|
addGlobalOptions(program).name("mutagent").description(`Mutagent runs AI coding agents in cloud sandboxes. Helix is its coding agent:
|
|
44208
44488
|
mutagent helix runs Helix on your task in a sandbox in your workspace.
|
|
44209
44489
|
Prime is Helix's lean agent: mutagent helix --prime runs it instead of the full orchestrator.
|
|
44490
|
+
mutagent architech runs the Architech harness the same way (the cloud form of the local architech).
|
|
44210
44491
|
A managed agent is an agent.md folder deployed with mutagent agent deploy.
|
|
44211
44492
|
|
|
44212
44493
|
Documentation: https://docs.mutagent.io/cli
|
|
@@ -44259,7 +44540,7 @@ ${chalk77.yellow("AI Agent Directive:")}
|
|
|
44259
44540
|
1. Sign in: with MUTAGENT_API_KEY set, run mutagent login --json. To help a user sign in,
|
|
44260
44541
|
run mutagent login --browser --json, show the printed URL to the user verbatim, and
|
|
44261
44542
|
wait: the CLI polls for up to 5 minutes.
|
|
44262
|
-
2. Pass --json to every command except a mutagent helix launch (-p, --mode json or rpc), whose output is
|
|
44543
|
+
2. Pass --json to every command except a mutagent helix or mutagent architech launch (-p, --mode json or rpc), whose output is the harness's own.
|
|
44263
44544
|
3. Run <command> --help before the first use of a command.
|
|
44264
44545
|
4. A --json response may carry _directive.renderedCard (a status card: copy it into your chat
|
|
44265
44546
|
reply verbatim before running another command), _directive.instruction (what to do next),
|
|
@@ -44283,9 +44564,10 @@ ${!hasCredentials() ? `
|
|
|
44283
44564
|
}
|
|
44284
44565
|
process.exit(0);
|
|
44285
44566
|
}
|
|
44286
|
-
const
|
|
44287
|
-
|
|
44288
|
-
|
|
44567
|
+
const helpJsonProduct = cloudHelpJsonProduct(rawArgs);
|
|
44568
|
+
const helixHelpJson = helpJsonProduct !== undefined;
|
|
44569
|
+
if (helpJsonProduct !== undefined) {
|
|
44570
|
+
process.stdout.write(`${JSON.stringify(helixCloudSurface(cliVersion, helpJsonProduct))}
|
|
44289
44571
|
`);
|
|
44290
44572
|
}
|
|
44291
44573
|
const rootOptionError = forwardedRootOptionRefusal(rawArgs);
|
|
@@ -44345,4 +44627,4 @@ if (process.env.CLI_VERSION) {
|
|
|
44345
44627
|
}
|
|
44346
44628
|
runCli(process.argv.slice(2), cliVersion);
|
|
44347
44629
|
|
|
44348
|
-
//# debugId=
|
|
44630
|
+
//# debugId=BBE3EBCBEECE0C5A64756E2164756E21
|