@m8t-stack/cli 0.2.27 → 0.2.29
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 +8 -8
- package/dist/cli.js +298 -146
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -931,7 +931,7 @@ var init_foundry_agents = __esm({
|
|
|
931
931
|
"use strict";
|
|
932
932
|
init_http();
|
|
933
933
|
init_errors();
|
|
934
|
-
METADATA_SOURCE = "m8t
|
|
934
|
+
METADATA_SOURCE = "m8t";
|
|
935
935
|
FOUNDRY_SCOPE2 = "https://ai.azure.com/.default";
|
|
936
936
|
API = "v1";
|
|
937
937
|
}
|
|
@@ -1177,7 +1177,7 @@ async function enableHostedBrain(args) {
|
|
|
1177
1177
|
// survive the relink version; the managed fields are re-asserted over the
|
|
1178
1178
|
// spread, and createCoderVersion applies the `brain` arg last.
|
|
1179
1179
|
...current.metadata,
|
|
1180
|
-
source: "m8t
|
|
1180
|
+
source: "m8t",
|
|
1181
1181
|
kind: "hosted",
|
|
1182
1182
|
persona: current.metadata?.persona ?? "coding-agent",
|
|
1183
1183
|
personaVersion: current.metadata?.personaVersion ?? null
|
|
@@ -1247,7 +1247,7 @@ var init_enable_hosted_brain = __esm({
|
|
|
1247
1247
|
import { Builtins, Cli } from "clipanion";
|
|
1248
1248
|
|
|
1249
1249
|
// src/lib/package-version.ts
|
|
1250
|
-
var CLI_VERSION = "0.2.
|
|
1250
|
+
var CLI_VERSION = "0.2.29";
|
|
1251
1251
|
|
|
1252
1252
|
// src/lib/render-error.ts
|
|
1253
1253
|
init_errors();
|
|
@@ -1412,7 +1412,7 @@ var BACKEND_RULES = [
|
|
|
1412
1412
|
{
|
|
1413
1413
|
code: "UPSTREAM_FAILED",
|
|
1414
1414
|
reason: "kv_secret_malformed",
|
|
1415
|
-
hint: () => "the Key Vault secret for this binding is in an unexpected shape. Manual cleanup may be required \u2014 contact your m8t
|
|
1415
|
+
hint: () => "the Key Vault secret for this binding is in an unexpected shape. Manual cleanup may be required \u2014 contact your m8t admin."
|
|
1416
1416
|
},
|
|
1417
1417
|
// NOTE: cascade_partial_failure is handled INLINE in the bind remove +
|
|
1418
1418
|
// bind cleanup command files (the rendering needs the structured
|
|
@@ -1442,50 +1442,32 @@ var BACKEND_RULES = [
|
|
|
1442
1442
|
}
|
|
1443
1443
|
];
|
|
1444
1444
|
var LOCAL_RULES = {
|
|
1445
|
-
// Task 12 — foundry-agent-get
|
|
1446
1445
|
AGENT_CREATE_VERSION_FAILED: "Re-run with `--verbose` for the full response body.",
|
|
1447
1446
|
AGENT_CREATE_VERSION_NO_VERSION: "Foundry returned 2xx but no version \u2014 likely an API regression. Re-try; if it persists, file an issue.",
|
|
1448
1447
|
AGENT_GET_FAILED: "Re-run with `--verbose` for the full response body.",
|
|
1449
1448
|
AGENT_NOT_FOUND: "Use `m8t brain create <name>` to create the worker first, OR run `m8t deploy <name>` to register an existing agent.",
|
|
1450
|
-
// Task 14 — brain-unlink
|
|
1451
1449
|
AGENT_REDEPLOY_FAILED: "Re-run with `--verbose` for the full response body.",
|
|
1452
1450
|
AGENT_REDEPLOY_NO_VERSION: "Foundry returned 2xx but no version. Re-try; if it persists, file an issue.",
|
|
1453
|
-
// Task 10/13/14
|
|
1454
1451
|
AGENT_YAML_NOT_FOUND: "Deploy the worker via `m8t deploy <name>` or the architect first.",
|
|
1455
|
-
// Task 16 — brain link command
|
|
1456
1452
|
APP_HEALTH_FAILED: "Run `m8t brain check-app` for details, then re-run this command.",
|
|
1457
|
-
// Task 14 — brain-unlink
|
|
1458
1453
|
APP_UNINSTALL_FAILED: "GitHub App-uninstall DELETE failed. Re-run with `--keep-app-install` if you want to skip this step.",
|
|
1459
|
-
// Task 13 — brain-link
|
|
1460
1454
|
ARM_AUTH: "Run `az login` and retry.",
|
|
1461
1455
|
// F2 smoke fix — m8t brain create: stageAsGitRepo step
|
|
1462
1456
|
BRAIN_GIT_INIT_FAILED: "If git is not installed, install it. Otherwise re-run with --verbose.",
|
|
1463
|
-
// Task 14 — brain-unlink
|
|
1464
1457
|
BRAIN_NOT_LINKED: "The worker has no brain link. Use `m8t brain link` or `m8t brain create` first.",
|
|
1465
|
-
// Task 13 — brain-link
|
|
1466
1458
|
BRAIN_YAML_MIRROR_FAILED: "GitHub Contents API PUT failed. Verify the App has `contents: write` permission on the repo.",
|
|
1467
|
-
// Task 13 — brain-link
|
|
1468
1459
|
CONN_CREATE_FAILED: "Foundry connection PUT failed. Verify Cognitive Services Contributor role on the project.",
|
|
1469
|
-
// Task 14 — brain-unlink
|
|
1470
1460
|
CONN_DELETE_FAILED: "Foundry connection DELETE failed. Verify your ARM subscription has Contributor on the project.",
|
|
1471
|
-
// Task 13 — brain-link
|
|
1472
1461
|
CONN_GET_FAILED: "Foundry connection GET failed. Verify your ARM subscription has access to the project.",
|
|
1473
|
-
//
|
|
1462
|
+
// rename pending: should be FOUNDRY_AUTH_FAILED
|
|
1474
1463
|
FOUNDRY_AUTH: "Run `az login` and retry.",
|
|
1475
|
-
// Task 12 — foundry-agent-get
|
|
1476
1464
|
FOUNDRY_AUTH_FAILED: "Run `az login` and retry.",
|
|
1477
|
-
// Task 15+16
|
|
1478
1465
|
KV_URI_NOT_FOUND: "Pass `--kv-uri` or set `AZURE_KEYVAULT_URI` / `KEYVAULT_URI`.",
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
PERSONA_PATH_NOT_ABSOLUTE: "The persona path in ~/.m8t-stack/foundry/<worker>.yaml must be absolute. Re-deploy the worker via the architect.",
|
|
1485
|
-
// Task 9 — persona-render
|
|
1486
|
-
PERSONA_PLACEHOLDER_UNSATISFIED: "Re-deploy the worker via the architect to repopulate fillableFieldValues, OR edit ~/.m8t-stack/foundry/<worker>.yaml manually.",
|
|
1487
|
-
// Task 9 — persona-render
|
|
1488
|
-
PERSONA_READ_FAILED: "Verify the persona path in ~/.m8t-stack/foundry/<worker>.yaml; the architect should have populated it at deploy time.",
|
|
1466
|
+
LINK_NO_INSTALLATION_ID: "Internal error \u2014 the CLI command must poll for the installation id before calling linkBrain. Report at https://github.com/m8t/m8t/issues.",
|
|
1467
|
+
M8T_REPO_ROOT_MISSING: "Re-run `m8t install` from a fresh m8t checkout \u2014 the post-install hook writes ~/.m8t/repo-root.",
|
|
1468
|
+
PERSONA_PATH_NOT_ABSOLUTE: "The persona path in ~/.m8t/foundry/<worker>.yaml must be absolute. Re-deploy the worker via the architect.",
|
|
1469
|
+
PERSONA_PLACEHOLDER_UNSATISFIED: "Re-deploy the worker via the architect to repopulate fillableFieldValues, OR edit ~/.m8t/foundry/<worker>.yaml manually.",
|
|
1470
|
+
PERSONA_READ_FAILED: "Verify the persona path in ~/.m8t/foundry/<worker>.yaml; the architect should have populated it at deploy time.",
|
|
1489
1471
|
// ── pre-existing entries ──────────────────────────────────────────────────
|
|
1490
1472
|
AUTH_NOT_SIGNED_IN: "you are not signed in to Azure \u2014 run 'az login' first.",
|
|
1491
1473
|
AUTH_EXPIRED: "your Azure login expired \u2014 run 'az login' to re-authenticate.",
|
|
@@ -11524,7 +11506,7 @@ function redactAzArgs(args) {
|
|
|
11524
11506
|
}
|
|
11525
11507
|
function runAz(args) {
|
|
11526
11508
|
return new Promise((resolve3, reject) => {
|
|
11527
|
-
const proc = spawn("az", args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
11509
|
+
const proc = spawn("az", args, { stdio: ["ignore", "pipe", "pipe"], shell: process.platform === "win32" });
|
|
11528
11510
|
const out = [];
|
|
11529
11511
|
const err = [];
|
|
11530
11512
|
proc.stdout.on("data", (d) => out.push(d));
|
|
@@ -11747,7 +11729,7 @@ import * as path2 from "path";
|
|
|
11747
11729
|
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
11748
11730
|
function configDir() {
|
|
11749
11731
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
11750
|
-
return path2.join(home, ".m8t
|
|
11732
|
+
return path2.join(home, ".m8t");
|
|
11751
11733
|
}
|
|
11752
11734
|
function getConfigPath() {
|
|
11753
11735
|
return path2.join(configDir(), "cli-config.yaml");
|
|
@@ -11810,7 +11792,7 @@ async function discoverGateway(opts) {
|
|
|
11810
11792
|
const candidates = [];
|
|
11811
11793
|
try {
|
|
11812
11794
|
for await (const app of client.containerApps.listBySubscription()) {
|
|
11813
|
-
if (app.tags?.
|
|
11795
|
+
if (app.tags?.m8t !== "gateway") continue;
|
|
11814
11796
|
const fqdn2 = app.configuration?.ingress?.fqdn;
|
|
11815
11797
|
const envs = app.template?.containers?.[0]?.env ?? [];
|
|
11816
11798
|
const envMap = /* @__PURE__ */ new Map();
|
|
@@ -11839,7 +11821,7 @@ async function discoverGateway(opts) {
|
|
|
11839
11821
|
if (candidates.length === 0) {
|
|
11840
11822
|
throw new LocalCliError({
|
|
11841
11823
|
code: "GATEWAY_DISCOVERY_ZERO",
|
|
11842
|
-
message: `No m8t
|
|
11824
|
+
message: `No m8t deployment found in subscription ${subscriptionId}.`,
|
|
11843
11825
|
hint: "If the deployment is in another subscription, run 'az account set --subscription <name>'."
|
|
11844
11826
|
});
|
|
11845
11827
|
}
|
|
@@ -11850,8 +11832,8 @@ async function discoverGateway(opts) {
|
|
|
11850
11832
|
if (pool.length === 0) {
|
|
11851
11833
|
throw new LocalCliError({
|
|
11852
11834
|
code: "GATEWAY_DISCOVERY_RG_NOT_FOUND",
|
|
11853
|
-
message: `No m8t
|
|
11854
|
-
hint: `m8t
|
|
11835
|
+
message: `No m8t gateway found in resource group '${opts.resourceGroup}' (subscription ${subscriptionId}).`,
|
|
11836
|
+
hint: `m8t gateways in this subscription: ${candidates.map((c) => c.resourceGroup).join(", ")}.`
|
|
11855
11837
|
});
|
|
11856
11838
|
}
|
|
11857
11839
|
}
|
|
@@ -11860,7 +11842,7 @@ async function discoverGateway(opts) {
|
|
|
11860
11842
|
chosen = pool[0];
|
|
11861
11843
|
} else if (opts.interactive) {
|
|
11862
11844
|
const resourceId = await select({
|
|
11863
|
-
message: `Multiple m8t
|
|
11845
|
+
message: `Multiple m8t deployments found in subscription ${subscriptionId}. Choose one:`,
|
|
11864
11846
|
choices: pool.map((c) => ({
|
|
11865
11847
|
name: `${c.name} (rg=${c.resourceGroup}, ${c.location})`,
|
|
11866
11848
|
value: c.resourceId
|
|
@@ -11877,7 +11859,7 @@ async function discoverGateway(opts) {
|
|
|
11877
11859
|
} else {
|
|
11878
11860
|
throw new LocalCliError({
|
|
11879
11861
|
code: "GATEWAY_DISCOVERY_MULTIPLE",
|
|
11880
|
-
message: `Multiple m8t
|
|
11862
|
+
message: `Multiple m8t gateways found in subscription ${subscriptionId}: ${pool.map((c) => `${c.name} (rg=${c.resourceGroup}, ${c.location})`).join("; ")}.`,
|
|
11881
11863
|
hint: `Re-run with --resource-group <rg> to pick one (e.g. --resource-group ${pool[0].resourceGroup}).`
|
|
11882
11864
|
});
|
|
11883
11865
|
}
|
|
@@ -11965,7 +11947,7 @@ var BindAddCommand = class extends M8tCommand {
|
|
|
11965
11947
|
description: "Azure subscription ID to discover gateway in (defaults to active az subscription)."
|
|
11966
11948
|
});
|
|
11967
11949
|
resourceGroup = Option.String("--resource-group", {
|
|
11968
|
-
description: "m8t
|
|
11950
|
+
description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
|
|
11969
11951
|
});
|
|
11970
11952
|
async executeCommand() {
|
|
11971
11953
|
if (!this.worker) {
|
|
@@ -12048,7 +12030,7 @@ var BindCleanupCommand = class extends M8tCommand {
|
|
|
12048
12030
|
description: "Azure subscription ID to discover gateway in (defaults to active az subscription)."
|
|
12049
12031
|
});
|
|
12050
12032
|
resourceGroup = Option2.String("--resource-group", {
|
|
12051
|
-
description: "m8t
|
|
12033
|
+
description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
|
|
12052
12034
|
});
|
|
12053
12035
|
async executeCommand() {
|
|
12054
12036
|
if (this.bindingId && this.allOrphaned) {
|
|
@@ -12189,7 +12171,7 @@ var BindListCommand = class extends M8tCommand {
|
|
|
12189
12171
|
description: "Azure subscription ID to discover gateway in (defaults to active az subscription)."
|
|
12190
12172
|
});
|
|
12191
12173
|
resourceGroup = Option3.String("--resource-group", {
|
|
12192
|
-
description: "m8t
|
|
12174
|
+
description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
|
|
12193
12175
|
});
|
|
12194
12176
|
async executeCommand() {
|
|
12195
12177
|
const mode = resolveOutputMode(
|
|
@@ -12269,7 +12251,7 @@ var BindRemoveCommand = class extends M8tCommand {
|
|
|
12269
12251
|
description: "Azure subscription ID to discover gateway in (defaults to active az subscription)."
|
|
12270
12252
|
});
|
|
12271
12253
|
resourceGroup = Option4.String("--resource-group", {
|
|
12272
|
-
description: "m8t
|
|
12254
|
+
description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
|
|
12273
12255
|
});
|
|
12274
12256
|
async executeCommand() {
|
|
12275
12257
|
const mode = resolveOutputMode(
|
|
@@ -12348,7 +12330,7 @@ var BindShowCommand = class extends M8tCommand {
|
|
|
12348
12330
|
description: "Azure subscription ID to discover gateway in (defaults to active az subscription)."
|
|
12349
12331
|
});
|
|
12350
12332
|
resourceGroup = Option5.String("--resource-group", {
|
|
12351
|
-
description: "m8t
|
|
12333
|
+
description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
|
|
12352
12334
|
});
|
|
12353
12335
|
async executeCommand() {
|
|
12354
12336
|
const mode = resolveOutputMode(
|
|
@@ -12422,7 +12404,7 @@ var FOUNDRY_CONFIG_KEYS = ["tenantId", "clientId", "projectEndpoint"];
|
|
|
12422
12404
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
12423
12405
|
function configDir2() {
|
|
12424
12406
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
12425
|
-
return path3.join(home, ".m8t
|
|
12407
|
+
return path3.join(home, ".m8t");
|
|
12426
12408
|
}
|
|
12427
12409
|
function getFoundryConfigPath() {
|
|
12428
12410
|
return path3.join(configDir2(), "config.yaml");
|
|
@@ -12539,7 +12521,7 @@ init_errors();
|
|
|
12539
12521
|
var ConfigSetCommand = class extends M8tCommand {
|
|
12540
12522
|
static paths = [["config", "set"]];
|
|
12541
12523
|
static usage = Command8.Usage({
|
|
12542
|
-
description: "Set a value in ~/.m8t
|
|
12524
|
+
description: "Set a value in ~/.m8t/config.yaml (tenantId | clientId | projectEndpoint)."
|
|
12543
12525
|
});
|
|
12544
12526
|
key = Option7.String();
|
|
12545
12527
|
value = Option7.String();
|
|
@@ -12574,7 +12556,7 @@ import { Command as Command9, Option as Option8 } from "clipanion";
|
|
|
12574
12556
|
var ConfigShowCommand = class extends M8tCommand {
|
|
12575
12557
|
static paths = [["config", "show"]];
|
|
12576
12558
|
static usage = Command9.Usage({
|
|
12577
|
-
description: "Show ~/.m8t
|
|
12559
|
+
description: "Show ~/.m8t/config.yaml (tenant/client/project) + the cached gateway.",
|
|
12578
12560
|
details: "Displays the Foundry config (config.yaml) and the gateway discovery cache (cli-config.yaml)."
|
|
12579
12561
|
});
|
|
12580
12562
|
output = Option8.String("--output");
|
|
@@ -12648,7 +12630,7 @@ var TeamAddCommand = class extends M8tCommand {
|
|
|
12648
12630
|
description: "Azure subscription ID to discover gateway in (defaults to active az subscription)."
|
|
12649
12631
|
});
|
|
12650
12632
|
resourceGroup = Option9.String("--resource-group", {
|
|
12651
|
-
description: "m8t
|
|
12633
|
+
description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
|
|
12652
12634
|
});
|
|
12653
12635
|
async executeCommand() {
|
|
12654
12636
|
const identities = {};
|
|
@@ -12741,7 +12723,7 @@ var TeamAddIdentityCommand = class extends M8tCommand {
|
|
|
12741
12723
|
description: "Azure subscription ID to discover gateway in (defaults to active az subscription)."
|
|
12742
12724
|
});
|
|
12743
12725
|
resourceGroup = Option10.String("--resource-group", {
|
|
12744
|
-
description: "m8t
|
|
12726
|
+
description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
|
|
12745
12727
|
});
|
|
12746
12728
|
async executeCommand() {
|
|
12747
12729
|
const identities = {};
|
|
@@ -12801,7 +12783,7 @@ var TeamListCommand = class extends M8tCommand {
|
|
|
12801
12783
|
description: "Azure subscription ID to discover gateway in (defaults to active az subscription)."
|
|
12802
12784
|
});
|
|
12803
12785
|
resourceGroup = Option11.String("--resource-group", {
|
|
12804
|
-
description: "m8t
|
|
12786
|
+
description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
|
|
12805
12787
|
});
|
|
12806
12788
|
async executeCommand() {
|
|
12807
12789
|
const mode = resolveOutputMode(
|
|
@@ -12870,7 +12852,7 @@ var TeamRemoveCommand = class extends M8tCommand {
|
|
|
12870
12852
|
description: "Azure subscription ID to discover gateway in (defaults to active az subscription)."
|
|
12871
12853
|
});
|
|
12872
12854
|
resourceGroup = Option12.String("--resource-group", {
|
|
12873
|
-
description: "m8t
|
|
12855
|
+
description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
|
|
12874
12856
|
});
|
|
12875
12857
|
async executeCommand() {
|
|
12876
12858
|
const mode = resolveOutputMode(
|
|
@@ -12934,7 +12916,7 @@ var TeamRemoveIdentityCommand = class extends M8tCommand {
|
|
|
12934
12916
|
description: "Azure subscription ID to discover gateway in (defaults to active az subscription)."
|
|
12935
12917
|
});
|
|
12936
12918
|
resourceGroup = Option13.String("--resource-group", {
|
|
12937
|
-
description: "m8t
|
|
12919
|
+
description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
|
|
12938
12920
|
});
|
|
12939
12921
|
async executeCommand() {
|
|
12940
12922
|
const channels = [];
|
|
@@ -12997,7 +12979,7 @@ var TeamShowCommand = class extends M8tCommand {
|
|
|
12997
12979
|
description: "Azure subscription ID to discover gateway in (defaults to active az subscription)."
|
|
12998
12980
|
});
|
|
12999
12981
|
resourceGroup = Option14.String("--resource-group", {
|
|
13000
|
-
description: "m8t
|
|
12982
|
+
description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
|
|
13001
12983
|
});
|
|
13002
12984
|
async executeCommand() {
|
|
13003
12985
|
const mode = resolveOutputMode(
|
|
@@ -13391,9 +13373,9 @@ async function probeAppInstallation(args) {
|
|
|
13391
13373
|
${body.slice(0, 300)}`);
|
|
13392
13374
|
}
|
|
13393
13375
|
async function tryOpenUrl(url, exec = defaultGhExec) {
|
|
13394
|
-
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
13376
|
+
const [cmd, args] = process.platform === "darwin" ? ["open", [url]] : process.platform === "win32" ? ["cmd", ["/c", "start", "", url]] : ["xdg-open", [url]];
|
|
13395
13377
|
try {
|
|
13396
|
-
await exec(cmd,
|
|
13378
|
+
await exec(cmd, args);
|
|
13397
13379
|
} catch {
|
|
13398
13380
|
}
|
|
13399
13381
|
}
|
|
@@ -13492,8 +13474,8 @@ var BrainAppCreateCommand = class extends M8tCommand {
|
|
|
13492
13474
|
});
|
|
13493
13475
|
}
|
|
13494
13476
|
const org = this.org;
|
|
13495
|
-
const pemOut = typeof this.pemOut === "string" ? this.pemOut : path4.join(os.homedir(), ".m8t
|
|
13496
|
-
const credsOut = typeof this.credsOut === "string" ? this.credsOut : path4.join(os.homedir(), ".m8t
|
|
13477
|
+
const pemOut = typeof this.pemOut === "string" ? this.pemOut : path4.join(os.homedir(), ".m8t", "github-app.pem");
|
|
13478
|
+
const credsOut = typeof this.credsOut === "string" ? this.credsOut : path4.join(os.homedir(), ".m8t", "github-app.json");
|
|
13497
13479
|
const port = Number(this.port);
|
|
13498
13480
|
const onProgress = (m) => this.context.stderr.write(` ${colors.dim(m)}
|
|
13499
13481
|
`);
|
|
@@ -13591,7 +13573,7 @@ function discoverKvUri(env, override) {
|
|
|
13591
13573
|
});
|
|
13592
13574
|
}
|
|
13593
13575
|
function tryResolveRepoRoot() {
|
|
13594
|
-
const marker = path5.join(os2.homedir(), ".m8t
|
|
13576
|
+
const marker = path5.join(os2.homedir(), ".m8t", "repo-root");
|
|
13595
13577
|
if (!fs5.existsSync(marker)) return null;
|
|
13596
13578
|
const root = fs5.readFileSync(marker, "utf8").trim();
|
|
13597
13579
|
return root.length > 0 ? root : null;
|
|
@@ -13601,7 +13583,7 @@ function resolveRepoRoot() {
|
|
|
13601
13583
|
if (root === null) {
|
|
13602
13584
|
throw new LocalCliError({
|
|
13603
13585
|
code: "M8T_REPO_ROOT_MISSING",
|
|
13604
|
-
message: "~/.m8t
|
|
13586
|
+
message: "~/.m8t/repo-root marker missing \u2014 m8t install never completed."
|
|
13605
13587
|
});
|
|
13606
13588
|
}
|
|
13607
13589
|
return root;
|
|
@@ -13756,7 +13738,7 @@ import * as path6 from "path";
|
|
|
13756
13738
|
import * as os3 from "os";
|
|
13757
13739
|
import { parse as parseYaml3, stringify as stringifyYaml3 } from "yaml";
|
|
13758
13740
|
function agentYamlPath(agentName, home = os3.homedir()) {
|
|
13759
|
-
return path6.join(home, ".m8t
|
|
13741
|
+
return path6.join(home, ".m8t", "foundry", `${agentName}.yaml`);
|
|
13760
13742
|
}
|
|
13761
13743
|
function readAgentYaml(agentName, home) {
|
|
13762
13744
|
const file = agentYamlPath(agentName, home);
|
|
@@ -13825,7 +13807,7 @@ function renderPersonaBody(personaPath, fillableFieldValues, instanceName) {
|
|
|
13825
13807
|
message: `Could not read persona file '${personaPath}': ${e.message}`
|
|
13826
13808
|
});
|
|
13827
13809
|
}
|
|
13828
|
-
const fmMatch = /^---\n[\s\S]*?\n
|
|
13810
|
+
const fmMatch = /^---\r?\n[\s\S]*?\r?\n---(?:\r?\n)+/.exec(raw);
|
|
13829
13811
|
const body = fmMatch ? raw.slice(fmMatch[0].length) : raw;
|
|
13830
13812
|
let rendered = body;
|
|
13831
13813
|
for (const [name, value] of Object.entries(fillableFieldValues)) {
|
|
@@ -13837,7 +13819,7 @@ function renderPersonaBody(personaPath, fillableFieldValues, instanceName) {
|
|
|
13837
13819
|
throw new LocalCliError({
|
|
13838
13820
|
code: "PERSONA_PLACEHOLDER_UNSATISFIED",
|
|
13839
13821
|
message: `Persona '${personaPath}' has un-substituted placeholders: ${names.join(", ")}`,
|
|
13840
|
-
hint: `Add these to fillableFieldValues in ~/.m8t
|
|
13822
|
+
hint: `Add these to fillableFieldValues in ~/.m8t/foundry/<agent>.yaml, or re-deploy the agent via the architect to repopulate.`
|
|
13841
13823
|
});
|
|
13842
13824
|
}
|
|
13843
13825
|
const out = rendered.replace(/\s+$/, "");
|
|
@@ -14685,7 +14667,7 @@ var BrainCreateCommand = class extends M8tCommand {
|
|
|
14685
14667
|
static paths = [["brain", "create"]];
|
|
14686
14668
|
static usage = Command18.Usage({
|
|
14687
14669
|
description: "Create a new brain repo from brain-template/ (optionally seeded) and link it to <worker>.",
|
|
14688
|
-
details: "Copies ~/.m8t
|
|
14670
|
+
details: "Copies ~/.m8t/repo-root/brain-template/ to a tmp dir, optionally overlays brain-seeds/<name>/ (via --seed), stages it as a git repo, runs gh repo create --source --push, then the link cascade. Default --repo-name: <worker>-brain. Default visibility: private.",
|
|
14689
14671
|
examples: [
|
|
14690
14672
|
["Create + link with defaults", "$0 brain create cmo --owner orkeren21"],
|
|
14691
14673
|
["Custom name + public", "$0 brain create cmo --owner orkeren21 --repo-name cmo-second-brain --public"],
|
|
@@ -15110,7 +15092,7 @@ async function listM8tAgents(args) {
|
|
|
15110
15092
|
if (!raw.name && !raw.id) continue;
|
|
15111
15093
|
const name = String(raw.name ?? raw.id);
|
|
15112
15094
|
const md = raw.metadata ?? raw.versions?.latest?.metadata ?? {};
|
|
15113
|
-
if (md.source === "m8t
|
|
15095
|
+
if (md.source === "m8t") {
|
|
15114
15096
|
result.push({ name, metadata: md });
|
|
15115
15097
|
}
|
|
15116
15098
|
}
|
|
@@ -15270,12 +15252,12 @@ async function unlinkBrain(args) {
|
|
|
15270
15252
|
if (yaml?.personaPath) {
|
|
15271
15253
|
let personaPath = yaml.personaPath;
|
|
15272
15254
|
if (!personaPath.startsWith("/")) {
|
|
15273
|
-
const marker = path11.join(args.home ?? os5.homedir(), ".m8t
|
|
15255
|
+
const marker = path11.join(args.home ?? os5.homedir(), ".m8t", "repo-root");
|
|
15274
15256
|
if (!fs12.existsSync(marker)) {
|
|
15275
15257
|
throw new LocalCliError({
|
|
15276
15258
|
code: "PERSONA_PATH_NOT_ABSOLUTE",
|
|
15277
15259
|
message: `personaPath '${personaPath}' is relative and the repo-root marker is missing.`,
|
|
15278
|
-
hint: "Re-run 'm8t install' from a fresh m8t
|
|
15260
|
+
hint: "Re-run 'm8t install' from a fresh m8t checkout (writes ~/.m8t/repo-root) \u2014 or edit the personaPath to absolute."
|
|
15279
15261
|
});
|
|
15280
15262
|
}
|
|
15281
15263
|
personaPath = path11.join(fs12.readFileSync(marker, "utf8").trim(), personaPath);
|
|
@@ -15547,7 +15529,7 @@ async function deployPromptAdvisor(args) {
|
|
|
15547
15529
|
cause: e
|
|
15548
15530
|
});
|
|
15549
15531
|
}
|
|
15550
|
-
const fmMatch = /^---\n([\s\S]*?)\n---/.exec(raw);
|
|
15532
|
+
const fmMatch = /^---\r?\n([\s\S]*?)\r?\n---/.exec(raw);
|
|
15551
15533
|
const fm = fmMatch ? parseYaml6(fmMatch[1]) : {};
|
|
15552
15534
|
const model = args.model ?? fm.targets?.foundry?.model;
|
|
15553
15535
|
if (!model) {
|
|
@@ -15629,7 +15611,7 @@ var AgentDeployAdvisorCommand = class extends M8tCommand {
|
|
|
15629
15611
|
description: "Azure subscription ID. Defaults to the current az account."
|
|
15630
15612
|
});
|
|
15631
15613
|
repoRootFlag = Option22.String("--repo-root", {
|
|
15632
|
-
description: "Path to the m8t
|
|
15614
|
+
description: "Path to the m8t repo checkout. Defaults to the ~/.m8t/repo-root marker."
|
|
15633
15615
|
});
|
|
15634
15616
|
output = Option22.String("--output", {
|
|
15635
15617
|
description: "Output format: pretty (default) or json."
|
|
@@ -15641,7 +15623,7 @@ var AgentDeployAdvisorCommand = class extends M8tCommand {
|
|
|
15641
15623
|
throw new LocalCliError({
|
|
15642
15624
|
code: "USAGE",
|
|
15643
15625
|
message: "--persona is required (e.g. --persona startup-advisor).",
|
|
15644
|
-
hint: "Pass the persona directory name under personas/ in your m8t
|
|
15626
|
+
hint: "Pass the persona directory name under personas/ in your m8t checkout."
|
|
15645
15627
|
});
|
|
15646
15628
|
}
|
|
15647
15629
|
if (!agentName) {
|
|
@@ -15823,7 +15805,7 @@ function readPersonaA2aCard(personaPath) {
|
|
|
15823
15805
|
} catch (e) {
|
|
15824
15806
|
throw new LocalCliError({ code: "PERSONA_READ_FAILED", message: `Could not read persona '${personaPath}': ${e.message}` });
|
|
15825
15807
|
}
|
|
15826
|
-
const fm = /^---\n([\s\S]*?)\n---/.exec(raw);
|
|
15808
|
+
const fm = /^---\r?\n([\s\S]*?)\r?\n---/.exec(raw);
|
|
15827
15809
|
if (!fm) throw new LocalCliError({ code: "PERSONA_NO_FRONTMATTER", message: `Persona '${personaPath}' has no frontmatter.` });
|
|
15828
15810
|
const front = parseYaml7(fm[1]);
|
|
15829
15811
|
const role = typeof front.role === "string" ? front.role : "";
|
|
@@ -16170,7 +16152,7 @@ var AgentRemoveCommand = class extends M8tCommand {
|
|
|
16170
16152
|
subscription = Option23.String("--subscription");
|
|
16171
16153
|
kvUri = Option23.String("--kv-uri");
|
|
16172
16154
|
resourceGroup = Option23.String("--resource-group", {
|
|
16173
|
-
description: "m8t
|
|
16155
|
+
description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
|
|
16174
16156
|
});
|
|
16175
16157
|
output = Option23.String("--output");
|
|
16176
16158
|
async executeCommand() {
|
|
@@ -16305,7 +16287,7 @@ function resolveBridgeUrl(opts) {
|
|
|
16305
16287
|
throw new LocalCliError({
|
|
16306
16288
|
code: "A2A_NO_GATEWAY_URL",
|
|
16307
16289
|
message: "Could not resolve the gateway URL for the A2A bridge.",
|
|
16308
|
-
hint: "Pass --gateway-url https://<gateway-fqdn>, set M8T_GATEWAY_URL, or add a gatewayUrl key to ~/.m8t
|
|
16290
|
+
hint: "Pass --gateway-url https://<gateway-fqdn>, set M8T_GATEWAY_URL, or add a gatewayUrl key to ~/.m8t/config.yaml."
|
|
16309
16291
|
});
|
|
16310
16292
|
}
|
|
16311
16293
|
return `${base}${A2A_PATH}`;
|
|
@@ -16317,7 +16299,7 @@ function clean(v) {
|
|
|
16317
16299
|
return t.length ? t : void 0;
|
|
16318
16300
|
}
|
|
16319
16301
|
function readConfigGatewayUrl(home) {
|
|
16320
|
-
const cfg = path13.join(home ?? os6.homedir(), ".m8t
|
|
16302
|
+
const cfg = path13.join(home ?? os6.homedir(), ".m8t", "config.yaml");
|
|
16321
16303
|
if (!fs16.existsSync(cfg)) return void 0;
|
|
16322
16304
|
try {
|
|
16323
16305
|
const o = parseYaml8(fs16.readFileSync(cfg, "utf8"));
|
|
@@ -16538,7 +16520,7 @@ function checkArchitectDrift() {
|
|
|
16538
16520
|
match: false,
|
|
16539
16521
|
sourceVersion: "",
|
|
16540
16522
|
installedVersion: "",
|
|
16541
|
-
advice: `Source persona not found at ${sourcePath}. Check ~/.m8t
|
|
16523
|
+
advice: `Source persona not found at ${sourcePath}. Check ~/.m8t/repo-root points at a valid checkout.`
|
|
16542
16524
|
};
|
|
16543
16525
|
}
|
|
16544
16526
|
const sourceVersion = readVersionFrontmatter(sourcePath);
|
|
@@ -16899,7 +16881,7 @@ function resolvePersona(persona, cwd = process.cwd()) {
|
|
|
16899
16881
|
} catch {
|
|
16900
16882
|
return { persona, personaVersion: null };
|
|
16901
16883
|
}
|
|
16902
|
-
const match = /^---\n([\s\S]*?)\n---/.exec(raw);
|
|
16884
|
+
const match = /^---\r?\n([\s\S]*?)\r?\n---/.exec(raw);
|
|
16903
16885
|
if (!match) return { persona, personaVersion: null };
|
|
16904
16886
|
let fm = null;
|
|
16905
16887
|
try {
|
|
@@ -16980,7 +16962,7 @@ async function assertPlatformLive(opts) {
|
|
|
16980
16962
|
if (e.code === "GATEWAY_DISCOVERY_ZERO") {
|
|
16981
16963
|
throw new LocalCliError({
|
|
16982
16964
|
code: "PLATFORM_NOT_LIVE",
|
|
16983
|
-
message: "The m8t
|
|
16965
|
+
message: "The m8t platform isn't deployed yet \u2014 there is no gateway in this subscription.",
|
|
16984
16966
|
hint: "Deploy it first: run the local bootstrap (`m8t bootstrap launch \u2026`) and wait for `m8t bootstrap status` to reach done. If it's in another subscription, run `az account set --subscription <id>`.",
|
|
16985
16967
|
cause: e
|
|
16986
16968
|
});
|
|
@@ -17154,7 +17136,7 @@ var CoderDeployCommand = class extends M8tCommand {
|
|
|
17154
17136
|
cpu: preset.cpu,
|
|
17155
17137
|
memory: preset.memory,
|
|
17156
17138
|
env,
|
|
17157
|
-
metadata: { ...currentMetadata, source: "m8t
|
|
17139
|
+
metadata: { ...currentMetadata, source: "m8t", kind: "hosted", persona: personaName, personaVersion },
|
|
17158
17140
|
onProgress
|
|
17159
17141
|
});
|
|
17160
17142
|
if (typeof this.brain === "string") {
|
|
@@ -17267,7 +17249,7 @@ var CoderDeployCommand = class extends M8tCommand {
|
|
|
17267
17249
|
this.context.stdout.write(` project: ${project.projectName} (${project.region})
|
|
17268
17250
|
`);
|
|
17269
17251
|
this.context.stdout.write(
|
|
17270
|
-
` ${colors.hint("next:")} it now appears on MCP (/m8t
|
|
17252
|
+
` ${colors.hint("next:")} it now appears on MCP (/m8t:workers), the web app, and (when --gateway-url was passed) as an a2a target.
|
|
17271
17253
|
`
|
|
17272
17254
|
);
|
|
17273
17255
|
return 0;
|
|
@@ -17601,7 +17583,7 @@ var AzureExecDeployCommand = class extends M8tCommand {
|
|
|
17601
17583
|
cpu: preset.cpu,
|
|
17602
17584
|
memory: preset.memory,
|
|
17603
17585
|
env,
|
|
17604
|
-
metadata: { source: "m8t
|
|
17586
|
+
metadata: { source: "m8t", kind: "hosted", persona: personaName, personaVersion },
|
|
17605
17587
|
onProgress
|
|
17606
17588
|
});
|
|
17607
17589
|
onProgress?.(`granting Contributor at ${grantScope}\u2026`);
|
|
@@ -18061,7 +18043,7 @@ async function resolveReleaseContent(manifest, opts = {}) {
|
|
|
18061
18043
|
return opts.contentDir;
|
|
18062
18044
|
}
|
|
18063
18045
|
const commit = manifest.platform.commit;
|
|
18064
|
-
const cacheRoot = opts.cacheRoot ?? path19.join(os8.homedir(), ".m8t
|
|
18046
|
+
const cacheRoot = opts.cacheRoot ?? path19.join(os8.homedir(), ".m8t", "cache");
|
|
18065
18047
|
const dest = path19.join(cacheRoot, `release-${commit}`);
|
|
18066
18048
|
if (fs20.existsSync(path19.join(dest, "personas"))) return dest;
|
|
18067
18049
|
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
@@ -18125,7 +18107,7 @@ async function discoverStampStorage(opts) {
|
|
|
18125
18107
|
url: `${ARM3}/subscriptions/${opts.subscriptionId}/resourceGroups/${opts.resourceGroup}/providers/Microsoft.Storage/storageAccounts?api-version=${STORAGE_API}`
|
|
18126
18108
|
}) ?? {};
|
|
18127
18109
|
const accounts = (list.value ?? []).filter((a) => a.properties?.primaryEndpoints?.table);
|
|
18128
|
-
const chosen = accounts.find((a) => a.tags?.
|
|
18110
|
+
const chosen = accounts.find((a) => a.tags?.m8t === "storage") ?? accounts.find((a) => a.tags?.["m8t:role"] === "gateway" || a.tags?.["m8t:role"] === "ledger") ?? (accounts.length === 1 ? accounts[0] : void 0);
|
|
18129
18111
|
const tableEndpoint = chosen?.properties?.primaryEndpoints?.table?.replace(/\/$/, "");
|
|
18130
18112
|
if (!tableEndpoint || !chosen?.id || !chosen.name) {
|
|
18131
18113
|
throw new LocalCliError({
|
|
@@ -18280,7 +18262,7 @@ function buildBicepParams(p) {
|
|
|
18280
18262
|
return params;
|
|
18281
18263
|
}
|
|
18282
18264
|
async function resolveRepoRoot2(home = os9.homedir()) {
|
|
18283
|
-
const marker = path20.join(home, ".m8t
|
|
18265
|
+
const marker = path20.join(home, ".m8t", "repo-root");
|
|
18284
18266
|
try {
|
|
18285
18267
|
const root = (await fs21.readFile(marker, "utf8")).trim();
|
|
18286
18268
|
if (!root) throw new Error("empty");
|
|
@@ -18288,8 +18270,8 @@ async function resolveRepoRoot2(home = os9.homedir()) {
|
|
|
18288
18270
|
} catch {
|
|
18289
18271
|
throw new LocalCliError({
|
|
18290
18272
|
code: "DEPLOY_NO_REPO_ROOT",
|
|
18291
|
-
message: "~/.m8t
|
|
18292
|
-
hint: "Run 'm8t install' from an m8t
|
|
18273
|
+
message: "~/.m8t/repo-root marker is missing or empty.",
|
|
18274
|
+
hint: "Run 'm8t install' from an m8t checkout (it writes the marker), or run 'm8t deploy' from the repo."
|
|
18293
18275
|
});
|
|
18294
18276
|
}
|
|
18295
18277
|
}
|
|
@@ -18353,7 +18335,7 @@ async function ensureResourceGroup(name, location) {
|
|
|
18353
18335
|
await runAz(["group", "show", "--name", name, "--output", "json"]).catch(() => "") || "null"
|
|
18354
18336
|
);
|
|
18355
18337
|
if (existing) return;
|
|
18356
|
-
await runAz(["group", "create", "--name", name, "--location", location, "--tags", "m8t
|
|
18338
|
+
await runAz(["group", "create", "--name", name, "--location", location, "--tags", "m8t=deployment"]);
|
|
18357
18339
|
}
|
|
18358
18340
|
function resolveAcrPullIdentity(opts) {
|
|
18359
18341
|
return opts.explicit ?? "";
|
|
@@ -18727,7 +18709,7 @@ function declaredFillableFields(personaPath) {
|
|
|
18727
18709
|
} catch {
|
|
18728
18710
|
return [];
|
|
18729
18711
|
}
|
|
18730
|
-
const fmMatch = /^---\n([\s\S]*?)\n---/.exec(raw);
|
|
18712
|
+
const fmMatch = /^---\r?\n([\s\S]*?)\r?\n---/.exec(raw);
|
|
18731
18713
|
if (!fmMatch) return [];
|
|
18732
18714
|
try {
|
|
18733
18715
|
const fm = parseYaml10(fmMatch[1]);
|
|
@@ -18825,13 +18807,13 @@ var PlatformStatusCommand = class extends M8tCommand {
|
|
|
18825
18807
|
});
|
|
18826
18808
|
subscription = Option29.String("--subscription");
|
|
18827
18809
|
resourceGroup = Option29.String("--resource-group", {
|
|
18828
|
-
description: "m8t
|
|
18810
|
+
description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
|
|
18829
18811
|
});
|
|
18830
18812
|
to = Option29.String("--to", {
|
|
18831
18813
|
description: "Check status against a pinned platform version (defaults to the current release channel)."
|
|
18832
18814
|
});
|
|
18833
18815
|
contentDir = Option29.String("--content-dir", {
|
|
18834
|
-
description: "Path to a local m8t
|
|
18816
|
+
description: "Path to a local m8t repo checkout (skips the tarball tree-SHA fetch)."
|
|
18835
18817
|
});
|
|
18836
18818
|
manifestUrl = Option29.String("--manifest-url", {
|
|
18837
18819
|
description: "Fetch the release manifest from this URL instead of the release channel."
|
|
@@ -19559,7 +19541,7 @@ var PlatformUpdateCommand = class extends M8tCommand {
|
|
|
19559
19541
|
});
|
|
19560
19542
|
subscription = Option30.String("--subscription");
|
|
19561
19543
|
resourceGroup = Option30.String("--resource-group", {
|
|
19562
|
-
description: "m8t
|
|
19544
|
+
description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
|
|
19563
19545
|
});
|
|
19564
19546
|
to = Option30.String("--to", {
|
|
19565
19547
|
description: "Pin the platform version to converge to (defaults to the current release channel)."
|
|
@@ -19575,7 +19557,7 @@ var PlatformUpdateCommand = class extends M8tCommand {
|
|
|
19575
19557
|
description: "Required with --force-infra \u2014 the existing deployment's resource-name suffix (avoids provisioning duplicates)."
|
|
19576
19558
|
});
|
|
19577
19559
|
contentDir = Option30.String("--content-dir", {
|
|
19578
|
-
description: "Path to a local m8t
|
|
19560
|
+
description: "Path to a local m8t repo checkout (skips the tarball fetch + tree-drift check)."
|
|
19579
19561
|
});
|
|
19580
19562
|
manifestUrl = Option30.String("--manifest-url", {
|
|
19581
19563
|
description: "Fetch the release manifest from this URL instead of the release channel."
|
|
@@ -20249,7 +20231,7 @@ var PlatformEnableCostReportCommand = class extends M8tCommand {
|
|
|
20249
20231
|
});
|
|
20250
20232
|
subscription = Option31.String("--subscription");
|
|
20251
20233
|
resourceGroup = Option31.String("--resource-group", {
|
|
20252
|
-
description: "m8t
|
|
20234
|
+
description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
|
|
20253
20235
|
});
|
|
20254
20236
|
acsEndpoint = Option31.String("--acs-endpoint", { required: true, description: "ACS data-plane endpoint, e.g. https://acs-<name>.communication.azure.com/" });
|
|
20255
20237
|
acsSender = Option31.String("--acs-sender", { required: true, description: "Managed-domain sender address, e.g. DoNotReply@<guid>.azurecomm.net" });
|
|
@@ -20341,7 +20323,7 @@ var PlatformEnableAutoUpdateCommand = class extends M8tCommand {
|
|
|
20341
20323
|
});
|
|
20342
20324
|
subscription = Option32.String("--subscription");
|
|
20343
20325
|
resourceGroup = Option32.String("--resource-group", {
|
|
20344
|
-
description: "m8t
|
|
20326
|
+
description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
|
|
20345
20327
|
});
|
|
20346
20328
|
suffix = Option32.String("--suffix", {
|
|
20347
20329
|
description: "The existing deployment's resource-name suffix. Required when it cannot be recovered from system/infra-params or the live gateway."
|
|
@@ -20485,7 +20467,7 @@ import { Command as Command36, Option as Option33 } from "clipanion";
|
|
|
20485
20467
|
|
|
20486
20468
|
// src/lib/app-reg.ts
|
|
20487
20469
|
init_errors();
|
|
20488
|
-
var APP_NAME = "m8t-
|
|
20470
|
+
var APP_NAME = "m8t-webapp";
|
|
20489
20471
|
var AZURE_CLI_FIRST_PARTY_APP_ID = "04b07795-8ddb-461a-bbee-02f9e1bf7b46";
|
|
20490
20472
|
var FOUNDRY_SP_APP_ID = "18a66f5f-dbdf-4c17-9dd7-1634712a9cbe";
|
|
20491
20473
|
var USER_IMPERSONATION_SCOPE_ID = "1a7925b5-f871-417a-9b8b-303f9f29fa10";
|
|
@@ -20525,10 +20507,10 @@ async function ensureExposeAnApi(appId, appObjectId) {
|
|
|
20525
20507
|
id: scopeId,
|
|
20526
20508
|
value: "user_impersonation",
|
|
20527
20509
|
type: "User",
|
|
20528
|
-
adminConsentDescription: "Allow the application to access m8t
|
|
20529
|
-
adminConsentDisplayName: "Access m8t
|
|
20530
|
-
userConsentDescription: "Allow the application to access m8t
|
|
20531
|
-
userConsentDisplayName: "Access m8t
|
|
20510
|
+
adminConsentDescription: "Allow the application to access m8t on behalf of the signed-in user.",
|
|
20511
|
+
adminConsentDisplayName: "Access m8t",
|
|
20512
|
+
userConsentDescription: "Allow the application to access m8t on your behalf.",
|
|
20513
|
+
userConsentDisplayName: "Access m8t",
|
|
20532
20514
|
isEnabled: true
|
|
20533
20515
|
}
|
|
20534
20516
|
];
|
|
@@ -20885,7 +20867,7 @@ var DeployCommand = class extends M8tCommand {
|
|
|
20885
20867
|
static paths = [["deploy"]];
|
|
20886
20868
|
static usage = Command36.Usage({
|
|
20887
20869
|
description: "Deploy (or update) the m8t gateway/webapp stack via Bicep.",
|
|
20888
|
-
details: "Ensures the Entra app reg (or pass --client-id to reuse an existing one \u2014 required if you can't create app regs), writes ~/.m8t
|
|
20870
|
+
details: "Ensures the Entra app reg (or pass --client-id to reuse an existing one \u2014 required if you can't create app regs), writes ~/.m8t/config.yaml, ensures the resource group, and runs deploy/main.bicep. The repo is located via ~/.m8t/repo-root."
|
|
20889
20871
|
});
|
|
20890
20872
|
subscription = Option33.String("--subscription");
|
|
20891
20873
|
resourceGroup = Option33.String("--resource-group", "rg-m8t-stack");
|
|
@@ -20934,7 +20916,7 @@ var DeployCommand = class extends M8tCommand {
|
|
|
20934
20916
|
throw new LocalCliError({
|
|
20935
20917
|
code: "DEPLOY_NO_FOUNDRY_ENDPOINT",
|
|
20936
20918
|
message: "No Foundry endpoint provided.",
|
|
20937
|
-
hint: "Pass --foundry-endpoint <url> or set projectEndpoint in ~/.m8t
|
|
20919
|
+
hint: "Pass --foundry-endpoint <url> or set projectEndpoint in ~/.m8t/config.yaml (m8t config set / m8t switch)."
|
|
20938
20920
|
});
|
|
20939
20921
|
}
|
|
20940
20922
|
if (this.whatIf) {
|
|
@@ -20943,7 +20925,7 @@ var DeployCommand = class extends M8tCommand {
|
|
|
20943
20925
|
throw new LocalCliError({
|
|
20944
20926
|
code: "DEPLOY_WHATIF_NO_CLIENT",
|
|
20945
20927
|
message: "--what-if needs a client id but none was provided or configured.",
|
|
20946
|
-
hint: "Pass --client-id <appId>, or run from a host with ~/.m8t
|
|
20928
|
+
hint: "Pass --client-id <appId>, or run from a host with ~/.m8t/config.yaml."
|
|
20947
20929
|
});
|
|
20948
20930
|
}
|
|
20949
20931
|
const foundryResourceId2 = await resolveFoundryResourceId(foundryEndpoint, this.foundryResourceId);
|
|
@@ -21564,7 +21546,7 @@ var WhoamiCommand = class extends M8tCommand {
|
|
|
21564
21546
|
description: "Azure subscription ID to discover gateway in (defaults to active az subscription)."
|
|
21565
21547
|
});
|
|
21566
21548
|
resourceGroup = Option37.String("--resource-group", {
|
|
21567
|
-
description: "m8t
|
|
21549
|
+
description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
|
|
21568
21550
|
});
|
|
21569
21551
|
async executeCommand() {
|
|
21570
21552
|
const mode = resolveOutputMode(
|
|
@@ -21635,7 +21617,7 @@ init_errors();
|
|
|
21635
21617
|
import { spawn as spawn4 } from "child_process";
|
|
21636
21618
|
function runAzd(args) {
|
|
21637
21619
|
return new Promise((resolve3, reject) => {
|
|
21638
|
-
const proc = spawn4("azd", args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
21620
|
+
const proc = spawn4("azd", args, { stdio: ["ignore", "pipe", "pipe"], shell: process.platform === "win32" });
|
|
21639
21621
|
const out = [];
|
|
21640
21622
|
const err = [];
|
|
21641
21623
|
proc.stdout.on("data", (d) => out.push(d));
|
|
@@ -21752,7 +21734,7 @@ function checkFoundryConfig(cfg) {
|
|
|
21752
21734
|
return {
|
|
21753
21735
|
name: "config.yaml",
|
|
21754
21736
|
status: "FAIL",
|
|
21755
|
-
detail: "missing or invalid ~/.m8t
|
|
21737
|
+
detail: "missing or invalid ~/.m8t/config.yaml",
|
|
21756
21738
|
remediation: "m8t switch (or m8t config set tenantId|clientId|projectEndpoint <value>)"
|
|
21757
21739
|
};
|
|
21758
21740
|
}
|
|
@@ -21876,27 +21858,46 @@ function checkRepoRoot(probe) {
|
|
|
21876
21858
|
return {
|
|
21877
21859
|
name: "brain repo-root",
|
|
21878
21860
|
status: "FAIL",
|
|
21879
|
-
detail: "~/.m8t
|
|
21880
|
-
remediation: 're-run the m8t
|
|
21861
|
+
detail: "~/.m8t/repo-root marker missing \u2014 m8t install never completed",
|
|
21862
|
+
remediation: 're-run the m8t install (writes ~/.m8t/repo-root), or: printf %s "$(git -C <m8t-checkout> rev-parse --show-toplevel)" > ~/.m8t/repo-root'
|
|
21881
21863
|
};
|
|
21882
21864
|
}
|
|
21883
21865
|
if (!probe.isDir) {
|
|
21884
21866
|
return {
|
|
21885
21867
|
name: "brain repo-root",
|
|
21886
21868
|
status: "FAIL",
|
|
21887
|
-
detail: `~/.m8t
|
|
21888
|
-
remediation: 'the m8t
|
|
21869
|
+
detail: `~/.m8t/repo-root \u2192 ${probe.path} \u2014 that path does not exist or is not a directory`,
|
|
21870
|
+
remediation: 'the m8t checkout moved or was deleted; point the marker at the current checkout: printf %s "$(git -C <m8t-checkout> rev-parse --show-toplevel)" > ~/.m8t/repo-root'
|
|
21889
21871
|
};
|
|
21890
21872
|
}
|
|
21891
21873
|
if (!probe.isGitCheckout) {
|
|
21892
21874
|
return {
|
|
21893
21875
|
name: "brain repo-root",
|
|
21894
21876
|
status: "WARN",
|
|
21895
|
-
detail: `~/.m8t
|
|
21896
|
-
remediation: "point the marker at the m8t
|
|
21877
|
+
detail: `~/.m8t/repo-root \u2192 ${probe.path} exists but is not a git checkout (no .git) \u2014 brain-loader template + persona paths may be stale`,
|
|
21878
|
+
remediation: "point the marker at the m8t git checkout (it reads targets/foundry/brain-loader.md from there)"
|
|
21879
|
+
};
|
|
21880
|
+
}
|
|
21881
|
+
return { name: "brain repo-root", status: "PASS", detail: `~/.m8t/repo-root \u2192 ${probe.path}` };
|
|
21882
|
+
}
|
|
21883
|
+
function checkLegacyStateDir(probe) {
|
|
21884
|
+
if (!probe.legacyExists) {
|
|
21885
|
+
return { name: "state dir", status: "PASS", detail: "no legacy ~/.m8t-stack folder" };
|
|
21886
|
+
}
|
|
21887
|
+
if (!probe.currentExists) {
|
|
21888
|
+
return {
|
|
21889
|
+
name: "state dir",
|
|
21890
|
+
status: "WARN",
|
|
21891
|
+
detail: "found legacy ~/.m8t-stack but no ~/.m8t \u2014 the state folder was renamed to ~/.m8t",
|
|
21892
|
+
remediation: "mv ~/.m8t-stack ~/.m8t"
|
|
21897
21893
|
};
|
|
21898
21894
|
}
|
|
21899
|
-
return {
|
|
21895
|
+
return {
|
|
21896
|
+
name: "state dir",
|
|
21897
|
+
status: "WARN",
|
|
21898
|
+
detail: "legacy ~/.m8t-stack exists alongside ~/.m8t \u2014 only ~/.m8t is read",
|
|
21899
|
+
remediation: "review ~/.m8t-stack for anything you still need, then remove it"
|
|
21900
|
+
};
|
|
21900
21901
|
}
|
|
21901
21902
|
|
|
21902
21903
|
// src/commands/doctor.ts
|
|
@@ -21963,7 +21964,7 @@ async function resolveAccountLocation(accountId) {
|
|
|
21963
21964
|
}
|
|
21964
21965
|
}
|
|
21965
21966
|
function probeRepoRoot() {
|
|
21966
|
-
const marker = path28.join(os11.homedir(), ".m8t
|
|
21967
|
+
const marker = path28.join(os11.homedir(), ".m8t", "repo-root");
|
|
21967
21968
|
if (!fs26.existsSync(marker)) {
|
|
21968
21969
|
return { markerExists: false, path: null, isDir: false, isGitCheckout: false };
|
|
21969
21970
|
}
|
|
@@ -21983,6 +21984,12 @@ function probeRepoRoot() {
|
|
|
21983
21984
|
const isGitCheckout = isDir && fs26.existsSync(path28.join(repoPath, ".git"));
|
|
21984
21985
|
return { markerExists: true, path: repoPath, isDir, isGitCheckout };
|
|
21985
21986
|
}
|
|
21987
|
+
function probeLegacyStateDir() {
|
|
21988
|
+
return {
|
|
21989
|
+
legacyExists: fs26.existsSync(path28.join(os11.homedir(), ".m8t-stack")),
|
|
21990
|
+
currentExists: fs26.existsSync(path28.join(os11.homedir(), ".m8t"))
|
|
21991
|
+
};
|
|
21992
|
+
}
|
|
21986
21993
|
var DoctorCommand = class extends M8tCommand {
|
|
21987
21994
|
static paths = [["doctor"]];
|
|
21988
21995
|
static usage = Command42.Usage({
|
|
@@ -21991,7 +21998,7 @@ var DoctorCommand = class extends M8tCommand {
|
|
|
21991
21998
|
output = Option39.String("--output");
|
|
21992
21999
|
agent = Option39.String("--agent");
|
|
21993
22000
|
resourceGroup = Option39.String("--resource-group", {
|
|
21994
|
-
description: "m8t
|
|
22001
|
+
description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
|
|
21995
22002
|
});
|
|
21996
22003
|
async executeCommand() {
|
|
21997
22004
|
const mode = resolveOutputMode(
|
|
@@ -22025,6 +22032,7 @@ var DoctorCommand = class extends M8tCommand {
|
|
|
22025
22032
|
emit(checkFoundryConfig(foundry));
|
|
22026
22033
|
emit(checkTenantAlignment(az, foundry));
|
|
22027
22034
|
emit(checkRepoRoot(probeRepoRoot()));
|
|
22035
|
+
emit(checkLegacyStateDir(probeLegacyStateDir()));
|
|
22028
22036
|
checking("gateway");
|
|
22029
22037
|
let gw = { ok: false, detail: "not probed" };
|
|
22030
22038
|
try {
|
|
@@ -22114,7 +22122,7 @@ import * as path29 from "path";
|
|
|
22114
22122
|
import { parse as parseYaml11, stringify as stringifyYaml4 } from "yaml";
|
|
22115
22123
|
function profilesDir() {
|
|
22116
22124
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
22117
|
-
return path29.join(home, ".m8t
|
|
22125
|
+
return path29.join(home, ".m8t", "profiles");
|
|
22118
22126
|
}
|
|
22119
22127
|
function getProfilePath(name) {
|
|
22120
22128
|
return path29.join(profilesDir(), `${path29.basename(name)}.yaml`);
|
|
@@ -22364,7 +22372,7 @@ var OpenCommand = class extends M8tCommand {
|
|
|
22364
22372
|
print = Option41.Boolean("--print", false);
|
|
22365
22373
|
output = Option41.String("--output");
|
|
22366
22374
|
resourceGroup = Option41.String("--resource-group", {
|
|
22367
|
-
description: "m8t
|
|
22375
|
+
description: "m8t resource group to disambiguate the gateway (multi-deployment subscriptions)."
|
|
22368
22376
|
});
|
|
22369
22377
|
async executeCommand() {
|
|
22370
22378
|
const mode = resolveOutputMode(
|
|
@@ -23173,7 +23181,7 @@ async function runPipeline(args) {
|
|
|
23173
23181
|
({ items, fetchError } = await fetchItems(sources.conversations, recoveredId));
|
|
23174
23182
|
if (g.source === "a2a" && !fetchError && items.length > 0 && sources.conversations.retrieveApp) {
|
|
23175
23183
|
const app = await sources.conversations.retrieveApp(recoveredId);
|
|
23176
|
-
if (app !== "m8t-
|
|
23184
|
+
if (app !== "m8t-a2a") {
|
|
23177
23185
|
didRecover = false;
|
|
23178
23186
|
items = [];
|
|
23179
23187
|
conversationId = void 0;
|
|
@@ -24508,13 +24516,13 @@ async function discoverLedgerResources(opts) {
|
|
|
24508
24516
|
url: `${ARM4}/subscriptions/${subscriptionId}/resourceGroups/${resourceGroup}/providers/Microsoft.Storage/storageAccounts?api-version=${STORAGE_API2}`
|
|
24509
24517
|
});
|
|
24510
24518
|
const accounts = storage.filter((a) => a.properties?.primaryEndpoints?.table);
|
|
24511
|
-
const ledgerAcct = accounts.find((a) => (a.tags?.["m8t
|
|
24519
|
+
const ledgerAcct = accounts.find((a) => (a.tags?.["m8t:role"] ?? a.properties?.tags?.["m8t:role"]) === "ledger") ?? (accounts.length === 1 ? accounts[0] : void 0);
|
|
24512
24520
|
const ledgerTableEndpoint = ledgerAcct?.properties?.primaryEndpoints?.table?.replace(/\/$/, "");
|
|
24513
24521
|
if (!ledgerTableEndpoint) {
|
|
24514
24522
|
throw new LocalCliError({
|
|
24515
24523
|
code: "DREAM_LEDGER_STORAGE_NOT_FOUND",
|
|
24516
24524
|
message: `No AgentLedger storage account found in resource group ${resourceGroup}.`,
|
|
24517
|
-
hint: `Found: ${accounts.map((a) => a.name).join(", ") || "(none)"}. Tag the ledger account 'm8t
|
|
24525
|
+
hint: `Found: ${accounts.map((a) => a.name).join(", ") || "(none)"}. Tag the ledger account 'm8t:role=ledger'.`
|
|
24518
24526
|
});
|
|
24519
24527
|
}
|
|
24520
24528
|
const ws = await authedJsonPagedValues({
|
|
@@ -25344,6 +25352,32 @@ var FoundryAwaitReadyCommand = class extends M8tCommand {
|
|
|
25344
25352
|
|
|
25345
25353
|
// src/commands/bootstrap/preflight.ts
|
|
25346
25354
|
import { Command as Command48, Option as Option45 } from "clipanion";
|
|
25355
|
+
|
|
25356
|
+
// ../../packages/telemetry-contract/artifact/tier-map.ts
|
|
25357
|
+
var EVENT_TIERS = {
|
|
25358
|
+
"enrolled": 1,
|
|
25359
|
+
"install-started": 1,
|
|
25360
|
+
"install-succeeded": 1,
|
|
25361
|
+
"install-failed": 1,
|
|
25362
|
+
"heartbeat": 1,
|
|
25363
|
+
"update-applied": 1,
|
|
25364
|
+
"update-failed": 1,
|
|
25365
|
+
"consent-changed": 1
|
|
25366
|
+
// extended additively for tier-2 usage events: "usage-rollup": 2
|
|
25367
|
+
};
|
|
25368
|
+
var EVENT_ENUM = Object.keys(EVENT_TIERS);
|
|
25369
|
+
|
|
25370
|
+
// ../../packages/telemetry-contract/src/disclosure.ts
|
|
25371
|
+
var DISCLOSURE_TIER1 = "Operational data. To support your installation, m8t receives limited operational data linked to it \u2014 installation and update events, installed versions, and service health signals, along with the company name and contact email you provide. This is service data used only to operate and support the platform; it contains none of your content. Details: TELEMETRY.md.";
|
|
25372
|
+
|
|
25373
|
+
// ../../packages/telemetry-contract/src/endpoints.ts
|
|
25374
|
+
var INGEST_BASE_URL = (process.env.M8T_INGEST_BASE_URL ?? "").trim() || "https://m8t-admin.wonderfuldesert-721e332f.eastus2.azurecontainerapps.io";
|
|
25375
|
+
function ingestUrl(path37) {
|
|
25376
|
+
const base = INGEST_BASE_URL.replace(/\/+$/, "");
|
|
25377
|
+
return `${base}${path37.startsWith("/") ? path37 : `/${path37}`}`;
|
|
25378
|
+
}
|
|
25379
|
+
|
|
25380
|
+
// src/commands/bootstrap/preflight.ts
|
|
25347
25381
|
init_errors();
|
|
25348
25382
|
|
|
25349
25383
|
// src/lib/bootstrap-preflight.ts
|
|
@@ -25394,7 +25428,7 @@ function buildPreflightBanner(who) {
|
|
|
25394
25428
|
"\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557",
|
|
25395
25429
|
"\u2551 \u26D4 STOP \u2014 READ THIS BEFORE CONTINUING \u2551",
|
|
25396
25430
|
"\u2551 \u2551",
|
|
25397
|
-
"\u2551 Installing m8t
|
|
25431
|
+
"\u2551 Installing m8t creates real Azure resources in YOUR \u2551",
|
|
25398
25432
|
"\u2551 subscription and assigns roles. To do that, the account you just \u2551",
|
|
25399
25433
|
"\u2551 signed in with MUST be: \u2551",
|
|
25400
25434
|
"\u2551 \u2551",
|
|
@@ -25418,7 +25452,7 @@ function buildPreflightBanner(who) {
|
|
|
25418
25452
|
var BootstrapPreflightCommand = class extends M8tCommand {
|
|
25419
25453
|
static paths = [["bootstrap", "preflight"]];
|
|
25420
25454
|
static usage = Command48.Usage({
|
|
25421
|
-
description: "Loudly verify you can install m8t
|
|
25455
|
+
description: "Loudly verify you can install m8t (Owner/UAA + directory admin) and hard-stop if not.",
|
|
25422
25456
|
details: "Step 1 of `m8t bootstrap`. Prints an unmissable admin-credentials notice, then checks: Owner or User Access Administrator at subscription scope (hard requirement), directory-admin capability to register the app (or pass --client-id), and registers Microsoft.ContainerInstance. Exits non-zero with the exact failing check + remedy.",
|
|
25423
25457
|
examples: [
|
|
25424
25458
|
["Run the preflight", "$0 bootstrap preflight"],
|
|
@@ -25433,6 +25467,9 @@ var BootstrapPreflightCommand = class extends M8tCommand {
|
|
|
25433
25467
|
const subscriptionId = (typeof this.subscription === "string" ? this.subscription : void 0) ?? account.subscriptionId;
|
|
25434
25468
|
const oid = await getCallerObjectId();
|
|
25435
25469
|
this.context.stdout.write(buildPreflightBanner({ upn: account.upn, tenantId: account.tenantId, subscriptionId }) + "\n");
|
|
25470
|
+
this.context.stdout.write(`
|
|
25471
|
+
${colors.dim(DISCLOSURE_TIER1)}
|
|
25472
|
+
`);
|
|
25436
25473
|
this.context.stdout.write("Checking your access\u2026\n");
|
|
25437
25474
|
const sub = await checkSubScopeAdmin(oid, subscriptionId);
|
|
25438
25475
|
this.context.stdout.write(line(sub.ok, `${sub.role ?? "Owner/UAA"} at subscription scope`, "resource + role-assignment rights"));
|
|
@@ -25442,7 +25479,7 @@ var BootstrapPreflightCommand = class extends M8tCommand {
|
|
|
25442
25479
|
}
|
|
25443
25480
|
if (!clientId) {
|
|
25444
25481
|
const appReg = await checkAppRegCapability(oid);
|
|
25445
|
-
this.context.stdout.write(line(appReg.ok, "Directory admin \u2014 can register the m8t
|
|
25482
|
+
this.context.stdout.write(line(appReg.ok, "Directory admin \u2014 can register the m8t app", "first-run app registration"));
|
|
25446
25483
|
if (!appReg.ok) {
|
|
25447
25484
|
this.context.stderr.write(failBlock(
|
|
25448
25485
|
appReg.inconclusive ? "Couldn't verify your directory admin role (Microsoft Graph denied the read \u2014 common for guest accounts)." : "You don't hold a directory admin role (Application / Cloud Application / Global Administrator).",
|
|
@@ -25504,7 +25541,7 @@ async function ensureResourceGroup2(opts) {
|
|
|
25504
25541
|
"--subscription",
|
|
25505
25542
|
opts.subscriptionId,
|
|
25506
25543
|
"--tags",
|
|
25507
|
-
"m8t
|
|
25544
|
+
"m8t=deployment",
|
|
25508
25545
|
"--only-show-errors"
|
|
25509
25546
|
]);
|
|
25510
25547
|
}
|
|
@@ -25584,6 +25621,7 @@ function buildAciCreateArgs(s) {
|
|
|
25584
25621
|
];
|
|
25585
25622
|
if (s.gatewayImageRef) env.push(`GATEWAY_IMAGE_REF=${s.gatewayImageRef}`);
|
|
25586
25623
|
if (s.foundryTracing) env.push(`FOUNDRY_TRACING=${s.foundryTracing}`);
|
|
25624
|
+
if (s.enrollContactEmail) env.push(`M8T_ENROLL_CONTACT_EMAIL=${s.enrollContactEmail}`);
|
|
25587
25625
|
if (s.githubApp) {
|
|
25588
25626
|
const g = s.githubApp;
|
|
25589
25627
|
env.push(
|
|
@@ -25710,7 +25748,7 @@ import * as fs29 from "fs/promises";
|
|
|
25710
25748
|
import * as os13 from "os";
|
|
25711
25749
|
import * as path31 from "path";
|
|
25712
25750
|
function stateDir(home) {
|
|
25713
|
-
return path31.join(home, ".m8t
|
|
25751
|
+
return path31.join(home, ".m8t");
|
|
25714
25752
|
}
|
|
25715
25753
|
function statePath(home) {
|
|
25716
25754
|
return path31.join(stateDir(home), "bootstrap.json");
|
|
@@ -25734,19 +25772,19 @@ async function writeBootstrapState(state, home = os13.homedir()) {
|
|
|
25734
25772
|
// src/commands/bootstrap/launch.ts
|
|
25735
25773
|
var DEFAULT_RG = "rg-m8t-stack";
|
|
25736
25774
|
var DEFAULT_INSTALLER = "ghcr.io/m8t-labs/m8t-installer";
|
|
25737
|
-
var DEFAULT_INSTALLER_TAG = "v0.1.
|
|
25775
|
+
var DEFAULT_INSTALLER_TAG = "v0.1.34";
|
|
25738
25776
|
var ACI_NAME = "m8t-installer";
|
|
25739
25777
|
var MI_NAME = "m8t-installer-mi";
|
|
25740
25778
|
var BootstrapLaunchCommand = class extends M8tCommand {
|
|
25741
25779
|
static paths = [["bootstrap", "launch"]];
|
|
25742
25780
|
static usage = Command49.Usage({
|
|
25743
25781
|
description: "Create + authorize the installer managed identity, then kick the cloud installer.",
|
|
25744
|
-
details: "Step 2 of `m8t bootstrap` (run after `preflight`). Ensures the resource group, creates the m8t
|
|
25782
|
+
details: "Step 2 of `m8t bootstrap` (run after `preflight`). Ensures the resource group, creates the m8t app registration (or uses --client-id), creates a user-assigned managed identity granted Owner at subscription scope, and launches the published m8t-installer image as an ACI run-to-completion job under that identity. Writes ~/.m8t/bootstrap.json for `status`/`reap`/`finish`.",
|
|
25745
25783
|
examples: [
|
|
25746
25784
|
["Launch in eastus2", "$0 bootstrap launch --location eastus2"],
|
|
25747
25785
|
["BYO app registration", "$0 bootstrap launch --location eastus2 --client-id <appId>"],
|
|
25748
|
-
["Pin a specific installer tag", "$0 bootstrap launch --location eastus2 --installer-tag v0.1.
|
|
25749
|
-
["Override the full installer image ref", "$0 bootstrap launch --location eastus2 --installer-image ghcr.io/m8t-labs/m8t-installer:v0.1.
|
|
25786
|
+
["Pin a specific installer tag", "$0 bootstrap launch --location eastus2 --installer-tag v0.1.33"],
|
|
25787
|
+
["Override the full installer image ref", "$0 bootstrap launch --location eastus2 --installer-image ghcr.io/m8t-labs/m8t-installer:v0.1.33"]
|
|
25750
25788
|
]
|
|
25751
25789
|
});
|
|
25752
25790
|
location = Option46.String("--location");
|
|
@@ -25775,7 +25813,7 @@ var BootstrapLaunchCommand = class extends M8tCommand {
|
|
|
25775
25813
|
const subscriptionId = (typeof this.subscription === "string" ? this.subscription : void 0) ?? account.subscriptionId;
|
|
25776
25814
|
const out = (m) => this.context.stderr.write(` ${colors.dim(m)}
|
|
25777
25815
|
`);
|
|
25778
|
-
const credsPath = typeof this.githubAppCreds === "string" ? this.githubAppCreds : path32.join(os14.homedir(), ".m8t
|
|
25816
|
+
const credsPath = typeof this.githubAppCreds === "string" ? this.githubAppCreds : path32.join(os14.homedir(), ".m8t", "github-app.json");
|
|
25779
25817
|
let githubApp;
|
|
25780
25818
|
if (fs30.existsSync(credsPath)) {
|
|
25781
25819
|
let parsed;
|
|
@@ -25811,7 +25849,7 @@ var BootstrapLaunchCommand = class extends M8tCommand {
|
|
|
25811
25849
|
}
|
|
25812
25850
|
out("registering Microsoft.ContainerInstance\u2026");
|
|
25813
25851
|
await registerContainerInstance(subscriptionId);
|
|
25814
|
-
out("resolving the m8t
|
|
25852
|
+
out("resolving the m8t app registration\u2026");
|
|
25815
25853
|
const appReg = await ensureAppReg({ tenantId: account.tenantId, clientId: clientIdOpt });
|
|
25816
25854
|
out(`ensuring resource group ${resourceGroup}\u2026`);
|
|
25817
25855
|
await ensureResourceGroup2({ name: resourceGroup, location, subscriptionId });
|
|
@@ -25850,7 +25888,8 @@ var BootstrapLaunchCommand = class extends M8tCommand {
|
|
|
25850
25888
|
image: installerImage,
|
|
25851
25889
|
gatewayImageRef,
|
|
25852
25890
|
foundryTracing: "skip",
|
|
25853
|
-
githubApp
|
|
25891
|
+
githubApp,
|
|
25892
|
+
enrollContactEmail: account.upn
|
|
25854
25893
|
});
|
|
25855
25894
|
this.context.stdout.write(
|
|
25856
25895
|
`${colors.success("\u2713")} installer launched in ${colors.field(resourceGroup)} (${location}).
|
|
@@ -25902,7 +25941,7 @@ var BootstrapStatusCommand = class extends M8tCommand {
|
|
|
25902
25941
|
if (!state) {
|
|
25903
25942
|
throw new LocalCliError({
|
|
25904
25943
|
code: "BOOTSTRAP_NO_STATE",
|
|
25905
|
-
message: "No bootstrap is in flight (no ~/.m8t
|
|
25944
|
+
message: "No bootstrap is in flight (no ~/.m8t/bootstrap.json).",
|
|
25906
25945
|
hint: "Run 'm8t bootstrap launch --location <region>' first."
|
|
25907
25946
|
});
|
|
25908
25947
|
}
|
|
@@ -26353,7 +26392,7 @@ function composeFounderIdentityNote(id) {
|
|
|
26353
26392
|
|
|
26354
26393
|
// src/lib/company-profile-seed.ts
|
|
26355
26394
|
function readGithubAppCreds(credsPath) {
|
|
26356
|
-
const p = credsPath ?? path33.join(os15.homedir(), ".m8t
|
|
26395
|
+
const p = credsPath ?? path33.join(os15.homedir(), ".m8t", "github-app.json");
|
|
26357
26396
|
try {
|
|
26358
26397
|
return JSON.parse(readFileSync20(p, "utf8"));
|
|
26359
26398
|
} catch {
|
|
@@ -26418,7 +26457,7 @@ async function applyProfileToBrain(args) {
|
|
|
26418
26457
|
});
|
|
26419
26458
|
}
|
|
26420
26459
|
function spawnDetachedSeedWatch() {
|
|
26421
|
-
const logPath = path33.join(os15.homedir(), ".m8t
|
|
26460
|
+
const logPath = path33.join(os15.homedir(), ".m8t", "seed-profile.log");
|
|
26422
26461
|
const fd = openSync(logPath, "a");
|
|
26423
26462
|
try {
|
|
26424
26463
|
const child = spawn6(process.execPath, [process.argv[1] ?? "", "bootstrap", "seed-profile", "--watch"], {
|
|
@@ -26497,7 +26536,7 @@ var BootstrapFinishCommand = class extends M8tCommand {
|
|
|
26497
26536
|
static paths = [["bootstrap", "finish"]];
|
|
26498
26537
|
static usage = Command52.Usage({
|
|
26499
26538
|
description: "Point your local tools at the now-live platform (repo-root marker, discovery cache, next steps).",
|
|
26500
|
-
details: "Final step of `m8t bootstrap` (after the install reaches done). Writes ~/.m8t
|
|
26539
|
+
details: "Final step of `m8t bootstrap` (after the install reaches done). Writes ~/.m8t/repo-root, points your local tools at the live gateway, and \u2014 if you completed the onboarding questionnaire \u2014 seeds your brain-backed advisor's brain with your company profile (best-effort; never blocks finish). Run `m8t bootstrap seed-profile` to seed manually later.",
|
|
26501
26540
|
examples: [["Finish local", "$0 bootstrap finish --repo-root /path/to/m8t"]]
|
|
26502
26541
|
});
|
|
26503
26542
|
repoRoot = Option49.String("--repo-root");
|
|
@@ -26517,7 +26556,7 @@ var BootstrapFinishCommand = class extends M8tCommand {
|
|
|
26517
26556
|
});
|
|
26518
26557
|
}
|
|
26519
26558
|
const repoRoot = (typeof this.repoRoot === "string" ? this.repoRoot : void 0) ?? process.cwd();
|
|
26520
|
-
const markerDir = path34.join(os16.homedir(), ".m8t
|
|
26559
|
+
const markerDir = path34.join(os16.homedir(), ".m8t");
|
|
26521
26560
|
await fs31.mkdir(markerDir, { recursive: true });
|
|
26522
26561
|
await fs31.writeFile(path34.join(markerDir, "repo-root"), `${repoRoot}
|
|
26523
26562
|
`, "utf8");
|
|
@@ -26577,7 +26616,7 @@ var BootstrapFinishCommand = class extends M8tCommand {
|
|
|
26577
26616
|
this.context.stdout.write(renderInstallSummary({ webappUrl, brainOrg }) + "\n");
|
|
26578
26617
|
this.context.stdout.write(
|
|
26579
26618
|
`${colors.field("Optional local tooling for your coding agent:")}
|
|
26580
|
-
\u2022 Talk to your deployed workers from agent sessions (e.g. /stacey) \u2014 install the m8t
|
|
26619
|
+
\u2022 Talk to your deployed workers from agent sessions (e.g. /stacey) \u2014 install the m8t plugin: guides/install/m8t-plugin.md.
|
|
26581
26620
|
\u2022 Azure-capable MCP servers (microsoft/azure-skills, Microsoft Learn) \u2014 see the optional steps in guides/install.md.
|
|
26582
26621
|
\u2022 Deploy workers conversationally with the opt-in persona skills \u2014 see guides/workers.md.
|
|
26583
26622
|
\u2022 Make sure your m8t CLI is current: npm i -g @m8t-stack/cli@latest
|
|
@@ -26614,7 +26653,7 @@ import * as fs32 from "fs";
|
|
|
26614
26653
|
import * as net from "net";
|
|
26615
26654
|
import * as os17 from "os";
|
|
26616
26655
|
import * as path35 from "path";
|
|
26617
|
-
import { spawn as spawn7 } from "child_process";
|
|
26656
|
+
import { spawn as spawn7, spawnSync as spawnSync6 } from "child_process";
|
|
26618
26657
|
init_errors();
|
|
26619
26658
|
init_rbac();
|
|
26620
26659
|
|
|
@@ -26836,14 +26875,14 @@ async function installWebDeps(repoRoot) {
|
|
|
26836
26875
|
await runInherit("pnpm", ["install"], repoRoot, "BOOTSTRAP_UI_INSTALL_FAILED");
|
|
26837
26876
|
}
|
|
26838
26877
|
function onboardingUiPaths(home = os17.homedir()) {
|
|
26839
|
-
const dir = path35.join(home, ".m8t
|
|
26878
|
+
const dir = path35.join(home, ".m8t");
|
|
26840
26879
|
return {
|
|
26841
26880
|
logPath: path35.join(dir, "onboarding-ui.log"),
|
|
26842
26881
|
pidPath: path35.join(dir, "onboarding-ui.pid")
|
|
26843
26882
|
};
|
|
26844
26883
|
}
|
|
26845
26884
|
function onboardingRelayPaths(home = os17.homedir()) {
|
|
26846
|
-
const dir = path35.join(home, ".m8t
|
|
26885
|
+
const dir = path35.join(home, ".m8t");
|
|
26847
26886
|
return {
|
|
26848
26887
|
logPath: path35.join(dir, "onboarding-relay.log"),
|
|
26849
26888
|
pidPath: path35.join(dir, "onboarding-relay.pid")
|
|
@@ -26880,7 +26919,8 @@ async function serveOnboardingUiDetached(args) {
|
|
|
26880
26919
|
detached: true,
|
|
26881
26920
|
stdio: ["ignore", fd, fd],
|
|
26882
26921
|
env: { ...process.env, PORT: args.port },
|
|
26883
|
-
shell
|
|
26922
|
+
// pnpm resolves to pnpm.cmd on Windows, which needs a shell to launch.
|
|
26923
|
+
shell: process.platform === "win32"
|
|
26884
26924
|
});
|
|
26885
26925
|
fs32.closeSync(fd);
|
|
26886
26926
|
if (child.pid == null) {
|
|
@@ -26920,7 +26960,8 @@ async function serveOnboardingRelayDetached(args) {
|
|
|
26920
26960
|
RELAY_ALLOWED_ORIGINS: "http://localhost:3000",
|
|
26921
26961
|
RELAY_PORT: "8790"
|
|
26922
26962
|
},
|
|
26923
|
-
shell
|
|
26963
|
+
// pnpm resolves to pnpm.cmd on Windows, which needs a shell to launch.
|
|
26964
|
+
shell: process.platform === "win32"
|
|
26924
26965
|
});
|
|
26925
26966
|
fs32.closeSync(fd);
|
|
26926
26967
|
if (child.pid == null) {
|
|
@@ -26959,10 +27000,14 @@ function stopPidFile(pidPath) {
|
|
|
26959
27000
|
}
|
|
26960
27001
|
const pid = Number(pidStr);
|
|
26961
27002
|
if (!Number.isNaN(pid) && pid > 0) {
|
|
26962
|
-
|
|
26963
|
-
|
|
26964
|
-
}
|
|
26965
|
-
|
|
27003
|
+
if (process.platform === "win32") {
|
|
27004
|
+
spawnSync6("taskkill", ["/pid", String(pid), "/T", "/F"], { stdio: "ignore" });
|
|
27005
|
+
} else {
|
|
27006
|
+
try {
|
|
27007
|
+
process.kill(-pid, "SIGTERM");
|
|
27008
|
+
} catch (e) {
|
|
27009
|
+
if (e.code !== "ESRCH") throw e;
|
|
27010
|
+
}
|
|
26966
27011
|
}
|
|
26967
27012
|
}
|
|
26968
27013
|
try {
|
|
@@ -27037,7 +27082,7 @@ var BootstrapUiCommand = class extends M8tCommand {
|
|
|
27037
27082
|
if (!state) {
|
|
27038
27083
|
throw new LocalCliError({
|
|
27039
27084
|
code: "BOOTSTRAP_NO_STATE",
|
|
27040
|
-
message: "No bootstrap is in flight (no ~/.m8t
|
|
27085
|
+
message: "No bootstrap is in flight (no ~/.m8t/bootstrap.json).",
|
|
27041
27086
|
hint: "Run 'm8t bootstrap launch --location <region>' first."
|
|
27042
27087
|
});
|
|
27043
27088
|
}
|
|
@@ -27053,8 +27098,8 @@ var BootstrapUiCommand = class extends M8tCommand {
|
|
|
27053
27098
|
this.context.stderr.write(` ${colors.dim(m)}
|
|
27054
27099
|
`);
|
|
27055
27100
|
};
|
|
27056
|
-
if (fs33.existsSync(path36.join(os18.homedir(), ".m8t
|
|
27057
|
-
out(colors.error("\u26A0 an existing ~/.m8t
|
|
27101
|
+
if (fs33.existsSync(path36.join(os18.homedir(), ".m8t", "config.yaml"))) {
|
|
27102
|
+
out(colors.error("\u26A0 an existing ~/.m8t/config.yaml will override the onboarding app registration in apps/web \u2014 if Microsoft sign-in fails, move it aside and retry."));
|
|
27058
27103
|
}
|
|
27059
27104
|
const credential2 = new DefaultAzureCredential20();
|
|
27060
27105
|
const account = await getAzAccount();
|
|
@@ -27177,7 +27222,7 @@ var BootstrapSeedProfileCommand = class extends M8tCommand {
|
|
|
27177
27222
|
credsPath: typeof this.githubAppCreds === "string" ? this.githubAppCreds : void 0
|
|
27178
27223
|
});
|
|
27179
27224
|
if (!ctx) {
|
|
27180
|
-
this.context.stderr.write(` ${colors.dim("no GitHub App creds (~/.m8t
|
|
27225
|
+
this.context.stderr.write(` ${colors.dim("no GitHub App creds (~/.m8t/github-app.json) \u2014 no brain to seed; skipping.")}
|
|
27181
27226
|
`);
|
|
27182
27227
|
return 0;
|
|
27183
27228
|
}
|
|
@@ -27214,10 +27259,116 @@ var BootstrapSeedProfileCommand = class extends M8tCommand {
|
|
|
27214
27259
|
}
|
|
27215
27260
|
};
|
|
27216
27261
|
|
|
27262
|
+
// src/commands/telemetry/enroll.ts
|
|
27263
|
+
import { Command as Command55, Option as Option52 } from "clipanion";
|
|
27264
|
+
init_errors();
|
|
27265
|
+
|
|
27266
|
+
// src/lib/telemetry-enroll.ts
|
|
27267
|
+
init_errors();
|
|
27268
|
+
async function enroll(args) {
|
|
27269
|
+
const f = args.fetchImpl ?? fetch;
|
|
27270
|
+
const url = args.baseUrl ? `${args.baseUrl.replace(/\/+$/, "")}/api/ingest/enroll` : ingestUrl("/api/ingest/enroll");
|
|
27271
|
+
let res;
|
|
27272
|
+
try {
|
|
27273
|
+
res = await f(url, {
|
|
27274
|
+
method: "POST",
|
|
27275
|
+
headers: { "content-type": "application/json" },
|
|
27276
|
+
body: JSON.stringify({ schemaVersion: 1, company: args.company, contactEmail: args.contactEmail, subscriptionId: args.subscriptionId, proof: null })
|
|
27277
|
+
});
|
|
27278
|
+
} catch (e) {
|
|
27279
|
+
throw new LocalCliError({ code: "TELEMETRY_ENROLL_UNREACHABLE", message: `Could not reach the telemetry ingest to enroll: ${e instanceof Error ? e.message : String(e)}` });
|
|
27280
|
+
}
|
|
27281
|
+
if (!res.ok) {
|
|
27282
|
+
const body = await res.text().catch(() => "");
|
|
27283
|
+
throw new LocalCliError({ code: "TELEMETRY_ENROLL_FAILED", message: `Enroll failed (HTTP ${res.status.toString()}): ${body}` });
|
|
27284
|
+
}
|
|
27285
|
+
const json = await res.json();
|
|
27286
|
+
if (!json.instanceId || !json.ingestKey) {
|
|
27287
|
+
throw new LocalCliError({ code: "TELEMETRY_ENROLL_BAD_RESPONSE", message: "Enroll response missing instanceId/ingestKey." });
|
|
27288
|
+
}
|
|
27289
|
+
return { instanceId: json.instanceId, ingestKey: json.ingestKey };
|
|
27290
|
+
}
|
|
27291
|
+
|
|
27292
|
+
// src/commands/telemetry/enroll.ts
|
|
27293
|
+
var INGEST_KEY_SECRET = "m8t-ingest-key";
|
|
27294
|
+
async function resolveKeyVaultName(containerAppResourceId) {
|
|
27295
|
+
const kvUri = (await runAz([
|
|
27296
|
+
"containerapp",
|
|
27297
|
+
"show",
|
|
27298
|
+
"--ids",
|
|
27299
|
+
containerAppResourceId,
|
|
27300
|
+
"--query",
|
|
27301
|
+
"properties.template.containers[0].env[?name=='KEY_VAULT_URI'].value | [0]",
|
|
27302
|
+
"-o",
|
|
27303
|
+
"tsv"
|
|
27304
|
+
])).trim();
|
|
27305
|
+
if (!kvUri) {
|
|
27306
|
+
throw new LocalCliError({
|
|
27307
|
+
code: "TELEMETRY_ENROLL_NO_KV",
|
|
27308
|
+
message: "Could not resolve the platform Key Vault: the gateway Container App has no KEY_VAULT_URI env var.",
|
|
27309
|
+
hint: "Verify the deployment via 'az containerapp show --ids <id> --query properties.template.containers[0].env'."
|
|
27310
|
+
});
|
|
27311
|
+
}
|
|
27312
|
+
const host = new URL(kvUri).hostname;
|
|
27313
|
+
const name = host.split(".")[0];
|
|
27314
|
+
if (!name) {
|
|
27315
|
+
throw new LocalCliError({ code: "TELEMETRY_ENROLL_BAD_KV_URI", message: `Could not parse a Key Vault name from KEY_VAULT_URI '${kvUri}'.` });
|
|
27316
|
+
}
|
|
27317
|
+
return name;
|
|
27318
|
+
}
|
|
27319
|
+
var TelemetryEnrollCommand = class extends M8tCommand {
|
|
27320
|
+
static paths = [["telemetry", "enroll"]];
|
|
27321
|
+
static usage = Command55.Usage({
|
|
27322
|
+
description: "Enroll this installation for operational telemetry (pre-existing installs).",
|
|
27323
|
+
details: "Mints an instance id + ingest key from the m8t telemetry ingest and stores the key in your platform Key Vault, the same place the installer writes it on a fresh install. Idempotent: refuses if a key already exists unless --force.",
|
|
27324
|
+
examples: [["Enroll", "$0 telemetry enroll"]]
|
|
27325
|
+
});
|
|
27326
|
+
company = Option52.String("--company", { description: "Your company name (optional)." });
|
|
27327
|
+
contactEmail = Option52.String("--contact-email", { description: "Contact email (default: your signed-in az UPN)." });
|
|
27328
|
+
subscription = Option52.String("--subscription", { description: "Azure subscription id (default: your active az subscription)." });
|
|
27329
|
+
resourceGroup = Option52.String("--resource-group", { description: "Resource group to disambiguate discovery, if you have more than one m8t deployment." });
|
|
27330
|
+
force = Option52.Boolean("--force", false, { description: "Re-enroll even if a key is already stored (mints a new instance id)." });
|
|
27331
|
+
async executeCommand() {
|
|
27332
|
+
const account = await getAzAccount();
|
|
27333
|
+
const subscriptionId = (typeof this.subscription === "string" ? this.subscription : void 0) ?? account.subscriptionId;
|
|
27334
|
+
const contactEmail = (typeof this.contactEmail === "string" ? this.contactEmail : void 0) ?? account.upn;
|
|
27335
|
+
const company = (typeof this.company === "string" ? this.company : void 0) ?? "";
|
|
27336
|
+
const d = await discoverGateway({
|
|
27337
|
+
subscriptionId,
|
|
27338
|
+
interactive: false,
|
|
27339
|
+
resourceGroup: typeof this.resourceGroup === "string" ? this.resourceGroup : void 0
|
|
27340
|
+
});
|
|
27341
|
+
const kvName = await resolveKeyVaultName(d.containerAppResourceId);
|
|
27342
|
+
if (this.force !== true) {
|
|
27343
|
+
let existing = "";
|
|
27344
|
+
try {
|
|
27345
|
+
existing = await runAz(["keyvault", "secret", "show", "--vault-name", kvName, "--name", INGEST_KEY_SECRET, "--query", "value", "-o", "tsv"]);
|
|
27346
|
+
} catch (e) {
|
|
27347
|
+
rethrowIfAzUnavailable(e);
|
|
27348
|
+
existing = "";
|
|
27349
|
+
}
|
|
27350
|
+
if (existing.trim()) {
|
|
27351
|
+
throw new LocalCliError({
|
|
27352
|
+
code: "TELEMETRY_ALREADY_ENROLLED",
|
|
27353
|
+
message: "This installation is already enrolled.",
|
|
27354
|
+
hint: "Pass --force to re-enroll (mints a new instance id)."
|
|
27355
|
+
});
|
|
27356
|
+
}
|
|
27357
|
+
}
|
|
27358
|
+
const { instanceId, ingestKey } = await enroll({ company, contactEmail, subscriptionId });
|
|
27359
|
+
await runAz(["keyvault", "secret", "set", "--vault-name", kvName, "--name", INGEST_KEY_SECRET, "--value", ingestKey, "--only-show-errors"]);
|
|
27360
|
+
this.context.stdout.write(
|
|
27361
|
+
`${colors.success("\u2713")} enrolled (instance ${instanceId}); ingest key stored in Key Vault ${kvName}. The gateway picks it up on its next cycle.
|
|
27362
|
+
`
|
|
27363
|
+
);
|
|
27364
|
+
return 0;
|
|
27365
|
+
}
|
|
27366
|
+
};
|
|
27367
|
+
|
|
27217
27368
|
// src/cli.ts
|
|
27218
27369
|
var cli = new Cli({
|
|
27219
27370
|
binaryName: "m8t",
|
|
27220
|
-
binaryLabel: "m8t CLI \u2014 manage m8t
|
|
27371
|
+
binaryLabel: "m8t CLI \u2014 manage m8t deployments",
|
|
27221
27372
|
binaryVersion: CLI_VERSION
|
|
27222
27373
|
});
|
|
27223
27374
|
cli.register(Builtins.HelpCommand);
|
|
@@ -27274,6 +27425,7 @@ cli.register(BootstrapReapCommand);
|
|
|
27274
27425
|
cli.register(BootstrapFinishCommand);
|
|
27275
27426
|
cli.register(BootstrapUiCommand);
|
|
27276
27427
|
cli.register(BootstrapSeedProfileCommand);
|
|
27428
|
+
cli.register(TelemetryEnrollCommand);
|
|
27277
27429
|
async function main() {
|
|
27278
27430
|
try {
|
|
27279
27431
|
return await cli.run(process.argv.slice(2));
|