@m8t-stack/cli 0.2.35 → 0.2.37
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 +13 -10
- package/dist/cli.js +267 -102
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -293,19 +293,9 @@ var init_secrets = __esm({
|
|
|
293
293
|
});
|
|
294
294
|
|
|
295
295
|
// ../../packages/github-app-auth/dist/esm/cache.js
|
|
296
|
-
var cache_exports = {};
|
|
297
|
-
__export(cache_exports, {
|
|
298
|
-
EXPIRY_SAFETY_MS: () => EXPIRY_SAFETY_MS,
|
|
299
|
-
_resetTokenCache: () => _resetTokenCache,
|
|
300
|
-
getCachedToken: () => getCachedToken,
|
|
301
|
-
putCachedToken: () => putCachedToken
|
|
302
|
-
});
|
|
303
296
|
function key(installationId, repository) {
|
|
304
297
|
return `${installationId}:${repository}`;
|
|
305
298
|
}
|
|
306
|
-
function _resetTokenCache() {
|
|
307
|
-
cache2.clear();
|
|
308
|
-
}
|
|
309
299
|
function getCachedToken(installationId, repository) {
|
|
310
300
|
const e = cache2.get(key(installationId, repository));
|
|
311
301
|
if (!e)
|
|
@@ -384,17 +374,18 @@ var init_mint = __esm({
|
|
|
384
374
|
});
|
|
385
375
|
|
|
386
376
|
// ../../packages/github-app-auth/dist/esm/rotate.js
|
|
377
|
+
function connectionStateKey(projectArmId, connectionName) {
|
|
378
|
+
return `${projectArmId}/connections/${connectionName}`;
|
|
379
|
+
}
|
|
387
380
|
async function rotateConnectionAuth(args) {
|
|
388
|
-
const { getCachedToken: getCachedToken2, putCachedToken: putCachedToken2 } = await Promise.resolve().then(() => (init_cache(), cache_exports));
|
|
389
|
-
const before = getCachedToken2(args.installationId, args.repository);
|
|
390
381
|
const minted = await mintInstallationToken({
|
|
391
382
|
credential: args.credential,
|
|
392
383
|
kvUri: args.kvUri,
|
|
393
384
|
installationId: args.installationId,
|
|
394
385
|
repository: args.repository
|
|
395
386
|
});
|
|
396
|
-
const
|
|
397
|
-
if (
|
|
387
|
+
const stateKey = connectionStateKey(args.projectArmId, args.connectionName);
|
|
388
|
+
if (connectionPatchState.get(stateKey) !== minted.token) {
|
|
398
389
|
const armTokenResp = await args.credential.getToken(ARM_SCOPE);
|
|
399
390
|
if (!armTokenResp?.token) {
|
|
400
391
|
throw new Error("rotateConnectionAuth: failed to acquire ARM management token");
|
|
@@ -423,17 +414,18 @@ async function rotateConnectionAuth(args) {
|
|
|
423
414
|
throw new Error(`rotateConnectionAuth: HTTP ${String(res.status)} on PATCH ${url}
|
|
424
415
|
${text.slice(0, 500)}`);
|
|
425
416
|
}
|
|
426
|
-
|
|
417
|
+
connectionPatchState.set(stateKey, minted.token);
|
|
427
418
|
}
|
|
428
419
|
return { rotatedAt: /* @__PURE__ */ new Date(), expiresAt: minted.expiresAt };
|
|
429
420
|
}
|
|
430
|
-
var ARM_SCOPE, FOUNDRY_API;
|
|
421
|
+
var ARM_SCOPE, FOUNDRY_API, connectionPatchState;
|
|
431
422
|
var init_rotate = __esm({
|
|
432
423
|
"../../packages/github-app-auth/dist/esm/rotate.js"() {
|
|
433
424
|
"use strict";
|
|
434
425
|
init_mint();
|
|
435
426
|
ARM_SCOPE = "https://management.azure.com/.default";
|
|
436
427
|
FOUNDRY_API = "2025-04-01-preview";
|
|
428
|
+
connectionPatchState = /* @__PURE__ */ new Map();
|
|
437
429
|
}
|
|
438
430
|
});
|
|
439
431
|
|
|
@@ -673,6 +665,53 @@ var init_foundry_agent_get = __esm({
|
|
|
673
665
|
}
|
|
674
666
|
});
|
|
675
667
|
|
|
668
|
+
// src/lib/foundry-agent-version.ts
|
|
669
|
+
async function createAgentVersion(args, fetchImpl = fetch) {
|
|
670
|
+
const token = await args.credential.getToken(FOUNDRY_DATA_SCOPE);
|
|
671
|
+
if (!token?.token) throw new LocalCliError({ code: "FOUNDRY_AUTH", message: "Could not acquire Foundry data-plane token" });
|
|
672
|
+
const url = `${args.projectEndpoint}/agents/${args.agentName}/versions?api-version=v1`;
|
|
673
|
+
const res = await fetchImpl(url, {
|
|
674
|
+
method: "POST",
|
|
675
|
+
headers: { Authorization: `Bearer ${token.token}`, "Content-Type": "application/json", ...args.extraHeaders ?? {} },
|
|
676
|
+
body: JSON.stringify({ definition: args.definition, metadata: args.metadata })
|
|
677
|
+
});
|
|
678
|
+
if (!res.ok) {
|
|
679
|
+
const text = await res.text();
|
|
680
|
+
throw new LocalCliError({ code: "AGENT_CREATE_VERSION_FAILED", message: `POST ${url}: HTTP ${res.status.toString()}
|
|
681
|
+
${text.slice(0, 500)}` });
|
|
682
|
+
}
|
|
683
|
+
await ensureAgentEndpointEntraIsolation(
|
|
684
|
+
{ credential: args.credential, projectEndpoint: args.projectEndpoint, agentName: args.agentName, extraHeaders: args.extraHeaders },
|
|
685
|
+
fetchImpl
|
|
686
|
+
);
|
|
687
|
+
const data = await res.json();
|
|
688
|
+
if (!data.version) throw new LocalCliError({ code: "AGENT_CREATE_VERSION_NO_VERSION", message: "createVersion returned no version" });
|
|
689
|
+
return data.version;
|
|
690
|
+
}
|
|
691
|
+
async function ensureAgentEndpointEntraIsolation(args, fetchImpl = fetch) {
|
|
692
|
+
const token = await args.credential.getToken(FOUNDRY_DATA_SCOPE);
|
|
693
|
+
if (!token?.token) throw new LocalCliError({ code: "FOUNDRY_AUTH", message: "Could not acquire Foundry data-plane token" });
|
|
694
|
+
const url = `${args.projectEndpoint}/agents/${args.agentName}?api-version=v1`;
|
|
695
|
+
const res = await fetchImpl(url, {
|
|
696
|
+
method: "PATCH",
|
|
697
|
+
headers: { Authorization: `Bearer ${token.token}`, "Content-Type": "application/json", ...args.extraHeaders ?? {} },
|
|
698
|
+
body: JSON.stringify({ agent_endpoint: { authorization_schemes: [{ type: "Entra", isolation_key_source: { kind: "Entra" } }] } })
|
|
699
|
+
});
|
|
700
|
+
if (!res.ok) {
|
|
701
|
+
const text = await res.text();
|
|
702
|
+
throw new LocalCliError({ code: "AGENT_ENDPOINT_AUTH_PATCH_FAILED", message: `PATCH ${url}: HTTP ${res.status.toString()}
|
|
703
|
+
${text.slice(0, 500)}` });
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
var FOUNDRY_DATA_SCOPE;
|
|
707
|
+
var init_foundry_agent_version = __esm({
|
|
708
|
+
"src/lib/foundry-agent-version.ts"() {
|
|
709
|
+
"use strict";
|
|
710
|
+
init_errors();
|
|
711
|
+
FOUNDRY_DATA_SCOPE = "https://ai.azure.com/.default";
|
|
712
|
+
}
|
|
713
|
+
});
|
|
714
|
+
|
|
676
715
|
// src/lib/brain-yaml-mirror.ts
|
|
677
716
|
import { parse as parseYaml4 } from "yaml";
|
|
678
717
|
function linkSection(args) {
|
|
@@ -841,6 +880,12 @@ async function createCoderVersion(args) {
|
|
|
841
880
|
foundryFeatures: "HostedAgents=V1Preview",
|
|
842
881
|
metadata
|
|
843
882
|
});
|
|
883
|
+
await ensureAgentEndpointEntraIsolation({
|
|
884
|
+
credential: args.credential,
|
|
885
|
+
projectEndpoint: args.endpoint,
|
|
886
|
+
agentName: args.name,
|
|
887
|
+
extraHeaders: { "Foundry-Features": "HostedAgents=V1Preview" }
|
|
888
|
+
});
|
|
844
889
|
const v = version.version;
|
|
845
890
|
if (v === void 0) {
|
|
846
891
|
throw new LocalCliError({
|
|
@@ -905,6 +950,11 @@ async function createPromptVersion(args) {
|
|
|
905
950
|
if (args.metadata.personaVersion !== null) metadata.personaVersion = args.metadata.personaVersion;
|
|
906
951
|
if (args.metadata.fillableFieldValues !== void 0) metadata.fillableFieldValues = args.metadata.fillableFieldValues;
|
|
907
952
|
const version = await project.agents.createVersion(args.name, definition, { metadata });
|
|
953
|
+
await ensureAgentEndpointEntraIsolation({
|
|
954
|
+
credential: args.credential,
|
|
955
|
+
projectEndpoint: args.endpoint,
|
|
956
|
+
agentName: args.name
|
|
957
|
+
});
|
|
908
958
|
const v = version.version;
|
|
909
959
|
if (v === void 0) {
|
|
910
960
|
throw new LocalCliError({
|
|
@@ -931,6 +981,7 @@ var init_foundry_agents = __esm({
|
|
|
931
981
|
"use strict";
|
|
932
982
|
init_http();
|
|
933
983
|
init_errors();
|
|
984
|
+
init_foundry_agent_version();
|
|
934
985
|
METADATA_SOURCE = "m8t";
|
|
935
986
|
FOUNDRY_SCOPE2 = "https://ai.azure.com/.default";
|
|
936
987
|
API = "v1";
|
|
@@ -1247,7 +1298,7 @@ var init_enable_hosted_brain = __esm({
|
|
|
1247
1298
|
import { Builtins, Cli } from "clipanion";
|
|
1248
1299
|
|
|
1249
1300
|
// src/lib/package-version.ts
|
|
1250
|
-
var CLI_VERSION = "0.2.
|
|
1301
|
+
var CLI_VERSION = "0.2.37";
|
|
1251
1302
|
|
|
1252
1303
|
// src/lib/render-error.ts
|
|
1253
1304
|
init_errors();
|
|
@@ -1341,7 +1392,7 @@ var BACKEND_RULES = [
|
|
|
1341
1392
|
reason: "no_adapter_registered",
|
|
1342
1393
|
hint: (e) => {
|
|
1343
1394
|
const channel = getDetailField(e, "channel") ?? "<channel>";
|
|
1344
|
-
return `no adapter for channel '${channel}'.
|
|
1395
|
+
return `no adapter for channel '${channel}'. The channel-specific adapter is not registered in this build.`;
|
|
1345
1396
|
}
|
|
1346
1397
|
},
|
|
1347
1398
|
{
|
|
@@ -1453,6 +1504,14 @@ var LOCAL_RULES = {
|
|
|
1453
1504
|
APP_HEALTH_FAILED: "Run `m8t brain check-app` for details, then re-run this command.",
|
|
1454
1505
|
APP_UNINSTALL_FAILED: "GitHub App-uninstall DELETE failed. Re-run with `--keep-app-install` if you want to skip this step.",
|
|
1455
1506
|
ARM_AUTH: "Run `az login` and retry.",
|
|
1507
|
+
// BOOTSTRAP_OCCUPANCY_UNVERIFIED and BOOTSTRAP_REINSTALL_TARGET_MISMATCH are
|
|
1508
|
+
// deliberately absent here: both are always thrown with an inline `hint`
|
|
1509
|
+
// (see bootstrap-occupancy.ts / commands/bootstrap/launch.ts), and
|
|
1510
|
+
// render-error.ts prefers that inline hint over this table — so a table
|
|
1511
|
+
// entry for either code would be dead text that could drift from what
|
|
1512
|
+
// actually prints. BOOTSTRAP_TARGET_OCCUPIED has no inline hint, so its
|
|
1513
|
+
// entry below is the live one.
|
|
1514
|
+
BOOTSTRAP_TARGET_OCCUPIED: "Pick an empty resource group with `--resource-group <new-rg>`, or run with both `--resource-group <rg>` and `--reinstall-into <rg>` (same group name) to install into the existing one anyway.",
|
|
1456
1515
|
// m8t brain create: stageAsGitRepo step
|
|
1457
1516
|
BRAIN_GIT_INIT_FAILED: "If git is not installed, install it. Otherwise re-run with --verbose.",
|
|
1458
1517
|
BRAIN_NOT_LINKED: "The worker has no brain link. Use `m8t brain link` or `m8t brain create` first.",
|
|
@@ -11303,6 +11362,14 @@ function isUndiciDispatcherVersionMismatchError(error) {
|
|
|
11303
11362
|
return false;
|
|
11304
11363
|
}
|
|
11305
11364
|
|
|
11365
|
+
// ../../packages/foundry-invoke/dist/esm/openai-error.js
|
|
11366
|
+
function openAIErrorStatus(err) {
|
|
11367
|
+
if (typeof err !== "object" || err === null)
|
|
11368
|
+
return void 0;
|
|
11369
|
+
const status = err.status;
|
|
11370
|
+
return typeof status === "number" ? status : void 0;
|
|
11371
|
+
}
|
|
11372
|
+
|
|
11306
11373
|
// ../../packages/foundry-invoke/dist/esm/invoke-cli-core.js
|
|
11307
11374
|
function isBrainConnPropagation(err) {
|
|
11308
11375
|
const e = err;
|
|
@@ -11329,9 +11396,10 @@ function errText(err) {
|
|
|
11329
11396
|
return `${e.code ?? ""} ${e.error?.code ?? ""} ${e.error?.message ?? ""} ${e.message ?? ""}`.trim();
|
|
11330
11397
|
}
|
|
11331
11398
|
function errStatus(err) {
|
|
11399
|
+
const direct = openAIErrorStatus(err);
|
|
11400
|
+
if (direct !== void 0)
|
|
11401
|
+
return direct;
|
|
11332
11402
|
const e = err;
|
|
11333
|
-
if (typeof e.status === "number")
|
|
11334
|
-
return e.status;
|
|
11335
11403
|
if (typeof e.upstreamStatus === "number")
|
|
11336
11404
|
return e.upstreamStatus;
|
|
11337
11405
|
const m = /\b(4\d\d|5\d\d)\b/.exec(e.message ?? "");
|
|
@@ -11929,7 +11997,7 @@ var BindAddCommand = class extends M8tCommand {
|
|
|
11929
11997
|
static paths = [["bind", "add"]];
|
|
11930
11998
|
static usage = Command2.Usage({
|
|
11931
11999
|
description: "Create a channel\u2192worker binding with bot token storage.",
|
|
11932
|
-
details: "Stores the bot token in Key Vault and writes a Bindings table row. Returns the webhook URL the channel platform should call.
|
|
12000
|
+
details: "Stores the bot token in Key Vault and writes a Bindings table row. Returns the webhook URL the channel platform should call. Channels without a registered adapter (Slack, Teams) fail with 'no_adapter_registered'.",
|
|
11933
12001
|
examples: [
|
|
11934
12002
|
[
|
|
11935
12003
|
"Add a Telegram binding for the cmo worker",
|
|
@@ -13898,49 +13966,7 @@ function hasA2aSnippet(instructions) {
|
|
|
13898
13966
|
|
|
13899
13967
|
// src/lib/brain-link.ts
|
|
13900
13968
|
init_foundry_agent_get();
|
|
13901
|
-
|
|
13902
|
-
// src/lib/foundry-agent-version.ts
|
|
13903
|
-
init_errors();
|
|
13904
|
-
var FOUNDRY_DATA_SCOPE = "https://ai.azure.com/.default";
|
|
13905
|
-
async function createAgentVersion(args, fetchImpl = fetch) {
|
|
13906
|
-
const token = await args.credential.getToken(FOUNDRY_DATA_SCOPE);
|
|
13907
|
-
if (!token?.token) throw new LocalCliError({ code: "FOUNDRY_AUTH", message: "Could not acquire Foundry data-plane token" });
|
|
13908
|
-
const url = `${args.projectEndpoint}/agents/${args.agentName}/versions?api-version=v1`;
|
|
13909
|
-
const res = await fetchImpl(url, {
|
|
13910
|
-
method: "POST",
|
|
13911
|
-
headers: { Authorization: `Bearer ${token.token}`, "Content-Type": "application/json", ...args.extraHeaders ?? {} },
|
|
13912
|
-
body: JSON.stringify({ definition: args.definition, metadata: args.metadata })
|
|
13913
|
-
});
|
|
13914
|
-
if (!res.ok) {
|
|
13915
|
-
const text = await res.text();
|
|
13916
|
-
throw new LocalCliError({ code: "AGENT_CREATE_VERSION_FAILED", message: `POST ${url}: HTTP ${res.status.toString()}
|
|
13917
|
-
${text.slice(0, 500)}` });
|
|
13918
|
-
}
|
|
13919
|
-
const data = await res.json();
|
|
13920
|
-
if (!data.version) throw new LocalCliError({ code: "AGENT_CREATE_VERSION_NO_VERSION", message: "createVersion returned no version" });
|
|
13921
|
-
await ensureAgentEndpointEntraIsolation(
|
|
13922
|
-
{ credential: args.credential, projectEndpoint: args.projectEndpoint, agentName: args.agentName, extraHeaders: args.extraHeaders },
|
|
13923
|
-
fetchImpl
|
|
13924
|
-
);
|
|
13925
|
-
return data.version;
|
|
13926
|
-
}
|
|
13927
|
-
async function ensureAgentEndpointEntraIsolation(args, fetchImpl = fetch) {
|
|
13928
|
-
const token = await args.credential.getToken(FOUNDRY_DATA_SCOPE);
|
|
13929
|
-
if (!token?.token) throw new LocalCliError({ code: "FOUNDRY_AUTH", message: "Could not acquire Foundry data-plane token" });
|
|
13930
|
-
const url = `${args.projectEndpoint}/agents/${args.agentName}?api-version=v1`;
|
|
13931
|
-
const res = await fetchImpl(url, {
|
|
13932
|
-
method: "PATCH",
|
|
13933
|
-
headers: { Authorization: `Bearer ${token.token}`, "Content-Type": "application/json", ...args.extraHeaders ?? {} },
|
|
13934
|
-
body: JSON.stringify({ agent_endpoint: { authorization_schemes: [{ type: "Entra", isolation_key_source: { kind: "Entra" } }] } })
|
|
13935
|
-
});
|
|
13936
|
-
if (!res.ok) {
|
|
13937
|
-
const text = await res.text();
|
|
13938
|
-
throw new LocalCliError({ code: "AGENT_ENDPOINT_AUTH_PATCH_FAILED", message: `PATCH ${url}: HTTP ${res.status.toString()}
|
|
13939
|
-
${text.slice(0, 500)}` });
|
|
13940
|
-
}
|
|
13941
|
-
}
|
|
13942
|
-
|
|
13943
|
-
// src/lib/brain-link.ts
|
|
13969
|
+
init_foundry_agent_version();
|
|
13944
13970
|
init_brain_yaml_mirror();
|
|
13945
13971
|
var FOUNDRY_ARM_API = "2025-04-01-preview";
|
|
13946
13972
|
var ARM_SCOPE4 = "https://management.azure.com/.default";
|
|
@@ -14131,7 +14157,7 @@ ${text.slice(0, 300)}`
|
|
|
14131
14157
|
target: MCP_SERVER_URL,
|
|
14132
14158
|
isSharedToAll: false,
|
|
14133
14159
|
credentials: { keys: { Authorization: "Bearer placeholder-will-be-rotated" } },
|
|
14134
|
-
metadata: { managedBy: "m8t-brain-
|
|
14160
|
+
metadata: { managedBy: "m8t-brain-link" }
|
|
14135
14161
|
}
|
|
14136
14162
|
});
|
|
14137
14163
|
const putRes = await fetch(url, {
|
|
@@ -14967,7 +14993,7 @@ var BrainLinkCommand = class extends M8tCommand {
|
|
|
14967
14993
|
static paths = [["brain", "link"]];
|
|
14968
14994
|
static usage = Command19.Usage({
|
|
14969
14995
|
description: "Link a worker to an existing brain repo. Idempotent.",
|
|
14970
|
-
details: "Installs the GitHub App on <repo> (browser click + poll), mints an installation token + PATCHes the Foundry connection, deploys a new agent version with the brain loader + tools[type:mcp] + metadata.brain JSON string, and pushes .m8t/brain.yaml to the repo.
|
|
14996
|
+
details: "Installs the GitHub App on <repo> (browser click + poll), mints an installation token + PATCHes the Foundry connection, deploys a new agent version with the brain loader + tools[type:mcp] + metadata.brain JSON string, and pushes .m8t/brain.yaml to the repo. PAT mode keeps working untouched. --force re-runs the full link cascade (loader re-render + createVersion + brain.yaml mirror) even when metadata.brain already matches \u2014 useful to rescue a stuck or stale link.",
|
|
14971
14997
|
examples: [
|
|
14972
14998
|
["Link cmo to orkeren21/cmo-brain", "$0 brain link cmo --repo orkeren21/cmo-brain"],
|
|
14973
14999
|
["Force a re-link (re-render brain loader + new agent version, even if already linked)", "$0 brain link cmo --repo orkeren21/cmo-brain --force"]
|
|
@@ -15242,6 +15268,7 @@ import * as fs12 from "fs";
|
|
|
15242
15268
|
import * as os5 from "os";
|
|
15243
15269
|
import * as path11 from "path";
|
|
15244
15270
|
init_foundry_agent_get();
|
|
15271
|
+
init_foundry_agent_version();
|
|
15245
15272
|
var FOUNDRY_ARM_API2 = "2025-04-01-preview";
|
|
15246
15273
|
var ARM_SCOPE5 = "https://management.azure.com/.default";
|
|
15247
15274
|
var GITHUB_APP_API = "https://api.github.com";
|
|
@@ -15687,6 +15714,7 @@ import { spawnSync as spawnSync2 } from "child_process";
|
|
|
15687
15714
|
// src/lib/a2a-enable.ts
|
|
15688
15715
|
init_errors();
|
|
15689
15716
|
init_foundry_agent_get();
|
|
15717
|
+
init_foundry_agent_version();
|
|
15690
15718
|
import { randomBytes as randomBytes2, createHash } from "crypto";
|
|
15691
15719
|
|
|
15692
15720
|
// src/lib/data-plane-ready.ts
|
|
@@ -18399,6 +18427,7 @@ async function runBicepDeployment(opts) {
|
|
|
18399
18427
|
|
|
18400
18428
|
// src/lib/platform-converge.ts
|
|
18401
18429
|
init_foundry_agent_get();
|
|
18430
|
+
init_foundry_agent_version();
|
|
18402
18431
|
init_errors();
|
|
18403
18432
|
|
|
18404
18433
|
// src/lib/persona-compose.ts
|
|
@@ -20049,7 +20078,7 @@ var PlatformConvergeCommand = class extends M8tCommand {
|
|
|
20049
20078
|
static usage = Command33.Usage({
|
|
20050
20079
|
category: "Platform",
|
|
20051
20080
|
description: "Headless updater-job driver: claim a pending apply-request and converge the platform to it.",
|
|
20052
|
-
details: "The Managed-Identity-authenticated entry point run by the updater Container Apps job. One invocation is one tick: it claims the pending apply-request row (if any), refuses a downgrade against the installed stamp, self-fetches and validates the target manifest, self-updates its own engine image when the manifest requires a newer CLI, then drives the
|
|
20081
|
+
details: "The Managed-Identity-authenticated entry point run by the updater Container Apps job. One invocation is one tick: it claims the pending apply-request row (if any), refuses a downgrade against the installed stamp, self-fetches and validates the target manifest, self-updates its own engine image when the manifest requires a newer CLI, then drives the converge engine behind the health-gate + auto-rollback. Reads its subscription/RG/endpoint/channel from env (MI_CLIENT_ID, SUBSCRIPTION_ID, RESOURCE_GROUP, FOUNDRY_ENDPOINT, M8T_UPDATE_CHANNEL_URL). Not intended for interactive use \u2014 the founder-facing path is 'm8t platform update'."
|
|
20053
20082
|
});
|
|
20054
20083
|
async executeCommand() {
|
|
20055
20084
|
const ctx = resolveHeadlessContextFromEnv(process.env);
|
|
@@ -21335,7 +21364,7 @@ function parseVerdict(stdout) {
|
|
|
21335
21364
|
var EvalSkillCommand = class extends M8tCommand {
|
|
21336
21365
|
static paths = [["eval", "skill"]];
|
|
21337
21366
|
static usage = Command38.Usage({
|
|
21338
|
-
description: "Vet one inbox skill candidate
|
|
21367
|
+
description: "Vet one inbox skill candidate: promote / reject / needs_review. Shells out to the Python `brain-eval` core (override its path with $BRAIN_EVAL_BIN)."
|
|
21339
21368
|
});
|
|
21340
21369
|
candidate = Option35.String();
|
|
21341
21370
|
skillsDir = Option35.String("--skills-dir");
|
|
@@ -21423,7 +21452,7 @@ function parseArmToken(tok, opts) {
|
|
|
21423
21452
|
if (!opts.allowStub) {
|
|
21424
21453
|
throw new LocalCliError({
|
|
21425
21454
|
code: "USAGE",
|
|
21426
|
-
message: `imported
|
|
21455
|
+
message: `imported arms are stub-only (a one-file placeholder) \u2014 pass --allow-stub to run one anyway, or use live/off/pinned for a real scored run (got '${tok}')`
|
|
21427
21456
|
});
|
|
21428
21457
|
}
|
|
21429
21458
|
return { state: { imported: ref }, profile };
|
|
@@ -21531,7 +21560,7 @@ function resolveJudgeDeployment(flag, env) {
|
|
|
21531
21560
|
if (typeof fromEnv === "string" && fromEnv.length > 0) return { deployment: fromEnv };
|
|
21532
21561
|
return {
|
|
21533
21562
|
deployment: "gpt-5-mini",
|
|
21534
|
-
warning: "no --deployment and no $EXAM_JUDGE_DEPLOYMENT \u2014 falling back to gpt-5-mini as the judge. Name the DISTINCT judge deployment before any blessing/calibration run
|
|
21563
|
+
warning: "no --deployment and no $EXAM_JUDGE_DEPLOYMENT \u2014 falling back to gpt-5-mini as the judge. Name the DISTINCT judge deployment before any blessing/calibration run."
|
|
21535
21564
|
};
|
|
21536
21565
|
}
|
|
21537
21566
|
var BRAIN_REPO_MARKERS = ["m8t-labs/", "/azure-advisor-brain", "/stacey-brain", "exam-arm-"];
|
|
@@ -21539,7 +21568,7 @@ function assertOutNotInBrainRepo(out) {
|
|
|
21539
21568
|
if (BRAIN_REPO_MARKERS.some((m) => out.includes(m))) {
|
|
21540
21569
|
throw new LocalCliError({
|
|
21541
21570
|
code: "USAGE",
|
|
21542
|
-
message: `--out '${out}' is under a brain repo \u2014 reports MUST live in the referee home (Law-1 guard
|
|
21571
|
+
message: `--out '${out}' is under a brain repo \u2014 reports MUST live in the referee home (Law-1 guard)`
|
|
21543
21572
|
});
|
|
21544
21573
|
}
|
|
21545
21574
|
}
|
|
@@ -21631,7 +21660,7 @@ function buildPlan(args) {
|
|
|
21631
21660
|
var EvalExamCommand = class extends M8tCommand {
|
|
21632
21661
|
static paths = [["eval", "exam"]];
|
|
21633
21662
|
static usage = Command39.Usage({
|
|
21634
|
-
description: "Run a brain exam
|
|
21663
|
+
description: "Run a brain exam: impact A/B + dream-delta. Resolves the plan, then shells out to the Python `brain-exam` orchestrator (override its path with $BRAIN_EXAM_BIN). Renders an ExamVerdict: three-valued verdict + power note + per-task flips."
|
|
21635
21664
|
});
|
|
21636
21665
|
worker = Option36.String();
|
|
21637
21666
|
arms = Option36.String("--arms");
|
|
@@ -21704,7 +21733,7 @@ var EvalExamCommand = class extends M8tCommand {
|
|
|
21704
21733
|
this.context.stdout.write(renderJson(plan) + "\n");
|
|
21705
21734
|
this.context.stdout.write(
|
|
21706
21735
|
`
|
|
21707
|
-
(dry-run) ~${String(arms.length)} arms x n=${String(reps)}; judge grading fan-out is the cost driver \u2014 confirm the run sits inside the ~150-550 judge-call band before driving workers
|
|
21736
|
+
(dry-run) ~${String(arms.length)} arms x n=${String(reps)}; judge grading fan-out is the cost driver \u2014 confirm the run sits inside the ~150-550 judge-call band before driving workers.
|
|
21708
21737
|
`
|
|
21709
21738
|
);
|
|
21710
21739
|
return 0;
|
|
@@ -24307,7 +24336,7 @@ function forcePolicyQuarantine(delta) {
|
|
|
24307
24336
|
return {
|
|
24308
24337
|
verb: "quarantine",
|
|
24309
24338
|
slug: slugify(delta.title),
|
|
24310
|
-
reason: "code-side standing-policy/auto-approval/privilege assertion
|
|
24339
|
+
reason: "code-side standing-policy/auto-approval/privilege assertion",
|
|
24311
24340
|
body: delta.body,
|
|
24312
24341
|
evidence: delta.evidence
|
|
24313
24342
|
};
|
|
@@ -25680,6 +25709,17 @@ function ingestUrl(path38) {
|
|
|
25680
25709
|
// src/commands/bootstrap/preflight.ts
|
|
25681
25710
|
init_errors();
|
|
25682
25711
|
|
|
25712
|
+
// src/lib/spend-disclosure.ts
|
|
25713
|
+
var SPEND_DISCLOSURE = [
|
|
25714
|
+
"You are about to install the m8t platform.",
|
|
25715
|
+
"",
|
|
25716
|
+
" - It installs into YOUR Azure subscription and YOUR GitHub account or organization.",
|
|
25717
|
+
" - The Azure resources it creates bill to your Azure account - this uses your budget.",
|
|
25718
|
+
" - With your workers installed, you can ask Azzy what you're spending at any time,",
|
|
25719
|
+
" and you can turn on a cost report by email every two weeks.",
|
|
25720
|
+
" - You can remove it later - see guides/uninstall.md."
|
|
25721
|
+
].join("\n");
|
|
25722
|
+
|
|
25683
25723
|
// src/lib/bootstrap-preflight.ts
|
|
25684
25724
|
var ADMIN_DIRECTORY_ROLES = ["Global Administrator", "Application Administrator", "Cloud Application Administrator"];
|
|
25685
25725
|
async function checkSubScopeAdmin(callerObjectId, subscriptionId) {
|
|
@@ -25766,6 +25806,7 @@ var BootstrapPreflightCommand = class extends M8tCommand {
|
|
|
25766
25806
|
const account = await getAzAccount();
|
|
25767
25807
|
const subscriptionId = (typeof this.subscription === "string" ? this.subscription : void 0) ?? account.subscriptionId;
|
|
25768
25808
|
const oid = await getCallerObjectId();
|
|
25809
|
+
this.context.stdout.write(SPEND_DISCLOSURE + "\n\n");
|
|
25769
25810
|
this.context.stdout.write(buildPreflightBanner({ upn: account.upn, tenantId: account.tenantId, subscriptionId }) + "\n");
|
|
25770
25811
|
this.context.stdout.write(`
|
|
25771
25812
|
${colors.dim(DISCLOSURE_TIER1)}
|
|
@@ -26076,10 +26117,95 @@ async function writeBootstrapState(state, home = os13.homedir()) {
|
|
|
26076
26117
|
await fs29.rename(tmp, statePath(home));
|
|
26077
26118
|
}
|
|
26078
26119
|
|
|
26120
|
+
// src/lib/bootstrap-occupancy.ts
|
|
26121
|
+
init_errors();
|
|
26122
|
+
var SAMPLE_LIMIT = 3;
|
|
26123
|
+
var M8T_NAME_RE = /^m8t/i;
|
|
26124
|
+
async function checkTargetRgOccupancy(opts) {
|
|
26125
|
+
let existsRaw;
|
|
26126
|
+
try {
|
|
26127
|
+
existsRaw = await runAz([
|
|
26128
|
+
"group",
|
|
26129
|
+
"exists",
|
|
26130
|
+
"--name",
|
|
26131
|
+
opts.resourceGroup,
|
|
26132
|
+
"--subscription",
|
|
26133
|
+
opts.subscriptionId,
|
|
26134
|
+
"-o",
|
|
26135
|
+
"tsv"
|
|
26136
|
+
]);
|
|
26137
|
+
} catch (cause) {
|
|
26138
|
+
throw unverified(opts.resourceGroup, cause);
|
|
26139
|
+
}
|
|
26140
|
+
const exists2 = existsRaw.trim().toLowerCase();
|
|
26141
|
+
if (exists2 === "false") return { state: "absent", found: [], total: 0, m8tShaped: false };
|
|
26142
|
+
if (exists2 !== "true") {
|
|
26143
|
+
throw unverified(opts.resourceGroup, new Error(`unexpected 'az group exists' output: ${exists2}`));
|
|
26144
|
+
}
|
|
26145
|
+
let names;
|
|
26146
|
+
try {
|
|
26147
|
+
const listRaw = await runAz([
|
|
26148
|
+
"resource",
|
|
26149
|
+
"list",
|
|
26150
|
+
"--resource-group",
|
|
26151
|
+
opts.resourceGroup,
|
|
26152
|
+
"--subscription",
|
|
26153
|
+
opts.subscriptionId,
|
|
26154
|
+
"--query",
|
|
26155
|
+
"[].name",
|
|
26156
|
+
"-o",
|
|
26157
|
+
"json"
|
|
26158
|
+
]);
|
|
26159
|
+
names = JSON.parse(listRaw);
|
|
26160
|
+
} catch (cause) {
|
|
26161
|
+
throw unverified(opts.resourceGroup, cause);
|
|
26162
|
+
}
|
|
26163
|
+
if (!Array.isArray(names)) {
|
|
26164
|
+
throw unverified(opts.resourceGroup, new Error("resource listing was not an array"));
|
|
26165
|
+
}
|
|
26166
|
+
if (names.length === 0) return { state: "empty", found: [], total: 0, m8tShaped: false };
|
|
26167
|
+
return {
|
|
26168
|
+
state: "occupied",
|
|
26169
|
+
found: names.slice(0, SAMPLE_LIMIT),
|
|
26170
|
+
total: names.length,
|
|
26171
|
+
// Computed BEFORE the cap: an m8t-named resource sorting past the sample
|
|
26172
|
+
// must still escalate the wording.
|
|
26173
|
+
m8tShaped: names.some((n) => M8T_NAME_RE.test(n))
|
|
26174
|
+
};
|
|
26175
|
+
}
|
|
26176
|
+
function unverified(resourceGroup, cause) {
|
|
26177
|
+
return new LocalCliError({
|
|
26178
|
+
code: "BOOTSTRAP_OCCUPANCY_UNVERIFIED",
|
|
26179
|
+
message: `Could not verify whether resource group '${resourceGroup}' is empty.`,
|
|
26180
|
+
hint: "Check your connection and 'az login', then retry.",
|
|
26181
|
+
cause
|
|
26182
|
+
});
|
|
26183
|
+
}
|
|
26184
|
+
function buildOccupiedRefusal(args) {
|
|
26185
|
+
const { resourceGroup: rg, subscriptionId, location, occupancy: o } = args;
|
|
26186
|
+
const hidden = o.total - o.found.length;
|
|
26187
|
+
const more = hidden > 0 ? ` (+${String(hidden)} more)` : "";
|
|
26188
|
+
const risk = o.m8tShaped ? "Installing into a non-empty resource group risks overwriting what's already there.\n This looks like an existing m8t deployment; installing here would overwrite its identity." : "Installing into a non-empty resource group risks overwriting what's already there.";
|
|
26189
|
+
return [
|
|
26190
|
+
"",
|
|
26191
|
+
"\u26D4 CANNOT PROCEED",
|
|
26192
|
+
` Resource group '${rg}' in subscription ${subscriptionId} is not empty \u2014 it holds`,
|
|
26193
|
+
` ${String(o.total)} resources, including: ${o.found.join(", ")}${more}.`,
|
|
26194
|
+
` ${risk}`,
|
|
26195
|
+
" remedy: pick an empty resource group \u2014",
|
|
26196
|
+
` m8t bootstrap launch --location ${location} --resource-group <new-rg>`,
|
|
26197
|
+
" or, if you really mean to install into this one:",
|
|
26198
|
+
` m8t bootstrap launch --location ${location} --resource-group ${rg} --reinstall-into ${rg}`,
|
|
26199
|
+
" Nothing has been created.",
|
|
26200
|
+
"",
|
|
26201
|
+
""
|
|
26202
|
+
].join("\n");
|
|
26203
|
+
}
|
|
26204
|
+
|
|
26079
26205
|
// src/commands/bootstrap/launch.ts
|
|
26080
26206
|
var DEFAULT_RG = "rg-m8t-stack";
|
|
26081
26207
|
var DEFAULT_INSTALLER = "ghcr.io/m8t-labs/m8t-installer";
|
|
26082
|
-
var DEFAULT_INSTALLER_TAG = "v0.1.
|
|
26208
|
+
var DEFAULT_INSTALLER_TAG = "v0.1.42";
|
|
26083
26209
|
var ACI_NAME = "m8t-installer";
|
|
26084
26210
|
var MI_NAME = "m8t-installer-mi";
|
|
26085
26211
|
var BootstrapLaunchCommand = class extends M8tCommand {
|
|
@@ -26090,8 +26216,8 @@ var BootstrapLaunchCommand = class extends M8tCommand {
|
|
|
26090
26216
|
examples: [
|
|
26091
26217
|
["Launch in eastus2", "$0 bootstrap launch --location eastus2"],
|
|
26092
26218
|
["BYO app registration", "$0 bootstrap launch --location eastus2 --client-id <appId>"],
|
|
26093
|
-
["Pin a specific installer tag", "$0 bootstrap launch --location eastus2 --installer-tag v0.1.
|
|
26094
|
-
["Override the full installer image ref", "$0 bootstrap launch --location eastus2 --installer-image ghcr.io/m8t-labs/m8t-installer:v0.1.
|
|
26219
|
+
["Pin a specific installer tag", "$0 bootstrap launch --location eastus2 --installer-tag v0.1.42"],
|
|
26220
|
+
["Override the full installer image ref", "$0 bootstrap launch --location eastus2 --installer-image ghcr.io/m8t-labs/m8t-installer:v0.1.42"],
|
|
26095
26221
|
["Share a support contact", "$0 bootstrap launch --location eastus2 --contact-email you@example.com --company 'Acme'"]
|
|
26096
26222
|
]
|
|
26097
26223
|
});
|
|
@@ -26108,12 +26234,18 @@ var BootstrapLaunchCommand = class extends M8tCommand {
|
|
|
26108
26234
|
githubAppCreds = Option47.String("--github-app-creds");
|
|
26109
26235
|
contactEmail = Option47.String("--contact-email", { description: "Share a contact email with m8t support. Not sent unless you pass it." });
|
|
26110
26236
|
company = Option47.String("--company", { description: "Share your company name with m8t support. Not sent unless you pass it." });
|
|
26237
|
+
// Value-carrying on purpose: a bare --force would be cargo-culted into
|
|
26238
|
+
// runbooks and harness prompts and erode the protection, whereas a faithful
|
|
26239
|
+
// paste can never accidentally carry the victim group's name. It AUTHORIZES
|
|
26240
|
+
// the target; --resource-group is what CHOOSES it.
|
|
26241
|
+
reinstallInto = Option47.String("--reinstall-into", { description: "Consent to installing into --resource-group even though it already holds resources. Must match the target group's name." });
|
|
26111
26242
|
async executeCommand() {
|
|
26112
26243
|
const location = typeof this.location === "string" ? this.location : void 0;
|
|
26113
26244
|
if (!location) {
|
|
26114
26245
|
throw new LocalCliError({ code: "USAGE", message: "--location is required.", hint: "Example: m8t bootstrap launch --location eastus2" });
|
|
26115
26246
|
}
|
|
26116
|
-
const
|
|
26247
|
+
const resourceGroupOpt = typeof this.resourceGroup === "string" ? this.resourceGroup : void 0;
|
|
26248
|
+
const resourceGroup = resourceGroupOpt ?? DEFAULT_RG;
|
|
26117
26249
|
const clientIdOpt = typeof this.clientId === "string" ? this.clientId : void 0;
|
|
26118
26250
|
const installerTag = (typeof this.installerTag === "string" ? this.installerTag : void 0) ?? DEFAULT_INSTALLER_TAG;
|
|
26119
26251
|
const installerImageOverride = typeof this.installerImage === "string" ? this.installerImage : void 0;
|
|
@@ -26123,6 +26255,28 @@ var BootstrapLaunchCommand = class extends M8tCommand {
|
|
|
26123
26255
|
const subscriptionId = (typeof this.subscription === "string" ? this.subscription : void 0) ?? account.subscriptionId;
|
|
26124
26256
|
const out = (m) => this.context.stderr.write(` ${colors.dim(m)}
|
|
26125
26257
|
`);
|
|
26258
|
+
const reinstallInto = typeof this.reinstallInto === "string" ? this.reinstallInto : void 0;
|
|
26259
|
+
if (reinstallInto !== void 0 && reinstallInto.toLowerCase() !== resourceGroup.toLowerCase()) {
|
|
26260
|
+
const targetExplanation = resourceGroupOpt === void 0 ? `you did not pass --resource-group, so the target is the default '${DEFAULT_RG}'` : `the target resource group is '${resourceGroup}'`;
|
|
26261
|
+
throw new LocalCliError({
|
|
26262
|
+
code: "BOOTSTRAP_REINSTALL_TARGET_MISMATCH",
|
|
26263
|
+
message: `--reinstall-into '${reinstallInto}' does not match \u2014 ${targetExplanation}.`,
|
|
26264
|
+
hint: `--reinstall-into authorizes the target; it does not choose it. Re-run with --resource-group ${reinstallInto} on its own first \u2014 the guard will show you what that group holds.`
|
|
26265
|
+
});
|
|
26266
|
+
}
|
|
26267
|
+
const occupancy = await checkTargetRgOccupancy({ resourceGroup, subscriptionId });
|
|
26268
|
+
if (occupancy.state === "occupied" && reinstallInto === void 0) {
|
|
26269
|
+
this.context.stderr.write(buildOccupiedRefusal({ resourceGroup, subscriptionId, location, occupancy }));
|
|
26270
|
+
throw new LocalCliError({
|
|
26271
|
+
code: "BOOTSTRAP_TARGET_OCCUPIED",
|
|
26272
|
+
message: `Resource group '${resourceGroup}' already holds ${String(occupancy.total)} resources.`
|
|
26273
|
+
});
|
|
26274
|
+
}
|
|
26275
|
+
if (this.context.env.M8T_HALT_AFTER_OCCUPANCY === "1") {
|
|
26276
|
+
this.context.stdout.write(`halt: occupancy check passed (${occupancy.state}) for ${resourceGroup}
|
|
26277
|
+
`);
|
|
26278
|
+
return 0;
|
|
26279
|
+
}
|
|
26126
26280
|
const credsPath = typeof this.githubAppCreds === "string" ? this.githubAppCreds : path32.join(os14.homedir(), ".m8t", "github-app.json");
|
|
26127
26281
|
let githubApp;
|
|
26128
26282
|
if (fs30.existsSync(credsPath)) {
|
|
@@ -27475,12 +27629,13 @@ function writeWebEnvLocal(args) {
|
|
|
27475
27629
|
});
|
|
27476
27630
|
}
|
|
27477
27631
|
const body = [
|
|
27478
|
-
"# Written by `m8t bootstrap ui` \u2014 onboarding
|
|
27632
|
+
"# Written by `m8t bootstrap ui` \u2014 local onboarding run (Simple Stacey).",
|
|
27633
|
+
"# Text-first: the intake voice stack is off unless the run passed --voice.",
|
|
27479
27634
|
"# STORAGE unset \u2192 gateway boot skipped; the webapp forwards your MSAL token to Foundry.",
|
|
27480
27635
|
`AZURE_TENANT_ID=${args.tenantId}`,
|
|
27481
27636
|
`AZURE_CLIENT_ID=${args.clientId}`,
|
|
27482
27637
|
`FOUNDRY_PROJECT_ENDPOINT=${args.foundryEndpoint}`,
|
|
27483
|
-
"VOICE_RELAY_PUBLIC_URL=ws://localhost:8790",
|
|
27638
|
+
...args.voice ? ["VOICE_RELAY_PUBLIC_URL=ws://localhost:8790", "NEXT_PUBLIC_M8T_INTAKE_VOICE=1"] : [],
|
|
27484
27639
|
"STORAGE_ACCOUNT_NAME=",
|
|
27485
27640
|
`M8T_INTERNAL_SECRET=${internalSecret}`,
|
|
27486
27641
|
"M8T_SINGLE_GATEWAY_PROCESS=1",
|
|
@@ -27797,8 +27952,9 @@ var BootstrapUiCommand = class extends M8tCommand {
|
|
|
27797
27952
|
details: [
|
|
27798
27953
|
"Run after `m8t bootstrap launch`, in parallel with `status --watch`. Waits for the cloud",
|
|
27799
27954
|
"installer's foundry-create phase, grants you Foundry data-plane access, deploys a no-brain",
|
|
27800
|
-
"Simple Stacey (stacey-intake), writes apps/web/.env.local (chat-only
|
|
27801
|
-
"starts the webapp detached so a coding agent can continue without opening
|
|
27955
|
+
"Simple Stacey (stacey-intake), writes apps/web/.env.local (chat-only unless --voice is set),",
|
|
27956
|
+
"installs deps, and starts the webapp detached so a coding agent can continue without opening",
|
|
27957
|
+
"a separate terminal.",
|
|
27802
27958
|
"",
|
|
27803
27959
|
"The command returns as soon as the server is ready (or after ~45 s if it is still compiling).",
|
|
27804
27960
|
"Use `--stop` to shut it down, `--foreground` to keep the old blocking behaviour."
|
|
@@ -27807,7 +27963,8 @@ var BootstrapUiCommand = class extends M8tCommand {
|
|
|
27807
27963
|
["Start the onboarding UI (backgrounds the server, returns)", "$0 bootstrap ui --repo-root /path/to/m8t"],
|
|
27808
27964
|
["Stop the running onboarding UI", "$0 bootstrap ui --stop"],
|
|
27809
27965
|
["Prep only (don't serve at all)", "$0 bootstrap ui --repo-root /path/to/m8t --prep-only"],
|
|
27810
|
-
["Foreground (blocking, old behaviour)", "$0 bootstrap ui --repo-root /path/to/m8t --foreground"]
|
|
27966
|
+
["Foreground (blocking, old behaviour)", "$0 bootstrap ui --repo-root /path/to/m8t --foreground"],
|
|
27967
|
+
["Experimental: enable the intake voice call", "$0 bootstrap ui --repo-root /path/to/m8t --voice"]
|
|
27811
27968
|
]
|
|
27812
27969
|
});
|
|
27813
27970
|
repoRoot = Option51.String("--repo-root");
|
|
@@ -27819,6 +27976,9 @@ var BootstrapUiCommand = class extends M8tCommand {
|
|
|
27819
27976
|
skipInstall = Option51.Boolean("--skip-install", false);
|
|
27820
27977
|
stop = Option51.Boolean("--stop", false);
|
|
27821
27978
|
foreground = Option51.Boolean("--foreground", false);
|
|
27979
|
+
voice = Option51.Boolean("--voice", false, {
|
|
27980
|
+
description: "Experimental/preview: enable the intake voice call and start the voice relay on :8790. Not a supported founder path \u2014 the intake is text-only by default."
|
|
27981
|
+
});
|
|
27822
27982
|
async executeCommand() {
|
|
27823
27983
|
if (this.stop === true) {
|
|
27824
27984
|
const stopped = stopOnboardingUi();
|
|
@@ -27885,7 +28045,8 @@ var BootstrapUiCommand = class extends M8tCommand {
|
|
|
27885
28045
|
repoRoot,
|
|
27886
28046
|
tenantId: account.tenantId,
|
|
27887
28047
|
clientId: state.appRegClientId,
|
|
27888
|
-
foundryEndpoint: endpoint
|
|
28048
|
+
foundryEndpoint: endpoint,
|
|
28049
|
+
voice: this.voice === true
|
|
27889
28050
|
});
|
|
27890
28051
|
if (!this.skipInstall) {
|
|
27891
28052
|
out("installing apps/web dependencies (pnpm)\u2026");
|
|
@@ -27900,15 +28061,17 @@ var BootstrapUiCommand = class extends M8tCommand {
|
|
|
27900
28061
|
return 0;
|
|
27901
28062
|
}
|
|
27902
28063
|
if (this.foreground === true) {
|
|
27903
|
-
|
|
27904
|
-
|
|
27905
|
-
|
|
27906
|
-
|
|
27907
|
-
|
|
27908
|
-
|
|
27909
|
-
|
|
27910
|
-
|
|
27911
|
-
|
|
28064
|
+
if (this.voice === true) {
|
|
28065
|
+
out("starting the voice relay on :8790 in the background\u2026");
|
|
28066
|
+
await serveOnboardingRelayDetached({
|
|
28067
|
+
repoRoot,
|
|
28068
|
+
foundryEndpoint: endpoint,
|
|
28069
|
+
tenantId: account.tenantId,
|
|
28070
|
+
clientId: state.appRegClientId,
|
|
28071
|
+
webInternalBaseUrl: "http://localhost:3000"
|
|
28072
|
+
});
|
|
28073
|
+
out("voice relay on :8790");
|
|
28074
|
+
}
|
|
27912
28075
|
const outcome2 = await deployOutcome;
|
|
27913
28076
|
if (!outcome2.ok) {
|
|
27914
28077
|
this.context.stderr.write(renderDeployFailure(outcome2.error));
|
|
@@ -27919,15 +28082,17 @@ var BootstrapUiCommand = class extends M8tCommand {
|
|
|
27919
28082
|
await runInherit("pnpm", ["--filter", "web", "dev"], repoRoot, "BOOTSTRAP_UI_DEV_FAILED");
|
|
27920
28083
|
return 0;
|
|
27921
28084
|
}
|
|
27922
|
-
|
|
27923
|
-
|
|
27924
|
-
|
|
27925
|
-
|
|
27926
|
-
|
|
27927
|
-
|
|
27928
|
-
|
|
27929
|
-
|
|
27930
|
-
|
|
28085
|
+
if (this.voice === true) {
|
|
28086
|
+
out("starting the voice relay on :8790 in the background\u2026");
|
|
28087
|
+
await serveOnboardingRelayDetached({
|
|
28088
|
+
repoRoot,
|
|
28089
|
+
foundryEndpoint: endpoint,
|
|
28090
|
+
tenantId: account.tenantId,
|
|
28091
|
+
clientId: state.appRegClientId,
|
|
28092
|
+
webInternalBaseUrl: "http://localhost:3000"
|
|
28093
|
+
});
|
|
28094
|
+
out("voice relay on :8790");
|
|
28095
|
+
}
|
|
27931
28096
|
out("starting the webapp on :3000 in the background\u2026");
|
|
27932
28097
|
const { alreadyRunning, logPath } = await serveOnboardingUiDetached({ repoRoot, port: this.port });
|
|
27933
28098
|
if (alreadyRunning) {
|