@cortexkit/aft 0.33.0 → 0.34.0

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.
@@ -69,4 +69,5 @@ export declare function shouldSkipDoctorFixConfirmation(argv: string[]): boolean
69
69
  export declare function doctorSkewBinaryDownloadDecision(argv: string[]): "prompt" | "proceed" | "skip";
70
70
  export declare function formatDoctorStorageStatus(h: DiagnosticReport["harnesses"][number]): string;
71
71
  export declare function fixPluginEntries(adapters: HarnessAdapter[]): Promise<void>;
72
+ export declare function deriveIssueTitleFromBody(body: string): string;
72
73
  //# sourceMappingURL=doctor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -10929,7 +10929,7 @@ var init_lsp_cache = __esm(() => {
10929
10929
 
10930
10930
  // src/lib/onnx.ts
10931
10931
  import { existsSync as existsSync10, readdirSync as readdirSync5, readlinkSync, realpathSync, statSync as statSync6 } from "node:fs";
10932
- import { isAbsolute, join as join9, resolve as resolve4, win32 } from "node:path";
10932
+ import { basename, isAbsolute, join as join9, resolve as resolve4, win32 } from "node:path";
10933
10933
  function getOnnxLibraryName() {
10934
10934
  if (process.platform === "darwin")
10935
10935
  return "libonnxruntime.dylib";
@@ -10992,10 +10992,29 @@ function findSystemOnnxRuntime() {
10992
10992
  searchPaths.push(...pathEntriesForPlatform());
10993
10993
  const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
10994
10994
  const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
10995
- searchPaths.push(join9(programFiles, "onnxruntime", "lib"), join9(programFiles, "Microsoft ONNX Runtime", "lib"), join9(programFiles, "Microsoft Machine Learning", "lib"), join9(programFilesX86, "onnxruntime", "lib"));
10995
+ searchPaths.push(join9(programFiles, "onnxruntime", "lib"), join9(programFiles, "Microsoft ONNX Runtime", "lib"), join9(programFiles, "Microsoft Machine Learning", "lib"), join9(programFilesX86, "onnxruntime", "lib"), ...(() => {
10996
+ const nugetPaths = [];
10997
+ const userProfile = process.env.USERPROFILE ?? "";
10998
+ if (!userProfile)
10999
+ return nugetPaths;
11000
+ const nugetPackageDir = join9(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
11001
+ if (!existsSync10(nugetPackageDir))
11002
+ return nugetPaths;
11003
+ try {
11004
+ for (const entry of readdirSync5(nugetPackageDir, { withFileTypes: true })) {
11005
+ if (!entry.isDirectory())
11006
+ continue;
11007
+ if (entry.name === "__globalPackagesFolder" || entry.name.startsWith("."))
11008
+ continue;
11009
+ nugetPaths.push(join9(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join9(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
11010
+ }
11011
+ } catch {}
11012
+ return nugetPaths;
11013
+ })());
10996
11014
  }
10997
11015
  const normalizeCase = process.platform === "win32" || process.platform === "darwin";
10998
11016
  const seen = new Set;
11017
+ const unknownVersionPaths = [];
10999
11018
  for (const dir of searchPaths) {
11000
11019
  let key = resolve4(dir).replace(/[/\\]+$/, "");
11001
11020
  if (normalizeCase)
@@ -11003,14 +11022,44 @@ function findSystemOnnxRuntime() {
11003
11022
  if (seen.has(key))
11004
11023
  continue;
11005
11024
  seen.add(key);
11006
- if (directoryContainsLibrary(dir, libName))
11007
- return dir;
11025
+ if (!directoryContainsLibrary(dir, libName))
11026
+ continue;
11027
+ const version = detectOrtVersion(dir);
11028
+ if (!version) {
11029
+ unknownVersionPaths.push(dir);
11030
+ continue;
11031
+ }
11032
+ if (!isOrtVersionCompatible(version))
11033
+ continue;
11034
+ return dir;
11008
11035
  }
11009
- return null;
11036
+ return unknownVersionPaths[0] ?? null;
11010
11037
  }
11011
11038
  function findCachedOnnxRuntime(storageDir) {
11012
11039
  const ortDir = join9(storageDir, "onnxruntime", ONNX_RUNTIME_VERSION);
11013
- return existsSync10(join9(ortDir, getOnnxLibraryName())) ? ortDir : null;
11040
+ const libName = getOnnxLibraryName();
11041
+ if (existsSync10(join9(ortDir, libName)))
11042
+ return ortDir;
11043
+ const libSubdir = join9(ortDir, "lib");
11044
+ if (existsSync10(join9(libSubdir, libName)))
11045
+ return libSubdir;
11046
+ return null;
11047
+ }
11048
+ function parseOrtVersionFromPath(value) {
11049
+ const name = basename(value);
11050
+ const semverish = name.match(/(?:^|[._-])(\d+\.\d+\.\d+(?:[-+][A-Za-z0-9.-]+)?)(?:\.(?:dylib|dll))?$/);
11051
+ if (semverish)
11052
+ return semverish[1].split(/[-+]/, 1)[0];
11053
+ return /\d+\.\d+\.\d+/.test(name) ? INVALID_ORT_VERSION : null;
11054
+ }
11055
+ function parseOrtVersionFromDirectoryPath(value) {
11056
+ const parts = value.split(/[\\/]+/).filter(Boolean).reverse();
11057
+ for (const part of parts) {
11058
+ const version = parseOrtVersionFromPath(part);
11059
+ if (version)
11060
+ return version;
11061
+ }
11062
+ return null;
11014
11063
  }
11015
11064
  function detectOrtVersion(libDir) {
11016
11065
  if (!existsSync10(libDir))
@@ -11018,28 +11067,32 @@ function detectOrtVersion(libDir) {
11018
11067
  const libName = getOnnxLibraryName();
11019
11068
  try {
11020
11069
  const entries = readdirSync5(libDir);
11070
+ const barePrefix = libName.replace(/\.(so|dylib|dll)$/, "");
11071
+ const expectedPrefix = process.platform === "win32" ? barePrefix.toLowerCase() : barePrefix;
11021
11072
  for (const entry of entries) {
11022
- if (!entry.startsWith(libName))
11073
+ const comparable = process.platform === "win32" ? entry.toLowerCase() : entry;
11074
+ if (!comparable.startsWith(expectedPrefix))
11023
11075
  continue;
11024
- const match = entry.match(/\.(\d+\.\d+\.\d+)$/);
11025
- if (match)
11026
- return match[1];
11076
+ const version = parseOrtVersionFromPath(entry);
11077
+ if (version)
11078
+ return version;
11027
11079
  }
11028
11080
  const base = join9(libDir, libName);
11029
11081
  if (existsSync10(base)) {
11030
11082
  try {
11031
11083
  const real = realpathSync(base);
11032
- const suffix = real.match(/\.(\d+\.\d+\.\d+)$/);
11033
- if (suffix)
11034
- return suffix[1];
11084
+ const version = parseOrtVersionFromPath(real) ?? parseOrtVersionFromDirectoryPath(real);
11085
+ if (version)
11086
+ return version;
11035
11087
  } catch {}
11036
11088
  try {
11037
11089
  const target = readlinkSync(base);
11038
- const suffix = target.match(/\.(\d+\.\d+\.\d+)$/);
11039
- if (suffix)
11040
- return suffix[1];
11090
+ const version = parseOrtVersionFromPath(target);
11091
+ if (version)
11092
+ return version;
11041
11093
  } catch {}
11042
11094
  }
11095
+ return parseOrtVersionFromDirectoryPath(libDir);
11043
11096
  } catch {}
11044
11097
  return null;
11045
11098
  }
@@ -11052,18 +11105,50 @@ function isOrtVersionCompatible(version) {
11052
11105
  return false;
11053
11106
  return minor >= REQUIRED_ORT_MIN_MINOR;
11054
11107
  }
11055
- var ONNX_RUNTIME_VERSION = "1.24.4", REQUIRED_ORT_MAJOR = 1, REQUIRED_ORT_MIN_MINOR = 20;
11108
+ var ONNX_RUNTIME_VERSION = "1.24.4", INVALID_ORT_VERSION = "<invalid>", REQUIRED_ORT_MAJOR = 1, REQUIRED_ORT_MIN_MINOR = 20;
11056
11109
  var init_onnx = () => {};
11057
11110
 
11058
11111
  // src/lib/sanitize.ts
11112
+ import { realpathSync as realpathSync2 } from "node:fs";
11059
11113
  import { homedir as homedir6, userInfo } from "node:os";
11060
11114
  function escapeRegex(value) {
11061
11115
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
11062
11116
  }
11117
+ function safeRealpath(p2) {
11118
+ try {
11119
+ return realpathSync2(p2);
11120
+ } catch {
11121
+ return null;
11122
+ }
11123
+ }
11124
+ function isSensitiveKeyName(keyName) {
11125
+ return SENSITIVE_KEY_WORD.test(keyName) || SEGMENTED_KEY_WORD.test(keyName) || CAMEL_CASE_KEY_WORD.test(keyName);
11126
+ }
11127
+ function redactSecrets(content) {
11128
+ let sanitized = content;
11129
+ sanitized = sanitized.replace(/\b((?:Proxy-)?Authorization[^\S\r\n]*:[^\S\r\n]*(?:Bearer|Basic)[^\S\r\n]+)[A-Za-z0-9._~+/-]+=*/gi, `$1${SECRET_PLACEHOLDER}`);
11130
+ sanitized = sanitized.replace(/\bgithub_pat_[A-Za-z0-9_]+\b/g, SECRET_PLACEHOLDER);
11131
+ sanitized = sanitized.replace(/\bgh(?:p|o|s)_[A-Za-z0-9_]{16,}\b/g, SECRET_PLACEHOLDER);
11132
+ sanitized = sanitized.replace(/\bsk-(?:live-)?[A-Za-z0-9][A-Za-z0-9_-]{7,}\b/g, SECRET_PLACEHOLDER);
11133
+ sanitized = sanitized.replace(JWT_PATTERN, SECRET_PLACEHOLDER);
11134
+ sanitized = sanitized.replace(AWS_ACCESS_KEY_ID_PATTERN, SECRET_PLACEHOLDER);
11135
+ sanitized = sanitized.replace(quotedSensitiveKeyValuePattern, (match, prefix, _keyQuote, keyName, valueQuote) => isSensitiveKeyName(keyName) ? `${prefix}${valueQuote}${SECRET_PLACEHOLDER}${valueQuote}` : match);
11136
+ sanitized = sanitized.replace(unquotedSensitiveKeyValuePattern, (match, prefix, keyName, valueQuote) => isSensitiveKeyName(keyName) ? `${prefix}${valueQuote}${SECRET_PLACEHOLDER}${valueQuote}` : match);
11137
+ sanitized = sanitized.replace(bareSensitiveKeyValuePattern, (match, prefix, keyName) => isSensitiveKeyName(keyName) ? `${prefix}${SECRET_PLACEHOLDER}` : match);
11138
+ sanitized = sanitized.replace(/\b([a-z][a-z0-9+.-]*:\/\/)[^@\s/?#]+@/gi, `$1${URL_CREDENTIAL_PLACEHOLDER}@`);
11139
+ sanitized = sanitized.replace(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi, "<EMAIL>");
11140
+ return sanitized;
11141
+ }
11063
11142
  function sanitizeContent(content) {
11064
11143
  const username = userInfo().username;
11065
11144
  const home = homedir6();
11066
- let sanitized = content;
11145
+ let sanitized = redactSecrets(content);
11146
+ const cwd = process.cwd();
11147
+ for (const candidate of new Set([cwd, safeRealpath(cwd)])) {
11148
+ if (candidate && candidate !== "/" && candidate !== home) {
11149
+ sanitized = sanitized.replace(new RegExp(escapeRegex(candidate), "g"), "<PROJECT>");
11150
+ }
11151
+ }
11067
11152
  if (home) {
11068
11153
  sanitized = sanitized.replace(new RegExp(escapeRegex(home), "g"), "~");
11069
11154
  }
@@ -11088,7 +11173,17 @@ function sanitizeValue(value) {
11088
11173
  }
11089
11174
  return value;
11090
11175
  }
11091
- var init_sanitize = () => {};
11176
+ var SECRET_PLACEHOLDER = "<REDACTED_SECRET>", URL_CREDENTIAL_PLACEHOLDER = "***", KEY_NAME = "[A-Za-z_][A-Za-z0-9_.-]*", SENSITIVE_KEY_WORD, SEGMENTED_KEY_WORD, CAMEL_CASE_KEY_WORD, JWT_PATTERN, AWS_ACCESS_KEY_ID_PATTERN, quotedSensitiveKeyValuePattern, unquotedSensitiveKeyValuePattern, bareSensitiveKeyValuePattern;
11177
+ var init_sanitize = __esm(() => {
11178
+ SENSITIVE_KEY_WORD = /(?:token|password|secret|api[_-]?key|passwd|pwd|credential)/i;
11179
+ SEGMENTED_KEY_WORD = /(?:^|[_.-])key(?:$|[_.-])/i;
11180
+ CAMEL_CASE_KEY_WORD = /[a-z0-9]Key(?:$|[A-Z_.-])/;
11181
+ JWT_PATTERN = /\beyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g;
11182
+ AWS_ACCESS_KEY_ID_PATTERN = /\b(?:AKIA|ASIA|AGPA|AIDA|AROA)[A-Z0-9]{16}\b/g;
11183
+ quotedSensitiveKeyValuePattern = new RegExp(String.raw`((['"])(${KEY_NAME})\2[^\S\r\n]*:[^\S\r\n]*)(['"])([^'"\r\n]+)\4`, "gi");
11184
+ unquotedSensitiveKeyValuePattern = new RegExp(String.raw`\b((${KEY_NAME})[^\S\r\n]*[=:][^\S\r\n]*)(['"])([^'"\r\n]+)\3`, "gi");
11185
+ bareSensitiveKeyValuePattern = new RegExp(String.raw`\b((${KEY_NAME})[^\S\r\n]*[=:][^\S\r\n]*)([^\s,;&'"]+)`, "gi");
11186
+ });
11092
11187
 
11093
11188
  // src/lib/diagnostics.ts
11094
11189
  import {
@@ -11640,13 +11735,25 @@ __export(exports_doctor, {
11640
11735
  formatDoctorStorageStatus: () => formatDoctorStorageStatus,
11641
11736
  fixPluginEntries: () => fixPluginEntries,
11642
11737
  doctorSkewBinaryDownloadDecision: () => doctorSkewBinaryDownloadDecision,
11738
+ deriveIssueTitleFromBody: () => deriveIssueTitleFromBody,
11643
11739
  clearOldBinaries: () => clearOldBinaries,
11644
11740
  clearDoctorCaches: () => clearDoctorCaches,
11645
11741
  buildDoctorFixPlan: () => buildDoctorFixPlan,
11646
11742
  DOCTOR_FORCE_CLEAR_TARGETS: () => DOCTOR_FORCE_CLEAR_TARGETS,
11647
11743
  DOCTOR_CLEAR_TARGET_OPTIONS: () => DOCTOR_CLEAR_TARGET_OPTIONS
11648
11744
  });
11649
- import { existsSync as existsSync13, mkdirSync as mkdirSync2, rmSync as rmSync4, statSync as statSync8, writeFileSync as writeFileSync2 } from "node:fs";
11745
+ import {
11746
+ chmodSync,
11747
+ existsSync as existsSync13,
11748
+ mkdirSync as mkdirSync2,
11749
+ mkdtempSync,
11750
+ readFileSync as readFileSync4,
11751
+ realpathSync as realpathSync3,
11752
+ rmSync as rmSync4,
11753
+ statSync as statSync8,
11754
+ writeFileSync as writeFileSync2
11755
+ } from "node:fs";
11756
+ import { tmpdir as tmpdir2 } from "node:os";
11650
11757
  import { join as join11 } from "node:path";
11651
11758
  async function runDoctor(options) {
11652
11759
  if (options.issue) {
@@ -12100,8 +12207,75 @@ function formatStorageSizes(sizes) {
12100
12207
  const parts = Object.entries(sizes).filter(([, size]) => size > 0).map(([key, size]) => `${key}: ${formatBytes(size)}`);
12101
12208
  return parts.length > 0 ? parts.join(", ") : "empty";
12102
12209
  }
12210
+ function isInteractiveTerminal() {
12211
+ return process.stdin.isTTY === true && process.stdout.isTTY === true;
12212
+ }
12213
+ function issueDescriptionSummaryFromBody(body) {
12214
+ const lines = body.split(/\r?\n/);
12215
+ const descriptionStart = lines.findIndex((line) => line.trim() === "## Description");
12216
+ if (descriptionStart !== -1) {
12217
+ const parts = [];
12218
+ for (let i = descriptionStart + 1;i < lines.length; i += 1) {
12219
+ const trimmed = lines[i].trim();
12220
+ if (trimmed.startsWith("## "))
12221
+ break;
12222
+ if (!trimmed)
12223
+ continue;
12224
+ parts.push(trimmed);
12225
+ if (parts.join(" ").length >= 72)
12226
+ break;
12227
+ }
12228
+ const summary = parts.join(" ").replace(/\s+/g, " ").trim();
12229
+ if (summary)
12230
+ return summary;
12231
+ }
12232
+ return lines.map((line) => line.trim()).find((line) => line.length > 0 && !line.startsWith("#") && !line.startsWith("```")) ?? "diagnostic report";
12233
+ }
12234
+ function deriveIssueTitleFromBody(body) {
12235
+ const summary = issueDescriptionSummaryFromBody(sanitizeContent(body));
12236
+ return sanitizeContent(`AFT issue: ${summary.slice(0, 72)}`);
12237
+ }
12238
+ function writeIssueReviewFile(body) {
12239
+ let reviewDir = null;
12240
+ try {
12241
+ reviewDir = mkdtempSync(join11(tmpdir2(), "aft-issue-"));
12242
+ if (process.platform !== "win32") {
12243
+ chmodSync(reviewDir, 448);
12244
+ }
12245
+ const outPath = join11(reviewDir, "issue.md");
12246
+ writeFileSync2(outPath, `${body}
12247
+ `, { encoding: "utf8", mode: 384, flag: "wx" });
12248
+ return { path: outPath, realPath: realpathSync3(outPath) };
12249
+ } catch (err) {
12250
+ if (reviewDir) {
12251
+ try {
12252
+ rmSync4(reviewDir, { recursive: true, force: true });
12253
+ } catch {}
12254
+ }
12255
+ O2.error(`Failed to write sanitized issue report: ${err instanceof Error ? err.message : String(err)}`);
12256
+ return null;
12257
+ }
12258
+ }
12259
+ function readReviewedIssueFile(reviewFile) {
12260
+ try {
12261
+ const realPath = realpathSync3(reviewFile.path);
12262
+ if (realPath !== reviewFile.realPath) {
12263
+ O2.error(`Review file path changed before filing; refusing to read ${reviewFile.path}.`);
12264
+ return null;
12265
+ }
12266
+ return readFileSync4(reviewFile.path, "utf8");
12267
+ } catch (err) {
12268
+ O2.error(`Failed to read reviewed issue report: ${err instanceof Error ? err.message : String(err)}`);
12269
+ return null;
12270
+ }
12271
+ }
12103
12272
  async function runIssueFlow(argv) {
12104
12273
  mt("AFT doctor --issue");
12274
+ if (!isInteractiveTerminal()) {
12275
+ wt("Non-interactive terminal — not collecting or filing automatically. Run `aft doctor --issue` from an interactive terminal so you can describe and review the report before filing.", "Manual filing");
12276
+ gt("Done.");
12277
+ return 0;
12278
+ }
12105
12279
  const adapters = await resolveAdaptersForCommand(argv, {
12106
12280
  allowMulti: true,
12107
12281
  verb: "include in the issue"
@@ -12153,14 +12327,35 @@ ${tail || "<no log output>"}
12153
12327
  ].join(`
12154
12328
  `);
12155
12329
  const body = capBodyToGithubLimit(sanitizeContent(rawBody));
12156
- const title = sanitizeContent(`AFT issue: ${description.slice(0, 72)}`);
12157
- const outPath = join11(process.cwd(), `aft-issue-${Date.now()}.md`);
12158
- writeFileSync2(outPath, `${body}
12159
- `);
12330
+ const reviewFile = writeIssueReviewFile(body);
12331
+ if (!reviewFile) {
12332
+ gt("Done — could not write the issue report.");
12333
+ return 1;
12334
+ }
12335
+ const outPath = reviewFile.path;
12160
12336
  O2.success(`Wrote sanitized issue body to ${outPath}`);
12337
+ wt(`Open and review the report before filing:
12338
+ ${outPath}
12339
+
12340
+ Home paths and your username have been stripped, but it still contains log lines and file paths from your project. Edit the file to remove anything you don't want public — your edits are used when you confirm below.`, "Review before filing");
12341
+ const proceed = await confirm("Have you reviewed the report above? File it as a GitHub issue now?", false);
12342
+ if (!proceed) {
12343
+ wt(`No issue filed. When ready, file manually at
12344
+ https://github.com/cortexkit/aft/issues/new and paste the contents of ${outPath}.`, "Skipped");
12345
+ gt("Done.");
12346
+ return 0;
12347
+ }
12348
+ const reviewedBody = readReviewedIssueFile(reviewFile);
12349
+ if (reviewedBody === null) {
12350
+ wt("No issue filed. Please review the report path above and file manually if needed.", "Skipped");
12351
+ gt("Done.");
12352
+ return 1;
12353
+ }
12354
+ const finalBody = capBodyToGithubLimit(sanitizeContent(reviewedBody));
12355
+ const finalTitle = deriveIssueTitleFromBody(finalBody);
12161
12356
  if (isGhInstalled()) {
12162
12357
  O2.info("Opening GitHub issue via `gh`…");
12163
- const result = createGitHubIssue("cortexkit/aft", title, body);
12358
+ const result = createGitHubIssue("cortexkit/aft", finalTitle, finalBody);
12164
12359
  if (result.url) {
12165
12360
  O2.success(`Issue filed: ${result.url}`);
12166
12361
  openBrowser(result.url);
@@ -12169,7 +12364,7 @@ ${tail || "<no log output>"}
12169
12364
  }
12170
12365
  O2.warn(`gh failed: ${result.stderr ?? "unknown error"}. Falling back to browser.`);
12171
12366
  }
12172
- const fallback = `https://github.com/cortexkit/aft/issues/new?title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}`;
12367
+ const fallback = `https://github.com/cortexkit/aft/issues/new?title=${encodeURIComponent(finalTitle)}&body=${encodeURIComponent(finalBody)}`;
12173
12368
  O2.info("Opening GitHub issue form in your browser…");
12174
12369
  openBrowser(fallback);
12175
12370
  wt(`If the browser didn't open, the sanitized body is at ${outPath}. Copy it into a new issue at https://github.com/cortexkit/aft/issues/new.`, "Fallback");
@@ -1 +1 @@
1
- {"version":3,"file":"onnx.d.ts","sourceRoot":"","sources":["../../src/lib/onnx.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,oBAAoB,WAAW,CAAC;AAE7C,wBAAgB,kBAAkB,IAAI,MAAM,CAI3C;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAkB7C;AA8BD,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,IAAI,CA0CrD;AAED,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGvE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAmC9D;AAED,+DAA+D;AAC/D,eAAO,MAAM,kBAAkB,IAAI,CAAC;AACpC,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAM/D;AAED,uEAAuE;AACvE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG;IAC9C,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;CACjB,CAQA"}
1
+ {"version":3,"file":"onnx.d.ts","sourceRoot":"","sources":["../../src/lib/onnx.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,oBAAoB,WAAW,CAAC;AAE7C,wBAAgB,kBAAkB,IAAI,MAAM,CAI3C;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAkB7C;AA8BD,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,IAAI,CAoErD;AACD,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUvE;AAyBD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAwC9D;AAED,+DAA+D;AAC/D,eAAO,MAAM,kBAAkB,IAAI,CAAC;AACpC,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAM/D;AAED,uEAAuE;AACvE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG;IAC9C,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;CACjB,CAQA"}
@@ -1 +1 @@
1
- {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/lib/sanitize.ts"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAgBvD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAarD"}
1
+ {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/lib/sanitize.ts"],"names":[],"mappings":"AAGA,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAmFD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA4BvD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAarD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/aft",
3
- "version": "0.33.0",
3
+ "version": "0.34.0",
4
4
  "type": "module",
5
5
  "description": "Unified CLI for Agent File Tools (AFT) — setup, doctor, and diagnostics across supported agent harnesses (OpenCode, Pi)",
6
6
  "license": "MIT",
@@ -19,11 +19,12 @@
19
19
  "build": "bun build src/index.ts --outfile dist/index.js --target node --format esm && tsc --emitDeclarationOnly",
20
20
  "typecheck": "tsc --noEmit",
21
21
  "test": "bun test",
22
- "prepublishOnly": "bun run build"
22
+ "prepublishOnly": "bun run build",
23
+ "test:unit": "bun test"
23
24
  },
24
25
  "dependencies": {
25
26
  "@clack/prompts": "^1.2.0",
26
- "@cortexkit/aft-bridge": "0.33.0",
27
+ "@cortexkit/aft-bridge": "0.34.0",
27
28
  "comment-json": "^4.6.2"
28
29
  },
29
30
  "devDependencies": {