@mutagent/cli 0.1.351 → 0.1.353
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/cli.js +116 -120
- package/dist/index.js +7 -7
- package/package.json +2 -2
package/dist/bin/cli.js
CHANGED
|
@@ -16783,7 +16783,7 @@ var init_sdk_debug = __esm(() => {
|
|
|
16783
16783
|
});
|
|
16784
16784
|
|
|
16785
16785
|
// src/lib/sdk-mappers.ts
|
|
16786
|
-
import {
|
|
16786
|
+
import { LlmProviderType as SDKProviderEnum } from "@mutagent/sdk/models";
|
|
16787
16787
|
function isProviderType(value2) {
|
|
16788
16788
|
return PROVIDER_TYPES.includes(value2);
|
|
16789
16789
|
}
|
|
@@ -17096,7 +17096,7 @@ class SDKClientWrapper {
|
|
|
17096
17096
|
}
|
|
17097
17097
|
async listProviders(filters) {
|
|
17098
17098
|
try {
|
|
17099
|
-
const response = await this.sdk.
|
|
17099
|
+
const response = await this.sdk.llmProviders.listProviderConfigs({
|
|
17100
17100
|
provider: filters?.type,
|
|
17101
17101
|
includeInactive: true
|
|
17102
17102
|
});
|
|
@@ -17114,7 +17114,7 @@ class SDKClientWrapper {
|
|
|
17114
17114
|
}
|
|
17115
17115
|
async getProvider(id) {
|
|
17116
17116
|
try {
|
|
17117
|
-
const response = await this.sdk.
|
|
17117
|
+
const response = await this.sdk.llmProviders.getProviderConfig({
|
|
17118
17118
|
id
|
|
17119
17119
|
});
|
|
17120
17120
|
return toProvider(response);
|
|
@@ -17190,7 +17190,7 @@ class SDKClientWrapper {
|
|
|
17190
17190
|
}
|
|
17191
17191
|
async testProvider(id) {
|
|
17192
17192
|
try {
|
|
17193
|
-
const response = await this.sdk.
|
|
17193
|
+
const response = await this.sdk.llmProviders.testProviderConfig({
|
|
17194
17194
|
id
|
|
17195
17195
|
});
|
|
17196
17196
|
return toProviderTestResult(response);
|
|
@@ -17236,7 +17236,7 @@ class SDKClientWrapper {
|
|
|
17236
17236
|
});
|
|
17237
17237
|
return scrubKnownSuccessDeep({ ...response2, workspaceId });
|
|
17238
17238
|
}
|
|
17239
|
-
const response = await this.sdk.
|
|
17239
|
+
const response = await this.sdk.llmProviders.updateProviderConfig({
|
|
17240
17240
|
id,
|
|
17241
17241
|
body: {
|
|
17242
17242
|
name: data.name,
|
|
@@ -17255,7 +17255,7 @@ class SDKClientWrapper {
|
|
|
17255
17255
|
async deleteProvider(id) {
|
|
17256
17256
|
const workspaceId = this.requireUnambiguousWorkspace();
|
|
17257
17257
|
try {
|
|
17258
|
-
await this.sdk.
|
|
17258
|
+
await this.sdk.llmProviders.deleteProviderConfig({ id });
|
|
17259
17259
|
return { workspaceId };
|
|
17260
17260
|
} catch (error3) {
|
|
17261
17261
|
this.handleError(error3);
|
|
@@ -17403,7 +17403,7 @@ function sessionView(row) {
|
|
|
17403
17403
|
return { ...row, revision: nullableInteger(row.revision) };
|
|
17404
17404
|
}
|
|
17405
17405
|
function bindAgentDeploymentSDK(sdk, endpoint, workspaceId) {
|
|
17406
|
-
const client = sdk.
|
|
17406
|
+
const client = sdk.managedAgents;
|
|
17407
17407
|
return {
|
|
17408
17408
|
endpoint,
|
|
17409
17409
|
workspaceId,
|
|
@@ -17540,8 +17540,8 @@ Run a managed agent with: mutagent helix agent @slug[:vN|:latest] [--env X] -p "
|
|
|
17540
17540
|
|
|
17541
17541
|
The compiler needs Bun 1.3.14 (on PATH, or MUTAGENT_BUN_BIN). agent run needs a
|
|
17542
17542
|
local Helix binary (mutagent install helix puts one at ~/.mutagent/bin/helix;
|
|
17543
|
-
MUTAGENT_HELIX_BIN selects another) and
|
|
17544
|
-
|
|
17543
|
+
MUTAGENT_HELIX_BIN selects another) and, on this machine, the key of the
|
|
17544
|
+
LLM provider that model names.
|
|
17545
17545
|
|
|
17546
17546
|
JSON: --json prints one result object on stdout. Revisions are numbers in JSON
|
|
17547
17547
|
and vN in messages.
|
|
@@ -17565,7 +17565,7 @@ uploaded. The archive must be outside the agent folder; an existing file needs
|
|
|
17565
17565
|
--force.
|
|
17566
17566
|
Example: mutagent agent pack invoice/agent.md --output invoice.tgz --json`,
|
|
17567
17567
|
run: `Compiles the folder and runs the task with the local Helix binary, in a
|
|
17568
|
-
temporary copy of the package on this machine; it is not isolated in a
|
|
17568
|
+
temporary copy of the package on this machine; it is not isolated in a sandbox. It
|
|
17569
17569
|
creates nothing in the workspace. The task is the positional text (or the words
|
|
17570
17570
|
after --). A slug is refused: a managed agent runs with mutagent helix agent @slug.
|
|
17571
17571
|
Example: mutagent agent run invoice/agent.md "Price three widget units."`,
|
|
@@ -19231,7 +19231,7 @@ init_sdk_client();
|
|
|
19231
19231
|
import { Command as Command6 } from "commander";
|
|
19232
19232
|
import chalk12 from "chalk";
|
|
19233
19233
|
init_errors();
|
|
19234
|
-
import {
|
|
19234
|
+
import { LlmProviderType as ProviderCatalogId } from "@mutagent/sdk/models";
|
|
19235
19235
|
|
|
19236
19236
|
// src/commands/providers/add.ts
|
|
19237
19237
|
init_sdk_client();
|
|
@@ -19744,7 +19744,7 @@ AI Agent Directive:
|
|
|
19744
19744
|
const isGateway = allowedFamilies !== undefined;
|
|
19745
19745
|
if (options.hostedFamily) {
|
|
19746
19746
|
if (!isGateway) {
|
|
19747
|
-
throw new MutagentError("HOSTED_FAMILY_NOT_APPLICABLE", `'${providerType}' serves its own models, so it has no hosted family.`, `Drop --hosted-family, or pick a gateway provider: ${[...GATEWAY_PROVIDERS].join(", ")}`);
|
|
19747
|
+
throw new MutagentError("HOSTED_FAMILY_NOT_APPLICABLE", `'${providerType}' serves its own models, so it has no hosted family.`, `Drop --hosted-family, or pick a gateway LLM provider: ${[...GATEWAY_PROVIDERS].join(", ")}`);
|
|
19748
19748
|
}
|
|
19749
19749
|
if (!allowedFamilies.includes(options.hostedFamily)) {
|
|
19750
19750
|
throw new MutagentError("INVALID_HOSTED_FAMILY", `'${providerType}' does not host '${options.hostedFamily}'.`, `${providerType} hosts: ${allowedFamilies.join(", ")}`);
|
|
@@ -19780,7 +19780,7 @@ AI Agent Directive:
|
|
|
19780
19780
|
_directive: directive
|
|
19781
19781
|
});
|
|
19782
19782
|
} else {
|
|
19783
|
-
output.success(`
|
|
19783
|
+
output.success(`LLM provider created: ${created.name}`);
|
|
19784
19784
|
console.log(` ID: ${created.id}`);
|
|
19785
19785
|
console.log(` Type: ${providerType}`);
|
|
19786
19786
|
if (options.hostedFamily) {
|
|
@@ -19792,7 +19792,7 @@ AI Agent Directive:
|
|
|
19792
19792
|
console.log(` Workspace: ${workspaceId}`);
|
|
19793
19793
|
console.log(` URL: ${providerLink(created.id)}`);
|
|
19794
19794
|
if (options.setDefault) {
|
|
19795
|
-
console.log(chalk8.green(" Set as default provider"));
|
|
19795
|
+
console.log(chalk8.green(" Set as the default LLM provider"));
|
|
19796
19796
|
}
|
|
19797
19797
|
console.log("");
|
|
19798
19798
|
console.log(chalk8.dim("API key is encrypted server-side. Use `providers get` to see masked key."));
|
|
@@ -19803,12 +19803,12 @@ AI Agent Directive:
|
|
|
19803
19803
|
});
|
|
19804
19804
|
}
|
|
19805
19805
|
function buildProviderCreatedDirective(provider, workspaceId) {
|
|
19806
|
-
const title = `
|
|
19806
|
+
const title = `LLM provider created: ${provider.name ?? "Unknown"}`;
|
|
19807
19807
|
const dashboardUrl = providerLink(provider.id);
|
|
19808
19808
|
const apiUrl = `/api/providers/${String(provider.id)}`;
|
|
19809
19809
|
const rows = [
|
|
19810
19810
|
{ label: "Name", value: provider.name ?? "Unknown" },
|
|
19811
|
-
{ label: "
|
|
19811
|
+
{ label: "LLM provider ID", value: String(provider.id) },
|
|
19812
19812
|
{ label: "Workspace", value: workspaceId }
|
|
19813
19813
|
];
|
|
19814
19814
|
const links = [
|
|
@@ -19888,7 +19888,7 @@ Only the fields you pass change. An update never sets the workspace default mode
|
|
|
19888
19888
|
_directive: directive
|
|
19889
19889
|
});
|
|
19890
19890
|
} else {
|
|
19891
|
-
output.success(`
|
|
19891
|
+
output.success(`LLM provider updated: ${updated.name}`);
|
|
19892
19892
|
console.log(` ID: ${updated.id}`);
|
|
19893
19893
|
if (updated.workspaceId) {
|
|
19894
19894
|
console.log(` Workspace: ${updated.workspaceId}`);
|
|
@@ -19905,11 +19905,11 @@ Only the fields you pass change. An update never sets the workspace default mode
|
|
|
19905
19905
|
}
|
|
19906
19906
|
function buildProviderUpdatedDirective(provider, requestId) {
|
|
19907
19907
|
const id = provider.id ?? requestId;
|
|
19908
|
-
const title = `
|
|
19908
|
+
const title = `LLM provider updated: ${provider.name ?? String(id)}`;
|
|
19909
19909
|
const dashboardUrl = providerLink(id);
|
|
19910
19910
|
const apiUrl = `/api/providers/${String(id)}`;
|
|
19911
19911
|
const rows = [
|
|
19912
|
-
{ label: "
|
|
19912
|
+
{ label: "LLM provider ID", value: String(id) },
|
|
19913
19913
|
...provider.name ? [{ label: "Name", value: provider.name }] : []
|
|
19914
19914
|
];
|
|
19915
19915
|
const links = [
|
|
@@ -19952,7 +19952,7 @@ AI Agent Directive:
|
|
|
19952
19952
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
19953
19953
|
try {
|
|
19954
19954
|
if (!options.force && !isJson) {
|
|
19955
|
-
throw new MutagentError("CONFIRMATION_REQUIRED", `Deleting provider ${id} requires confirmation. ` + "Warning: encrypted API keys are irrecoverable after deletion.", `Run: mutagent providers delete --help
|
|
19955
|
+
throw new MutagentError("CONFIRMATION_REQUIRED", `Deleting LLM provider ${id} requires confirmation. ` + "Warning: encrypted API keys are irrecoverable after deletion.", `Run: mutagent providers delete --help
|
|
19956
19956
|
` + `[Agent: Ask the user to confirm via MultiChoice, then pass --force]
|
|
19957
19957
|
` + `Use --force to confirm: mutagent providers delete ${id} --force`);
|
|
19958
19958
|
}
|
|
@@ -19972,7 +19972,7 @@ AI Agent Directive:
|
|
|
19972
19972
|
});
|
|
19973
19973
|
echoDirectiveToStderr(directive);
|
|
19974
19974
|
} else {
|
|
19975
|
-
output.success(`
|
|
19975
|
+
output.success(`LLM provider ${id} already deleted (idempotent)`);
|
|
19976
19976
|
}
|
|
19977
19977
|
return;
|
|
19978
19978
|
}
|
|
@@ -19988,7 +19988,7 @@ AI Agent Directive:
|
|
|
19988
19988
|
_directive: directive
|
|
19989
19989
|
});
|
|
19990
19990
|
} else {
|
|
19991
|
-
output.success(`Deleted provider: ${id}`);
|
|
19991
|
+
output.success(`Deleted LLM provider: ${id}`);
|
|
19992
19992
|
if (deletedFrom) {
|
|
19993
19993
|
console.log(` Workspace: ${deletedFrom}`);
|
|
19994
19994
|
}
|
|
@@ -20000,9 +20000,9 @@ AI Agent Directive:
|
|
|
20000
20000
|
});
|
|
20001
20001
|
}
|
|
20002
20002
|
function buildProviderDeletedDirective(id) {
|
|
20003
|
-
const title = `
|
|
20003
|
+
const title = `LLM provider deleted: ${id}`;
|
|
20004
20004
|
const settingsUrl = providerSettingsLink();
|
|
20005
|
-
const rows = [{ label: "
|
|
20005
|
+
const rows = [{ label: "LLM provider ID", value: id }];
|
|
20006
20006
|
const links = [{ label: "Settings", url: settingsUrl }];
|
|
20007
20007
|
const next = [`mutagent providers list --json`];
|
|
20008
20008
|
return {
|
|
@@ -20784,7 +20784,7 @@ Plan:`));
|
|
|
20784
20784
|
output.output({
|
|
20785
20785
|
success: failed.length === 0,
|
|
20786
20786
|
cloudExecution: "not-verified",
|
|
20787
|
-
modelRoster: "Explicit lists are authoritative; recognized native identities use the service-pinned catalogue when no list is declared. Other custom providers require declarations.",
|
|
20787
|
+
modelRoster: "Explicit lists are authoritative; recognized native identities use the service-pinned catalogue when no list is declared. Other custom LLM providers require declarations.",
|
|
20788
20788
|
workspaceId: target,
|
|
20789
20789
|
endpoint: config.endpoint ?? "https://api.mutagent.io",
|
|
20790
20790
|
agentDir,
|
|
@@ -20825,7 +20825,7 @@ var VALID_PROVIDER_TYPES = Object.values(ProviderCatalogId);
|
|
|
20825
20825
|
function validateProviderType(type4) {
|
|
20826
20826
|
const match = VALID_PROVIDER_TYPES.find((entry) => entry === type4);
|
|
20827
20827
|
if (!match) {
|
|
20828
|
-
throw new MutagentError("INVALID_PROVIDER_TYPE", `Invalid provider type: ${type4}`, `Valid types: ${VALID_PROVIDER_TYPES.join(", ")}`);
|
|
20828
|
+
throw new MutagentError("INVALID_PROVIDER_TYPE", `Invalid LLM provider type: ${type4}`, `Valid types: ${VALID_PROVIDER_TYPES.join(", ")}`);
|
|
20829
20829
|
}
|
|
20830
20830
|
return match;
|
|
20831
20831
|
}
|
|
@@ -20903,7 +20903,7 @@ Examples:
|
|
|
20903
20903
|
output.output({ ...result, data: withLinks });
|
|
20904
20904
|
} else {
|
|
20905
20905
|
if (result.data.length === 0) {
|
|
20906
|
-
output.info("No providers configured.");
|
|
20906
|
+
output.info("No LLM providers configured.");
|
|
20907
20907
|
output.info(`Configure at: ${providerSettingsLink()}`);
|
|
20908
20908
|
} else {
|
|
20909
20909
|
const formatted = result.data.map((p) => ({
|
|
@@ -20966,7 +20966,7 @@ ${chalk12.dim("Tests the connection and lists the models the LLM provider report
|
|
|
20966
20966
|
try {
|
|
20967
20967
|
const client = await getSDKClient();
|
|
20968
20968
|
if (!isJson) {
|
|
20969
|
-
output.info(`Testing provider ${id}...`);
|
|
20969
|
+
output.info(`Testing LLM provider ${id}...`);
|
|
20970
20970
|
}
|
|
20971
20971
|
const result = scrubKnownSuccessDeep(await client.testProvider(id));
|
|
20972
20972
|
if (isJson) {
|
|
@@ -20974,7 +20974,7 @@ ${chalk12.dim("Tests the connection and lists the models the LLM provider report
|
|
|
20974
20974
|
} else {
|
|
20975
20975
|
if (result.success) {
|
|
20976
20976
|
const latency = typeof result.latencyMs === "number" ? ` (${String(result.latencyMs)}ms)` : "";
|
|
20977
|
-
output.success(`
|
|
20977
|
+
output.success(`LLM provider test passed${latency}`);
|
|
20978
20978
|
console.log(chalk12.green(`Message: ${result.message}`));
|
|
20979
20979
|
if (result.models && result.models.length > 0) {
|
|
20980
20980
|
console.log(chalk12.bold(`
|
|
@@ -20984,7 +20984,7 @@ Available Models:`));
|
|
|
20984
20984
|
});
|
|
20985
20985
|
}
|
|
20986
20986
|
} else {
|
|
20987
|
-
output.error(`
|
|
20987
|
+
output.error(`LLM provider test failed: ${result.message}`);
|
|
20988
20988
|
if (result.error) {
|
|
20989
20989
|
console.log(chalk12.red(`Error: ${result.error}`));
|
|
20990
20990
|
}
|
|
@@ -23868,13 +23868,13 @@ var TRANSPORT_TABLE = [
|
|
|
23868
23868
|
takesValue: false,
|
|
23869
23869
|
class: "cross",
|
|
23870
23870
|
via: "args",
|
|
23871
|
-
note: "The
|
|
23871
|
+
note: "The sandbox runs the same launcher, so its diagnostics flag means the same there."
|
|
23872
23872
|
},
|
|
23873
23873
|
{
|
|
23874
23874
|
token: "--refresh-runtime",
|
|
23875
23875
|
takesValue: false,
|
|
23876
23876
|
class: "reject",
|
|
23877
|
-
reason: "the
|
|
23877
|
+
reason: "the sandbox image already contains Helix",
|
|
23878
23878
|
alternative: "The image pins its own Helix build; see `mutagent sandbox presets`."
|
|
23879
23879
|
},
|
|
23880
23880
|
{
|
|
@@ -23895,7 +23895,7 @@ var TRANSPORT_TABLE = [
|
|
|
23895
23895
|
takesValue: true,
|
|
23896
23896
|
class: "translate",
|
|
23897
23897
|
launcherClass: "cross",
|
|
23898
|
-
note: "On `helix agent`, the definition selector: resolved against the LOCAL agent dirs when this machine has it
|
|
23898
|
+
note: "On `helix agent`, the definition selector: resolved against the LOCAL agent dirs when this machine has it, and the definition body is sent, because the sandbox would resolve the same name to its BUNDLED agent first. A name not found here is sent as `--name <name>` in args and the sandbox resolves it (bundled roster, then its agent dirs); the sandbox refuses an unknown name rather than running a different one. See agent-argv.ts. On the launcher arms (bare `helix`, `helix --prime`), pi’s session label, forwarded as typed like `-n`."
|
|
23899
23899
|
},
|
|
23900
23900
|
{
|
|
23901
23901
|
token: "--agent",
|
|
@@ -23920,21 +23920,21 @@ var TRANSPORT_TABLE = [
|
|
|
23920
23920
|
token: "--api-key",
|
|
23921
23921
|
takesValue: true,
|
|
23922
23922
|
class: "reject",
|
|
23923
|
-
reason: "it would
|
|
23923
|
+
reason: "it would send an LLM provider key over the network and show it in the sandbox’s process list",
|
|
23924
23924
|
alternative: "An LLM key for a cloud run belongs in the workspace’s LLM providers: `mutagent providers add -k <key> …`, or `mutagent providers mirror` to copy your local Helix logins."
|
|
23925
23925
|
},
|
|
23926
23926
|
{
|
|
23927
23927
|
token: "--list-models",
|
|
23928
23928
|
takesValue: true,
|
|
23929
23929
|
class: "reject",
|
|
23930
|
-
reason: "it prints
|
|
23931
|
-
alternative: "Run
|
|
23930
|
+
reason: "it prints the model list and exits; a cloud run would start a sandbox for it",
|
|
23931
|
+
alternative: "Run: mutagent helix models"
|
|
23932
23932
|
},
|
|
23933
23933
|
{
|
|
23934
23934
|
token: "--system-prompt",
|
|
23935
23935
|
takesValue: true,
|
|
23936
23936
|
class: "translate",
|
|
23937
|
-
note: "
|
|
23937
|
+
note: "A value that names a local file is read here and sent as text; any other value is sent as it is."
|
|
23938
23938
|
},
|
|
23939
23939
|
{
|
|
23940
23940
|
token: "--append-system-prompt",
|
|
@@ -23958,7 +23958,7 @@ var TRANSPORT_TABLE = [
|
|
|
23958
23958
|
takesValue: false,
|
|
23959
23959
|
class: "cross",
|
|
23960
23960
|
via: "args",
|
|
23961
|
-
note: "Same flag as --no-skills.
|
|
23961
|
+
note: "Same flag as --no-skills. Turns off the skills in the sandbox image."
|
|
23962
23962
|
},
|
|
23963
23963
|
{ token: "--no-prompt-templates", takesValue: false, class: "cross", via: "args" },
|
|
23964
23964
|
{ token: "-np", takesValue: false, class: "cross", via: "args" },
|
|
@@ -24011,7 +24011,7 @@ var TRANSPORT_TABLE = [
|
|
|
24011
24011
|
token: "--tui-mode",
|
|
24012
24012
|
takesValue: true,
|
|
24013
24013
|
class: "reject",
|
|
24014
|
-
reason: "
|
|
24014
|
+
reason: "a cloud run has no terminal",
|
|
24015
24015
|
alternative: "Drop it."
|
|
24016
24016
|
},
|
|
24017
24017
|
{
|
|
@@ -24026,14 +24026,14 @@ var TRANSPORT_TABLE = [
|
|
|
24026
24026
|
takesValue: true,
|
|
24027
24027
|
class: "reject",
|
|
24028
24028
|
reason: HOST_PATH,
|
|
24029
|
-
alternative: "Capture the session you want to fork with `mutagent helix session checkpoint`, then restore it into a new
|
|
24029
|
+
alternative: "Capture the session you want to fork with `mutagent helix session checkpoint`, then restore it into a new sandbox."
|
|
24030
24030
|
},
|
|
24031
24031
|
{
|
|
24032
24032
|
token: "--session-dir",
|
|
24033
24033
|
takesValue: true,
|
|
24034
24034
|
class: "reject",
|
|
24035
24035
|
reason: HOST_PATH,
|
|
24036
|
-
alternative: "Sessions
|
|
24036
|
+
alternative: "Sessions are stored inside the sandbox; read them with `mutagent sandbox exec --sandbox <id>`."
|
|
24037
24037
|
},
|
|
24038
24038
|
{ token: "--no-session", takesValue: false, class: "cross", via: "args" },
|
|
24039
24039
|
{ token: "--session-id", takesValue: true, class: "cross", via: "args" },
|
|
@@ -24048,15 +24048,15 @@ var TRANSPORT_TABLE = [
|
|
|
24048
24048
|
token: "--continue",
|
|
24049
24049
|
takesValue: false,
|
|
24050
24050
|
class: "reject",
|
|
24051
|
-
reason: "there is no previous session in a
|
|
24052
|
-
alternative: "Run against a
|
|
24051
|
+
reason: "there is no previous session in a new sandbox to continue",
|
|
24052
|
+
alternative: "Run against a sandbox you kept: `mutagent helix agent --sandbox <id> …`, or restore a checkpoint."
|
|
24053
24053
|
},
|
|
24054
24054
|
{
|
|
24055
24055
|
token: "-c",
|
|
24056
24056
|
takesValue: false,
|
|
24057
24057
|
class: "reject",
|
|
24058
|
-
reason: "there is no previous session in a
|
|
24059
|
-
alternative: "Run against a
|
|
24058
|
+
reason: "there is no previous session in a new sandbox to continue",
|
|
24059
|
+
alternative: "Run against a sandbox you kept: `mutagent helix agent --sandbox <id> …`, or restore a checkpoint."
|
|
24060
24060
|
},
|
|
24061
24061
|
{
|
|
24062
24062
|
token: "--resume",
|
|
@@ -24076,7 +24076,7 @@ var TRANSPORT_TABLE = [
|
|
|
24076
24076
|
token: "--export",
|
|
24077
24077
|
takesValue: true,
|
|
24078
24078
|
class: "reject",
|
|
24079
|
-
reason: "it writes a file on the machine the harness runs on, which is the
|
|
24079
|
+
reason: "it writes a file on the machine the harness runs on, which is the sandbox; the file is deleted with it",
|
|
24080
24080
|
alternative: "Capture the stream instead: `mutagent helix agent … --json > run.ndjson`."
|
|
24081
24081
|
},
|
|
24082
24082
|
{ token: "--verbose", takesValue: false, class: "cross", via: "args" },
|
|
@@ -24085,26 +24085,26 @@ var TRANSPORT_TABLE = [
|
|
|
24085
24085
|
token: "--approve",
|
|
24086
24086
|
takesValue: false,
|
|
24087
24087
|
class: "drop",
|
|
24088
|
-
notice: "--approve is
|
|
24088
|
+
notice: "--approve is ignored: a cloud sandbox always trusts the project."
|
|
24089
24089
|
},
|
|
24090
24090
|
{
|
|
24091
24091
|
token: "-a",
|
|
24092
24092
|
takesValue: false,
|
|
24093
24093
|
class: "drop",
|
|
24094
|
-
notice: "-a is
|
|
24094
|
+
notice: "-a is ignored: a cloud sandbox always trusts the project."
|
|
24095
24095
|
},
|
|
24096
24096
|
{
|
|
24097
24097
|
token: "--no-approve",
|
|
24098
24098
|
takesValue: false,
|
|
24099
24099
|
class: "reject",
|
|
24100
|
-
reason: "
|
|
24100
|
+
reason: "without project trust the agent cannot read the workspace, and a cloud run cannot ask you for it",
|
|
24101
24101
|
alternative: "Drop it, or restrict the agent with --tools / --exclude-tools instead."
|
|
24102
24102
|
},
|
|
24103
24103
|
{
|
|
24104
24104
|
token: "-na",
|
|
24105
24105
|
takesValue: false,
|
|
24106
24106
|
class: "reject",
|
|
24107
|
-
reason: "
|
|
24107
|
+
reason: "without project trust the agent cannot read the workspace, and a cloud run cannot ask you for it",
|
|
24108
24108
|
alternative: "Drop it, or restrict the agent with --tools / --exclude-tools instead."
|
|
24109
24109
|
},
|
|
24110
24110
|
{
|
|
@@ -24239,13 +24239,13 @@ function argumentLabel(args, i, files) {
|
|
|
24239
24239
|
function checkArgsForRoute(args, files = []) {
|
|
24240
24240
|
args.forEach((arg, i) => {
|
|
24241
24241
|
if (arg === "") {
|
|
24242
|
-
throw new MutagentError("INVALID_ARGUMENTS", `${argumentLabel(args, i, files)} is empty, and a session
|
|
24242
|
+
throw new MutagentError("INVALID_ARGUMENTS", `${argumentLabel(args, i, files)} is empty, and a cloud session refuses an empty argument.`, "Give it a value, or drop the flag.", 2);
|
|
24243
24243
|
}
|
|
24244
24244
|
});
|
|
24245
24245
|
}
|
|
24246
24246
|
function checkSandboxId(value2) {
|
|
24247
24247
|
if (value2?.trim().startsWith("-") === true) {
|
|
24248
|
-
throw new MutagentError("INVALID_ARGUMENTS", `--sandbox needs a sandbox id, and got a flag instead: ${redactToken(value2.trim())}`, "Name the
|
|
24248
|
+
throw new MutagentError("INVALID_ARGUMENTS", `--sandbox needs a sandbox id, and got a flag instead: ${redactToken(value2.trim())}`, "Name the sandbox: --sandbox <id>. 'mutagent sandbox ls' shows the running ones.", 2);
|
|
24249
24249
|
}
|
|
24250
24250
|
}
|
|
24251
24251
|
|
|
@@ -24321,7 +24321,7 @@ function planAgentArgv(argv, deps, flags = {}) {
|
|
|
24321
24321
|
continue;
|
|
24322
24322
|
}
|
|
24323
24323
|
if (token.startsWith("@")) {
|
|
24324
|
-
throw rejection(redactToken(token), "an @file argument is read from the machine the harness runs on, and the
|
|
24324
|
+
throw rejection(redactToken(token), "an @file argument is read from the machine the harness runs on, and the sandbox has no copy of it", "Inline the file’s contents into the task, or `mutagent sandbox exec` it into a sandbox you kept. File upload does not exist yet.");
|
|
24325
24325
|
}
|
|
24326
24326
|
if (token.startsWith("--")) {
|
|
24327
24327
|
forwardFlag(token);
|
|
@@ -24333,7 +24333,7 @@ function planAgentArgv(argv, deps, flags = {}) {
|
|
|
24333
24333
|
continue;
|
|
24334
24334
|
}
|
|
24335
24335
|
if (token.startsWith("-")) {
|
|
24336
|
-
throw rejection(redactToken(token), "the harness rejects unknown short options outright, so forwarding it would fail inside the
|
|
24336
|
+
throw rejection(redactToken(token), "the harness rejects unknown short options outright, so forwarding it would fail inside the sandbox instead of here", "Check the spelling against `helix agent --help`, or use the long form.");
|
|
24337
24337
|
}
|
|
24338
24338
|
if (i === 0 && source2 === undefined) {
|
|
24339
24339
|
source2 = { kind: "prompt", value: token };
|
|
@@ -24405,7 +24405,7 @@ function planAgentArgv(argv, deps, flags = {}) {
|
|
|
24405
24405
|
};
|
|
24406
24406
|
}
|
|
24407
24407
|
function rejection(token, reason, alternative) {
|
|
24408
|
-
return new MutagentError("INVALID_ARGUMENTS", `${token}
|
|
24408
|
+
return new MutagentError("INVALID_ARGUMENTS", `${token} is not supported in a cloud run: ${reason}.`, alternative, 2);
|
|
24409
24409
|
}
|
|
24410
24410
|
function resolveDefinition(source2, deps) {
|
|
24411
24411
|
if (source2 === undefined) {
|
|
@@ -24435,7 +24435,7 @@ function resolveDefinition(source2, deps) {
|
|
|
24435
24435
|
const path = findAgentFile(source2.value, roots, deps);
|
|
24436
24436
|
if (path === undefined) {
|
|
24437
24437
|
return {
|
|
24438
|
-
origin: `--name ${source2.value} (not on this machine; resolved
|
|
24438
|
+
origin: `--name ${source2.value} (not on this machine; resolved in the sandbox; searched: ${roots.join(", ")})`,
|
|
24439
24439
|
forwardName: source2.value
|
|
24440
24440
|
};
|
|
24441
24441
|
}
|
|
@@ -24521,14 +24521,14 @@ function nativeMode(args, print, rpc = false) {
|
|
|
24521
24521
|
return "json";
|
|
24522
24522
|
if (print)
|
|
24523
24523
|
return "text";
|
|
24524
|
-
throw new MutagentError("NOT_SUPPORTED", "
|
|
24524
|
+
throw new MutagentError("NOT_SUPPORTED", "mutagent helix has no terminal chat UI.", 'Use -p "<task>" for a complete run, --mode json "<task>" for events, or --mode rpc with a JSONL client.', 2);
|
|
24525
24525
|
}
|
|
24526
24526
|
function nativeTaskNotices(mode, messages) {
|
|
24527
24527
|
if (mode === "rpc") {
|
|
24528
|
-
return messages.length === 0 ? [] : ["
|
|
24528
|
+
return messages.length === 0 ? [] : ["An interactive session ignores positional messages; send the task as a prompt command on stdin."];
|
|
24529
24529
|
}
|
|
24530
24530
|
if (!messages.some((message) => message.trim() !== "")) {
|
|
24531
|
-
throw new MutagentError("MISSING_ARGUMENTS", "A
|
|
24531
|
+
throw new MutagentError("MISSING_ARGUMENTS", "A headless cloud run needs a task.", 'Add -p "<task>" or use --mode json "<task>".', 2);
|
|
24532
24532
|
}
|
|
24533
24533
|
return [];
|
|
24534
24534
|
}
|
|
@@ -24947,7 +24947,7 @@ function parseSessionPayload(data) {
|
|
|
24947
24947
|
const record3 = parseRecord(data);
|
|
24948
24948
|
if (!record3)
|
|
24949
24949
|
return null;
|
|
24950
|
-
const { seq, ts: ts2, sessionId, status, exitCode, lastSeq, generation } = record3;
|
|
24950
|
+
const { seq, ts: ts2, sessionId, status, exitCode, lastSeq, generation, mode } = record3;
|
|
24951
24951
|
if (typeof seq !== "number" || typeof sessionId !== "string" || typeof status !== "string") {
|
|
24952
24952
|
return null;
|
|
24953
24953
|
}
|
|
@@ -24958,7 +24958,8 @@ function parseSessionPayload(data) {
|
|
|
24958
24958
|
status,
|
|
24959
24959
|
exitCode: typeof exitCode === "number" ? exitCode : null,
|
|
24960
24960
|
lastSeq: typeof lastSeq === "number" ? lastSeq : -1,
|
|
24961
|
-
generation: typeof generation === "number" ? generation : 0
|
|
24961
|
+
generation: typeof generation === "number" ? generation : 0,
|
|
24962
|
+
...typeof mode === "string" ? { mode } : {}
|
|
24962
24963
|
};
|
|
24963
24964
|
}
|
|
24964
24965
|
function parseLivePayload(data) {
|
|
@@ -25315,7 +25316,7 @@ async function runStreamSession(options) {
|
|
|
25315
25316
|
break;
|
|
25316
25317
|
}
|
|
25317
25318
|
if (!alreadyDelivered(payload2.seq)) {
|
|
25318
|
-
sink.notice(`Session ${payload2.sessionId} started.`);
|
|
25319
|
+
sink.notice(`Session ${payload2.sessionId} started${payload2.mode === undefined ? "" : ` (${payload2.mode})`}.`);
|
|
25319
25320
|
}
|
|
25320
25321
|
continue;
|
|
25321
25322
|
}
|
|
@@ -25409,7 +25410,7 @@ function gapNotice(lastSeq, nextSeq) {
|
|
|
25409
25410
|
}
|
|
25410
25411
|
function exhausted(lastSeq, cause, onDisconnect) {
|
|
25411
25412
|
const detail = cause instanceof Error ? ` (${cause.message})` : "";
|
|
25412
|
-
const guidance = onDisconnect === "released" ? "This was a
|
|
25413
|
+
const guidance = onDisconnect === "released" ? "This was a single-command run: the server deletes the sandbox when the connection drops, so nothing is left running and there is nothing to re-attach to. Run the turn again, or use --no-stream to wait for the whole result in one reply." : `The sandbox is still running — nothing was destroyed. Resume with: mutagent sandbox attach <id> --since ${String(lastSeq)}`;
|
|
25413
25414
|
return new MutagentError("STREAM_DISCONNECTED", `Lost the sandbox stream and could not reconnect${detail}.`, guidance, 5);
|
|
25414
25415
|
}
|
|
25415
25416
|
function isGapError(payload) {
|
|
@@ -25526,11 +25527,11 @@ async function runNativeSession(options) {
|
|
|
25526
25527
|
}
|
|
25527
25528
|
const closed = await options.closeInput(inputController.signal);
|
|
25528
25529
|
if (!closed.closed) {
|
|
25529
|
-
throw new MutagentError("RPC_INPUT_REJECTED", "The session did not confirm stdin closure.", "
|
|
25530
|
+
throw new MutagentError("RPC_INPUT_REJECTED", "The session did not confirm stdin closure.", "Check the session: mutagent helix session ls. No signal was sent in place of EOF.", 1);
|
|
25530
25531
|
}
|
|
25531
25532
|
};
|
|
25532
25533
|
try {
|
|
25533
|
-
notice("Session " + options.reference + (options.interrupt === undefined ? ". Ctrl-C detaches." : ". Ctrl-C
|
|
25534
|
+
notice("Session " + options.reference + (options.interrupt === undefined ? ". Ctrl-C detaches." : ". Ctrl-C stops the session (SIGINT)."));
|
|
25534
25535
|
if (options.interruptRequested)
|
|
25535
25536
|
onSigint();
|
|
25536
25537
|
const result = await runStreamSession({
|
|
@@ -25610,15 +25611,15 @@ async function runCloudLaunch(plan, mode) {
|
|
|
25610
25611
|
checkArgsForRoute(plan.args);
|
|
25611
25612
|
const sandbox = plan.sandbox?.trim();
|
|
25612
25613
|
if (sandbox && plan.preset !== undefined) {
|
|
25613
|
-
throw new MutagentError("INVALID_ARGUMENTS", "--preset cannot select an existing --sandbox.", "Drop --sandbox for automatic placement, or drop --preset to use
|
|
25614
|
+
throw new MutagentError("INVALID_ARGUMENTS", "--preset cannot select an existing --sandbox.", "Drop --sandbox for automatic placement, or drop --preset to use that sandbox.", 2);
|
|
25614
25615
|
}
|
|
25615
25616
|
if (sandbox && plan.sandboxProvider !== undefined) {
|
|
25616
|
-
throw new MutagentError("INVALID_ARGUMENTS", "--sandbox-provider cannot select an existing --sandbox.", "Drop --sandbox to
|
|
25617
|
+
throw new MutagentError("INVALID_ARGUMENTS", "--sandbox-provider cannot select an existing --sandbox.", "Drop --sandbox to start a new sandbox on that sandbox provider, or drop --sandbox-provider to use that sandbox.", 2);
|
|
25617
25618
|
}
|
|
25618
25619
|
const args = plan.args;
|
|
25619
25620
|
const body = {
|
|
25620
25621
|
arm: plan.arm,
|
|
25621
|
-
mode: mode === "rpc" ? "
|
|
25622
|
+
mode: mode === "rpc" ? "interactive" : "headless",
|
|
25622
25623
|
...args.length === 0 ? {} : { args },
|
|
25623
25624
|
...plan.environment === undefined ? {} : { environment: plan.environment },
|
|
25624
25625
|
...plan.cwd === undefined ? {} : { cwd: plan.cwd }
|
|
@@ -25635,10 +25636,10 @@ async function runCloudLaunch(plan, mode) {
|
|
|
25635
25636
|
...plan.sandboxProvider === undefined ? {} : { sandboxProvider: plan.sandboxProvider }
|
|
25636
25637
|
});
|
|
25637
25638
|
if (!session.reference) {
|
|
25638
|
-
throw new MutagentError("INVALID_RESPONSE", "The server
|
|
25639
|
+
throw new MutagentError("INVALID_RESPONSE", "The server did not return a session reference.", "Run: mutagent helix doctor", 1);
|
|
25639
25640
|
}
|
|
25640
25641
|
if (session.arm !== plan.arm || session.mode !== body.mode) {
|
|
25641
|
-
throw new MutagentError("INVALID_RESPONSE", "The server started a different
|
|
25642
|
+
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: mutagent helix session ls", 1);
|
|
25642
25643
|
}
|
|
25643
25644
|
process.removeListener("SIGINT", queueInterrupt);
|
|
25644
25645
|
await attachLaunched({ reference: session.reference, sessionId: session.sessionId }, mode === "rpc", interruptRequested);
|
|
@@ -25665,16 +25666,15 @@ async function runManagedAgentLaunch(launch, write = (line) => {
|
|
|
25665
25666
|
...launch.sandboxProvider === undefined ? {} : { sandboxProvider: launch.sandboxProvider }
|
|
25666
25667
|
});
|
|
25667
25668
|
if (!session.reference || session.agent === undefined) {
|
|
25668
|
-
throw new MutagentError("INVALID_RESPONSE", "The server did not return a
|
|
25669
|
+
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.", 1);
|
|
25669
25670
|
}
|
|
25670
25671
|
if (session.arm !== "agent" || plan.mode !== undefined && session.mode !== plan.mode) {
|
|
25671
|
-
throw new MutagentError("INVALID_RESPONSE", "The server started a different
|
|
25672
|
+
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: mutagent helix session ls", 1);
|
|
25672
25673
|
}
|
|
25673
|
-
|
|
25674
|
-
write("[mutagent] " + JSON.stringify({ reference: session.reference, sandboxId: session.sandboxId, agent: session.agent, mode }) + `
|
|
25674
|
+
write("[mutagent] " + JSON.stringify({ reference: session.reference, sandboxId: session.sandboxId, agent: session.agent, mode: session.mode }) + `
|
|
25675
25675
|
`);
|
|
25676
25676
|
process.removeListener("SIGINT", queueInterrupt);
|
|
25677
|
-
await attachLaunched(session, session.mode === "
|
|
25677
|
+
await attachLaunched(session, session.mode === "interactive", interruptRequested);
|
|
25678
25678
|
return session;
|
|
25679
25679
|
} finally {
|
|
25680
25680
|
process.removeListener("SIGINT", queueInterrupt);
|
|
@@ -25749,14 +25749,14 @@ function planManagedAgentRun(argv, flags) {
|
|
|
25749
25749
|
throw usage("-p runs headless and --rpc runs interactive, so pass one of them", `Run: ${example} or mutagent helix agent @${address.slug} --rpc`);
|
|
25750
25750
|
}
|
|
25751
25751
|
if (task !== undefined)
|
|
25752
|
-
return { address, mode: "
|
|
25752
|
+
return { address, mode: "headless", task };
|
|
25753
25753
|
if (flags.rpc === true)
|
|
25754
|
-
return { address, mode: "
|
|
25754
|
+
return { address, mode: "interactive" };
|
|
25755
25755
|
return { address };
|
|
25756
25756
|
}
|
|
25757
25757
|
|
|
25758
25758
|
// src/commands/helix/agent.ts
|
|
25759
|
-
var MISSING_TASK_MESSAGE = 'cloud
|
|
25759
|
+
var MISSING_TASK_MESSAGE = 'a cloud run needs a task: pass -p "<task>", or --rpc for an interactive session';
|
|
25760
25760
|
function registerAgentCommand(parent, registration, deps = defaultPlanDeps()) {
|
|
25761
25761
|
const jsonSource = registration?.jsonSource ?? parent;
|
|
25762
25762
|
parent.command("agent").description("Run a Helix agent in the cloud, or a managed agent by @slug").argument("[argv...]", "Agent definition, then the task and Helix flags; or @slug[:vN|:latest] for a managed agent").allowUnknownOption(true).allowExcessArguments(true).option("--sandbox <id>", "(internal) Run in an existing sandbox, by sandbox id").option("--preset <name>", "Sandbox preset (not with --sandbox)").option("--sandbox-provider <name>", "Run on this configured sandbox provider").option("--env <name>", "Workspace Environment to load for this run (see mutagent env ls)").option("--rpc", "Read JSON commands on stdin; write events on stdout").option("--cwd <path>", "Working directory in the sandbox").addHelpText("after", [
|
|
@@ -25791,12 +25791,12 @@ function registerAgentCommand(parent, registration, deps = defaultPlanDeps()) {
|
|
|
25791
25791
|
" With --mode rpc, closing stdin ends the session's input; a dropped connection only detaches.",
|
|
25792
25792
|
" Output is Helix's own, even with --json.",
|
|
25793
25793
|
" Ctrl-C on a native launch sends SIGINT to the session, which stops it; the exit status is reported.",
|
|
25794
|
-
" A sandbox idle for 15 minutes is checkpointed
|
|
25794
|
+
" A sandbox idle for 15 minutes is stopped; an interactive session in it is checkpointed first.",
|
|
25795
25795
|
"",
|
|
25796
25796
|
"AI Agent Directive:",
|
|
25797
25797
|
' For a managed agent, run mutagent helix agent @slug --env <slot> -p "<task>" and keep the',
|
|
25798
25798
|
" reference from the stderr receipt; session attach, send and signal take it.",
|
|
25799
|
-
"
|
|
25799
|
+
" Keep the definition and the task separate, and pass -p, --mode json or --mode rpc explicitly.",
|
|
25800
25800
|
" Local paths that cannot travel are refused; read the recovery message."
|
|
25801
25801
|
].join(`
|
|
25802
25802
|
`)).action(async (argv, options) => {
|
|
@@ -25876,7 +25876,7 @@ function withPlannedFlags(options, own) {
|
|
|
25876
25876
|
init_errors();
|
|
25877
25877
|
var LAUNCHER_OWN_FLAGS = ["--sandbox", "--preset", "--sandbox-provider", "--cwd", "--env", "--rpc"];
|
|
25878
25878
|
function rejection2(token, reason, alternative) {
|
|
25879
|
-
return new MutagentError("NOT_SUPPORTED", `${token}
|
|
25879
|
+
return new MutagentError("NOT_SUPPORTED", `${token} is not supported in a cloud run: ${reason}`, alternative, 2);
|
|
25880
25880
|
}
|
|
25881
25881
|
function planLauncherArgv(argv, deps = defaultPlanDeps()) {
|
|
25882
25882
|
let arm = "classic";
|
|
@@ -25941,7 +25941,7 @@ function planLauncherArgv(argv, deps = defaultPlanDeps()) {
|
|
|
25941
25941
|
continue;
|
|
25942
25942
|
}
|
|
25943
25943
|
if (token.startsWith("@")) {
|
|
25944
|
-
throw rejection2(redactToken(token), "an @file argument is read from the machine the harness runs on, and the
|
|
25944
|
+
throw rejection2(redactToken(token), "an @file argument is read from the machine the harness runs on, and the sandbox has no copy of it", "Inline the file’s contents into the task, or `mutagent sandbox exec` it into a sandbox you kept. File upload does not exist yet.");
|
|
25945
25945
|
}
|
|
25946
25946
|
if (token.startsWith("--")) {
|
|
25947
25947
|
forwardFlag(token);
|
|
@@ -25953,7 +25953,7 @@ function planLauncherArgv(argv, deps = defaultPlanDeps()) {
|
|
|
25953
25953
|
continue;
|
|
25954
25954
|
}
|
|
25955
25955
|
if (token.startsWith("-")) {
|
|
25956
|
-
throw rejection2(redactToken(token), "the harness rejects unknown short options outright, so forwarding it would fail inside the
|
|
25956
|
+
throw rejection2(redactToken(token), "the harness rejects unknown short options outright, so forwarding it would fail inside the sandbox instead of here", "Check the spelling against `helix --help`, or use the long form.");
|
|
25957
25957
|
}
|
|
25958
25958
|
task ??= token;
|
|
25959
25959
|
messages.push(token);
|
|
@@ -26638,7 +26638,7 @@ Types:
|
|
|
26638
26638
|
--line sends one JSON object as written, for a command the four types do not
|
|
26639
26639
|
cover. It cannot be combined with --type or a message.
|
|
26640
26640
|
|
|
26641
|
-
Only
|
|
26641
|
+
Only interactive sessions (started with --mode rpc or --rpc) accept input, and a session
|
|
26642
26642
|
that has ended refuses it; 'mutagent helix session ls' shows which are live.
|
|
26643
26643
|
With a sandbox id and --session, if the sandbox is being stopped for idling, send
|
|
26644
26644
|
waits the time the server asks and retries once. If the session's sandbox was stopped for idling,
|
|
@@ -26662,7 +26662,7 @@ AI Agent Directive:
|
|
|
26662
26662
|
const built2 = buildLine(messageParts.join(" ").trim(), options);
|
|
26663
26663
|
const result2 = await sendHelixInput(id, built2.line);
|
|
26664
26664
|
if (!result2.accepted) {
|
|
26665
|
-
throw new MutagentError("RPC_INPUT_REJECTED", "The session did not accept the command.", "
|
|
26665
|
+
throw new MutagentError("RPC_INPUT_REJECTED", "The session did not accept the command.", "Check the session: mutagent helix session ls", 1);
|
|
26666
26666
|
}
|
|
26667
26667
|
if (isJson)
|
|
26668
26668
|
output.output({ success: result2.accepted, reference: id, ...built2, ...result2, _links: { api: liveSessionPath(id) } });
|
|
@@ -26777,7 +26777,7 @@ when the agent has stopped reading its input.
|
|
|
26777
26777
|
Exits non-zero if the session had already ended.
|
|
26778
26778
|
The sandbox is not deleted: its files and event log stay, and
|
|
26779
26779
|
'mutagent helix session attach <reference>' shows what the session did. A sandbox
|
|
26780
|
-
idle for 15 minutes is checkpointed
|
|
26780
|
+
idle for 15 minutes is stopped; an interactive session in it is checkpointed first.
|
|
26781
26781
|
|
|
26782
26782
|
AI Agent Directive:
|
|
26783
26783
|
--json returns ONE object: { success, reference, signal, signalled, _links }.
|
|
@@ -26792,7 +26792,7 @@ AI Agent Directive:
|
|
|
26792
26792
|
const signal2 = resolveSignal(options.type);
|
|
26793
26793
|
const result2 = await signalHelixSession(id, signal2);
|
|
26794
26794
|
if (!result2.signalled) {
|
|
26795
|
-
throw new MutagentError("SESSION_SIGNAL_REJECTED", "The session was not signalled.", "
|
|
26795
|
+
throw new MutagentError("SESSION_SIGNAL_REJECTED", "The session was not signalled.", "Check the session: mutagent helix session ls", 1);
|
|
26796
26796
|
}
|
|
26797
26797
|
if (isJson)
|
|
26798
26798
|
output.output({ success: result2.signalled, reference: id, signal: signal2, ...result2, _links: { api: liveSessionPath(id) } });
|
|
@@ -26853,7 +26853,7 @@ A session reference (hs1_...) is printed when a run starts and listed by 'sessio
|
|
|
26853
26853
|
attach, send, signal, close-input, checkpoint, checkpoints and restore take it.
|
|
26854
26854
|
start and 'ls <sandbox-id>' are internal and take a sandbox id.
|
|
26855
26855
|
checkpoint saves a session's conversation; restore continues it in a rebuilt sandbox.
|
|
26856
|
-
A sandbox idle for 15 minutes is
|
|
26856
|
+
A sandbox idle for 15 minutes is stopped; an interactive session in it is checkpointed first.
|
|
26857
26857
|
|
|
26858
26858
|
AI Agent Directive:
|
|
26859
26859
|
Start work with 'mutagent helix --mode rpc' and keep the session reference it
|
|
@@ -26885,7 +26885,7 @@ function withSessionFlags(options, own) {
|
|
|
26885
26885
|
};
|
|
26886
26886
|
}
|
|
26887
26887
|
function registerStart(session, root) {
|
|
26888
|
-
session.command("start").description("(internal) Start a Helix session in an existing sandbox, by sandbox id").argument("<sandbox-id>", "Sandbox to start the session in").argument("[args...]", "Helix flags (put -- before them)").allowUnknownOption(true).allowExcessArguments(true).option("--rpc", "
|
|
26888
|
+
session.command("start").description("(internal) Start a Helix session in an existing sandbox, by sandbox id").argument("<sandbox-id>", "Sandbox to start the session in").argument("[args...]", "Helix flags (put -- before them)").allowUnknownOption(true).allowExcessArguments(true).option("--rpc", "Start an interactive session that accepts 'session send' (default: headless, runs once and ends)").option("--cwd <path>", "Working directory (default: $HOME for an interactive session)").option("--env <name>", "Workspace Environment to load (see mutagent env ls)").addHelpText("after", `
|
|
26889
26889
|
Examples:
|
|
26890
26890
|
${chalk27.dim("$")} mutagent helix session start sbx_123 --rpc
|
|
26891
26891
|
${chalk27.dim("$")} mutagent helix session start sbx_123 --rpc --env staging
|
|
@@ -26894,7 +26894,7 @@ Examples:
|
|
|
26894
26894
|
|
|
26895
26895
|
Prints the session id. Address the session as <sandbox-id> --session <session-id>
|
|
26896
26896
|
for send, signal and checkpoint, and watch it with 'mutagent sandbox attach <sandbox-id>'.
|
|
26897
|
-
Only an --rpc
|
|
26897
|
+
Only an interactive session (--rpc) accepts 'session send'; a headless session runs its task and ends.
|
|
26898
26898
|
Flags after -- go to Helix. A flag that names a file on this machine is refused,
|
|
26899
26899
|
because the sandbox cannot read it. A leading positional, --prompt, --file or
|
|
26900
26900
|
--name is the agent definition, resolved on this machine first.
|
|
@@ -26913,7 +26913,7 @@ AI Agent Directive:
|
|
|
26913
26913
|
process.stderr.write(`[mutagent] ${notice}
|
|
26914
26914
|
`);
|
|
26915
26915
|
const opts = withSessionFlags(options, planned.own);
|
|
26916
|
-
const mode = opts.rpc === true ? "
|
|
26916
|
+
const mode = opts.rpc === true ? "interactive" : "headless";
|
|
26917
26917
|
const args = planned.args;
|
|
26918
26918
|
const result = await startSession(id, {
|
|
26919
26919
|
mode,
|
|
@@ -26933,8 +26933,8 @@ AI Agent Directive:
|
|
|
26933
26933
|
...opts.env === undefined ? {} : { environment: opts.env },
|
|
26934
26934
|
_links: sandboxLinks(id),
|
|
26935
26935
|
_directive: {
|
|
26936
|
-
instruction: mode === "
|
|
26937
|
-
next: mode === "
|
|
26936
|
+
instruction: mode === "interactive" ? "The session is live and reading its stdin. Attach to watch it; send to steer it." : "The session runs its task to completion and ends. Attach to watch it; it does not accept input.",
|
|
26937
|
+
next: mode === "interactive" ? [
|
|
26938
26938
|
`mutagent sandbox attach ${id} --json`,
|
|
26939
26939
|
`mutagent helix session send ${id} --session ${sessionId} "<message>" --json`
|
|
26940
26940
|
] : [`mutagent sandbox attach ${id} --json`]
|
|
@@ -26944,7 +26944,7 @@ AI Agent Directive:
|
|
|
26944
26944
|
}
|
|
26945
26945
|
output.success(`Session ${sessionId} started in ${id} (${mode})`);
|
|
26946
26946
|
console.error(chalk27.dim(` Watch it: mutagent sandbox attach ${id}`));
|
|
26947
|
-
if (mode === "
|
|
26947
|
+
if (mode === "interactive") {
|
|
26948
26948
|
console.error(chalk27.dim(` Talk to it: mutagent helix session send ${id} --session ${sessionId} "<message>"`));
|
|
26949
26949
|
}
|
|
26950
26950
|
} catch (error3) {
|
|
@@ -26965,7 +26965,7 @@ Examples:
|
|
|
26965
26965
|
|
|
26966
26966
|
Every session in the workspace, live and ended, newest activity first.
|
|
26967
26967
|
STATUS is live (running now), ended (finished; exitCode in --json), stopped-for-idling
|
|
26968
|
-
(its sandbox was idle for 15 minutes
|
|
26968
|
+
(its sandbox was idle for 15 minutes and was stopped) or restored
|
|
26969
26969
|
(running in a sandbox rebuilt from a checkpoint). AGENT is slug:vN for a session
|
|
26970
26970
|
run from a managed agent (mutagent helix agent @slug) and blank otherwise. MODE is
|
|
26971
26971
|
interactive or headless. ARM and MODE are blank for sessions older than those fields.
|
|
@@ -27000,7 +27000,7 @@ AI Agent Directive:
|
|
|
27000
27000
|
if (isJson) {
|
|
27001
27001
|
output.output({
|
|
27002
27002
|
workspaceId,
|
|
27003
|
-
sessions
|
|
27003
|
+
sessions,
|
|
27004
27004
|
count: sessions.length,
|
|
27005
27005
|
...nextCursor === undefined ? {} : { nextCursor }
|
|
27006
27006
|
});
|
|
@@ -27009,7 +27009,7 @@ AI Agent Directive:
|
|
|
27009
27009
|
if (sessions.length === 0) {
|
|
27010
27010
|
console.log(chalk27.gray("No Helix sessions in this workspace yet."));
|
|
27011
27011
|
console.log("");
|
|
27012
|
-
console.log('
|
|
27012
|
+
console.log(' Start one: mutagent helix -p "<task>" or mutagent helix --rpc');
|
|
27013
27013
|
return;
|
|
27014
27014
|
}
|
|
27015
27015
|
output.output(sessions.map((s) => ({
|
|
@@ -27017,7 +27017,7 @@ AI Agent Directive:
|
|
|
27017
27017
|
SANDBOX: s.sandboxId,
|
|
27018
27018
|
AGENT: s.agent ?? "",
|
|
27019
27019
|
ARM: s.arm ?? "",
|
|
27020
|
-
MODE:
|
|
27020
|
+
MODE: s.mode ?? "",
|
|
27021
27021
|
STATUS: s.status,
|
|
27022
27022
|
"LAST ACTIVITY": s.lastActivityAt
|
|
27023
27023
|
})));
|
|
@@ -27121,18 +27121,13 @@ function requireSession(raw, example) {
|
|
|
27121
27121
|
return sessionId;
|
|
27122
27122
|
throw new MutagentError("MISSING_ARGUMENTS", "--session is required — a sandbox can hold more than one session.", `Run: ${example} --session <session-id>`, 2);
|
|
27123
27123
|
}
|
|
27124
|
-
function publicMode(mode) {
|
|
27125
|
-
if (mode === undefined)
|
|
27126
|
-
return "";
|
|
27127
|
-
return mode === "rpc" ? "interactive" : "headless";
|
|
27128
|
-
}
|
|
27129
27124
|
|
|
27130
27125
|
// src/commands/helix/models.ts
|
|
27131
27126
|
import chalk28 from "chalk";
|
|
27132
27127
|
init_errors();
|
|
27133
27128
|
function printView(view, output) {
|
|
27134
27129
|
if (view.models.length === 0) {
|
|
27135
|
-
console.log(chalk28.gray("No Helix Cloud models: this workspace has no active LLM provider
|
|
27130
|
+
console.log(chalk28.gray("No Helix Cloud models: this workspace has no active LLM provider that Helix can use."));
|
|
27136
27131
|
console.log("");
|
|
27137
27132
|
console.log(" Add one: mutagent providers add --provider <id> --name <name> --api-key <key>");
|
|
27138
27133
|
} else {
|
|
@@ -27145,7 +27140,7 @@ function printView(view, output) {
|
|
|
27145
27140
|
console.log(view.default === null ? chalk28.yellow("No default set — a run without --model answers 428. Set one: mutagent helix models default <provider/model>") : `Default: ${view.default}`);
|
|
27146
27141
|
}
|
|
27147
27142
|
if (view.unmapped.length > 0) {
|
|
27148
|
-
console.log(chalk28.yellow(`Not usable
|
|
27143
|
+
console.log(chalk28.yellow(`Not usable by Helix Cloud (Helix cannot load this LLM provider's key): ${view.unmapped.join(", ")}`));
|
|
27149
27144
|
}
|
|
27150
27145
|
}
|
|
27151
27146
|
function registerModelsCommand(helix) {
|
|
@@ -27428,9 +27423,10 @@ function createHelixCommand() {
|
|
|
27428
27423
|
"Each run prints its session reference (hs1_...) on stderr. Use it with",
|
|
27429
27424
|
"mutagent helix session attach, send, signal and checkpoint.",
|
|
27430
27425
|
"Ctrl-C sends SIGINT to the session, which stops it; the exit status is reported.",
|
|
27431
|
-
"There is no
|
|
27426
|
+
"There is no terminal chat UI: choose -p, --mode json or --mode rpc.",
|
|
27432
27427
|
"With --mode rpc, closing stdin ends the session's input; a dropped connection only detaches.",
|
|
27433
|
-
"A sandbox idle for 15 minutes is
|
|
27428
|
+
"A sandbox idle for 15 minutes is stopped; an interactive session in it is checkpointed first.",
|
|
27429
|
+
"mutagent helix session restore continues a checkpointed session in a new sandbox.",
|
|
27434
27430
|
"",
|
|
27435
27431
|
"AI Agent Directive:",
|
|
27436
27432
|
" Choose -p, --mode json or --mode rpc explicitly.",
|
|
@@ -27564,7 +27560,7 @@ function resolveNetwork(requested, rules) {
|
|
|
27564
27560
|
}
|
|
27565
27561
|
const policy2 = requested.trim();
|
|
27566
27562
|
if (!EGRESS_POLICIES.includes(policy2)) {
|
|
27567
|
-
throw new MutagentError("INVALID_ARGUMENTS", `--egress must be one of ${EGRESS_POLICIES.join(", ")}, got "${requested}".`, "Use --egress allow to drive a Helix session; the default, deny, leaves the
|
|
27563
|
+
throw new MutagentError("INVALID_ARGUMENTS", `--egress must be one of ${EGRESS_POLICIES.join(", ")}, got "${requested}".`, "Use --egress allow to drive a Helix session; the default, deny, leaves the sandbox without network access.");
|
|
27568
27564
|
}
|
|
27569
27565
|
if (policy2 !== "allowlist") {
|
|
27570
27566
|
if (rules.length > 0) {
|
|
@@ -27676,7 +27672,7 @@ command and is removed unless --keep. With --sandbox, output streams as it is pr
|
|
|
27676
27672
|
--preset and --keep are refused there. The sandbox command's exit code is this command's.
|
|
27677
27673
|
|
|
27678
27674
|
AI Agent Directive:
|
|
27679
|
-
Use --no-stream --json (or the
|
|
27675
|
+
Use --no-stream --json (or the single-command form, which is always blocking) for a
|
|
27680
27676
|
result you intend to parse: one object, no NDJSON to reassemble.
|
|
27681
27677
|
Run 'mutagent sandbox ls --json' first to confirm a --sandbox id is running.
|
|
27682
27678
|
`).action(async (argv, options) => {
|
|
@@ -27741,7 +27737,7 @@ function rejectOneShotOnlyFlags(options) {
|
|
|
27741
27737
|
offenders.push("--keep");
|
|
27742
27738
|
if (offenders.length === 0)
|
|
27743
27739
|
return;
|
|
27744
|
-
throw new MutagentError("INVALID_ARGUMENTS", `${offenders.join(" and ")} ${offenders.length === 1 ? "applies" : "apply"} only to a fresh sandbox, but --sandbox names an existing one.`, "Drop --sandbox to run
|
|
27740
|
+
throw new MutagentError("INVALID_ARGUMENTS", `${offenders.join(" and ")} ${offenders.length === 1 ? "applies" : "apply"} only to a fresh sandbox, but --sandbox names an existing one.`, "Drop --sandbox to run the command in a new sandbox, or drop these flags to run in the existing one.");
|
|
27745
27741
|
}
|
|
27746
27742
|
function createExecOpener(id, body) {
|
|
27747
27743
|
let submitted = false;
|
|
@@ -28155,15 +28151,15 @@ Examples:
|
|
|
28155
28151
|
${chalk35.dim("$")} mutagent sandbox traces sbx_1
|
|
28156
28152
|
${chalk35.dim("$")} mutagent sandbox rm sbx_1 --force
|
|
28157
28153
|
|
|
28158
|
-
|
|
28154
|
+
Single command vs kept sandbox:
|
|
28159
28155
|
${chalk35.bold("exec")} without --sandbox starts a fresh sandbox from a preset, runs one command
|
|
28160
28156
|
and removes the sandbox. ${chalk35.bold("spawn")} starts a sandbox from an image and leaves it running
|
|
28161
28157
|
for ${chalk35.bold("attach")} and ${chalk35.bold("exec --sandbox")}.
|
|
28162
28158
|
|
|
28163
28159
|
Lifecycle:
|
|
28164
28160
|
Ctrl-C, a dropped connection or a closed terminal detaches; the sandbox keeps running.
|
|
28165
|
-
After 15 minutes with no input, attach, exec or agent turn, the server
|
|
28166
|
-
|
|
28161
|
+
After 15 minutes with no input, attach, exec or agent turn, the server stops it;
|
|
28162
|
+
an interactive Helix session in it is checkpointed first and can be restored with
|
|
28167
28163
|
\`mutagent helix session restore <reference>\`. \`sandbox rm\` destroys a sandbox now.
|
|
28168
28164
|
|
|
28169
28165
|
Output:
|
|
@@ -28400,8 +28396,8 @@ Examples:
|
|
|
28400
28396
|
Entries you name are set and the rest stay; the Environment is created if missing.
|
|
28401
28397
|
--replace removes every entry you do not name, secrets included.
|
|
28402
28398
|
Positional KEY=VALUE and --from-file are variables; --secret and --secrets-from-file are
|
|
28403
|
-
secrets (encrypted at rest, never returned). Both
|
|
28404
|
-
cannot be both.
|
|
28399
|
+
secrets (encrypted at rest, never returned). Both are set as environment variables in
|
|
28400
|
+
the sandbox. A name cannot be both.
|
|
28405
28401
|
--secret takes every KEY=VALUE after it, so put variables first:
|
|
28406
28402
|
${chalk36.dim("$")} mutagent env set demo A=1 --secret TOKEN=x
|
|
28407
28403
|
A value may contain '=': TOKEN=a=b stores "a=b".
|
|
@@ -28476,8 +28472,8 @@ Examples:
|
|
|
28476
28472
|
${chalk36.dim("$")} mutagent env rm demo --force
|
|
28477
28473
|
${chalk36.dim("$")} mutagent env rm demo --json
|
|
28478
28474
|
|
|
28479
|
-
Deletes the Environment and its encrypted secrets.
|
|
28480
|
-
they were
|
|
28475
|
+
Deletes the Environment and its encrypted secrets. Sandboxes already running keep the
|
|
28476
|
+
values they were given; the next run naming this Environment fails.
|
|
28481
28477
|
Without --force (and without --json) the command refuses; it never prompts.
|
|
28482
28478
|
An unknown name is an error.
|
|
28483
28479
|
|
|
@@ -28708,8 +28704,8 @@ function helixKeyRefusal() {
|
|
|
28708
28704
|
To pass the Mutagent platform key instead, put it before the command (mutagent --api-key <mutagent-key> helix …) or export MUTAGENT_API_KEY.`, 2);
|
|
28709
28705
|
}
|
|
28710
28706
|
function sandboxExecKeyRefusal() {
|
|
28711
|
-
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
|
|
28712
|
-
Arguments for the command in the
|
|
28707
|
+
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()}
|
|
28708
|
+
Arguments for the command in the sandbox go after --: mutagent sandbox exec --sandbox <id> -- <command> [args…].
|
|
28713
28709
|
To pass the Mutagent platform key instead, put it before the command (mutagent --api-key <mutagent-key> sandbox exec …) or export MUTAGENT_API_KEY.`, 2);
|
|
28714
28710
|
}
|
|
28715
28711
|
function rootValueOptionRefusal(option, label) {
|
|
@@ -29241,4 +29237,4 @@ if (isAgentInvocation(rawArgs)) {
|
|
|
29241
29237
|
program.parse(argvForCommander, { from: "user" });
|
|
29242
29238
|
}
|
|
29243
29239
|
|
|
29244
|
-
//# debugId=
|
|
29240
|
+
//# debugId=EBAEE05DDF8C12AA64756E2164756E21
|
package/dist/index.js
CHANGED
|
@@ -708,7 +708,7 @@ var init_sdk_debug = __esm(() => {
|
|
|
708
708
|
});
|
|
709
709
|
|
|
710
710
|
// src/lib/sdk-mappers.ts
|
|
711
|
-
import {
|
|
711
|
+
import { LlmProviderType as SDKProviderEnum } from "@mutagent/sdk/models";
|
|
712
712
|
function isProviderType(value) {
|
|
713
713
|
return PROVIDER_TYPES.includes(value);
|
|
714
714
|
}
|
|
@@ -1021,7 +1021,7 @@ class SDKClientWrapper {
|
|
|
1021
1021
|
}
|
|
1022
1022
|
async listProviders(filters) {
|
|
1023
1023
|
try {
|
|
1024
|
-
const response = await this.sdk.
|
|
1024
|
+
const response = await this.sdk.llmProviders.listProviderConfigs({
|
|
1025
1025
|
provider: filters?.type,
|
|
1026
1026
|
includeInactive: true
|
|
1027
1027
|
});
|
|
@@ -1039,7 +1039,7 @@ class SDKClientWrapper {
|
|
|
1039
1039
|
}
|
|
1040
1040
|
async getProvider(id) {
|
|
1041
1041
|
try {
|
|
1042
|
-
const response = await this.sdk.
|
|
1042
|
+
const response = await this.sdk.llmProviders.getProviderConfig({
|
|
1043
1043
|
id
|
|
1044
1044
|
});
|
|
1045
1045
|
return toProvider(response);
|
|
@@ -1115,7 +1115,7 @@ class SDKClientWrapper {
|
|
|
1115
1115
|
}
|
|
1116
1116
|
async testProvider(id) {
|
|
1117
1117
|
try {
|
|
1118
|
-
const response = await this.sdk.
|
|
1118
|
+
const response = await this.sdk.llmProviders.testProviderConfig({
|
|
1119
1119
|
id
|
|
1120
1120
|
});
|
|
1121
1121
|
return toProviderTestResult(response);
|
|
@@ -1161,7 +1161,7 @@ class SDKClientWrapper {
|
|
|
1161
1161
|
});
|
|
1162
1162
|
return scrubKnownSuccessDeep({ ...response2, workspaceId });
|
|
1163
1163
|
}
|
|
1164
|
-
const response = await this.sdk.
|
|
1164
|
+
const response = await this.sdk.llmProviders.updateProviderConfig({
|
|
1165
1165
|
id,
|
|
1166
1166
|
body: {
|
|
1167
1167
|
name: data.name,
|
|
@@ -1180,7 +1180,7 @@ class SDKClientWrapper {
|
|
|
1180
1180
|
async deleteProvider(id) {
|
|
1181
1181
|
const workspaceId = this.requireUnambiguousWorkspace();
|
|
1182
1182
|
try {
|
|
1183
|
-
await this.sdk.
|
|
1183
|
+
await this.sdk.llmProviders.deleteProviderConfig({ id });
|
|
1184
1184
|
return { workspaceId };
|
|
1185
1185
|
} catch (error) {
|
|
1186
1186
|
this.handleError(error);
|
|
@@ -1480,4 +1480,4 @@ export {
|
|
|
1480
1480
|
ApiError
|
|
1481
1481
|
};
|
|
1482
1482
|
|
|
1483
|
-
//# debugId=
|
|
1483
|
+
//# debugId=0E9FCC198FD63F3C64756E2164756E21
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mutagent/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.353",
|
|
4
4
|
"description": "Bun-native CLI for the MutagenT AI platform - auth, provider config, and lifecycle-tool installer for AI-native workflows",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@inquirer/prompts": "^8.7.2",
|
|
45
|
-
"@mutagent/sdk": "0.
|
|
45
|
+
"@mutagent/sdk": "0.6.0",
|
|
46
46
|
"chalk": "^5.3.0",
|
|
47
47
|
"commander": "^12.1.0",
|
|
48
48
|
"cosmiconfig": "^9.0.0",
|