@m8t-stack/cli 0.2.14 → 0.2.15

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
@@ -1198,7 +1198,7 @@ var init_enable_hosted_brain = __esm({
1198
1198
  import { Builtins, Cli } from "clipanion";
1199
1199
 
1200
1200
  // src/lib/package-version.ts
1201
- var CLI_VERSION = "0.2.14";
1201
+ var CLI_VERSION = "0.2.15";
1202
1202
 
1203
1203
  // src/lib/render-error.ts
1204
1204
  init_errors();
@@ -13197,6 +13197,18 @@ async function ghAuthLoginDevice(exec = defaultGhExec) {
13197
13197
  });
13198
13198
  }
13199
13199
  }
13200
+ async function getGhToken(exec = defaultGhExec) {
13201
+ const r = await exec("gh", ["auth", "token"]);
13202
+ const tok = r.stdout.trim();
13203
+ if (r.exitCode !== 0 || !tok) {
13204
+ throw new LocalCliError({
13205
+ code: "GH_TOKEN_FAILED",
13206
+ message: `gh auth token failed (exit ${r.exitCode.toString()}): ${(r.stderr || r.stdout).slice(0, 200)}`,
13207
+ hint: "Run `gh auth login` to authenticate the GitHub CLI."
13208
+ });
13209
+ }
13210
+ return tok;
13211
+ }
13200
13212
  async function getRepoId(owner, repo, exec = defaultGhExec) {
13201
13213
  const r = await exec("gh", ["api", `/repos/${owner}/${repo}`, "--jq", ".id"]);
13202
13214
  if (r.exitCode !== 0) {
@@ -13300,6 +13312,34 @@ async function tryOpenUrl(url, exec = defaultGhExec) {
13300
13312
  } catch {
13301
13313
  }
13302
13314
  }
13315
+ function ghRepoProbe(args) {
13316
+ const exec = args.exec ?? defaultGhExec;
13317
+ const slug = `${args.owner}/${args.repo}`;
13318
+ return {
13319
+ repoStatus: async () => {
13320
+ const r = await exec("gh", ["api", "-i", `/repos/${slug}`]);
13321
+ const combined = `${r.stdout}
13322
+ ${r.stderr}`;
13323
+ const header = /^HTTP\/[\d.]+\s+(\d{3})/m.exec(combined);
13324
+ if (header) return Number(header[1]);
13325
+ const ghErr = /\(HTTP (\d{3})\)/.exec(combined);
13326
+ if (ghErr) return Number(ghErr[1]);
13327
+ if (r.exitCode === 0) return 200;
13328
+ throw new LocalCliError({
13329
+ code: "GH_REPO_PROBE_FAILED",
13330
+ message: `gh api /repos/${slug} failed (exit ${r.exitCode.toString()}): ${(r.stderr || r.stdout).slice(0, 200)}`
13331
+ });
13332
+ },
13333
+ getFile: async (path29) => {
13334
+ const r = await exec("gh", ["api", "-H", "Accept: application/vnd.github.raw+json", `/repos/${slug}/contents/${path29}`]);
13335
+ return r.exitCode === 0 ? r.stdout : null;
13336
+ },
13337
+ isEmpty: async () => {
13338
+ const r = await exec("gh", ["api", `/repos/${slug}/contents`]);
13339
+ return r.exitCode !== 0;
13340
+ }
13341
+ };
13342
+ }
13303
13343
 
13304
13344
  // src/commands/brain/app-create.ts
13305
13345
  init_errors();
@@ -13534,6 +13574,7 @@ import { readFileSync as readFileSync6 } from "fs";
13534
13574
  import * as fs10 from "fs";
13535
13575
  import * as os4 from "os";
13536
13576
  import * as path9 from "path";
13577
+ import * as readline2 from "readline/promises";
13537
13578
  import { DefaultAzureCredential as DefaultAzureCredential4 } from "@azure/identity";
13538
13579
  init_errors();
13539
13580
 
@@ -14065,6 +14106,20 @@ function materializeBrainTree(opts) {
14065
14106
  init_errors();
14066
14107
  init_esm2();
14067
14108
  import { spawn as spawn3 } from "child_process";
14109
+ import { parse as parseYaml5 } from "yaml";
14110
+ function isM8tBrainMarker(yamlText) {
14111
+ if (!yamlText.trim()) return false;
14112
+ let parsed;
14113
+ try {
14114
+ parsed = parseYaml5(yamlText);
14115
+ } catch {
14116
+ return false;
14117
+ }
14118
+ if (!parsed || typeof parsed !== "object") return false;
14119
+ const root = parsed;
14120
+ const isObj2 = (v) => typeof v === "object" && v !== null;
14121
+ return isObj2(root.engine) || isObj2(root.processes) || isObj2(root.link);
14122
+ }
14068
14123
  async function createBlankRepo(args) {
14069
14124
  const res = await fetch(`https://api.github.com/orgs/${args.org}/repos`, {
14070
14125
  method: "POST",
@@ -14195,8 +14250,119 @@ async function commitFilesViaApp(args) {
14195
14250
  });
14196
14251
  await api(`/git/refs/heads/${args.branch}`, { method: "PATCH", body: JSON.stringify({ sha: commit.sha }) });
14197
14252
  }
14253
+ async function probeRepoState(probe) {
14254
+ const status = await probe.repoStatus();
14255
+ if (status === 404) return "absent";
14256
+ if (status !== 200) {
14257
+ throw new LocalCliError({
14258
+ code: "GH_REPO_PROBE_FAILED",
14259
+ message: `GET repo returned HTTP ${status.toString()} (expected 200 or 404)`
14260
+ });
14261
+ }
14262
+ const marker = await probe.getFile(".m8t/brain.yaml");
14263
+ if (marker !== null && isM8tBrainMarker(marker)) return "m8t-brain";
14264
+ if (await probe.isEmpty()) return "empty";
14265
+ return "foreign";
14266
+ }
14267
+ function appRepoProbe(args) {
14268
+ const doFetch = args.fetchImpl ?? fetch;
14269
+ const H = ghHeaders(args.token);
14270
+ return {
14271
+ repoStatus: async () => {
14272
+ const res = await doFetch(`${GH_API}/repos/${args.repo}`, { headers: H, signal: AbortSignal.timeout(GH_REQUEST_TIMEOUT_MS) });
14273
+ return res.status;
14274
+ },
14275
+ getFile: (path29) => readRepoFileViaApp({ token: args.token, repo: args.repo, path: path29, fetchImpl: args.fetchImpl }),
14276
+ isEmpty: async () => {
14277
+ const res = await doFetch(`${GH_API}/repos/${args.repo}/contents`, { headers: H, signal: AbortSignal.timeout(GH_REQUEST_TIMEOUT_MS) });
14278
+ return res.status === 404;
14279
+ }
14280
+ };
14281
+ }
14282
+
14283
+ // src/lib/brain-repo-collision.ts
14284
+ init_errors();
14285
+ var DEFAULT_MAX_ATTEMPTS = 20;
14286
+ function actionForState(state) {
14287
+ switch (state) {
14288
+ case "absent":
14289
+ return "create";
14290
+ case "m8t-brain":
14291
+ return "reuse";
14292
+ case "empty":
14293
+ return "adopt";
14294
+ case "foreign":
14295
+ throw new LocalCliError({
14296
+ code: "FOREIGN_REPO_COLLISION",
14297
+ message: `A repo already exists but isn't an m8t brain.`
14298
+ });
14299
+ }
14300
+ }
14301
+ function candidate(base, n) {
14302
+ return n === 1 ? base : `${base}-${n.toString()}`;
14303
+ }
14304
+ async function scan(base, classify, accept, startAt, maxAttempts) {
14305
+ for (let n = startAt; n <= maxAttempts; n++) {
14306
+ const name = candidate(base, n);
14307
+ const state = await classify(name);
14308
+ if (accept(state)) return { repoName: name, state };
14309
+ }
14310
+ throw new LocalCliError({
14311
+ code: "REPO_NAME_SCAN_EXHAUSTED",
14312
+ message: `Could not find a free repo name for "${base}" after ${maxAttempts.toString()} attempts.`
14313
+ });
14314
+ }
14315
+ async function resolveRepoCollision(args) {
14316
+ const max = args.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
14317
+ const state = await args.classify(args.repoName);
14318
+ if (args.force === "new") {
14319
+ const found = await scan(args.repoName, args.classify, (s) => s === "absent", 1, max);
14320
+ return { repoName: found.repoName, action: "create" };
14321
+ }
14322
+ if (args.force === "reuse") {
14323
+ return { repoName: args.repoName, action: actionForState(state) };
14324
+ }
14325
+ if (state === "absent") return { repoName: args.repoName, action: "create" };
14326
+ if (args.interactive && args.prompt) {
14327
+ const choice = await args.prompt({ repoName: args.repoName, state });
14328
+ if (choice === "abort") {
14329
+ throw new LocalCliError({ code: "BRAIN_CREATE_ABORTED", message: "Aborted by the operator." });
14330
+ }
14331
+ if (choice === "new") {
14332
+ const found = await scan(args.repoName, args.classify, (s) => s !== "foreign", 2, max);
14333
+ return { repoName: found.repoName, action: actionForState(found.state) };
14334
+ }
14335
+ return { repoName: args.repoName, action: actionForState(state) };
14336
+ }
14337
+ if (state === "foreign") {
14338
+ throw new LocalCliError({
14339
+ code: "FOREIGN_REPO_COLLISION",
14340
+ message: `A repo with this name already exists but isn't an m8t brain, so it won't be touched. Rename that repo or install into a different org, then re-run.`
14341
+ });
14342
+ }
14343
+ return { repoName: args.repoName, action: actionForState(state) };
14344
+ }
14198
14345
 
14199
14346
  // src/commands/brain/create.ts
14347
+ async function promptCollision(ctx, info) {
14348
+ const rl = readline2.createInterface({ input: ctx.stdin, output: ctx.stdout });
14349
+ try {
14350
+ if (info.state === "foreign") {
14351
+ const ans2 = (await rl.question(
14352
+ `A repo "${info.repoName}" already exists but isn't an m8t brain. Create a new "${info.repoName}-2" instead? [Y/n] (n aborts) `
14353
+ )).trim().toLowerCase();
14354
+ return ans2 === "" || ans2 === "y" || ans2 === "yes" ? "new" : "abort";
14355
+ }
14356
+ const ans = (await rl.question(
14357
+ `An m8t brain "${info.repoName}" already exists. Reuse it? [Y/n] (n creates "${info.repoName}-2", or "a" aborts) `
14358
+ )).trim().toLowerCase();
14359
+ if (ans === "" || ans === "y" || ans === "yes") return "reuse";
14360
+ if (ans === "a" || ans === "abort") return "abort";
14361
+ return "new";
14362
+ } finally {
14363
+ rl.close();
14364
+ }
14365
+ }
14200
14366
  function stageAsGitRepo(dir) {
14201
14367
  const steps = [
14202
14368
  { args: ["init", "-b", "main"], label: "git init" },
@@ -14239,6 +14405,8 @@ var BrainCreateCommand = class extends M8tCommand {
14239
14405
  appId = Option17.String("--app-id", { description: "GitHub App id (no-gh path); with --app-pem/--installation-id, create the repo via the App instead of gh." });
14240
14406
  appPem = Option17.String("--app-pem", { description: "Path to the App private-key PEM (no-gh path)." });
14241
14407
  installationId = Option17.String("--installation-id", { description: "Org installation id for the App (no-gh path)." });
14408
+ reuse = Option17.Boolean("--reuse", false, { description: "If the brain repo already exists, reuse it (non-interactive). Errors if the repo isn't a valid m8t brain." });
14409
+ newName = Option17.Boolean("--new", false, { description: "If the brain repo name is taken, create a fresh suffixed repo (e.g. <name>-2) instead of reusing." });
14242
14410
  async executeCommand() {
14243
14411
  const owner = typeof this.owner === "string" ? this.owner : void 0;
14244
14412
  const worker = typeof this.worker === "string" ? this.worker : void 0;
@@ -14303,59 +14471,95 @@ var BrainCreateCommand = class extends M8tCommand {
14303
14471
  const tmpDir = fs10.mkdtempSync(path9.join(os4.tmpdir(), `m8t-brain-create-${worker}-`));
14304
14472
  let result;
14305
14473
  let resolvedInstallationId = null;
14474
+ const force = this.reuse === true ? "reuse" : this.newName === true ? "new" : void 0;
14475
+ const interactive = !useAppPath && this.context.stdout.isTTY === true;
14476
+ let token;
14477
+ let classify;
14478
+ if (useAppPath) {
14479
+ token = await mintInstallationTokenFromPem({
14480
+ appId: appIdOpt,
14481
+ privateKeyPem: readFileSync6(appPemOpt, "utf8"),
14482
+ installationId: installationIdOpt
14483
+ });
14484
+ const tok = token;
14485
+ classify = (name) => probeRepoState(appRepoProbe({ token: tok, repo: `${owner}/${name}` }));
14486
+ } else {
14487
+ classify = (name) => probeRepoState(ghRepoProbe({ owner, repo: name }));
14488
+ }
14489
+ const decision = await resolveRepoCollision({
14490
+ repoName,
14491
+ classify,
14492
+ interactive,
14493
+ force,
14494
+ prompt: interactive ? (info) => promptCollision(
14495
+ { stdin: this.context.stdin, stdout: this.context.stdout },
14496
+ info
14497
+ ) : void 0
14498
+ });
14499
+ const finalName = decision.repoName;
14500
+ const needsPush = decision.action === "create" || decision.action === "adopt";
14501
+ if (finalName !== repoName) {
14502
+ this.context.stdout.write(`${colors.hint("note:")} using repo name ${colors.field(finalName)} (${decision.action}).
14503
+ `);
14504
+ }
14306
14505
  try {
14307
- materializeBrainTree({ templateSrc, destDir: tmpDir, seedDir });
14308
- this.context.stdout.write(
14309
- seedName ? `${colors.dim("\u2192")} copied brain-template/ + overlaid seed ${colors.field(seedName)} to ${tmpDir}
14506
+ if (needsPush) {
14507
+ materializeBrainTree({ templateSrc, destDir: tmpDir, seedDir });
14508
+ this.context.stdout.write(
14509
+ seedName ? `${colors.dim("\u2192")} copied brain-template/ + overlaid seed ${colors.field(seedName)} to ${tmpDir}
14310
14510
  ` : `${colors.dim("\u2192")} copied brain-template/ to ${tmpDir}
14311
14511
  `
14312
- );
14512
+ );
14513
+ }
14313
14514
  if (useAppPath) {
14314
- this.context.stdout.write(`${colors.dim("\u2192")} creating ${owner}/${repoName} via the GitHub App (no gh)\u2026
14515
+ const appToken = token ?? "";
14516
+ if (decision.action === "create") {
14517
+ this.context.stdout.write(`${colors.dim("\u2192")} creating ${owner}/${finalName} via the GitHub App (no gh)\u2026
14518
+ `);
14519
+ await createBlankRepo({ token: appToken, org: owner, name: finalName, private: !this.public_ });
14520
+ await pushSeed({ token: appToken, org: owner, name: finalName, branch, sourceDir: tmpDir });
14521
+ this.context.stdout.write(`${colors.success("\u2713")} repo created + seeded via the App
14522
+ `);
14523
+ } else if (decision.action === "adopt") {
14524
+ this.context.stdout.write(`${colors.dim("\u2192")} seeding the existing empty repo ${owner}/${finalName} via the GitHub App\u2026
14525
+ `);
14526
+ await pushSeed({ token: appToken, org: owner, name: finalName, branch, sourceDir: tmpDir });
14527
+ this.context.stdout.write(`${colors.success("\u2713")} empty repo seeded via the App
14528
+ `);
14529
+ } else {
14530
+ this.context.stdout.write(`${colors.success("\u2713")} reusing the existing brain ${owner}/${finalName}
14315
14531
  `);
14316
- const pem = readFileSync6(appPemOpt, "utf8");
14317
- const appJwt = signAppJwt({ appId: appIdOpt, privateKeyPem: pem });
14318
- const tokRes = await fetch(
14319
- `https://api.github.com/app/installations/${installationIdOpt}/access_tokens`,
14320
- {
14321
- method: "POST",
14322
- headers: {
14323
- Authorization: `Bearer ${appJwt}`,
14324
- Accept: "application/vnd.github+json",
14325
- "X-GitHub-Api-Version": "2022-11-28",
14326
- "User-Agent": "m8t"
14327
- }
14328
- }
14329
- );
14330
- if (!tokRes.ok) {
14331
- throw new LocalCliError({
14332
- code: "GH_APP_TOKEN_FAILED",
14333
- message: `mint installation token HTTP ${tokRes.status.toString()}: ${(await tokRes.text()).slice(0, 300)}`
14334
- });
14335
14532
  }
14336
- const token = (await tokRes.json()).token;
14337
- await createBlankRepo({ token, org: owner, name: repoName, private: !this.public_ });
14338
- await pushSeed({ token, org: owner, name: repoName, branch, sourceDir: tmpDir });
14339
14533
  resolvedInstallationId = installationIdOpt;
14340
- this.context.stdout.write(`${colors.success("\u2713")} repo created + seeded via the App
14341
- `);
14342
14534
  } else {
14343
- stageAsGitRepo(tmpDir);
14344
- this.context.stdout.write(`${colors.dim("\u2192")} creating repo ${owner}/${repoName} (${this.public_ ? "public" : "private"})\u2026
14535
+ if (decision.action === "create") {
14536
+ stageAsGitRepo(tmpDir);
14537
+ this.context.stdout.write(`${colors.dim("\u2192")} creating repo ${owner}/${finalName} (${this.public_ ? "public" : "private"})\u2026
14538
+ `);
14539
+ await createRepo({ owner, name: finalName, private: !this.public_, source: tmpDir });
14540
+ this.context.stdout.write(`${colors.success("\u2713")} repo created
14541
+ `);
14542
+ } else if (decision.action === "adopt") {
14543
+ this.context.stdout.write(`${colors.dim("\u2192")} seeding the existing empty repo ${owner}/${finalName}\u2026
14345
14544
  `);
14346
- await createRepo({ owner, name: repoName, private: !this.public_, source: tmpDir });
14347
- this.context.stdout.write(`${colors.success("\u2713")} repo created
14545
+ const ghToken = await getGhToken();
14546
+ await pushSeed({ token: ghToken, org: owner, name: finalName, branch, sourceDir: tmpDir });
14547
+ this.context.stdout.write(`${colors.success("\u2713")} empty repo seeded
14348
14548
  `);
14349
- const repoId = await getRepoId(owner, repoName);
14549
+ } else {
14550
+ this.context.stdout.write(`${colors.success("\u2713")} reusing the existing brain ${owner}/${finalName}
14551
+ `);
14552
+ }
14553
+ const repoId = await getRepoId(owner, finalName);
14350
14554
  const { slug, appId: secretAppId, privateKeyPem } = await readAppSecrets({ credential: credential2, kvUri });
14351
14555
  const initialJwt = signAppJwt({ appId: secretAppId, privateKeyPem });
14352
- resolvedInstallationId = await probeAppInstallation({ owner, repo: repoName, jwt: initialJwt });
14556
+ resolvedInstallationId = await probeAppInstallation({ owner, repo: finalName, jwt: initialJwt });
14353
14557
  if (resolvedInstallationId) {
14354
- this.context.stdout.write(` ${colors.success("\u2713")} App already installed on ${colors.field(`${owner}/${repoName}`)} (installation ${resolvedInstallationId}); skipping browser open.
14558
+ this.context.stdout.write(` ${colors.success("\u2713")} App already installed on ${colors.field(`${owner}/${finalName}`)} (installation ${resolvedInstallationId}); skipping browser open.
14355
14559
  `);
14356
14560
  } else {
14357
14561
  const url = installUrl(slug, repoId);
14358
- this.context.stdout.write(`${colors.field("\u2192")} Install the m8t-brain App on ${owner}/${repoName}:
14562
+ this.context.stdout.write(`${colors.field("\u2192")} Install the m8t-brain App on ${owner}/${finalName}:
14359
14563
  ${url}
14360
14564
  `);
14361
14565
  await tryOpenUrl(url);
@@ -14363,10 +14567,10 @@ var BrainCreateCommand = class extends M8tCommand {
14363
14567
  `);
14364
14568
  resolvedInstallationId = await pollForInstallation({
14365
14569
  owner,
14366
- repo: repoName,
14570
+ repo: finalName,
14367
14571
  // Mint fresh JWT each tick — App JWTs are 10-min TTL, poll defaults to 5 min
14368
14572
  // but the timeout is a soft default, so don't depend on the inequality.
14369
- probe: () => probeAppInstallation({ owner, repo: repoName, jwt: signAppJwt({ appId: secretAppId, privateKeyPem }) }),
14573
+ probe: () => probeAppInstallation({ owner, repo: finalName, jwt: signAppJwt({ appId: secretAppId, privateKeyPem }) }),
14370
14574
  onTick: (n) => {
14371
14575
  if (n % 5 === 0) this.context.stderr.write(` ${colors.dim(`\u2026still waiting (${(n * 2).toString()}s)`)}
14372
14576
  `);
@@ -14382,7 +14586,7 @@ var BrainCreateCommand = class extends M8tCommand {
14382
14586
  projectEndpoint: project.endpoint,
14383
14587
  projectArmId: `${project.accountScope}/projects/${project.projectName}`,
14384
14588
  agentName: worker,
14385
- repo: `${owner}/${repoName}`,
14589
+ repo: `${owner}/${finalName}`,
14386
14590
  branch,
14387
14591
  repoRoot,
14388
14592
  installationId: resolvedInstallationId,
@@ -14396,7 +14600,7 @@ var BrainCreateCommand = class extends M8tCommand {
14396
14600
  this.context.stdout.write(
14397
14601
  renderJson({
14398
14602
  worker,
14399
- repo: `${owner}/${repoName}`,
14603
+ repo: `${owner}/${finalName}`,
14400
14604
  branch,
14401
14605
  installationId: resolvedInstallationId,
14402
14606
  connectionName: result.connectionName,
@@ -14406,10 +14610,10 @@ var BrainCreateCommand = class extends M8tCommand {
14406
14610
  return 0;
14407
14611
  }
14408
14612
  this.context.stdout.write(
14409
- `${colors.success("\u2713")} created + linked ${colors.field(worker)} \u2194 ${colors.field(`${owner}/${repoName}`)} (agent version ${result.foundryVersion ?? ""}).
14613
+ `${colors.success("\u2713")} created + linked ${colors.field(worker)} \u2194 ${colors.field(`${owner}/${finalName}`)} (agent version ${result.foundryVersion ?? ""}).
14410
14614
  `
14411
14615
  );
14412
- this.context.stdout.write(` ${colors.hint("brain repo:")} https://github.com/${owner}/${repoName}
14616
+ this.context.stdout.write(` ${colors.hint("brain repo:")} https://github.com/${owner}/${finalName}
14413
14617
  `);
14414
14618
  this.context.stdout.write(` ${colors.hint("token:")} rotates lazily on every invoke (60min TTL, 10min safety margin).
14415
14619
  `);
@@ -15010,7 +15214,7 @@ init_errors();
15010
15214
  // src/lib/deploy-prompt-advisor.ts
15011
15215
  import * as fs12 from "fs";
15012
15216
  import * as path11 from "path";
15013
- import { parse as parseYaml5 } from "yaml";
15217
+ import { parse as parseYaml6 } from "yaml";
15014
15218
  init_foundry_agents();
15015
15219
  init_errors();
15016
15220
  function findPersonasRoot(hint) {
@@ -15038,7 +15242,7 @@ async function deployPromptAdvisor(args) {
15038
15242
  });
15039
15243
  }
15040
15244
  const fmMatch = /^---\n([\s\S]*?)\n---/.exec(raw);
15041
- const fm = fmMatch ? parseYaml5(fmMatch[1]) : {};
15245
+ const fm = fmMatch ? parseYaml6(fmMatch[1]) : {};
15042
15246
  const model = args.model ?? fm.targets?.foundry?.model;
15043
15247
  if (!model) {
15044
15248
  throw new LocalCliError({
@@ -15305,7 +15509,7 @@ async function awaitAgentQueryable(args) {
15305
15509
  init_errors();
15306
15510
  init_esm();
15307
15511
  import * as fs13 from "fs";
15308
- import { parse as parseYaml6 } from "yaml";
15512
+ import { parse as parseYaml7 } from "yaml";
15309
15513
  function readPersonaA2aCard(personaPath) {
15310
15514
  let raw;
15311
15515
  try {
@@ -15315,7 +15519,7 @@ function readPersonaA2aCard(personaPath) {
15315
15519
  }
15316
15520
  const fm = /^---\n([\s\S]*?)\n---/.exec(raw);
15317
15521
  if (!fm) throw new LocalCliError({ code: "PERSONA_NO_FRONTMATTER", message: `Persona '${personaPath}' has no frontmatter.` });
15318
- const front = parseYaml6(fm[1]);
15522
+ const front = parseYaml7(fm[1]);
15319
15523
  const role = typeof front.role === "string" ? front.role : "";
15320
15524
  const cardYaml = front.targets?.foundry?.["a2a-card"];
15321
15525
  if (!cardYaml || typeof cardYaml !== "object") {
@@ -15801,7 +16005,7 @@ init_errors();
15801
16005
  import * as fs15 from "fs";
15802
16006
  import * as os6 from "os";
15803
16007
  import * as path12 from "path";
15804
- import { parse as parseYaml7 } from "yaml";
16008
+ import { parse as parseYaml8 } from "yaml";
15805
16009
  var A2A_PATH = "/api/a2a/mcp";
15806
16010
  function resolveBridgeUrl(opts) {
15807
16011
  const env = opts.env ?? process.env;
@@ -15825,7 +16029,7 @@ function readConfigGatewayUrl(home) {
15825
16029
  const cfg = path12.join(home ?? os6.homedir(), ".m8t-stack", "config.yaml");
15826
16030
  if (!fs15.existsSync(cfg)) return void 0;
15827
16031
  try {
15828
- const o = parseYaml7(fs15.readFileSync(cfg, "utf8"));
16032
+ const o = parseYaml8(fs15.readFileSync(cfg, "utf8"));
15829
16033
  return typeof o.gatewayUrl === "string" ? o.gatewayUrl : void 0;
15830
16034
  } catch {
15831
16035
  return void 0;
@@ -16327,7 +16531,7 @@ async function deployHostedWorker(args) {
16327
16531
  // src/lib/persona.ts
16328
16532
  import * as fs17 from "fs";
16329
16533
  import * as path15 from "path";
16330
- import { parse as parseYaml8 } from "yaml";
16534
+ import { parse as parseYaml9 } from "yaml";
16331
16535
  function findRepoRoot(startDir) {
16332
16536
  let dir = path15.resolve(startDir);
16333
16537
  for (; ; ) {
@@ -16351,7 +16555,7 @@ function resolvePersona(persona, cwd = process.cwd()) {
16351
16555
  if (!match) return { persona, personaVersion: null };
16352
16556
  let fm = null;
16353
16557
  try {
16354
- fm = parseYaml8(match[1]);
16558
+ fm = parseYaml9(match[1]);
16355
16559
  } catch {
16356
16560
  return { persona, personaVersion: null };
16357
16561
  }
@@ -18256,9 +18460,9 @@ var EvalSkillCommand = class extends M8tCommand {
18256
18460
  return Promise.resolve(this._runCommand());
18257
18461
  }
18258
18462
  _runCommand() {
18259
- const candidate = typeof this.candidate === "string" ? this.candidate : void 0;
18463
+ const candidate2 = typeof this.candidate === "string" ? this.candidate : void 0;
18260
18464
  const skillsDir = typeof this.skillsDir === "string" ? this.skillsDir : void 0;
18261
- if (!candidate) {
18465
+ if (!candidate2) {
18262
18466
  throw new LocalCliError({ code: "USAGE", message: "<path> positional argument is required" });
18263
18467
  }
18264
18468
  if (!skillsDir) {
@@ -18267,7 +18471,7 @@ var EvalSkillCommand = class extends M8tCommand {
18267
18471
  const outputFlag = this.output === "json" || this.output === "auto" || this.output === "pretty" ? this.output : "pretty";
18268
18472
  const mode = resolveOutputMode(outputFlag, this.context.stdout);
18269
18473
  const bin = process.env.BRAIN_EVAL_BIN ?? "brain-eval";
18270
- const args = ["skill", candidate, "--skills-dir", skillsDir, "--json"];
18474
+ const args = ["skill", candidate2, "--skills-dir", skillsDir, "--json"];
18271
18475
  if (this.noJudge === true) args.push("--no-judge");
18272
18476
  if (typeof this.deployment === "string") args.push("--deployment", this.deployment);
18273
18477
  const res = spawnSync3(bin, args, { encoding: "utf-8" });
@@ -19256,7 +19460,7 @@ import { Command as Command41, Option as Option39 } from "clipanion";
19256
19460
  // src/lib/profiles.ts
19257
19461
  import * as fs20 from "fs/promises";
19258
19462
  import * as path21 from "path";
19259
- import { parse as parseYaml9, stringify as stringifyYaml4 } from "yaml";
19463
+ import { parse as parseYaml10, stringify as stringifyYaml4 } from "yaml";
19260
19464
  function profilesDir() {
19261
19465
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
19262
19466
  return path21.join(home, ".m8t-stack", "profiles");
@@ -19281,7 +19485,7 @@ async function listProfiles() {
19281
19485
  async function readProfile(name) {
19282
19486
  try {
19283
19487
  const raw = await fs20.readFile(getProfilePath(name), "utf8");
19284
- const parsed = parseYaml9(raw);
19488
+ const parsed = parseYaml10(raw);
19285
19489
  if (!parsed || typeof parsed !== "object") return null;
19286
19490
  return parsed;
19287
19491
  } catch (e) {
@@ -20451,16 +20655,16 @@ function buildAdvancePlan(worker, cursor, physicalPks, consumedRowsByPk, failedT
20451
20655
  for (const pk of physicalPks) {
20452
20656
  const rowsForPk = consumedRowsByPk[pk] ?? [];
20453
20657
  const { ts, consumedRowKeys } = computeWatermark(rowsForPk, now.toISOString(), safetyLagSeconds);
20454
- let candidate = ts;
20658
+ let candidate2 = ts;
20455
20659
  const prior = Object.hasOwn(cursor.watermarks, pk) ? cursor.watermarks[pk].ts : void 0;
20456
20660
  if (prior)
20457
20661
  priorTsByPk[pk] = prior;
20458
- if (prior && candidate < prior)
20459
- candidate = prior;
20662
+ if (prior && candidate2 < prior)
20663
+ candidate2 = prior;
20460
20664
  const failed = failedTsByPk[pk];
20461
- if (failed && candidate >= failed)
20462
- candidate = justBefore(failed);
20463
- watermarks[pk] = { ts: candidate, consumedRowKeys };
20665
+ if (failed && candidate2 >= failed)
20666
+ candidate2 = justBefore(failed);
20667
+ watermarks[pk] = { ts: candidate2, consumedRowKeys };
20464
20668
  consumedKeysByPk[pk] = consumedRowKeys;
20465
20669
  }
20466
20670
  return {
@@ -20854,12 +21058,12 @@ function validateDelta(d) {
20854
21058
  }
20855
21059
  function extractJson(text) {
20856
21060
  const fenced = /```(?:json)?\s*([\s\S]*?)```/.exec(text);
20857
- const candidate = (fenced ? fenced[1] : text).trim();
20858
- const start = candidate.indexOf("{");
20859
- const end = candidate.lastIndexOf("}");
21061
+ const candidate2 = (fenced ? fenced[1] : text).trim();
21062
+ const start = candidate2.indexOf("{");
21063
+ const end = candidate2.lastIndexOf("}");
20860
21064
  if (start === -1 || end === -1 || end < start)
20861
21065
  throw new Error("no JSON object found");
20862
- return JSON.parse(candidate.slice(start, end + 1));
21066
+ return JSON.parse(candidate2.slice(start, end + 1));
20863
21067
  }
20864
21068
  async function propose(model, system, user, opts = {}) {
20865
21069
  const sleep2 = opts.sleep ?? defaultSleep2;
@@ -21439,14 +21643,14 @@ function narrowAdvance(src, kept) {
21439
21643
  for (const pk of Object.keys(src.watermarks)) {
21440
21644
  const rows = keptRowsByPk[pk] ?? [];
21441
21645
  const { ts, consumedRowKeys } = computeWatermark(rows, now, safetyLagSeconds);
21442
- let candidate = ts;
21646
+ let candidate2 = ts;
21443
21647
  const prior = priorTsByPk[pk];
21444
- if (prior && candidate < prior)
21445
- candidate = prior;
21648
+ if (prior && candidate2 < prior)
21649
+ candidate2 = prior;
21446
21650
  const failed = src.failedTsByPk[pk];
21447
- if (failed && candidate >= failed)
21448
- candidate = justBefore(failed);
21449
- watermarks[pk] = { ts: candidate, consumedRowKeys };
21651
+ if (failed && candidate2 >= failed)
21652
+ candidate2 = justBefore(failed);
21653
+ watermarks[pk] = { ts: candidate2, consumedRowKeys };
21450
21654
  consumedRowsByPk[pk] = consumedRowKeys;
21451
21655
  }
21452
21656
  return {
@@ -21548,7 +21752,7 @@ async function emitDigest(input, deps, digest) {
21548
21752
  }
21549
21753
 
21550
21754
  // ../../packages/brain/engine/dist/esm/dream/config.js
21551
- import { parse as parseYaml10 } from "yaml";
21755
+ import { parse as parseYaml11 } from "yaml";
21552
21756
  var DEFAULT_DREAM_MODEL = "gpt-5.4";
21553
21757
  function asCadence(v) {
21554
21758
  return v === "nightly" ? "nightly" : "off";
@@ -21556,7 +21760,7 @@ function asCadence(v) {
21556
21760
  function parseDreamerConfig(rawYaml, env) {
21557
21761
  let parsed;
21558
21762
  try {
21559
- parsed = parseYaml10(rawYaml);
21763
+ parsed = parseYaml11(rawYaml);
21560
21764
  } catch {
21561
21765
  return { enabled: false, cadence: "off", model: env.M8T_DREAM_MODEL ?? DEFAULT_DREAM_MODEL };
21562
21766
  }
@@ -21570,16 +21774,16 @@ function parseDreamerConfig(rawYaml, env) {
21570
21774
  }
21571
21775
 
21572
21776
  // ../../packages/brain/engine/dist/esm/cost-report/config.js
21573
- import { parse as parseYaml11 } from "yaml";
21777
+ import { parse as parseYaml12 } from "yaml";
21574
21778
 
21575
21779
  // ../../packages/brain/engine/dist/esm/librarian/codify/persistence-guard.js
21576
21780
  var ZERO_WIDTH_RE = new RegExp("\u200B|\u200C|\u200D|\uFEFF", "g");
21577
21781
 
21578
21782
  // ../../packages/brain/engine/dist/esm/librarian/janitor/frontmatter.js
21579
- import { parse as parseYaml12, stringify as stringifyYaml5 } from "yaml";
21783
+ import { parse as parseYaml13, stringify as stringifyYaml5 } from "yaml";
21580
21784
 
21581
21785
  // ../../packages/brain/engine/dist/esm/librarian/config.js
21582
- import { parse as parseYaml13 } from "yaml";
21786
+ import { parse as parseYaml14 } from "yaml";
21583
21787
 
21584
21788
  // src/lib/dream-discovery.ts
21585
21789
  init_http();