@m8t-stack/cli 0.2.82 → 0.2.83

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
@@ -1467,7 +1467,7 @@ var init_enable_hosted_brain = __esm({
1467
1467
  import { Builtins, Cli } from "clipanion";
1468
1468
 
1469
1469
  // src/lib/package-version.ts
1470
- var CLI_VERSION = "0.2.82";
1470
+ var CLI_VERSION = "0.2.83";
1471
1471
 
1472
1472
  // src/lib/render-error.ts
1473
1473
  init_errors();
@@ -28892,21 +28892,28 @@ var ARM4 = "https://management.azure.com";
28892
28892
  var ARM_SCOPE8 = "https://management.azure.com/.default";
28893
28893
  var STORAGE_API2 = "2023-05-01";
28894
28894
  var LA_API = "2023-09-01";
28895
+ var tagOf = (a, key2) => a.tags?.[key2] ?? a.properties?.tags?.[key2];
28896
+ function selectLedgerAccount(accounts, storageAccount) {
28897
+ if (storageAccount) return accounts.find((a) => a.name === storageAccount);
28898
+ const managed = accounts.filter((a) => tagOf(a, "managedBy") === "m8t");
28899
+ return managed.find((a) => tagOf(a, "m8t") === "storage") ?? managed.at(0) ?? accounts.find((a) => tagOf(a, "m8t:role") === "ledger") ?? (accounts.length === 1 ? accounts[0] : void 0);
28900
+ }
28895
28901
  async function discoverLedgerResources(opts) {
28896
- const { credential: credential2, subscriptionId, resourceGroup } = opts;
28902
+ const { credential: credential2, subscriptionId, resourceGroup, storageAccount } = opts;
28897
28903
  const storage = await authedJsonPagedValues({
28898
28904
  credential: credential2,
28899
28905
  scope: ARM_SCOPE8,
28900
28906
  url: `${ARM4}/subscriptions/${subscriptionId}/resourceGroups/${resourceGroup}/providers/Microsoft.Storage/storageAccounts?api-version=${STORAGE_API2}`
28901
28907
  });
28902
28908
  const accounts = storage.filter((a) => a.properties?.primaryEndpoints?.table);
28903
- const ledgerAcct = accounts.find((a) => (a.tags?.["m8t:role"] ?? a.properties?.tags?.["m8t:role"]) === "ledger") ?? (accounts.length === 1 ? accounts[0] : void 0);
28909
+ const ledgerAcct = selectLedgerAccount(accounts, storageAccount);
28904
28910
  const ledgerTableEndpoint = ledgerAcct?.properties?.primaryEndpoints?.table?.replace(/\/$/, "");
28905
28911
  if (!ledgerTableEndpoint) {
28912
+ const found = accounts.map((a) => a.name).join(", ") || "(none)";
28906
28913
  throw new LocalCliError({
28907
28914
  code: "DREAM_LEDGER_STORAGE_NOT_FOUND",
28908
- message: `No AgentLedger storage account found in resource group ${resourceGroup}.`,
28909
- hint: `Found: ${accounts.map((a) => a.name).join(", ") || "(none)"}. Tag the ledger account 'm8t:role=ledger'.`
28915
+ message: storageAccount ? `Storage account '${storageAccount}' was not found in resource group ${resourceGroup}, or has no table endpoint.` : `No AgentLedger storage account found in resource group ${resourceGroup}.`,
28916
+ hint: `Found: ${found}. Pass --storage-account <name> to select one explicitly.`
28910
28917
  });
28911
28918
  }
28912
28919
  const ws = await authedJsonPagedValues({
@@ -28948,6 +28955,7 @@ async function resolveDreamContext(opts) {
28948
28955
  });
28949
28956
  const resourceGroup = rgFromScope(project.accountScope);
28950
28957
  const { ledgerTableEndpoint, workspaceId } = await discoverLedgerResources({
28958
+ storageAccount: opts.storageAccount,
28951
28959
  credential: credential2,
28952
28960
  subscriptionId,
28953
28961
  resourceGroup
@@ -29015,6 +29023,9 @@ var DreamRunCommand = class extends M8tCommand {
29015
29023
  });
29016
29024
  subscription = Option49.String("--subscription");
29017
29025
  endpoint = Option49.String("--endpoint");
29026
+ storageAccount = Option49.String("--storage-account", {
29027
+ description: "Ledger storage account name (skips tag-based discovery)"
29028
+ });
29018
29029
  output = Option49.String("--output");
29019
29030
  // Resolution seam — overridden by tests; built lazily at runtime otherwise.
29020
29031
  deps;
@@ -29032,7 +29043,8 @@ var DreamRunCommand = class extends M8tCommand {
29032
29043
  const liveContext = await liveDeps.resolveContext({
29033
29044
  worker,
29034
29045
  subscription: typeof this.subscription === "string" ? this.subscription : void 0,
29035
- endpoint: typeof this.endpoint === "string" ? this.endpoint : void 0
29046
+ endpoint: typeof this.endpoint === "string" ? this.endpoint : void 0,
29047
+ storageAccount: typeof this.storageAccount === "string" ? this.storageAccount : void 0
29036
29048
  });
29037
29049
  const liveCursor = await liveDeps.readCursor(liveContext.worker);
29038
29050
  const result2 = await liveDeps.runDream({
@@ -29079,7 +29091,8 @@ var DreamRunCommand = class extends M8tCommand {
29079
29091
  const context = await deps.resolveContext({
29080
29092
  worker,
29081
29093
  subscription: typeof this.subscription === "string" ? this.subscription : void 0,
29082
- endpoint: typeof this.endpoint === "string" ? this.endpoint : void 0
29094
+ endpoint: typeof this.endpoint === "string" ? this.endpoint : void 0,
29095
+ storageAccount: typeof this.storageAccount === "string" ? this.storageAccount : void 0
29083
29096
  });
29084
29097
  const now = /* @__PURE__ */ new Date();
29085
29098
  const cursor = await deps.readCursor(context.worker);
@@ -29429,13 +29442,28 @@ function defaultDeps2() {
29429
29442
  const { ledgerTableEndpoint } = await discoverLedgerResources({
29430
29443
  credential: credential2,
29431
29444
  subscriptionId,
29432
- resourceGroup: m[1]
29445
+ resourceGroup: m[1],
29446
+ storageAccount: opts.storageAccount
29433
29447
  });
29434
29448
  return { projectEndpoint: project.endpoint, ledgerTableEndpoint };
29435
29449
  },
29436
29450
  async fetchRows(ctx, fromIso, toIso) {
29437
29451
  const client = new TableClient8(ctx.ledgerTableEndpoint, LEDGER_TABLE_NAME2, credential2);
29438
- return fetchLedgerRows({ workers: [], source: "all", from: fromIso, to: toIso }, client);
29452
+ try {
29453
+ return await fetchLedgerRows({ workers: [], source: "all", from: fromIso, to: toIso }, client);
29454
+ } catch (e) {
29455
+ const msg = e instanceof Error ? e.message : String(e);
29456
+ if (statusOf2(e) === 403 || msg.includes("AuthorizationPermissionMismatch")) {
29457
+ const account = /https:\/\/([^.]+)\./.exec(ctx.ledgerTableEndpoint)?.[1] ?? "the ledger account";
29458
+ throw new LocalCliError({
29459
+ code: "sweep_ledger_forbidden",
29460
+ message: `Not authorized to read the ledger table on '${account}'.`,
29461
+ hint: `Reading table rows needs a data-plane role: grant 'Storage Table Data Reader' on that storage account to the signed-in identity (owning the account is not enough).`,
29462
+ cause: e
29463
+ });
29464
+ }
29465
+ throw e;
29466
+ }
29439
29467
  },
29440
29468
  async retrieveMetadata(ctx, conversationId) {
29441
29469
  try {
@@ -29506,6 +29534,9 @@ var ConversationsSweepCommand = class extends M8tCommand {
29506
29534
  });
29507
29535
  subscription = Option50.String("--subscription", { description: "Azure subscription id override" });
29508
29536
  endpoint = Option50.String("--endpoint", { description: "Foundry project endpoint override" });
29537
+ storageAccount = Option50.String("--storage-account", {
29538
+ description: "Ledger storage account name (skips tag-based discovery)"
29539
+ });
29509
29540
  deps = defaultDeps2();
29510
29541
  async executeCommand() {
29511
29542
  const out = this.context.stdout;
@@ -29522,7 +29553,11 @@ var ConversationsSweepCommand = class extends M8tCommand {
29522
29553
  const cutoffIso = new Date(now - retentionDays * DAY_MS).toISOString();
29523
29554
  const fromIso = new Date(now - lookback * DAY_MS).toISOString();
29524
29555
  const toIso = new Date(now).toISOString();
29525
- const ctx = await this.deps.resolveContext({ subscription: this.subscription, endpoint: this.endpoint });
29556
+ const ctx = await this.deps.resolveContext({
29557
+ subscription: this.subscription,
29558
+ endpoint: this.endpoint,
29559
+ storageAccount: this.storageAccount
29560
+ });
29526
29561
  out.write(`Scanning ledger activity ${fromIso} \u2192 ${toIso}; retention cutoff ${cutoffIso}.
29527
29562
  `);
29528
29563
  const rows = await this.deps.fetchRows(ctx, fromIso, toIso);