mlclaw 0.4.7 → 0.4.8

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/mlclaw.mjs CHANGED
@@ -1202,8 +1202,8 @@ var require_command = __commonJS({
1202
1202
  "node_modules/commander/lib/command.js"(exports) {
1203
1203
  var EventEmitter = __require("node:events").EventEmitter;
1204
1204
  var childProcess = __require("node:child_process");
1205
- var path17 = __require("node:path");
1206
- var fs17 = __require("node:fs");
1205
+ var path16 = __require("node:path");
1206
+ var fs16 = __require("node:fs");
1207
1207
  var process5 = __require("node:process");
1208
1208
  var { Argument: Argument2, humanReadableArgName } = require_argument();
1209
1209
  var { CommanderError: CommanderError2 } = require_error();
@@ -2197,7 +2197,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2197
2197
  * @param {string} subcommandName
2198
2198
  */
2199
2199
  _checkForMissingExecutable(executableFile, executableDir, subcommandName) {
2200
- if (fs17.existsSync(executableFile)) return;
2200
+ if (fs16.existsSync(executableFile)) return;
2201
2201
  const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory";
2202
2202
  const executableMissing = `'${executableFile}' does not exist
2203
2203
  - if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
@@ -2215,11 +2215,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
2215
2215
  let launchWithNode = false;
2216
2216
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
2217
2217
  function findFile(baseDir, baseName) {
2218
- const localBin = path17.resolve(baseDir, baseName);
2219
- if (fs17.existsSync(localBin)) return localBin;
2220
- if (sourceExt.includes(path17.extname(baseName))) return void 0;
2218
+ const localBin = path16.resolve(baseDir, baseName);
2219
+ if (fs16.existsSync(localBin)) return localBin;
2220
+ if (sourceExt.includes(path16.extname(baseName))) return void 0;
2221
2221
  const foundExt = sourceExt.find(
2222
- (ext) => fs17.existsSync(`${localBin}${ext}`)
2222
+ (ext) => fs16.existsSync(`${localBin}${ext}`)
2223
2223
  );
2224
2224
  if (foundExt) return `${localBin}${foundExt}`;
2225
2225
  return void 0;
@@ -2231,21 +2231,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
2231
2231
  if (this._scriptPath) {
2232
2232
  let resolvedScriptPath;
2233
2233
  try {
2234
- resolvedScriptPath = fs17.realpathSync(this._scriptPath);
2234
+ resolvedScriptPath = fs16.realpathSync(this._scriptPath);
2235
2235
  } catch {
2236
2236
  resolvedScriptPath = this._scriptPath;
2237
2237
  }
2238
- executableDir = path17.resolve(
2239
- path17.dirname(resolvedScriptPath),
2238
+ executableDir = path16.resolve(
2239
+ path16.dirname(resolvedScriptPath),
2240
2240
  executableDir
2241
2241
  );
2242
2242
  }
2243
2243
  if (executableDir) {
2244
2244
  let localFile = findFile(executableDir, executableFile);
2245
2245
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
2246
- const legacyName = path17.basename(
2246
+ const legacyName = path16.basename(
2247
2247
  this._scriptPath,
2248
- path17.extname(this._scriptPath)
2248
+ path16.extname(this._scriptPath)
2249
2249
  );
2250
2250
  if (legacyName !== this._name) {
2251
2251
  localFile = findFile(
@@ -2256,7 +2256,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2256
2256
  }
2257
2257
  executableFile = localFile || executableFile;
2258
2258
  }
2259
- launchWithNode = sourceExt.includes(path17.extname(executableFile));
2259
+ launchWithNode = sourceExt.includes(path16.extname(executableFile));
2260
2260
  let proc;
2261
2261
  if (process5.platform !== "win32") {
2262
2262
  if (launchWithNode) {
@@ -3171,7 +3171,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
3171
3171
  * @return {Command}
3172
3172
  */
3173
3173
  nameFromFilename(filename) {
3174
- this._name = path17.basename(filename, path17.extname(filename));
3174
+ this._name = path16.basename(filename, path16.extname(filename));
3175
3175
  return this;
3176
3176
  }
3177
3177
  /**
@@ -3185,9 +3185,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
3185
3185
  * @param {string} [path]
3186
3186
  * @return {(string|null|Command)}
3187
3187
  */
3188
- executableDir(path18) {
3189
- if (path18 === void 0) return this._executableDir;
3190
- this._executableDir = path18;
3188
+ executableDir(path17) {
3189
+ if (path17 === void 0) return this._executableDir;
3190
+ this._executableDir = path17;
3191
3191
  return this;
3192
3192
  }
3193
3193
  /**
@@ -8952,7 +8952,7 @@ var init_cli = __esm({
8952
8952
  });
8953
8953
 
8954
8954
  // src/mlclaw/cli.ts
8955
- import fs16 from "node:fs/promises";
8955
+ import fs15 from "node:fs/promises";
8956
8956
  import { realpathSync } from "node:fs";
8957
8957
  import os8 from "node:os";
8958
8958
  import process4 from "node:process";
@@ -10124,10 +10124,10 @@ function parseGatewayLocation(value) {
10124
10124
 
10125
10125
  // src/mlclaw/git.ts
10126
10126
  import { execFile as execFile2 } from "node:child_process";
10127
- import fs13 from "node:fs/promises";
10127
+ import fs12 from "node:fs/promises";
10128
10128
  import os5 from "node:os";
10129
- import path14 from "node:path";
10130
- import { fileURLToPath as fileURLToPath3 } from "node:url";
10129
+ import path13 from "node:path";
10130
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
10131
10131
  import { promisify as promisify2 } from "node:util";
10132
10132
 
10133
10133
  // src/vendor/hfjs-xet/error.ts
@@ -13950,10 +13950,10 @@ var CurrentXorbInfo = class {
13950
13950
  hash: computeXorbHash(xorbChunksCleaned),
13951
13951
  chunks: xorbChunksCleaned,
13952
13952
  id: this.id,
13953
- files: Object.entries(this.fileProcessedBytes).map(([path17, processedBytes]) => ({
13954
- path: path17,
13955
- progress: processedBytes / this.fileSize[path17],
13956
- lastSentProgress: ((this.fileUploadedBytes[path17] ?? 0) + (processedBytes - (this.fileUploadedBytes[path17] ?? 0)) * PROCESSING_PROGRESS_RATIO) / this.fileSize[path17]
13953
+ files: Object.entries(this.fileProcessedBytes).map(([path16, processedBytes]) => ({
13954
+ path: path16,
13955
+ progress: processedBytes / this.fileSize[path16],
13956
+ lastSentProgress: ((this.fileUploadedBytes[path16] ?? 0) + (processedBytes - (this.fileUploadedBytes[path16] ?? 0)) * PROCESSING_PROGRESS_RATIO) / this.fileSize[path16]
13957
13957
  }))
13958
13958
  };
13959
13959
  }
@@ -14826,7 +14826,7 @@ var BucketClient = class {
14826
14826
  if (paths.length === 0) {
14827
14827
  return;
14828
14828
  }
14829
- await this.batch(paths.map((path17) => ({ type: "deleteFile", path: path17 })));
14829
+ await this.batch(paths.map((path16) => ({ type: "deleteFile", path: path16 })));
14830
14830
  }
14831
14831
  async batch(operations) {
14832
14832
  const body = `${operations.map((op) => JSON.stringify(op)).join("\n")}
@@ -14842,8 +14842,8 @@ var BucketClient = class {
14842
14842
  * any other failure (including bucket/auth errors), so a missing object is
14843
14843
  * never conflated with an unreachable bucket.
14844
14844
  */
14845
- async downloadFile(path17) {
14846
- const url = `${this.hubUrl}/buckets/${this.bucket}/resolve/${encodeURIComponent(path17)}`;
14845
+ async downloadFile(path16) {
14846
+ const url = `${this.hubUrl}/buckets/${this.bucket}/resolve/${encodeURIComponent(path16)}`;
14847
14847
  const response = await this.fetchWithRetry(url);
14848
14848
  if (response.status === 404) {
14849
14849
  await this.assertBucketAccessible();
@@ -14945,19 +14945,19 @@ var HubApi = class {
14945
14945
  async deploymentControlStore(owner, deploymentId) {
14946
14946
  const repoId = `${owner}/mlclaw-control-${deploymentId.replaceAll("-", "")}`;
14947
14947
  await this.ensurePrivateModelRepo(repoId);
14948
- const path17 = "control-lease.json";
14948
+ const path16 = "control-lease.json";
14949
14949
  return {
14950
- read: async () => await this.readModelDocument(repoId, path17),
14951
- compareAndSwap: async (expectedRevision, value) => await this.commitModelDocument(repoId, path17, expectedRevision, value)
14950
+ read: async () => await this.readModelDocument(repoId, path16),
14951
+ compareAndSwap: async (expectedRevision, value) => await this.commitModelDocument(repoId, path16, expectedRevision, value)
14952
14952
  };
14953
14953
  }
14954
14954
  async deploymentClaimStore(owner) {
14955
14955
  const repoId = `${owner}/mlclaw-control-claims`;
14956
14956
  await this.ensurePrivateModelRepo(repoId);
14957
- const path17 = "control-lease.json";
14957
+ const path16 = "control-lease.json";
14958
14958
  return {
14959
- read: async () => await this.readModelDocument(repoId, path17),
14960
- compareAndSwap: async (expectedRevision, value) => await this.commitModelDocument(repoId, path17, expectedRevision, value)
14959
+ read: async () => await this.readModelDocument(repoId, path16),
14960
+ compareAndSwap: async (expectedRevision, value) => await this.commitModelDocument(repoId, path16, expectedRevision, value)
14961
14961
  };
14962
14962
  }
14963
14963
  async createDockerSpace(repoId, options) {
@@ -15185,9 +15185,9 @@ var HubApi = class {
15185
15185
  encoding: "base64"
15186
15186
  }
15187
15187
  })),
15188
- ...(params.deletePaths ?? []).map((path17) => ({
15188
+ ...(params.deletePaths ?? []).map((path16) => ({
15189
15189
  key: "deletedFile",
15190
- value: { path: path17 }
15190
+ value: { path: path16 }
15191
15191
  }))
15192
15192
  ].map((entry) => JSON.stringify(entry)).join("\n");
15193
15193
  await this.request(`/api/spaces/${repoId}/commit/${encodeURIComponent(params.branch ?? "main")}`, {
@@ -15217,10 +15217,10 @@ var HubApi = class {
15217
15217
  if (info.sha) return;
15218
15218
  await this.commitModelDocument(repoId, "README.md", "", "# ML Claw deployment control\n");
15219
15219
  }
15220
- async readModelDocument(repoId, path17) {
15220
+ async readModelDocument(repoId, path16) {
15221
15221
  const info = await this.requestJson(`/api/models/${repoId}`);
15222
15222
  if (!info.sha) throw new Error(`control repository ${repoId} has no revision`);
15223
- const url = `${this.hubUrl}/${repoId}/resolve/${info.sha}/${path17.split("/").map(encodeURIComponent).join("/")}`;
15223
+ const url = `${this.hubUrl}/${repoId}/resolve/${info.sha}/${path16.split("/").map(encodeURIComponent).join("/")}`;
15224
15224
  const response = await this.fetchImpl(url, {
15225
15225
  headers: { Authorization: `Bearer ${this.token}` }
15226
15226
  });
@@ -15228,16 +15228,16 @@ var HubApi = class {
15228
15228
  if (!response.ok) throw new HubApiError2(response.status, url, await response.text());
15229
15229
  return { value: JSON.parse(await response.text()), revision: info.sha };
15230
15230
  }
15231
- async commitModelDocument(repoId, path17, parentCommit, value) {
15231
+ async commitModelDocument(repoId, path16, parentCommit, value) {
15232
15232
  const header = {
15233
15233
  summary: value === null ? "Release deployment control" : "Update deployment control",
15234
15234
  description: "ML Claw deployment reconciliation state"
15235
15235
  };
15236
15236
  if (parentCommit) header.parentCommit = parentCommit;
15237
- const operation = value === null ? { key: "deletedFile", value: { path: path17 } } : {
15237
+ const operation = value === null ? { key: "deletedFile", value: { path: path16 } } : {
15238
15238
  key: "file",
15239
15239
  value: {
15240
- path: path17,
15240
+ path: path16,
15241
15241
  content: Buffer.from(typeof value === "string" ? value : `${JSON.stringify(value, null, 2)}
15242
15242
  `).toString(
15243
15243
  "base64"
@@ -15381,21 +15381,22 @@ function nextLink(header) {
15381
15381
  return null;
15382
15382
  }
15383
15383
 
15384
+ // src/mlclaw/release-config.generated.ts
15385
+ var RELEASE_CONFIG = {
15386
+ "packageVersion": "0.4.8",
15387
+ "openclawVersion": "2026.7.1",
15388
+ "brokerkitVersion": "hf-broker/v0.4.2",
15389
+ "brokerkitPluginVersion": "0.3.4",
15390
+ "runtimeImageRepository": "ghcr.io/huggingface/mlclaw"
15391
+ };
15392
+
15384
15393
  // src/mlclaw/runtime-image.ts
15385
- import fs12 from "node:fs";
15386
- import path13 from "node:path";
15387
- import { fileURLToPath as fileURLToPath2 } from "node:url";
15388
- var DEFAULT_OPENCLAW_VERSION = "2026.7.1";
15389
- var DEFAULT_BROKERKIT_PLUGIN_VERSION = "0.3.3";
15390
- var DEFAULT_BROKERKIT_VERSION = "hf-broker/v0.4.0";
15391
- var DEFAULT_RUNTIME_IMAGE_REPOSITORY = "ghcr.io/huggingface/mlclaw";
15392
- var PACKAGE_METADATA = readPackageMetadata();
15393
- var PACKAGE_VERSION = packageString("version", "unknown");
15394
- var OPENCLAW_VERSION = packageConfigString("openclawVersion", DEFAULT_OPENCLAW_VERSION);
15394
+ var PACKAGE_VERSION = RELEASE_CONFIG.packageVersion;
15395
+ var OPENCLAW_VERSION = RELEASE_CONFIG.openclawVersion;
15395
15396
  var OPENCLAW_BASE_IMAGE = `ghcr.io/openclaw/openclaw:${OPENCLAW_VERSION}`;
15396
- var BROKERKIT_PLUGIN_VERSION = packageConfigString("brokerkitPluginVersion", DEFAULT_BROKERKIT_PLUGIN_VERSION);
15397
- var BROKERKIT_VERSION = packageConfigString("brokerkitVersion", DEFAULT_BROKERKIT_VERSION);
15398
- var RUNTIME_IMAGE_REPOSITORY = packageConfigString("runtimeImageRepository", DEFAULT_RUNTIME_IMAGE_REPOSITORY);
15397
+ var BROKERKIT_PLUGIN_VERSION = RELEASE_CONFIG.brokerkitPluginVersion;
15398
+ var BROKERKIT_VERSION = RELEASE_CONFIG.brokerkitVersion;
15399
+ var RUNTIME_IMAGE_REPOSITORY = RELEASE_CONFIG.runtimeImageRepository;
15399
15400
  var DEFAULT_RUNTIME_IMAGE_TAG = `${PACKAGE_VERSION}-openclaw-${OPENCLAW_VERSION}`;
15400
15401
  var DEFAULT_RUNTIME_IMAGE = `${RUNTIME_IMAGE_REPOSITORY}:${DEFAULT_RUNTIME_IMAGE_TAG}`;
15401
15402
  function resolveRuntimeImage(value, env = process.env) {
@@ -15413,45 +15414,16 @@ function resolveSpaceRuntimeImage(opts, env = process.env) {
15413
15414
  function bundledSpaceRuntimeRef(templateRev) {
15414
15415
  return `bundled:${templateRev}`;
15415
15416
  }
15416
- function packageString(key, fallback) {
15417
- const value = PACKAGE_METADATA[key];
15418
- return typeof value === "string" && value.trim() ? value.trim() : fallback;
15419
- }
15420
- function packageConfigString(key, fallback) {
15421
- const value = PACKAGE_METADATA.config?.[key];
15422
- return typeof value === "string" && value.trim() ? value.trim() : fallback;
15423
- }
15424
- function readPackageMetadata() {
15425
- let dir = path13.dirname(fileURLToPath2(import.meta.url));
15426
- while (true) {
15427
- const candidate = path13.join(dir, "package.json");
15428
- try {
15429
- return JSON.parse(fs12.readFileSync(candidate, "utf8"));
15430
- } catch (err) {
15431
- if (!isMissingFileError(err)) {
15432
- throw err;
15433
- }
15434
- }
15435
- const parent = path13.dirname(dir);
15436
- if (parent === dir) {
15437
- throw new Error("could not find package.json while resolving default runtime image");
15438
- }
15439
- dir = parent;
15440
- }
15441
- }
15442
- function isMissingFileError(err) {
15443
- return err instanceof Error && "code" in err && err.code === "ENOENT";
15444
- }
15445
15417
 
15446
15418
  // src/mlclaw/git.ts
15447
15419
  var execFileAsync2 = promisify2(execFile2);
15448
15420
  async function pushTemplateToSpace(params) {
15449
- const tempRoot = await fs13.mkdtemp(path14.join(os5.tmpdir(), "mlclaw-space-"));
15421
+ const tempRoot = await fs12.mkdtemp(path13.join(os5.tmpdir(), "mlclaw-space-"));
15450
15422
  try {
15451
15423
  const sourceDir = params.sourceDir ?? process.env.MLCLAW_SOURCE_DIR ?? await findPackagedSourceRoot();
15452
15424
  const templateRev = await currentTemplateRev(sourceDir);
15453
- const outDir = path14.join(tempRoot, "space");
15454
- await fs13.mkdir(outDir, { recursive: true });
15425
+ const outDir = path13.join(tempRoot, "space");
15426
+ await fs12.mkdir(outDir, { recursive: true });
15455
15427
  await generateSpaceRepo(sourceDir, outDir, {
15456
15428
  ...params.runtimeImage ? { runtimeImage: params.runtimeImage } : {}
15457
15429
  });
@@ -15469,7 +15441,7 @@ async function pushTemplateToSpace(params) {
15469
15441
  });
15470
15442
  return { templateRev };
15471
15443
  } finally {
15472
- await fs13.rm(tempRoot, { recursive: true, force: true });
15444
+ await fs12.rm(tempRoot, { recursive: true, force: true });
15473
15445
  }
15474
15446
  }
15475
15447
  async function currentTemplateRev(sourceDir) {
@@ -15482,7 +15454,7 @@ async function currentTemplateRev(sourceDir) {
15482
15454
  }
15483
15455
  } catch {
15484
15456
  }
15485
- const pkg = JSON.parse(await fs13.readFile(path14.join(sourceDir, "package.json"), "utf8"));
15457
+ const pkg = JSON.parse(await fs12.readFile(path13.join(sourceDir, "package.json"), "utf8"));
15486
15458
  return `npm:${pkg.name ?? "mlclaw"}@${pkg.version ?? "unknown"}`;
15487
15459
  }
15488
15460
  async function generateSpaceRepo(sourceDir, outDir, options = {}) {
@@ -15508,13 +15480,13 @@ async function generateSpaceRepo(sourceDir, outDir, options = {}) {
15508
15480
  );
15509
15481
  }
15510
15482
  for (const [from, to] of copies) {
15511
- await copyExisting(path14.join(sourceDir, from), path14.join(outDir, to));
15483
+ await copyExisting(path13.join(sourceDir, from), path13.join(outDir, to));
15512
15484
  }
15513
- const hfLogoPng = await fs13.readFile(path14.join(sourceDir, "assets/hf-logo.png"));
15514
- await fs13.writeFile(path14.join(outDir, "assets/hf-logo.png.base64"), `${hfLogoPng.toString("base64")}
15485
+ const hfLogoPng = await fs12.readFile(path13.join(sourceDir, "assets/hf-logo.png"));
15486
+ await fs12.writeFile(path13.join(outDir, "assets/hf-logo.png.base64"), `${hfLogoPng.toString("base64")}
15515
15487
  `, "utf8");
15516
- await fs13.writeFile(
15517
- path14.join(outDir, "Dockerfile"),
15488
+ await fs12.writeFile(
15489
+ path13.join(outDir, "Dockerfile"),
15518
15490
  options.runtimeImage ? imageDockerfile(options.runtimeImage) : bundledDockerfile(),
15519
15491
  "utf8"
15520
15492
  );
@@ -15602,13 +15574,13 @@ CMD ["/app/entrypoint.sh"]
15602
15574
  `;
15603
15575
  }
15604
15576
  async function findPackagedSourceRoot() {
15605
- const start = path14.dirname(fileURLToPath3(import.meta.url));
15577
+ const start = path13.dirname(fileURLToPath2(import.meta.url));
15606
15578
  let dir = start;
15607
15579
  while (true) {
15608
15580
  if (await hasPackagedSourceFiles(dir)) {
15609
15581
  return dir;
15610
15582
  }
15611
- const parent = path14.dirname(dir);
15583
+ const parent = path13.dirname(dir);
15612
15584
  if (parent === dir) {
15613
15585
  throw new Error("Could not find packaged ML Claw source files. Reinstall the mlclaw npm package.");
15614
15586
  }
@@ -15625,20 +15597,20 @@ async function hasPackagedSourceFiles(dir) {
15625
15597
  "src/hf-bucket-client/client.ts"
15626
15598
  ];
15627
15599
  try {
15628
- await Promise.all(required.map((file) => fs13.access(path14.join(dir, file))));
15600
+ await Promise.all(required.map((file) => fs12.access(path13.join(dir, file))));
15629
15601
  return true;
15630
15602
  } catch {
15631
15603
  return false;
15632
15604
  }
15633
15605
  }
15634
15606
  async function copyExisting(from, to) {
15635
- const stat = await fs13.stat(from);
15636
- await fs13.mkdir(path14.dirname(to), { recursive: true });
15607
+ const stat = await fs12.stat(from);
15608
+ await fs12.mkdir(path13.dirname(to), { recursive: true });
15637
15609
  if (stat.isDirectory()) {
15638
- await fs13.cp(from, to, { recursive: true });
15610
+ await fs12.cp(from, to, { recursive: true });
15639
15611
  } else {
15640
- await fs13.copyFile(from, to);
15641
- await fs13.chmod(to, stat.mode);
15612
+ await fs12.copyFile(from, to);
15613
+ await fs12.chmod(to, stat.mode);
15642
15614
  }
15643
15615
  }
15644
15616
  async function readFilesForCommit(root) {
@@ -15646,24 +15618,24 @@ async function readFilesForCommit(root) {
15646
15618
  for (const relativePath of await listFiles(root)) {
15647
15619
  files.push({
15648
15620
  path: relativePath,
15649
- content: await fs13.readFile(path14.join(root, relativePath))
15621
+ content: await fs12.readFile(path13.join(root, relativePath))
15650
15622
  });
15651
15623
  }
15652
15624
  return files;
15653
15625
  }
15654
15626
  async function listFiles(root, dir = "") {
15655
- const absoluteDir = path14.join(root, dir);
15656
- const entries = await fs13.readdir(absoluteDir, { withFileTypes: true });
15627
+ const absoluteDir = path13.join(root, dir);
15628
+ const entries = await fs12.readdir(absoluteDir, { withFileTypes: true });
15657
15629
  const files = [];
15658
15630
  for (const entry of entries) {
15659
- const relativePath = path14.posix.join(dir.split(path14.sep).join(path14.posix.sep), entry.name);
15660
- const absolutePath = path14.join(root, relativePath);
15631
+ const relativePath = path13.posix.join(dir.split(path13.sep).join(path13.posix.sep), entry.name);
15632
+ const absolutePath = path13.join(root, relativePath);
15661
15633
  if (entry.isDirectory()) {
15662
15634
  files.push(...await listFiles(root, relativePath));
15663
15635
  } else if (entry.isFile()) {
15664
15636
  files.push(relativePath);
15665
15637
  } else {
15666
- const stat = await fs13.stat(absolutePath);
15638
+ const stat = await fs12.stat(absolutePath);
15667
15639
  if (stat.isFile()) {
15668
15640
  files.push(relativePath);
15669
15641
  }
@@ -15742,9 +15714,9 @@ function deriveLocalAccessToken(sessionSecret) {
15742
15714
  }
15743
15715
 
15744
15716
  // src/mlclaw/local-config.ts
15745
- import fs14 from "node:fs/promises";
15717
+ import fs13 from "node:fs/promises";
15746
15718
  import os6 from "node:os";
15747
- import path15 from "node:path";
15719
+ import path14 from "node:path";
15748
15720
  import { createHash as createHash2 } from "node:crypto";
15749
15721
 
15750
15722
  // node_modules/zod/v3/external.js
@@ -16225,8 +16197,8 @@ function getErrorMap() {
16225
16197
 
16226
16198
  // node_modules/zod/v3/helpers/parseUtil.js
16227
16199
  var makeIssue = (params) => {
16228
- const { data, path: path17, errorMaps, issueData } = params;
16229
- const fullPath = [...path17, ...issueData.path || []];
16200
+ const { data, path: path16, errorMaps, issueData } = params;
16201
+ const fullPath = [...path16, ...issueData.path || []];
16230
16202
  const fullIssue = {
16231
16203
  ...issueData,
16232
16204
  path: fullPath
@@ -16342,11 +16314,11 @@ var errorUtil;
16342
16314
 
16343
16315
  // node_modules/zod/v3/types.js
16344
16316
  var ParseInputLazyPath = class {
16345
- constructor(parent, value, path17, key) {
16317
+ constructor(parent, value, path16, key) {
16346
16318
  this._cachedPath = [];
16347
16319
  this.parent = parent;
16348
16320
  this.data = value;
16349
- this._path = path17;
16321
+ this._path = path16;
16350
16322
  this._key = key;
16351
16323
  }
16352
16324
  get path() {
@@ -19852,7 +19824,7 @@ var manifestFields = {
19852
19824
  model: external_exports.string().min(1).max(512),
19853
19825
  runtimeImage: external_exports.string().min(1).max(1024),
19854
19826
  brokerCredential: external_exports.object({
19855
- profileId: external_exports.literal("hf-broker-complete-v1"),
19827
+ credentialKind: external_exports.literal("fine_grained_user_token"),
19856
19828
  account: external_exports.string().min(1).max(128),
19857
19829
  fingerprintSha256: external_exports.string().regex(/^[a-f0-9]{64}$/),
19858
19830
  verifiedAt: external_exports.string().datetime()
@@ -19884,24 +19856,24 @@ function defaultConfigRoot(env = process.env) {
19884
19856
  }
19885
19857
  const xdg = env.XDG_CONFIG_HOME?.trim();
19886
19858
  if (xdg) {
19887
- return path15.join(xdg, "mlclaw");
19859
+ return path14.join(xdg, "mlclaw");
19888
19860
  }
19889
- return path15.join(os6.homedir(), ".config", "mlclaw");
19861
+ return path14.join(os6.homedir(), ".config", "mlclaw");
19890
19862
  }
19891
19863
  function localConfigPaths(root) {
19892
19864
  return {
19893
19865
  root,
19894
- deploymentsDir: path15.join(root, "deployments"),
19895
- secretsDir: path15.join(root, "secrets"),
19896
- operationsDir: path15.join(root, "operations"),
19897
- locksDir: path15.join(root, "locks")
19866
+ deploymentsDir: path14.join(root, "deployments"),
19867
+ secretsDir: path14.join(root, "secrets"),
19868
+ operationsDir: path14.join(root, "operations"),
19869
+ locksDir: path14.join(root, "locks")
19898
19870
  };
19899
19871
  }
19900
19872
  function manifestPath(root, agent) {
19901
- return path15.join(localConfigPaths(root).deploymentsDir, `${assertAgentName(agent)}.json`);
19873
+ return path14.join(localConfigPaths(root).deploymentsDir, `${assertAgentName(agent)}.json`);
19902
19874
  }
19903
19875
  function secretEnvPath(root, agent) {
19904
- return path15.join(localConfigPaths(root).secretsDir, `${assertAgentName(agent)}.env`);
19876
+ return path14.join(localConfigPaths(root).secretsDir, `${assertAgentName(agent)}.env`);
19905
19877
  }
19906
19878
  async function writeManifest(root, input) {
19907
19879
  const manifest = input.version === 1 ? importLegacyManifest(legacyManifestSchema.parse(input)) : manifestSchema.parse(input);
@@ -19911,7 +19883,7 @@ async function writeManifest(root, input) {
19911
19883
  }
19912
19884
  async function readManifest(root, agent) {
19913
19885
  const file = manifestPath(root, agent);
19914
- const raw = JSON.parse(await fs14.readFile(file, "utf8"));
19886
+ const raw = JSON.parse(await fs13.readFile(file, "utf8"));
19915
19887
  const version = raw && typeof raw === "object" && "version" in raw ? raw.version : void 0;
19916
19888
  const parsed = version === 1 ? legacyManifestSchema.parse(raw) : manifestSchema.parse(raw);
19917
19889
  if (parsed.version === 1) {
@@ -19924,7 +19896,7 @@ async function readManifest(root, agent) {
19924
19896
  }
19925
19897
  async function listManifests(root) {
19926
19898
  const dir = localConfigPaths(root).deploymentsDir;
19927
- const entries = await fs14.readdir(dir, { withFileTypes: true }).catch((error) => {
19899
+ const entries = await fs13.readdir(dir, { withFileTypes: true }).catch((error) => {
19928
19900
  if (error.code === "ENOENT") return [];
19929
19901
  throw error;
19930
19902
  });
@@ -19935,7 +19907,7 @@ async function listManifests(root) {
19935
19907
  }
19936
19908
  async function manifestExists(root, agent) {
19937
19909
  try {
19938
- await fs14.access(manifestPath(root, agent));
19910
+ await fs13.access(manifestPath(root, agent));
19939
19911
  return true;
19940
19912
  } catch {
19941
19913
  return false;
@@ -19950,7 +19922,7 @@ async function writeSecretEnv(root, agent, values) {
19950
19922
  await writePrivateFile(file, renderSecretEnv(values));
19951
19923
  }
19952
19924
  async function readSecretEnv(root, agent) {
19953
- return parseSecretEnv(await fs14.readFile(secretEnvPath(root, agent), "utf8"));
19925
+ return parseSecretEnv(await fs13.readFile(secretEnvPath(root, agent), "utf8"));
19954
19926
  }
19955
19927
  function parseSecretEnv(raw) {
19956
19928
  const out = {};
@@ -19982,17 +19954,17 @@ function importLegacyManifest(manifest) {
19982
19954
  return { ...manifest, version: 2, deploymentId, desiredGeneration: 0 };
19983
19955
  }
19984
19956
  async function writePrivateFile(file, content) {
19985
- await fs14.mkdir(path15.dirname(file), { recursive: true, mode: 448 });
19957
+ await fs13.mkdir(path14.dirname(file), { recursive: true, mode: 448 });
19986
19958
  const temporary = `${file}.${process.pid}.${Date.now()}.tmp`;
19987
- await fs14.writeFile(temporary, content, { encoding: "utf8", mode: 384, flag: "wx" });
19988
- await fs14.rename(temporary, file);
19989
- await fs14.chmod(file, 384);
19959
+ await fs13.writeFile(temporary, content, { encoding: "utf8", mode: 384, flag: "wx" });
19960
+ await fs13.rename(temporary, file);
19961
+ await fs13.chmod(file, 384);
19990
19962
  }
19991
19963
 
19992
19964
  // src/mlclaw/deployment-state.ts
19993
- import fs15 from "node:fs/promises";
19965
+ import fs14 from "node:fs/promises";
19994
19966
  import os7 from "node:os";
19995
- import path16 from "node:path";
19967
+ import path15 from "node:path";
19996
19968
  import { randomUUID } from "node:crypto";
19997
19969
  var DEPLOYMENT_PATH = ".mlclaw/deployment.json";
19998
19970
  var DESIRED_STATE_PATH = ".mlclaw/desired-state.json";
@@ -20139,7 +20111,7 @@ function newOperation(manifest, now) {
20139
20111
  }
20140
20112
  async function writeOperation(root, client, operation) {
20141
20113
  const parsed = operationSchema.parse(operation);
20142
- const local = path16.join(localConfigPaths(root).operationsDir, `${parsed.operationId}.json`);
20114
+ const local = path15.join(localConfigPaths(root).operationsDir, `${parsed.operationId}.json`);
20143
20115
  await atomicPrivateWrite(local, stringify(parsed));
20144
20116
  await client.uploadFiles([jsonBlob(`.mlclaw/operations/${parsed.operationId}.json`, parsed)]);
20145
20117
  }
@@ -20155,13 +20127,13 @@ async function updateOperation(root, client, operation, state, now, detail) {
20155
20127
  }
20156
20128
  async function readResumableOperation(root, deploymentId, targetGeneration) {
20157
20129
  const directory = localConfigPaths(root).operationsDir;
20158
- const entries = await fs15.readdir(directory, { withFileTypes: true }).catch((error) => {
20130
+ const entries = await fs14.readdir(directory, { withFileTypes: true }).catch((error) => {
20159
20131
  if (error.code === "ENOENT") return [];
20160
20132
  throw error;
20161
20133
  });
20162
20134
  const operations = await Promise.all(
20163
20135
  entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map(async (entry) => {
20164
- const raw = await fs15.readFile(path16.join(directory, entry.name), "utf8");
20136
+ const raw = await fs14.readFile(path15.join(directory, entry.name), "utf8");
20165
20137
  return operationSchema.parse(JSON.parse(raw));
20166
20138
  })
20167
20139
  );
@@ -20170,12 +20142,12 @@ async function readResumableOperation(root, deploymentId, targetGeneration) {
20170
20142
  ).sort((a, b2) => b2.updatedAt.localeCompare(a.updatedAt))[0] ?? null;
20171
20143
  }
20172
20144
  async function withDeploymentLock(root, deploymentId, task) {
20173
- const file = path16.join(localConfigPaths(root).locksDir, `${deploymentId}.lock`);
20174
- await fs15.mkdir(path16.dirname(file), { recursive: true, mode: 448 });
20145
+ const file = path15.join(localConfigPaths(root).locksDir, `${deploymentId}.lock`);
20146
+ await fs14.mkdir(path15.dirname(file), { recursive: true, mode: 448 });
20175
20147
  const token = randomUUID();
20176
20148
  const lock = stringify({ pid: process.pid, host: os7.hostname(), token, createdAt: (/* @__PURE__ */ new Date()).toISOString() });
20177
20149
  try {
20178
- await fs15.writeFile(file, lock, { flag: "wx", mode: 384 });
20150
+ await fs14.writeFile(file, lock, { flag: "wx", mode: 384 });
20179
20151
  } catch (error) {
20180
20152
  if (error.code !== "EEXIST") throw error;
20181
20153
  if (!await replaceStaleLocalLock(file, lock)) {
@@ -20198,38 +20170,38 @@ async function withDeploymentLock(root, deploymentId, task) {
20198
20170
  async function replaceStaleLocalLock(file, replacement) {
20199
20171
  const guard = `${file}.reclaim`;
20200
20172
  try {
20201
- await fs15.mkdir(guard);
20173
+ await fs14.mkdir(guard);
20202
20174
  } catch (error) {
20203
20175
  if (error.code === "EEXIST") return false;
20204
20176
  throw error;
20205
20177
  }
20206
20178
  try {
20207
- const [raw, stat] = await Promise.all([fs15.readFile(file, "utf8"), fs15.stat(file)]);
20179
+ const [raw, stat] = await Promise.all([fs14.readFile(file, "utf8"), fs14.stat(file)]);
20208
20180
  const value = JSON.parse(raw);
20209
20181
  if (value.host !== os7.hostname() || typeof value.pid !== "number") return false;
20210
20182
  const createdAt = typeof value.createdAt === "string" ? Date.parse(value.createdAt) : Number.NaN;
20211
20183
  const lastRefresh = Number.isFinite(createdAt) ? Math.max(createdAt, stat.mtimeMs) : stat.mtimeMs;
20212
20184
  if (processIsAlive(value.pid) && Date.now() - lastRefresh <= LOCAL_LOCK_STALE_MS) return false;
20213
- await fs15.rm(file);
20214
- await fs15.writeFile(file, replacement, { flag: "wx", mode: 384 });
20185
+ await fs14.rm(file);
20186
+ await fs14.writeFile(file, replacement, { flag: "wx", mode: 384 });
20215
20187
  return true;
20216
20188
  } catch {
20217
20189
  return false;
20218
20190
  } finally {
20219
- await fs15.rm(guard, { recursive: true, force: true });
20191
+ await fs14.rm(guard, { recursive: true, force: true });
20220
20192
  }
20221
20193
  }
20222
20194
  async function refreshOwnedLocalLock(file, token) {
20223
20195
  if (!await localLockHasToken(file, token)) return;
20224
20196
  const now = /* @__PURE__ */ new Date();
20225
- await fs15.utimes(file, now, now);
20197
+ await fs14.utimes(file, now, now);
20226
20198
  }
20227
20199
  async function removeOwnedLocalLock(file, token) {
20228
- if (await localLockHasToken(file, token)) await fs15.rm(file, { force: true });
20200
+ if (await localLockHasToken(file, token)) await fs14.rm(file, { force: true });
20229
20201
  }
20230
20202
  async function localLockHasToken(file, token) {
20231
20203
  try {
20232
- const value = JSON.parse(await fs15.readFile(file, "utf8"));
20204
+ const value = JSON.parse(await fs14.readFile(file, "utf8"));
20233
20205
  return value.token === token;
20234
20206
  } catch {
20235
20207
  return false;
@@ -20295,19 +20267,19 @@ async function readDocument(client, file, schema) {
20295
20267
  if (blob.size > MAX_CONTROL_BYTES) throw new Error(`${file} exceeds ${MAX_CONTROL_BYTES} bytes`);
20296
20268
  return schema.parse(JSON.parse(await blob.text()));
20297
20269
  }
20298
- function jsonBlob(path17, value) {
20299
- return { path: path17, content: new Blob([stringify(value)], { type: "application/json" }) };
20270
+ function jsonBlob(path16, value) {
20271
+ return { path: path16, content: new Blob([stringify(value)], { type: "application/json" }) };
20300
20272
  }
20301
20273
  function stringify(value) {
20302
20274
  return `${JSON.stringify(value, null, 2)}
20303
20275
  `;
20304
20276
  }
20305
20277
  async function atomicPrivateWrite(file, content) {
20306
- await fs15.mkdir(path16.dirname(file), { recursive: true, mode: 448 });
20278
+ await fs14.mkdir(path15.dirname(file), { recursive: true, mode: 448 });
20307
20279
  const temporary = `${file}.${process.pid}.tmp`;
20308
- await fs15.writeFile(temporary, content, { mode: 384, flag: "wx" });
20309
- await fs15.rename(temporary, file);
20310
- await fs15.chmod(file, 384);
20280
+ await fs14.writeFile(temporary, content, { mode: 384, flag: "wx" });
20281
+ await fs14.rename(temporary, file);
20282
+ await fs14.chmod(file, 384);
20311
20283
  }
20312
20284
 
20313
20285
  // src/mlclaw/telegram.ts
@@ -20347,116 +20319,13 @@ function delay(ms) {
20347
20319
 
20348
20320
  // src/mlclaw/hf-broker-credential.ts
20349
20321
  import { createHash as createHash3 } from "node:crypto";
20350
-
20351
- // src/mlclaw/hf-broker-credential-requirements.json
20352
- var hf_broker_credential_requirements_default = {
20353
- version: 1,
20354
- profile_id: "hf-broker-complete-v1",
20355
- token_form_url: "https://huggingface.co/settings/tokens/new",
20356
- token_type: "fineGrained",
20357
- requires_gated_repositories: true,
20358
- personal_permissions: [
20359
- "collection.read",
20360
- "collection.write",
20361
- "discussion.write",
20362
- "inference.endpoints.infer.write",
20363
- "inference.endpoints.write",
20364
- "inference.serverless.write",
20365
- "job.write",
20366
- "repo.access.read",
20367
- "repo.content.read",
20368
- "repo.write",
20369
- "sql-console.embed.write",
20370
- "user.billing.read",
20371
- "user.mcp.read",
20372
- "user.notifications.read",
20373
- "user.notifications.write",
20374
- "user.papers.write",
20375
- "user.preferences.write",
20376
- "user.settings.notifications.write",
20377
- "user.social.likes.write",
20378
- "user.webhooks.read",
20379
- "user.webhooks.write"
20380
- ],
20381
- global_permissions: [
20382
- "discussion.write",
20383
- "post.write"
20384
- ],
20385
- organization_permissions: [
20386
- "collection.read",
20387
- "collection.write",
20388
- "discussion.write",
20389
- "inference.endpoints.infer.write",
20390
- "inference.endpoints.write",
20391
- "inference.serverless.write",
20392
- "job.write",
20393
- "org.auditLog.write",
20394
- "org.billing.read",
20395
- "org.members.read",
20396
- "org.members.write",
20397
- "org.networkSecurity.read",
20398
- "org.networkSecurity.write",
20399
- "org.read",
20400
- "org.repos.read",
20401
- "org.serviceAccounts.read",
20402
- "org.serviceAccounts.write",
20403
- "org.write",
20404
- "repo.access.read",
20405
- "repo.content.read",
20406
- "repo.write",
20407
- "resourceGroup.write",
20408
- "sql-console.embed.write"
20409
- ]
20410
- };
20411
-
20412
- // src/mlclaw/hf-broker-credential.ts
20413
- var permissionListSchema = external_exports.array(external_exports.string().min(1)).min(1).superRefine((permissions, context) => {
20414
- if (permissions.some((permission) => permission !== permission.trim())) {
20415
- context.addIssue({ code: external_exports.ZodIssueCode.custom, message: "permissions must not contain outer whitespace" });
20416
- }
20417
- if (new Set(permissions).size !== permissions.length) {
20418
- context.addIssue({ code: external_exports.ZodIssueCode.custom, message: "permissions must be unique" });
20419
- }
20420
- if (permissions.some((permission, index) => index > 0 && permission < permissions[index - 1])) {
20421
- context.addIssue({ code: external_exports.ZodIssueCode.custom, message: "permissions must be sorted" });
20422
- }
20423
- });
20424
- var profileSchema = external_exports.object({
20425
- version: external_exports.literal(1),
20426
- profile_id: external_exports.literal("hf-broker-complete-v1"),
20427
- token_form_url: external_exports.literal("https://huggingface.co/settings/tokens/new"),
20428
- token_type: external_exports.literal("fineGrained"),
20429
- requires_gated_repositories: external_exports.literal(true),
20430
- personal_permissions: permissionListSchema,
20431
- global_permissions: permissionListSchema,
20432
- organization_permissions: permissionListSchema
20433
- }).strict();
20434
- var BROKER_CREDENTIAL_PROFILE = Object.freeze(profileSchema.parse(hf_broker_credential_requirements_default));
20435
- var HF_TOKEN_CREATE_URL = BROKER_CREDENTIAL_PROFILE.token_form_url;
20436
- var BROKER_PERSONAL_PERMISSIONS = BROKER_CREDENTIAL_PROFILE.personal_permissions;
20437
- var BROKER_GLOBAL_PERMISSIONS = BROKER_CREDENTIAL_PROFILE.global_permissions;
20438
- var BROKER_ORGANIZATION_PERMISSIONS = BROKER_CREDENTIAL_PROFILE.organization_permissions;
20439
- function buildBrokerTokenUrl(owner, accountName) {
20440
- const url = new URL(HF_TOKEN_CREATE_URL);
20441
- url.searchParams.set("tokenType", BROKER_CREDENTIAL_PROFILE.token_type);
20442
- for (const permission of BROKER_PERSONAL_PERMISSIONS) {
20443
- url.searchParams.append("ownUserPermissions", permission);
20444
- }
20445
- for (const permission of BROKER_GLOBAL_PERMISSIONS) {
20446
- url.searchParams.append("globalPermissions", permission);
20447
- }
20448
- url.searchParams.set("canReadGatedRepos", String(BROKER_CREDENTIAL_PROFILE.requires_gated_repositories));
20449
- if (owner !== accountName) {
20450
- url.searchParams.append("orgs", owner);
20451
- for (const permission of BROKER_ORGANIZATION_PERMISSIONS) {
20452
- url.searchParams.append("orgPermissions", permission);
20453
- }
20454
- }
20455
- return url.toString();
20456
- }
20457
- function assessBrokerCredential(identity, owner) {
20322
+ var HF_TOKEN_CREATE_URL = "https://huggingface.co/settings/tokens/new?tokenType=fineGrained";
20323
+ function buildBrokerTokenUrl() {
20324
+ return HF_TOKEN_CREATE_URL;
20325
+ }
20326
+ function assessBrokerCredential(identity) {
20458
20327
  const accessToken = identity.auth?.accessToken;
20459
- if (accessToken?.role !== BROKER_CREDENTIAL_PROFILE.token_type) {
20328
+ if (accessToken?.role !== "fineGrained") {
20460
20329
  return {
20461
20330
  status: "unsupported",
20462
20331
  reason: "HF Broker requires a dedicated fine-grained Hugging Face token"
@@ -20468,40 +20337,16 @@ function assessBrokerCredential(identity, owner) {
20468
20337
  reason: "Hugging Face omitted this fine-grained token's permission details"
20469
20338
  };
20470
20339
  }
20471
- const personalAvailable = new Set(scopedPermissions(accessToken.fineGrained.scoped, "user", identity.name));
20472
- const globalAvailable = new Set(accessToken.fineGrained.global);
20473
- const missing = BROKER_PERSONAL_PERMISSIONS.filter((permission) => !personalAvailable.has(permission));
20474
- missing.push(
20475
- ...BROKER_GLOBAL_PERMISSIONS.filter((permission) => !globalAvailable.has(permission)).map(
20476
- (permission) => `global:${permission}`
20477
- )
20478
- );
20479
- if (!accessToken.fineGrained.canReadGatedRepos) {
20480
- missing.push("canReadGatedRepos");
20481
- }
20482
- if (owner !== identity.name) {
20483
- const organizationAvailable = new Set(scopedPermissions(accessToken.fineGrained.scoped, "org", owner));
20484
- missing.push(
20485
- ...BROKER_ORGANIZATION_PERMISSIONS.filter((permission) => !organizationAvailable.has(permission)).map(
20486
- (permission) => `org:${permission}`
20487
- )
20488
- );
20489
- }
20490
- missing.sort();
20491
- return missing.length === 0 ? { status: "sufficient" } : { status: "insufficient", missing };
20340
+ return { status: "sufficient" };
20492
20341
  }
20493
20342
  function brokerCredentialMetadata(token, identity, verifiedAt) {
20494
20343
  return {
20495
- profileId: BROKER_CREDENTIAL_PROFILE.profile_id,
20344
+ credentialKind: "fine_grained_user_token",
20496
20345
  account: identity.name,
20497
20346
  fingerprintSha256: createHash3("sha256").update(token).digest("hex"),
20498
20347
  verifiedAt: verifiedAt.toISOString()
20499
20348
  };
20500
20349
  }
20501
- function scopedPermissions(scopes, type, name) {
20502
- if (!Array.isArray(scopes)) return [];
20503
- return scopes.filter((scope) => scope.entity.type === type && (!scope.entity.name || scope.entity.name === name)).flatMap((scope) => scope.permissions);
20504
- }
20505
20350
 
20506
20351
  // src/mlclaw/tailscale.ts
20507
20352
  import { execFile as execFile3 } from "node:child_process";
@@ -21492,7 +21337,6 @@ async function resolveBootstrapPlan(params) {
21492
21337
  const existingSecrets = await readSecretEnv(runtime.configRoot, agentName).catch(() => ({}));
21493
21338
  const brokerCredential = await resolveBrokerHfToken({
21494
21339
  opts,
21495
- owner,
21496
21340
  hfIdentity,
21497
21341
  ...providedBrokerHfToken ? { preferredToken: providedBrokerHfToken } : {},
21498
21342
  existingSecrets,
@@ -22236,7 +22080,7 @@ async function deployLocalBootstrap(plan, opts, runtime, desiredChanged = true,
22236
22080
  await writeSecretEnv(runtime.configRoot, plan.agentName, previousSecrets);
22237
22081
  } else {
22238
22082
  await assertLease();
22239
- await fs16.rm(secretEnvPath(runtime.configRoot, plan.agentName), { force: true });
22083
+ await fs15.rm(secretEnvPath(runtime.configRoot, plan.agentName), { force: true });
22240
22084
  }
22241
22085
  if (previousContainer?.running && previousManifest) {
22242
22086
  await startLocalGateway({ manifest: previousManifest, runtime, pull: false, refresh: true, assertLease });
@@ -22265,7 +22109,7 @@ async function deployLocalBootstrap(plan, opts, runtime, desiredChanged = true,
22265
22109
  }
22266
22110
  if (!previousManifest) {
22267
22111
  await assertLease();
22268
- await fs16.rm(manifestPath(runtime.configRoot, plan.agentName), { force: true });
22112
+ await fs15.rm(manifestPath(runtime.configRoot, plan.agentName), { force: true });
22269
22113
  }
22270
22114
  } catch (rollbackError) {
22271
22115
  throw new AggregateError([error, rollbackError], "local bootstrap and rollback both failed");
@@ -24015,7 +23859,7 @@ async function readOptionalTelegramToken(opts, runtime) {
24015
23859
  return direct;
24016
23860
  }
24017
23861
  if (opts.telegramTokenFile) {
24018
- const raw = await fs16.readFile(opts.telegramTokenFile, "utf8");
23862
+ const raw = await fs15.readFile(opts.telegramTokenFile, "utf8");
24019
23863
  const match = raw.match(/(?:^|\n)\s*TELEGRAM_BOT_TOKEN\s*=\s*['"]?([^'"\n]+)['"]?/);
24020
23864
  return (match?.[1] ?? raw.trim()).trim();
24021
23865
  }
@@ -24037,7 +23881,7 @@ async function readOptionalRouterTokenFile(file) {
24037
23881
  if (!file) {
24038
23882
  return void 0;
24039
23883
  }
24040
- const raw = await fs16.readFile(file, "utf8");
23884
+ const raw = await fs15.readFile(file, "utf8");
24041
23885
  const parsed = parseSecretEnv(raw);
24042
23886
  return nonEmpty(parsed.MLCLAW_ROUTER_TOKEN) ?? nonEmpty(parsed.HF_ROUTER_TOKEN) ?? nonEmpty(raw);
24043
23887
  }
@@ -24048,7 +23892,7 @@ async function credentialsStatus(requestedAgent, runtime) {
24048
23892
  if (!metadata) throw new Error("verified HF Broker credential metadata is missing");
24049
23893
  runtime.stdout.log(`Agent: ${manifest.agent}`);
24050
23894
  runtime.stdout.log(`Status: healthy`);
24051
- runtime.stdout.log(`Profile: ${metadata.profileId}`);
23895
+ runtime.stdout.log(`Credential kind: ${metadata.credentialKind}`);
24052
23896
  runtime.stdout.log(`Account: ${metadata.account}`);
24053
23897
  runtime.stdout.log(`Fingerprint: ${metadata.fingerprintSha256.slice(0, 12)}`);
24054
23898
  runtime.stdout.log(`Verified: ${metadata.verifiedAt}`);
@@ -24062,7 +23906,7 @@ async function verifiedStoredBrokerCredential(manifest, runtime) {
24062
23906
  `HF Broker credential metadata is missing; run \`mlclaw credentials repair ${manifest.agent}\` to complete the cutover`
24063
23907
  );
24064
23908
  }
24065
- const verified = await verifyBrokerHfToken(token, manifest.owner, manifest.brokerCredential.account, runtime);
23909
+ const verified = await verifyBrokerHfToken(token, manifest.brokerCredential.account, runtime);
24066
23910
  const observed = brokerCredentialMetadata(token, verified.identity, runtime.now());
24067
23911
  if (observed.fingerprintSha256 !== manifest.brokerCredential.fingerprintSha256) {
24068
23912
  throw new Error(
@@ -24082,14 +23926,14 @@ async function credentialsRepair(requestedAgent, opts, runtime) {
24082
23926
  const suppliedToken = fileToken ?? nonEmpty(runtime.env.MLCLAW_BROKER_HF_TOKEN);
24083
23927
  let replacement;
24084
23928
  if (suppliedToken) {
24085
- replacement = await verifyBrokerHfToken(suppliedToken, manifest.owner, account, runtime);
23929
+ replacement = await verifyBrokerHfToken(suppliedToken, account, runtime);
24086
23930
  } else {
24087
23931
  if (!runtime.prompt.isInteractive()) {
24088
23932
  throw new Error(
24089
23933
  "credential repair requires --broker-hf-token-file, MLCLAW_BROKER_HF_TOKEN, or an interactive terminal"
24090
23934
  );
24091
23935
  }
24092
- replacement = await promptForBrokerHfToken(manifest.owner, account, runtime);
23936
+ replacement = await promptForBrokerHfToken(account, runtime);
24093
23937
  }
24094
23938
  const updatedManifest = {
24095
23939
  ...manifest,
@@ -24260,7 +24104,7 @@ async function resolveBrokerHfToken(params) {
24260
24104
  const configuredToken = fileToken ?? environmentToken ?? nonEmpty(params.preferredToken) ?? nonEmpty(params.existingSecrets.MLCLAW_BROKER_HF_TOKEN);
24261
24105
  if (configuredToken) {
24262
24106
  try {
24263
- return await verifyBrokerHfToken(configuredToken, params.owner, params.hfIdentity.name, params.runtime);
24107
+ return await verifyBrokerHfToken(configuredToken, params.hfIdentity.name, params.runtime);
24264
24108
  } catch (error) {
24265
24109
  if (fileToken || environmentToken || params.preferredToken) throw error;
24266
24110
  if (params.runtime.prompt.isInteractive()) {
@@ -24280,19 +24124,19 @@ async function resolveBrokerHfToken(params) {
24280
24124
  "a dedicated HF Broker credential is required; set MLCLAW_BROKER_HF_TOKEN, pass --broker-hf-token-file, or run bootstrap interactively"
24281
24125
  );
24282
24126
  }
24283
- return await promptForBrokerHfToken(params.owner, params.hfIdentity.name, params.runtime);
24127
+ return await promptForBrokerHfToken(params.hfIdentity.name, params.runtime);
24284
24128
  }
24285
- async function promptForBrokerHfToken(owner, account, runtime) {
24129
+ async function promptForBrokerHfToken(account, runtime) {
24286
24130
  runtime.prompt.note(
24287
- "ML Claw will open a Hugging Face token form with BrokerKit's permissions preselected. Create a dedicated token and paste it here. Your current HF CLI login will not be changed.",
24131
+ "ML Claw will open a Hugging Face fine-grained token form. Choose the permissions and resources this broker may use, create a dedicated token, and paste it here. Your current HF CLI login will not be changed.",
24288
24132
  "HF Broker credential"
24289
24133
  );
24290
- const url = buildBrokerTokenUrl(owner, account);
24134
+ const url = buildBrokerTokenUrl();
24291
24135
  const opened = await runtime.hfCli.openUrl(url);
24292
24136
  runtime.prompt.note(
24293
24137
  `${opened ? "The token form was opened in your browser." : "Open this token form in your browser."}
24294
24138
 
24295
- Name and create the token, then copy it. The URL contains permission names only; it contains no credential. The exact URL is printed below.`,
24139
+ Choose the permissions and resources, name and create the token, then copy it. The URL contains no credential. The exact URL is printed below.`,
24296
24140
  "Create the broker token"
24297
24141
  );
24298
24142
  runtime.stdout.log(url);
@@ -24302,7 +24146,7 @@ Name and create the token, then copy it. The URL contains permission names only;
24302
24146
  "Hugging Face broker token"
24303
24147
  );
24304
24148
  try {
24305
- const verified = await verifyBrokerHfToken(replacement, owner, account, runtime);
24149
+ const verified = await verifyBrokerHfToken(replacement, account, runtime);
24306
24150
  runtime.prompt.note(
24307
24151
  "The dedicated broker token was verified. It will be stored only in ML Claw's trusted broker configuration.",
24308
24152
  "HF Broker credential ready"
@@ -24316,12 +24160,12 @@ Name and create the token, then copy it. The URL contains permission names only;
24316
24160
  }
24317
24161
  }
24318
24162
  }
24319
- async function verifyBrokerHfToken(token, owner, expectedAccount, runtime) {
24163
+ async function verifyBrokerHfToken(token, expectedAccount, runtime) {
24320
24164
  const identity = await runtime.hubFactory(token).whoami();
24321
24165
  if (identity.name !== expectedAccount) {
24322
24166
  throw new Error(`broker token belongs to ${identity.name}, not ${expectedAccount}`);
24323
24167
  }
24324
- const assessment = assessBrokerCredential(identity, owner);
24168
+ const assessment = assessBrokerCredential(identity);
24325
24169
  if (assessment.status !== "sufficient") {
24326
24170
  throw new Error(brokerCredentialAssessmentDetail(assessment));
24327
24171
  }
@@ -24329,17 +24173,14 @@ async function verifyBrokerHfToken(token, owner, expectedAccount, runtime) {
24329
24173
  }
24330
24174
  async function readOptionalBrokerHfTokenFile(file) {
24331
24175
  if (!file) return void 0;
24332
- const raw = await fs16.readFile(file, "utf8");
24176
+ const raw = await fs15.readFile(file, "utf8");
24333
24177
  const parsed = parseSecretEnv(raw);
24334
24178
  const token = nonEmpty(parsed.MLCLAW_BROKER_HF_TOKEN) ?? nonEmpty(raw);
24335
24179
  if (!token) throw new Error("HF Broker token file is empty");
24336
24180
  return token;
24337
24181
  }
24338
24182
  function brokerCredentialAssessmentDetail(assessment) {
24339
- if (assessment.status === "unsupported") return assessment.reason;
24340
- const shown = assessment.missing.slice(0, 8);
24341
- const remaining = assessment.missing.length - shown.length;
24342
- return `The HF Broker credential is missing ${assessment.missing.length} required permission${assessment.missing.length === 1 ? "" : "s"}: ${shown.join(", ")}${remaining > 0 ? `, and ${remaining} more` : ""}`;
24183
+ return assessment.reason;
24343
24184
  }
24344
24185
  function errorMessage(error) {
24345
24186
  return error instanceof Error ? error.message : String(error);