@m8t-stack/cli 0.2.97 → 0.2.98

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1487,7 +1487,7 @@ function installFoundryDnsShim() {
1487
1487
  }
1488
1488
 
1489
1489
  // src/lib/package-version.ts
1490
- var CLI_VERSION = "0.2.97";
1490
+ var CLI_VERSION = "0.2.98";
1491
1491
 
1492
1492
  // src/lib/render-error.ts
1493
1493
  init_errors();
@@ -21207,17 +21207,46 @@ function sortObj(o) {
21207
21207
 
21208
21208
  // src/lib/gateway-live-params.ts
21209
21209
  async function readLiveGatewayEnvVar(opts) {
21210
- const args = ["containerapp", "show", "-n", opts.gatewayName, "-g", opts.resourceGroup];
21211
- if (opts.subscriptionId) args.push("--subscription", opts.subscriptionId);
21212
- args.push("--query", `properties.template.containers[0].env[?name=='${opts.name}'].value | [0]`, "-o", "tsv");
21210
+ const show = ["containerapp", "show", "-n", opts.gatewayName, "-g", opts.resourceGroup];
21211
+ if (opts.subscriptionId) show.push("--subscription", opts.subscriptionId);
21212
+ show.push("--query", `properties.template.containers[0].env[?name=='${opts.name}'] | [0]`, "-o", "json");
21213
21213
  let raw;
21214
21214
  try {
21215
- raw = await runAz(args);
21215
+ raw = await runAz(show);
21216
+ } catch (e) {
21217
+ return { kind: "unreadable", detail: e.message };
21218
+ }
21219
+ const text = raw.trim();
21220
+ if (text === "" || text === "null" || text === "None") return { kind: "absent" };
21221
+ let entry;
21222
+ try {
21223
+ entry = JSON.parse(text);
21216
21224
  } catch {
21217
- return "";
21225
+ return { kind: "unreadable", detail: "the env entry did not parse as JSON" };
21218
21226
  }
21219
- const v = raw.trim();
21220
- return v === "None" ? "" : v;
21227
+ if (typeof entry.value === "string" && entry.value !== "") {
21228
+ return { kind: "value", value: entry.value };
21229
+ }
21230
+ if (typeof entry.secretRef !== "string" || entry.secretRef === "") {
21231
+ return { kind: "absent" };
21232
+ }
21233
+ const secret = ["containerapp", "secret", "show", "-n", opts.gatewayName, "-g", opts.resourceGroup];
21234
+ if (opts.subscriptionId) secret.push("--subscription", opts.subscriptionId);
21235
+ secret.push("--secret-name", entry.secretRef, "--query", "value", "-o", "tsv");
21236
+ let secretRaw;
21237
+ try {
21238
+ secretRaw = await runAz(secret);
21239
+ } catch (e) {
21240
+ return {
21241
+ kind: "unreadable",
21242
+ detail: `could not read secret '${entry.secretRef}': ${e.message}`
21243
+ };
21244
+ }
21245
+ const value = secretRaw.trim();
21246
+ if (value === "" || value === "None") {
21247
+ return { kind: "unreadable", detail: `secret '${entry.secretRef}' read back empty` };
21248
+ }
21249
+ return { kind: "value", value };
21221
21250
  }
21222
21251
  async function readLiveGatewayImage(opts) {
21223
21252
  const args = ["containerapp", "show", "-n", opts.gatewayName, "-g", opts.resourceGroup];
@@ -21233,6 +21262,19 @@ async function readLiveGatewayImage(opts) {
21233
21262
  function readLiveVoiceInternalSecret(opts) {
21234
21263
  return readLiveGatewayEnvVar({ ...opts, name: "M8T_INTERNAL_SECRET" });
21235
21264
  }
21265
+ function voiceSecretParam(read, gatewayName) {
21266
+ if (read.kind === "value") return { value: read.value };
21267
+ if (read.kind === "absent") {
21268
+ return {
21269
+ value: "",
21270
+ warning: `gateway '${gatewayName}' has no M8T_INTERNAL_SECRET to preserve, so this converge will mint one, rolling BOTH the gateway and the voice relay. Expected on a first deploy.`
21271
+ };
21272
+ }
21273
+ return {
21274
+ value: "",
21275
+ warning: `could not read the voice-relay secret (M8T_INTERNAL_SECRET) off gateway '${gatewayName}': ${read.detail}. The variable may well be set \u2014 this converge will mint a NEW secret anyway, rolling BOTH the gateway and the voice relay.`
21276
+ };
21277
+ }
21236
21278
 
21237
21279
  // src/lib/platform-converge.ts
21238
21280
  var ORDER = ["infra", "gateway", "codingAgent", "azureExecutor", "personas", "brainSeeds"];
@@ -22463,16 +22505,16 @@ async function buildConvergeDeps(args) {
22463
22505
  }
22464
22506
  args.onProgress?.("subscription-scoped modules skipped: updater is RG-scoped; sub-level changes require a founder-run CLI converge.");
22465
22507
  const gatewayName = args.suffix ? `m8t-gateway-${args.suffix}` : void 0;
22466
- const voiceInternalSecret = gatewayName ? await readLiveVoiceInternalSecret({
22467
- gatewayName,
22468
- resourceGroup: args.resourceGroup,
22469
- subscriptionId: args.subscriptionId
22470
- }) : "";
22471
- if (gatewayName && !voiceInternalSecret) {
22472
- args.onProgress?.(
22473
- `could not read the live voice-relay secret (M8T_INTERNAL_SECRET) off gateway '${gatewayName}' \u2014 the read failed or the variable is missing. This infra converge will re-mint the secret, rolling BOTH the gateway and the voice relay.`
22474
- );
22475
- }
22508
+ const secret = gatewayName ? voiceSecretParam(
22509
+ await readLiveVoiceInternalSecret({
22510
+ gatewayName,
22511
+ resourceGroup: args.resourceGroup,
22512
+ subscriptionId: args.subscriptionId
22513
+ }),
22514
+ gatewayName
22515
+ ) : { value: "" };
22516
+ const voiceInternalSecret = secret.value;
22517
+ if (secret.warning !== void 0) args.onProgress?.(secret.warning);
22476
22518
  const opts = {
22477
22519
  suffix: args.suffix,
22478
22520
  assignSubscriptionRoles: false,
@@ -24343,11 +24385,12 @@ var PlatformEnableAutoUpdateCommand = class extends M8tCommand {
24343
24385
  message: `Could not read the live image for gateway '${gatewayName}' in resource group ${resourceGroup}.`
24344
24386
  });
24345
24387
  }
24346
- const voiceInternalSecret = await readLiveVoiceInternalSecret({
24347
- gatewayName,
24348
- resourceGroup,
24349
- subscriptionId
24350
- });
24388
+ const voiceSecret = voiceSecretParam(
24389
+ await readLiveVoiceInternalSecret({ gatewayName, resourceGroup, subscriptionId }),
24390
+ gatewayName
24391
+ );
24392
+ if (voiceSecret.warning !== void 0) log(colors.warn(voiceSecret.warning));
24393
+ const voiceInternalSecret = voiceSecret.value;
24351
24394
  const stampedLocation = stampedParams?.bicep.location;
24352
24395
  const location = typeof this.location === "string" && this.location.length > 0 ? this.location : stampedLocation !== void 0 && stampedLocation.length > 0 ? stampedLocation : (await runAz(["resource", "list", "-g", resourceGroup, "--subscription", subscriptionId, "--query", "[0].location", "-o", "tsv"])).trim();
24353
24396
  if (!location) {
@@ -32775,24 +32818,35 @@ async function reactiveSeedOnInstallComplete(args) {
32775
32818
  }
32776
32819
 
32777
32820
  // src/lib/install-summary.ts
32778
- var DEFAULT_WORKERS = [
32779
- { name: "ezra", label: "Ezra - Azure Expert", brain: "ezra-brain" }
32780
- ];
32821
+ var WORKER_LABELS = {
32822
+ ezra: "Ezra - Azure Expert",
32823
+ stacey: "Stacey - Startup Advisor"
32824
+ };
32825
+ function workerNameOf(brainRepo) {
32826
+ const leaf = brainRepo.slice(brainRepo.lastIndexOf("/") + 1);
32827
+ return leaf.endsWith("-brain") ? leaf.slice(0, -"-brain".length) : leaf;
32828
+ }
32781
32829
  function renderInstallSummary(args) {
32782
32830
  const open4 = args.webappUrl ? `${args.webappUrl} (or run: m8t open)` : "run: m8t open";
32831
+ const brains = args.brains ?? [];
32783
32832
  const lines = [
32784
32833
  "\u2705 Your m8t platform is ready to use.",
32785
32834
  ` Open it: ${open4}`,
32786
32835
  ""
32787
32836
  ];
32788
- if (args.brainOrg) {
32837
+ if (brains.length > 0) {
32838
+ const workers = brains.map((brain) => {
32839
+ const name = workerNameOf(brain);
32840
+ return { name, label: WORKER_LABELS[name] ?? name, brain };
32841
+ });
32789
32842
  lines.push(" Your team:");
32790
- for (const w of DEFAULT_WORKERS) {
32791
- lines.push(` \u2022 ${w.label} \xB7 brain: ${args.brainOrg}/${w.brain}`);
32843
+ for (const w of workers) {
32844
+ lines.push(` \u2022 ${w.label} \xB7 brain: ${w.brain}`);
32792
32845
  }
32846
+ const handles = workers.map((w) => `@${w.name} (or /${w.name})`).join(", ");
32793
32847
  lines.push(
32794
32848
  "",
32795
- " Reach them: @ezra (or /ezra) in your coding agent",
32849
+ ` Reach them: ${handles} in your coding agent`,
32796
32850
  " \xB7 the webapp \xB7 or connect Telegram in the webapp (Channels)"
32797
32851
  );
32798
32852
  } else {
@@ -34278,14 +34332,7 @@ async function finalizeInstall(args, deps = defaultFinalizeDeps) {
34278
34332
  ` : "") + "\n"
34279
34333
  );
34280
34334
  }
34281
- let brainOrg = null;
34282
- try {
34283
- const credsRaw = await fs39.readFile(path44.join(markerDir, "github-app.json"), "utf8");
34284
- const creds = JSON.parse(credsRaw);
34285
- brainOrg = typeof creds.org === "string" ? creds.org : null;
34286
- } catch {
34287
- }
34288
- args.stdout(renderInstallSummary({ webappUrl, brainOrg }) + "\n");
34335
+ args.stdout(renderInstallSummary({ webappUrl, brains: args.doc.result?.brains }) + "\n");
34289
34336
  args.stdout(
34290
34337
  `${colors.field("Optional local tooling for your coding agent:")}
34291
34338
  \u2022 Talk to your deployed workers from agent sessions (e.g. /ezra) \u2014 install the m8t plugin: guides/install/m8t-plugin.md.
@@ -35410,6 +35457,7 @@ var FAILURE_REASONS = /* @__PURE__ */ new Set([
35410
35457
  "not-connected",
35411
35458
  "not-authorized",
35412
35459
  "mate-unavailable",
35460
+ "mate-ambiguous",
35413
35461
  "busy",
35414
35462
  "bad-request",
35415
35463
  "decision-not-pending"
@@ -35878,12 +35926,10 @@ function decodeAgents(data) {
35878
35926
  return data.agents.filter(isRecord6);
35879
35927
  }
35880
35928
  function resolveAgentName(agents, personaKey) {
35881
- const matches = agents.filter(
35882
- (agent) => agent.personaKey === personaKey && isAgentName(agent.name)
35883
- );
35929
+ const matches = agents.filter((agent) => agent.personaKey === personaKey);
35884
35930
  if (matches.length === 0) return null;
35885
35931
  if (matches.length > 1) {
35886
- throw new PredispatchFailure("mate-unavailable");
35932
+ throw new PredispatchFailure("mate-ambiguous");
35887
35933
  }
35888
35934
  const match = matches[0];
35889
35935
  if (!isAgentName(match.name)) {
@@ -36152,11 +36198,23 @@ async function rosterCompanions(sink, deps = {}) {
36152
36198
  { personaKey: "startup-advisor", displayName: "Stacey", portraitKey: "stacey" },
36153
36199
  { personaKey: "ezra", displayName: "Ezra", portraitKey: "ezra" }
36154
36200
  ];
36201
+ const faults = [];
36155
36202
  const mates = PRESENTABLE.flatMap((mate) => {
36156
- const agentName = resolveAgentName(agents, mate.personaKey);
36203
+ let agentName;
36204
+ try {
36205
+ agentName = resolveAgentName(agents, mate.personaKey);
36206
+ } catch (error) {
36207
+ if (!(error instanceof PredispatchFailure)) throw error;
36208
+ faults.push(error.reason);
36209
+ return [];
36210
+ }
36157
36211
  return agentName === null ? [] : [{ ...mate, agentName, activeSince }];
36158
36212
  });
36159
- if (mates.length === 0) throw new PredispatchFailure("mate-unavailable");
36213
+ if (mates.length === 0) {
36214
+ throw new PredispatchFailure(
36215
+ faults.includes("mate-ambiguous") ? "mate-ambiguous" : "mate-unavailable"
36216
+ );
36217
+ }
36160
36218
  const event = parseEvent({ type: "roster", origin, mates });
36161
36219
  sink(event);
36162
36220
  return event;