@skillrecordings/cli 0.15.0 → 0.16.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.
package/dist/index.js CHANGED
@@ -1479,9 +1479,9 @@ var require_url_state_machine = __commonJS({
1479
1479
  url.username += percentEncodeChar(decoded[i], isUserinfoPercentEncode);
1480
1480
  }
1481
1481
  };
1482
- module.exports.setThePassword = function(url, password2) {
1482
+ module.exports.setThePassword = function(url, password3) {
1483
1483
  url.password = "";
1484
- const decoded = punycode.ucs2.decode(password2);
1484
+ const decoded = punycode.ucs2.decode(password3);
1485
1485
  for (let i = 0; i < decoded.length; ++i) {
1486
1486
  url.password += percentEncodeChar(decoded[i], isUserinfoPercentEncode);
1487
1487
  }
@@ -16736,7 +16736,7 @@ var require_proxy_agent = __commonJS({
16736
16736
  const { proxyTunnel = true } = opts;
16737
16737
  super();
16738
16738
  const url = this.#getUrl(opts);
16739
- const { href, origin, port, protocol, username, password: password2, hostname: proxyHostname } = url;
16739
+ const { href, origin, port, protocol, username, password: password3, hostname: proxyHostname } = url;
16740
16740
  this[kProxy] = { uri: href, protocol };
16741
16741
  this[kRequestTls] = opts.requestTls;
16742
16742
  this[kProxyTls] = opts.proxyTls;
@@ -16748,8 +16748,8 @@ var require_proxy_agent = __commonJS({
16748
16748
  this[kProxyHeaders]["proxy-authorization"] = `Basic ${opts.auth}`;
16749
16749
  } else if (opts.token) {
16750
16750
  this[kProxyHeaders]["proxy-authorization"] = opts.token;
16751
- } else if (username && password2) {
16752
- this[kProxyHeaders]["proxy-authorization"] = `Basic ${Buffer.from(`${decodeURIComponent(username)}:${decodeURIComponent(password2)}`).toString("base64")}`;
16751
+ } else if (username && password3) {
16752
+ this[kProxyHeaders]["proxy-authorization"] = `Basic ${Buffer.from(`${decodeURIComponent(username)}:${decodeURIComponent(password3)}`).toString("base64")}`;
16753
16753
  }
16754
16754
  const connect = buildConnector({ ...opts.proxyTls });
16755
16755
  this[kConnectEndpoint] = buildConnector({ ...opts.requestTls });
@@ -19843,7 +19843,7 @@ var require_snapshot_recorder = __commonJS({
19843
19843
  "use strict";
19844
19844
  init_esm_shims();
19845
19845
  var { writeFile: writeFile9, readFile: readFile10, mkdir: mkdir2 } = __require("fs/promises");
19846
- var { dirname: dirname8, resolve: resolve9 } = __require("path");
19846
+ var { dirname: dirname7, resolve: resolve9 } = __require("path");
19847
19847
  var { setTimeout: setTimeout2, clearTimeout: clearTimeout2 } = __require("timers");
19848
19848
  var { InvalidArgumentError, UndiciError } = require_errors();
19849
19849
  var { hashId, isUrlExcludedFactory, normalizeHeaders, createHeaderFilters } = require_snapshot_utils();
@@ -20074,7 +20074,7 @@ var require_snapshot_recorder = __commonJS({
20074
20074
  throw new InvalidArgumentError("Snapshot path is required");
20075
20075
  }
20076
20076
  const resolvedPath = resolve9(path);
20077
- await mkdir2(dirname8(resolvedPath), { recursive: true });
20077
+ await mkdir2(dirname7(resolvedPath), { recursive: true });
20078
20078
  const data2 = Array.from(this.#snapshots.entries()).map(([hash, snapshot]) => ({
20079
20079
  hash,
20080
20080
  snapshot
@@ -26406,8 +26406,8 @@ var require_fetch = __commonJS({
26406
26406
  let authorizationValue = null;
26407
26407
  if (hasAuthenticationEntry(httpRequest) && (httpRequest.useURLCredentials === void 0 || !includesCredentials(requestCurrentURL(httpRequest)))) {
26408
26408
  } else if (includesCredentials(requestCurrentURL(httpRequest)) && isAuthenticationFetch) {
26409
- const { username, password: password2 } = requestCurrentURL(httpRequest);
26410
- authorizationValue = `Basic ${Buffer.from(`${username}:${password2}`).toString("base64")}`;
26409
+ const { username, password: password3 } = requestCurrentURL(httpRequest);
26410
+ authorizationValue = `Basic ${Buffer.from(`${username}:${password3}`).toString("base64")}`;
26411
26411
  }
26412
26412
  if (authorizationValue !== null) {
26413
26413
  httpRequest.headersList.append("Authorization", authorizationValue, false);
@@ -74714,9 +74714,9 @@ init_esm_shims();
74714
74714
  var ABBREVIATED_THRESHOLD = 2;
74715
74715
  var MINIMAL_THRESHOLD = 5;
74716
74716
  var ROOT_DESCRIPTIONS = {
74717
- full: "Skill Recordings support agent CLI \u2014 triage, investigate, and manage customer conversations.\n\n Getting Started:\n 1. skill auth setup Configure 1Password secrets (Front API token, DB, etc.)\n 2. skill auth status Verify your credentials are working\n 3. skill front inbox See what needs attention right now\n\n Common Workflows:\n Triage inbox skill front inbox \u2192 skill front triage\n Investigate ticket skill front conversation <id> --messages\n Bulk cleanup skill front bulk-archive --older-than 30d\n Generate report skill front report --inbox support\n Check deploys skill deploys\n\n For AI Agents (Claude Code, MCP):\n skill mcp Start JSON-RPC server with 9 Front tools\n skill plugin sync Install the Claude Code plugin\n All commands support --json for structured, HATEOAS-enriched output",
74718
- abbreviated: "Skill Recordings support agent CLI \u2014 triage and investigate support conversations.\n\n Start here:\n skill auth setup Configure 1Password + secrets\n skill front inbox See what needs attention\n skill front triage Auto-categorize conversations\n\n Common:\n skill front conversation <id> --messages\n skill front reply <id>\n skill deploys\n skill mcp\n",
74719
- minimal: "Skill Recordings support agent CLI. Try: skill front inbox, skill front triage, skill auth status. Use --help for details."
74717
+ full: "Skill Recordings support agent CLI \u2014 triage, investigate, and manage customer conversations.\n\n Getting Started:\n 1. skill wizard Interactive app setup wizard\n 2. skill keys Manage your personal API keys\n 3. skill front inbox See what needs attention right now\n\n Common Workflows:\n Triage inbox skill front inbox \u2192 skill front triage\n Investigate ticket skill front conversation <id> --messages\n Bulk cleanup skill front bulk-archive --older-than 30d\n Generate report skill front report --inbox support\n Check deploys skill deploys\n\n For AI Agents (Claude Code, MCP):\n skill mcp Start JSON-RPC server with 9 Front tools\n skill plugin sync Install the Claude Code plugin\n All commands support --json for structured, HATEOAS-enriched output",
74718
+ abbreviated: "Skill Recordings support agent CLI \u2014 triage and investigate support conversations.\n\n Start here:\n skill wizard Set up a new product\n skill keys Manage API keys\n skill front inbox See what needs attention\n skill front triage Auto-categorize conversations\n\n Common:\n skill front conversation <id> --messages\n skill front reply <id>\n skill deploys\n skill mcp\n",
74719
+ minimal: "Skill Recordings support agent CLI. Try: skill wizard, skill keys, skill front inbox, skill front triage. Use --help for details."
74720
74720
  };
74721
74721
  var FRONT_DESCRIPTIONS = {
74722
74722
  full: "Front conversations, inboxes, tags, archival, and reporting.\n\n Prerequisites:\n FRONT_API_TOKEN must be set. Run: skill auth setup\n\n Start here:\n skill front inbox See unassigned conversations\n skill front inbox support List conversations in a specific inbox\n skill front triage AI-powered categorization of inbox items\n\n Investigate a conversation:\n skill front conversation <id> -m Full conversation with messages\n skill front message <id> Single message details + body\n\n Take action:\n skill front assign <id> Assign to a teammate\n skill front reply <id> Draft a reply (HITL, never auto-sends)\n skill front tag <id> Add a tag\n skill front archive <id> Archive a resolved conversation\n\n Bulk operations:\n skill front bulk-archive Archive old/spam conversations\n skill front report Volume + tag + sender forensics\n\n All commands accept --json for HATEOAS-enriched output with _links and _actions.",
@@ -76954,11 +76954,11 @@ Saved to ${options.output}`);
76954
76954
  }
76955
76955
  }
76956
76956
  async function toEvalite(options) {
76957
- const { readFileSync: readFileSync12 } = await import("fs");
76957
+ const { readFileSync: readFileSync13 } = await import("fs");
76958
76958
  const { ctx } = options;
76959
76959
  const outputJson = ctx.format === "json";
76960
76960
  const data2 = JSON.parse(
76961
- readFileSync12(options.input, "utf-8")
76961
+ readFileSync13(options.input, "utf-8")
76962
76962
  );
76963
76963
  const evaliteData = data2.map((d) => ({
76964
76964
  input: d.triggerMessage.body,
@@ -77019,15 +77019,19 @@ init_esm_shims();
77019
77019
 
77020
77020
  // src/commands/config/get.ts
77021
77021
  init_esm_shims();
77022
- import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
77022
+ import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
77023
77023
  import { Decrypter as Decrypter2 } from "age-encryption";
77024
77024
 
77025
+ // src/commands/config/set.ts
77026
+ init_esm_shims();
77027
+ import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
77028
+ import { password, select as select2 } from "@inquirer/prompts";
77029
+ import { Decrypter, Encrypter, identityToRecipient } from "age-encryption";
77030
+
77025
77031
  // src/commands/config/init.ts
77026
77032
  init_esm_shims();
77027
- import { existsSync as existsSync3, mkdirSync, writeFileSync as writeFileSync3 } from "fs";
77028
77033
  import { homedir as homedir2 } from "os";
77029
77034
  import { join as join2 } from "path";
77030
- import { generateIdentity, identityToRecipient } from "age-encryption";
77031
77035
  function getUserConfigDir2() {
77032
77036
  return join2(homedir2(), ".config", "skill");
77033
77037
  }
@@ -77036,68 +77040,27 @@ function getAgeKeyPath() {
77036
77040
  }
77037
77041
  async function configInitAction(ctx, options = {}) {
77038
77042
  const outputJson = options.json === true || ctx.format === "json";
77039
- const keyPath = getAgeKeyPath();
77040
- const configDir = getUserConfigDir2();
77041
- if (existsSync3(keyPath) && !options.force) {
77042
- const result = {
77043
- success: false,
77044
- error: `Age key already exists at ${keyPath}. Use --force to overwrite.`
77045
- };
77046
- if (outputJson) {
77047
- ctx.output.data(result);
77048
- } else {
77049
- ctx.output.error(result.error);
77050
- ctx.output.data(`
77051
- To view your public key: skill config public-key`);
77052
- }
77053
- process.exitCode = EXIT_CODES.usage;
77054
- return;
77055
- }
77056
- try {
77057
- if (!existsSync3(configDir)) {
77058
- mkdirSync(configDir, { recursive: true, mode: 448 });
77059
- }
77060
- const identity = await generateIdentity();
77061
- const recipient = await identityToRecipient(identity);
77062
- writeFileSync3(keyPath, identity, { encoding: "utf8", mode: 384 });
77063
- const result = {
77064
- success: true,
77065
- keyPath,
77066
- publicKey: recipient
77067
- };
77068
- if (outputJson) {
77069
- ctx.output.data(result);
77070
- } else {
77071
- ctx.output.success("Age keypair generated successfully!");
77072
- ctx.output.data(`
77073
- Private key saved to: ${keyPath}`);
77074
- ctx.output.data(`Public key (age recipient): ${recipient}`);
77075
- ctx.output.data(
77076
- "\n\u26A0\uFE0F Keep your private key secure. Anyone with access can decrypt your config."
77077
- );
77078
- ctx.output.data("\nNext steps:");
77079
- ctx.output.data(" 1. Set config values: skill config set KEY=value");
77080
- ctx.output.data(" 2. View config: skill config list");
77081
- }
77082
- } catch (error) {
77083
- const result = {
77084
- success: false,
77085
- error: error instanceof Error ? error.message : "Failed to generate keypair"
77086
- };
77087
- if (outputJson) {
77088
- ctx.output.data(result);
77089
- } else {
77090
- ctx.output.error(`Failed to generate keypair: ${result.error}`);
77091
- }
77092
- process.exitCode = EXIT_CODES.error;
77043
+ const result = {
77044
+ success: false,
77045
+ error: "DEPRECATED: skill config init is no longer needed.\nThe CLI now uses the 1Password age key for encryption.\nUse `skill keys` to manage your personal API keys."
77046
+ };
77047
+ if (outputJson) {
77048
+ ctx.output.data(result);
77049
+ } else {
77050
+ ctx.output.error("\u26A0\uFE0F DEPRECATED: skill config init is no longer needed.");
77051
+ ctx.output.data("");
77052
+ ctx.output.data("The CLI now uses the 1Password age key for encryption.");
77053
+ ctx.output.data("Local age keypairs are no longer required.");
77054
+ ctx.output.data("");
77055
+ ctx.output.data("To manage your personal API keys:");
77056
+ ctx.output.data(" skill keys Interactive setup");
77057
+ ctx.output.data(" skill keys add Add a personal API key");
77058
+ ctx.output.data(" skill keys status Show key provenance");
77093
77059
  }
77060
+ process.exitCode = EXIT_CODES.usage;
77094
77061
  }
77095
77062
 
77096
77063
  // src/commands/config/set.ts
77097
- init_esm_shims();
77098
- import { existsSync as existsSync4, readFileSync as readFileSync2, writeFileSync as writeFileSync4 } from "fs";
77099
- import { password, select as select2 } from "@inquirer/prompts";
77100
- import { Decrypter, Encrypter, identityToRecipient as identityToRecipient2 } from "age-encryption";
77101
77064
  function getEncryptedConfigPath() {
77102
77065
  return `${getUserConfigDir2()}/.env.user.encrypted`;
77103
77066
  }
@@ -77110,7 +77073,7 @@ function parseKeyValue(input2) {
77110
77073
  return { key, value };
77111
77074
  }
77112
77075
  async function readExistingConfig(identity, configPath) {
77113
- if (!existsSync4(configPath)) {
77076
+ if (!existsSync3(configPath)) {
77114
77077
  return {};
77115
77078
  }
77116
77079
  try {
@@ -77137,7 +77100,7 @@ async function readExistingConfig(identity, configPath) {
77137
77100
  async function configSetAction(ctx, keyValue, options = {}) {
77138
77101
  const outputJson = options.json === true || ctx.format === "json";
77139
77102
  const keyPath = getAgeKeyPath();
77140
- if (!existsSync4(keyPath)) {
77103
+ if (!existsSync3(keyPath)) {
77141
77104
  const result = {
77142
77105
  success: false,
77143
77106
  error: "Age key not found. Run: skill config init"
@@ -77189,7 +77152,7 @@ async function configSetAction(ctx, keyValue, options = {}) {
77189
77152
  }
77190
77153
  try {
77191
77154
  const identity = readFileSync2(keyPath, "utf8").trim();
77192
- const recipient = await identityToRecipient2(identity);
77155
+ const recipient = await identityToRecipient(identity);
77193
77156
  const configPath = getEncryptedConfigPath();
77194
77157
  const config = await readExistingConfig(identity, configPath);
77195
77158
  config[parsed.key] = parsed.value;
@@ -77197,7 +77160,7 @@ async function configSetAction(ctx, keyValue, options = {}) {
77197
77160
  const encrypter = new Encrypter();
77198
77161
  encrypter.addRecipient(recipient);
77199
77162
  const encrypted = await encrypter.encrypt(envContent + "\n");
77200
- writeFileSync4(configPath, Buffer.from(encrypted));
77163
+ writeFileSync3(configPath, Buffer.from(encrypted));
77201
77164
  const result = {
77202
77165
  success: true,
77203
77166
  key: parsed.key,
@@ -77224,9 +77187,24 @@ async function configSetAction(ctx, keyValue, options = {}) {
77224
77187
  }
77225
77188
 
77226
77189
  // src/commands/config/get.ts
77190
+ async function getAgeKeyFrom1Password2() {
77191
+ if (!process.env.OP_SERVICE_ACCOUNT_TOKEN) {
77192
+ return null;
77193
+ }
77194
+ try {
77195
+ const { OnePasswordProvider: OnePasswordProvider2 } = await import("./secrets-MGVPGMFJ.js");
77196
+ const op = new OnePasswordProvider2();
77197
+ if (!await op.isAvailable()) {
77198
+ return null;
77199
+ }
77200
+ return await op.resolve("op://Support/skill-cli-age-key/private_key");
77201
+ } catch {
77202
+ return null;
77203
+ }
77204
+ }
77227
77205
  async function decryptConfig(identity) {
77228
77206
  const configPath = getEncryptedConfigPath();
77229
- if (!existsSync5(configPath)) {
77207
+ if (!existsSync4(configPath)) {
77230
77208
  return {};
77231
77209
  }
77232
77210
  const encrypted = readFileSync3(configPath);
@@ -77254,11 +77232,11 @@ async function decryptConfig(identity) {
77254
77232
  }
77255
77233
  async function configGetAction(ctx, key, options = {}) {
77256
77234
  const outputJson = options.json === true || ctx.format === "json";
77257
- const keyPath = getAgeKeyPath();
77258
- if (!existsSync5(keyPath)) {
77235
+ const identity = await getAgeKeyFrom1Password2();
77236
+ if (!identity) {
77259
77237
  const result = {
77260
77238
  success: false,
77261
- error: "Age key not found. Run: skill config init"
77239
+ error: "OP_SERVICE_ACCOUNT_TOKEN not set. Required for encrypted config."
77262
77240
  };
77263
77241
  if (outputJson) {
77264
77242
  ctx.output.data(result);
@@ -77269,7 +77247,6 @@ async function configGetAction(ctx, key, options = {}) {
77269
77247
  return;
77270
77248
  }
77271
77249
  try {
77272
- const identity = readFileSync3(keyPath, "utf8").trim();
77273
77250
  const config = await decryptConfig(identity);
77274
77251
  if (!(key in config)) {
77275
77252
  const result2 = {
@@ -77312,11 +77289,26 @@ async function configGetAction(ctx, key, options = {}) {
77312
77289
 
77313
77290
  // src/commands/config/list.ts
77314
77291
  init_esm_shims();
77315
- import { existsSync as existsSync6, readFileSync as readFileSync4 } from "fs";
77292
+ import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
77316
77293
  import { Decrypter as Decrypter3 } from "age-encryption";
77294
+ async function getAgeKeyFrom1Password3() {
77295
+ if (!process.env.OP_SERVICE_ACCOUNT_TOKEN) {
77296
+ return null;
77297
+ }
77298
+ try {
77299
+ const { OnePasswordProvider: OnePasswordProvider2 } = await import("./secrets-MGVPGMFJ.js");
77300
+ const op = new OnePasswordProvider2();
77301
+ if (!await op.isAvailable()) {
77302
+ return null;
77303
+ }
77304
+ return await op.resolve("op://Support/skill-cli-age-key/private_key");
77305
+ } catch {
77306
+ return null;
77307
+ }
77308
+ }
77317
77309
  async function decryptConfig2(identity) {
77318
77310
  const configPath = getEncryptedConfigPath();
77319
- if (!existsSync6(configPath)) {
77311
+ if (!existsSync5(configPath)) {
77320
77312
  return {};
77321
77313
  }
77322
77314
  const encrypted = readFileSync4(configPath);
@@ -77344,11 +77336,11 @@ async function decryptConfig2(identity) {
77344
77336
  }
77345
77337
  async function configListAction(ctx, options = {}) {
77346
77338
  const outputJson = options.json === true || ctx.format === "json";
77347
- const keyPath = getAgeKeyPath();
77348
- if (!existsSync6(keyPath)) {
77339
+ const identity = await getAgeKeyFrom1Password3();
77340
+ if (!identity) {
77349
77341
  const result = {
77350
77342
  success: false,
77351
- error: "Age key not found. Run: skill config init"
77343
+ error: "OP_SERVICE_ACCOUNT_TOKEN not set. Required for encrypted config."
77352
77344
  };
77353
77345
  if (outputJson) {
77354
77346
  ctx.output.data(result);
@@ -77359,7 +77351,6 @@ async function configListAction(ctx, options = {}) {
77359
77351
  return;
77360
77352
  }
77361
77353
  try {
77362
- const identity = readFileSync4(keyPath, "utf8").trim();
77363
77354
  const config = await decryptConfig2(identity);
77364
77355
  const keys = Object.keys(config);
77365
77356
  if (keys.length === 0) {
@@ -77424,7 +77415,7 @@ var buildContext2 = async (command, json) => {
77424
77415
  };
77425
77416
  function registerConfigCommands(program3) {
77426
77417
  const config = program3.command("config").description("Manage user-specific config overrides (encrypted)");
77427
- config.command("init").description("Generate age keypair for user config encryption").option("--force", "Overwrite existing keypair").option("--json", "Output as JSON").action(async (options, command) => {
77418
+ config.command("init").description("[DEPRECATED] No longer needed - use `skill keys` instead").option("--force", "Overwrite existing keypair").option("--json", "Output as JSON").action(async (options, command) => {
77428
77419
  const ctx = await buildContext2(command, options.json);
77429
77420
  await configInitAction(ctx, options);
77430
77421
  });
@@ -80114,7 +80105,7 @@ init_esm_shims();
80114
80105
  // src/commands/eval-pipeline/run.ts
80115
80106
  init_esm_shims();
80116
80107
  import { createHash as createHash2 } from "crypto";
80117
- import { existsSync as existsSync7, mkdirSync as mkdirSync2, readFileSync as readFileSync5, rmSync, writeFileSync as writeFileSync5 } from "fs";
80108
+ import { existsSync as existsSync6, mkdirSync, readFileSync as readFileSync5, rmSync, writeFileSync as writeFileSync4 } from "fs";
80118
80109
  import { join as join5 } from "path";
80119
80110
  import { readFile as readFile6 } from "fs/promises";
80120
80111
  import { glob as glob4 } from "glob";
@@ -80532,7 +80523,7 @@ function getClassifySourceHash() {
80532
80523
  join5(process.cwd(), "../core/src/pipeline/classify.ts")
80533
80524
  ];
80534
80525
  for (const path of possiblePaths) {
80535
- if (existsSync7(path)) {
80526
+ if (existsSync6(path)) {
80536
80527
  const content = readFileSync5(path, "utf-8");
80537
80528
  return createHash2("md5").update(content).digest("hex");
80538
80529
  }
@@ -80544,7 +80535,7 @@ function getClassifySourceHash() {
80544
80535
  function loadCachedClassify(cacheKey) {
80545
80536
  const cachePath = join5(CACHE_DIR, `${cacheKey}.json`);
80546
80537
  try {
80547
- if (existsSync7(cachePath)) {
80538
+ if (existsSync6(cachePath)) {
80548
80539
  return JSON.parse(readFileSync5(cachePath, "utf-8"));
80549
80540
  }
80550
80541
  } catch {
@@ -80553,17 +80544,17 @@ function loadCachedClassify(cacheKey) {
80553
80544
  }
80554
80545
  function saveCachedClassify(cacheKey, result) {
80555
80546
  try {
80556
- if (!existsSync7(CACHE_DIR)) {
80557
- mkdirSync2(CACHE_DIR, { recursive: true });
80547
+ if (!existsSync6(CACHE_DIR)) {
80548
+ mkdirSync(CACHE_DIR, { recursive: true });
80558
80549
  }
80559
80550
  const cachePath = join5(CACHE_DIR, `${cacheKey}.json`);
80560
- writeFileSync5(cachePath, JSON.stringify(result));
80551
+ writeFileSync4(cachePath, JSON.stringify(result));
80561
80552
  } catch {
80562
80553
  }
80563
80554
  }
80564
80555
  function clearClassifyCache() {
80565
80556
  try {
80566
- if (existsSync7(CACHE_DIR)) {
80557
+ if (existsSync6(CACHE_DIR)) {
80567
80558
  rmSync(CACHE_DIR, { recursive: true, force: true });
80568
80559
  }
80569
80560
  } catch {
@@ -81555,7 +81546,7 @@ function registerEvalPipelineCommands(program3) {
81555
81546
 
81556
81547
  // src/commands/eval-prompt.ts
81557
81548
  init_esm_shims();
81558
- import { existsSync as existsSync8, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "fs";
81549
+ import { existsSync as existsSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
81559
81550
  import { generateText as generateText2, stepCountIs as stepCountIs2, tool as tool4 } from "ai";
81560
81551
  import { z as z5 } from "zod";
81561
81552
  var leakPatterns = [
@@ -81742,7 +81733,7 @@ async function runEval2(ctx, options) {
81742
81733
  try {
81743
81734
  let prompt = SUPPORT_AGENT_PROMPT;
81744
81735
  if (promptPath) {
81745
- if (!existsSync8(promptPath)) {
81736
+ if (!existsSync7(promptPath)) {
81746
81737
  throw new CLIError({
81747
81738
  userMessage: `Prompt file not found: ${promptPath}.`,
81748
81739
  suggestion: "Verify the prompt path and try again."
@@ -81755,7 +81746,7 @@ async function runEval2(ctx, options) {
81755
81746
  } else if (!outputJson) {
81756
81747
  ctx.output.message("Using production prompt");
81757
81748
  }
81758
- if (!existsSync8(datasetPath)) {
81749
+ if (!existsSync7(datasetPath)) {
81759
81750
  throw new CLIError({
81760
81751
  userMessage: `Dataset not found: ${datasetPath}.`,
81761
81752
  suggestion: "Provide a valid dataset file path."
@@ -81838,7 +81829,7 @@ async function runEval2(ctx, options) {
81838
81829
  });
81839
81830
  }
81840
81831
  if (outputPath) {
81841
- writeFileSync6(outputPath, JSON.stringify(results, null, 2));
81832
+ writeFileSync5(outputPath, JSON.stringify(results, null, 2));
81842
81833
  if (!outputJson) {
81843
81834
  ctx.output.success(`Saved results to ${outputPath}`);
81844
81835
  }
@@ -81867,7 +81858,7 @@ async function comparePrompts(ctx, options) {
81867
81858
  try {
81868
81859
  const baselinePrompt = baseline ? readFileSync6(baseline, "utf-8") : SUPPORT_AGENT_PROMPT;
81869
81860
  const candidatePrompt = readFileSync6(candidate, "utf-8");
81870
- if (!existsSync8(datasetPath)) {
81861
+ if (!existsSync7(datasetPath)) {
81871
81862
  throw new CLIError({
81872
81863
  userMessage: `Dataset not found: ${datasetPath}.`,
81873
81864
  suggestion: "Provide a valid dataset file path."
@@ -82015,8 +82006,8 @@ init_esm_shims();
82015
82006
 
82016
82007
  // src/commands/faq/classify.ts
82017
82008
  init_esm_shims();
82018
- import { appendFileSync, existsSync as existsSync9, mkdirSync as mkdirSync3, readFileSync as readFileSync7 } from "fs";
82019
- import { dirname as dirname3, join as join7, resolve as resolve3 } from "path";
82009
+ import { appendFileSync, existsSync as existsSync8, mkdirSync as mkdirSync2, readFileSync as readFileSync7 } from "fs";
82010
+ import { dirname as dirname2, join as join7, resolve as resolve3 } from "path";
82020
82011
  import { generateObject } from "ai";
82021
82012
  import { z as z6 } from "zod";
82022
82013
  var PROJECT_ROOT = resolve3(__dirname, "../../../..");
@@ -82083,7 +82074,7 @@ async function loadConversationsFromParquet(parquetPath) {
82083
82074
  }
82084
82075
  function loadExistingClassifications(outputPath) {
82085
82076
  const classifiedIds = /* @__PURE__ */ new Set();
82086
- if (!existsSync9(outputPath)) {
82077
+ if (!existsSync8(outputPath)) {
82087
82078
  return classifiedIds;
82088
82079
  }
82089
82080
  const content = readFileSync7(outputPath, "utf-8");
@@ -82201,7 +82192,7 @@ async function faqClassify(ctx, options) {
82201
82192
  ctx.output.data(` Dry run: ${options.dryRun ?? false}`);
82202
82193
  ctx.output.data("");
82203
82194
  }
82204
- if (!existsSync9(parquetPath)) {
82195
+ if (!existsSync8(parquetPath)) {
82205
82196
  handleFaqClassifyError(
82206
82197
  ctx,
82207
82198
  new CLIError({
@@ -82212,7 +82203,7 @@ async function faqClassify(ctx, options) {
82212
82203
  );
82213
82204
  return;
82214
82205
  }
82215
- if (!existsSync9(taxonomyPath)) {
82206
+ if (!existsSync8(taxonomyPath)) {
82216
82207
  handleFaqClassifyError(
82217
82208
  ctx,
82218
82209
  new CLIError({
@@ -82223,9 +82214,9 @@ async function faqClassify(ctx, options) {
82223
82214
  );
82224
82215
  return;
82225
82216
  }
82226
- const outputDir = dirname3(outputPath);
82227
- if (!existsSync9(outputDir)) {
82228
- mkdirSync3(outputDir, { recursive: true });
82217
+ const outputDir = dirname2(outputPath);
82218
+ if (!existsSync8(outputDir)) {
82219
+ mkdirSync2(outputDir, { recursive: true });
82229
82220
  }
82230
82221
  if (!outputJson) ctx.output.data("\u{1F4DA} Loading taxonomy...");
82231
82222
  const taxonomy = JSON.parse(readFileSync7(taxonomyPath, "utf-8"));
@@ -82393,18 +82384,18 @@ function registerFaqClassifyCommands(program3) {
82393
82384
 
82394
82385
  // src/commands/faq/cluster.ts
82395
82386
  init_esm_shims();
82396
- import { existsSync as existsSync11 } from "fs";
82387
+ import { existsSync as existsSync10 } from "fs";
82397
82388
  import { join as join9, resolve as resolve4 } from "path";
82398
82389
 
82399
82390
  // ../core/src/faq/production-clusterer.ts
82400
82391
  init_esm_shims();
82401
- import { existsSync as existsSync10, mkdirSync as mkdirSync4, readFileSync as readFileSync8, writeFileSync as writeFileSync7 } from "fs";
82392
+ import { existsSync as existsSync9, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
82402
82393
  import { join as join8 } from "path";
82403
82394
  function readPhase0Assignments(phase0Path) {
82404
82395
  const assignmentsPath = join8(phase0Path, "clusters/v1/assignments.json");
82405
- if (!existsSync10(assignmentsPath)) {
82396
+ if (!existsSync9(assignmentsPath)) {
82406
82397
  const latestPath = join8(phase0Path, "clusters/latest/assignments.json");
82407
- if (!existsSync10(latestPath)) {
82398
+ if (!existsSync9(latestPath)) {
82408
82399
  throw new Error(`Phase 0 assignments not found at ${assignmentsPath}`);
82409
82400
  }
82410
82401
  const content2 = readFileSync8(latestPath, "utf-8");
@@ -82415,9 +82406,9 @@ function readPhase0Assignments(phase0Path) {
82415
82406
  }
82416
82407
  function readPhase0Labels(phase0Path) {
82417
82408
  const labelsPath = join8(phase0Path, "clusters/v1/labels.json");
82418
- if (!existsSync10(labelsPath)) {
82409
+ if (!existsSync9(labelsPath)) {
82419
82410
  const latestPath = join8(phase0Path, "clusters/latest/labels.json");
82420
- if (!existsSync10(latestPath)) {
82411
+ if (!existsSync9(latestPath)) {
82421
82412
  throw new Error(`Phase 0 labels not found at ${labelsPath}`);
82422
82413
  }
82423
82414
  const content2 = readFileSync8(latestPath, "utf-8");
@@ -82430,9 +82421,9 @@ function readPhase0Labels(phase0Path) {
82430
82421
  }
82431
82422
  function readPhase0Metrics(phase0Path) {
82432
82423
  const metricsPath = join8(phase0Path, "clusters/v1/metrics.json");
82433
- if (!existsSync10(metricsPath)) {
82424
+ if (!existsSync9(metricsPath)) {
82434
82425
  const latestPath = join8(phase0Path, "clusters/latest/metrics.json");
82435
- if (!existsSync10(latestPath)) {
82426
+ if (!existsSync9(latestPath)) {
82436
82427
  throw new Error(`Phase 0 metrics not found at ${metricsPath}`);
82437
82428
  }
82438
82429
  return JSON.parse(readFileSync8(latestPath, "utf-8"));
@@ -82553,17 +82544,17 @@ async function generateProductionClustering(options) {
82553
82544
  }
82554
82545
  function writeProductionArtifacts(result, outputPath) {
82555
82546
  const versionPath = join8(outputPath, result.version);
82556
- if (!existsSync10(versionPath)) {
82557
- mkdirSync4(versionPath, { recursive: true });
82547
+ if (!existsSync9(versionPath)) {
82548
+ mkdirSync3(versionPath, { recursive: true });
82558
82549
  }
82559
82550
  const resultPath = join8(versionPath, "clustering-result.json");
82560
- writeFileSync7(resultPath, JSON.stringify(result, null, 2));
82551
+ writeFileSync6(resultPath, JSON.stringify(result, null, 2));
82561
82552
  console.log(`\u2705 Written: ${resultPath}`);
82562
82553
  const assignmentsPath = join8(versionPath, "assignments.json");
82563
- writeFileSync7(assignmentsPath, JSON.stringify(result.assignments, null, 2));
82554
+ writeFileSync6(assignmentsPath, JSON.stringify(result.assignments, null, 2));
82564
82555
  console.log(`\u2705 Written: ${assignmentsPath}`);
82565
82556
  const clustersPath = join8(versionPath, "clusters.json");
82566
- writeFileSync7(
82557
+ writeFileSync6(
82567
82558
  clustersPath,
82568
82559
  JSON.stringify(
82569
82560
  {
@@ -82589,14 +82580,14 @@ function writeProductionArtifacts(result, outputPath) {
82589
82580
  priorityTier: c.priorityTier
82590
82581
  }))
82591
82582
  };
82592
- writeFileSync7(summaryPath, JSON.stringify(summary, null, 2));
82583
+ writeFileSync6(summaryPath, JSON.stringify(summary, null, 2));
82593
82584
  console.log(`\u2705 Written: ${summaryPath}`);
82594
82585
  const latestPath = join8(outputPath, "latest");
82595
- if (existsSync10(latestPath)) {
82586
+ if (existsSync9(latestPath)) {
82596
82587
  const { rmSync: rmSync2 } = __require("fs");
82597
82588
  rmSync2(latestPath, { recursive: true, force: true });
82598
82589
  }
82599
- mkdirSync4(latestPath, { recursive: true });
82590
+ mkdirSync3(latestPath, { recursive: true });
82600
82591
  for (const file of [
82601
82592
  "clustering-result.json",
82602
82593
  "assignments.json",
@@ -82605,7 +82596,7 @@ function writeProductionArtifacts(result, outputPath) {
82605
82596
  ]) {
82606
82597
  const src = join8(versionPath, file);
82607
82598
  const dst = join8(latestPath, file);
82608
- writeFileSync7(dst, readFileSync8(src));
82599
+ writeFileSync6(dst, readFileSync8(src));
82609
82600
  }
82610
82601
  console.log(`\u2705 Updated: ${latestPath}`);
82611
82602
  }
@@ -82663,19 +82654,19 @@ function validatePaths(phase0Path) {
82663
82654
  const assignmentsPath = join9(phase0Path, "clusters/v1/assignments.json");
82664
82655
  const labelsPath = join9(phase0Path, "clusters/v1/labels.json");
82665
82656
  const metricsPath = join9(phase0Path, "clusters/v1/metrics.json");
82666
- if (!existsSync11(assignmentsPath)) {
82657
+ if (!existsSync10(assignmentsPath)) {
82667
82658
  throw new CLIError({
82668
82659
  userMessage: `Phase 0 assignments not found at ${assignmentsPath}.`,
82669
82660
  suggestion: "Run Phase 0 clustering first or specify the correct --phase0-path."
82670
82661
  });
82671
82662
  }
82672
- if (!existsSync11(labelsPath)) {
82663
+ if (!existsSync10(labelsPath)) {
82673
82664
  throw new CLIError({
82674
82665
  userMessage: `Phase 0 labels not found at ${labelsPath}.`,
82675
82666
  suggestion: "Verify the --phase0-path points to valid artifacts."
82676
82667
  });
82677
82668
  }
82678
- if (!existsSync11(metricsPath)) {
82669
+ if (!existsSync10(metricsPath)) {
82679
82670
  throw new CLIError({
82680
82671
  userMessage: `Phase 0 metrics not found at ${metricsPath}.`,
82681
82672
  suggestion: "Verify the --phase0-path points to valid artifacts."
@@ -82756,12 +82747,12 @@ function registerFaqClusterCommands(program3) {
82756
82747
 
82757
82748
  // src/commands/faq/extract.ts
82758
82749
  init_esm_shims();
82759
- import { existsSync as existsSync13 } from "fs";
82750
+ import { existsSync as existsSync12 } from "fs";
82760
82751
  import { join as join11, resolve as resolve5 } from "path";
82761
82752
 
82762
82753
  // ../core/src/faq/extractor.ts
82763
82754
  init_esm_shims();
82764
- import { existsSync as existsSync12, mkdirSync as mkdirSync5, readFileSync as readFileSync9, writeFileSync as writeFileSync8 } from "fs";
82755
+ import { existsSync as existsSync11, mkdirSync as mkdirSync4, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
82765
82756
  import { join as join10 } from "path";
82766
82757
 
82767
82758
  // ../core/src/faq/review.ts
@@ -83377,11 +83368,11 @@ async function extractFaqCandidates(options) {
83377
83368
  }
83378
83369
  function writeExtractionArtifacts(result, outputPath) {
83379
83370
  const versionPath = join10(outputPath, result.version);
83380
- if (!existsSync12(versionPath)) {
83381
- mkdirSync5(versionPath, { recursive: true });
83371
+ if (!existsSync11(versionPath)) {
83372
+ mkdirSync4(versionPath, { recursive: true });
83382
83373
  }
83383
83374
  const resultPath = join10(versionPath, "extraction-result.json");
83384
- writeFileSync8(resultPath, JSON.stringify(result, null, 2));
83375
+ writeFileSync7(resultPath, JSON.stringify(result, null, 2));
83385
83376
  console.log(`\u2705 Written: ${resultPath}`);
83386
83377
  const candidatesPath = join10(versionPath, "candidates.json");
83387
83378
  const candidatesData = {
@@ -83401,10 +83392,10 @@ function writeExtractionArtifacts(result, outputPath) {
83401
83392
  sourceConversations: c.sourceConversations.slice(0, 5)
83402
83393
  }))
83403
83394
  };
83404
- writeFileSync8(candidatesPath, JSON.stringify(candidatesData, null, 2));
83395
+ writeFileSync7(candidatesPath, JSON.stringify(candidatesData, null, 2));
83405
83396
  console.log(`\u2705 Written: ${candidatesPath}`);
83406
83397
  const statsPath = join10(versionPath, "stats.json");
83407
- writeFileSync8(
83398
+ writeFileSync7(
83408
83399
  statsPath,
83409
83400
  JSON.stringify(
83410
83401
  {
@@ -83418,11 +83409,11 @@ function writeExtractionArtifacts(result, outputPath) {
83418
83409
  );
83419
83410
  console.log(`\u2705 Written: ${statsPath}`);
83420
83411
  const latestPath = join10(outputPath, "latest");
83421
- if (existsSync12(latestPath)) {
83412
+ if (existsSync11(latestPath)) {
83422
83413
  const { rmSync: rmSync2 } = __require("fs");
83423
83414
  rmSync2(latestPath, { recursive: true, force: true });
83424
83415
  }
83425
- mkdirSync5(latestPath, { recursive: true });
83416
+ mkdirSync4(latestPath, { recursive: true });
83426
83417
  for (const file of [
83427
83418
  "extraction-result.json",
83428
83419
  "candidates.json",
@@ -83430,8 +83421,8 @@ function writeExtractionArtifacts(result, outputPath) {
83430
83421
  ]) {
83431
83422
  const src = join10(versionPath, file);
83432
83423
  const dst = join10(latestPath, file);
83433
- if (existsSync12(src)) {
83434
- writeFileSync8(dst, readFileSync9(src));
83424
+ if (existsSync11(src)) {
83425
+ writeFileSync7(dst, readFileSync9(src));
83435
83426
  }
83436
83427
  }
83437
83428
  console.log(`\u2705 Updated: ${latestPath}`);
@@ -83495,13 +83486,13 @@ var DEFAULT_GOLDEN_PATH = join11(
83495
83486
  var DEFAULT_OUTPUT_PATH3 = join11(PROJECT_ROOT3, "artifacts/phase-1/extraction");
83496
83487
  var DEFAULT_CACHE_PATH = `${process.env.HOME}/skill/data/front-cache.db`;
83497
83488
  function validatePaths2(ctx, clusteringPath, goldenPath, outputJson) {
83498
- if (!existsSync13(clusteringPath)) {
83489
+ if (!existsSync12(clusteringPath)) {
83499
83490
  throw new CLIError({
83500
83491
  userMessage: `Clustering result not found at ${clusteringPath}.`,
83501
83492
  suggestion: "Run `bun src/index.ts faq cluster` first to generate clustering."
83502
83493
  });
83503
83494
  }
83504
- if (goldenPath && !existsSync13(goldenPath)) {
83495
+ if (goldenPath && !existsSync12(goldenPath)) {
83505
83496
  if (!outputJson) {
83506
83497
  ctx.output.warn(`Golden responses not found at ${goldenPath}`);
83507
83498
  ctx.output.warn("Golden matching will be disabled.");
@@ -83530,7 +83521,7 @@ async function faqExtract(ctx, options) {
83530
83521
  ctx.output.data("");
83531
83522
  }
83532
83523
  validatePaths2(ctx, clusteringPath, goldenPath, outputJson);
83533
- if (!existsSync13(cachePath)) {
83524
+ if (!existsSync12(cachePath)) {
83534
83525
  const cliError = new CLIError({
83535
83526
  userMessage: `DuckDB cache not found at ${cachePath}.`,
83536
83527
  suggestion: "Run `bun src/index.ts front-cache sync` first to populate cache."
@@ -83552,7 +83543,7 @@ async function faqExtract(ctx, options) {
83552
83543
  }
83553
83544
  const extractionOptions = {
83554
83545
  clusteringPath,
83555
- goldenPath: existsSync13(goldenPath) ? goldenPath : void 0,
83546
+ goldenPath: existsSync12(goldenPath) ? goldenPath : void 0,
83556
83547
  source,
83557
83548
  outputPath,
83558
83549
  version,
@@ -83672,7 +83663,7 @@ function registerFaqExtractCommands(program3) {
83672
83663
 
83673
83664
  // src/commands/faq/mine.ts
83674
83665
  init_esm_shims();
83675
- import { writeFileSync as writeFileSync9 } from "fs";
83666
+ import { writeFileSync as writeFileSync8 } from "fs";
83676
83667
 
83677
83668
  // ../core/src/faq/index.ts
83678
83669
  init_esm_shims();
@@ -92489,7 +92480,7 @@ async function faqMine(ctx, options) {
92489
92480
  }))
92490
92481
  };
92491
92482
  if (options.export) {
92492
- writeFileSync9(options.export, JSON.stringify(rawData, null, 2), "utf-8");
92483
+ writeFileSync8(options.export, JSON.stringify(rawData, null, 2), "utf-8");
92493
92484
  if (outputJson) {
92494
92485
  ctx.output.data({
92495
92486
  success: true,
@@ -92563,7 +92554,7 @@ async function faqMine(ctx, options) {
92563
92554
  generatedAt: c.generatedAt.toISOString()
92564
92555
  }))
92565
92556
  };
92566
- writeFileSync9(
92557
+ writeFileSync8(
92567
92558
  options.export,
92568
92559
  JSON.stringify(exportData, null, 2),
92569
92560
  "utf-8"
@@ -92626,7 +92617,7 @@ function registerFaqMineCommands(program3) {
92626
92617
  // src/commands/faq/review.ts
92627
92618
  init_esm_shims();
92628
92619
  import { spawnSync } from "child_process";
92629
- import { existsSync as existsSync14, readFileSync as readFileSync10, unlinkSync, writeFileSync as writeFileSync10 } from "fs";
92620
+ import { existsSync as existsSync13, readFileSync as readFileSync10, unlinkSync, writeFileSync as writeFileSync9 } from "fs";
92630
92621
  import { tmpdir } from "os";
92631
92622
  import { join as join12 } from "path";
92632
92623
  import { confirm as confirm2, select as select3 } from "@inquirer/prompts";
@@ -92704,7 +92695,7 @@ Save and close the editor when done.
92704
92695
  The sections are separated by "## Question" and "## Answer" headers.
92705
92696
  -->
92706
92697
  `;
92707
- writeFileSync10(tmpFile, content, "utf-8");
92698
+ writeFileSync9(tmpFile, content, "utf-8");
92708
92699
  try {
92709
92700
  const result = spawnSync(editor, [tmpFile], {
92710
92701
  stdio: "inherit",
@@ -92732,7 +92723,7 @@ The sections are separated by "## Question" and "## Answer" headers.
92732
92723
  answer: editedAnswer
92733
92724
  };
92734
92725
  } finally {
92735
- if (existsSync14(tmpFile)) {
92726
+ if (existsSync13(tmpFile)) {
92736
92727
  unlinkSync(tmpFile);
92737
92728
  }
92738
92729
  }
@@ -94927,7 +94918,7 @@ function registerInboxCommand(front) {
94927
94918
 
94928
94919
  // src/commands/front/pull-conversations.ts
94929
94920
  init_esm_shims();
94930
- import { writeFileSync as writeFileSync11 } from "fs";
94921
+ import { writeFileSync as writeFileSync10 } from "fs";
94931
94922
  async function pullConversations(ctx, options) {
94932
94923
  const { inbox, limit: limit2 = 50, output, filter: filter4 } = options;
94933
94924
  const outputJson = options.json === true || ctx.format === "json";
@@ -95060,7 +95051,7 @@ Built ${samples.length} eval samples`);
95060
95051
  ctx.output.data(` ${cat}: ${count}`);
95061
95052
  }
95062
95053
  if (output) {
95063
- writeFileSync11(output, JSON.stringify(samples, null, 2));
95054
+ writeFileSync10(output, JSON.stringify(samples, null, 2));
95064
95055
  ctx.output.data(`
95065
95056
  Saved to ${output}`);
95066
95057
  } else if (outputJson) {
@@ -103241,7 +103232,7 @@ var compile3 = wrapCompile(compile2);
103241
103232
  var _compileUnsafe = wrapCompile(compileUnsafe);
103242
103233
  var _compileToken = wrapCompile(compileToken);
103243
103234
  function getSelectorFunc(searchFunc) {
103244
- return function select6(query, elements, options) {
103235
+ return function select7(query, elements, options) {
103245
103236
  const opts = convertOptionFormats(options);
103246
103237
  if (typeof query !== "function") {
103247
103238
  query = compileUnsafe(query, opts, elements);
@@ -113895,6 +113886,216 @@ function registerKbCommands(program3) {
113895
113886
  });
113896
113887
  }
113897
113888
 
113889
+ // src/commands/keys/index.ts
113890
+ init_esm_shims();
113891
+ import { existsSync as existsSync14, readFileSync as readFileSync12 } from "fs";
113892
+ import { password as password2, select as select5 } from "@inquirer/prompts";
113893
+ import { Decrypter as Decrypter4 } from "age-encryption";
113894
+ var buildContext4 = async (command, json) => {
113895
+ const opts = typeof command.optsWithGlobals === "function" ? command.optsWithGlobals() : {
113896
+ ...command.parent?.opts(),
113897
+ ...command.opts()
113898
+ };
113899
+ return createContext({
113900
+ format: json ? "json" : opts.format,
113901
+ verbose: opts.verbose,
113902
+ quiet: opts.quiet
113903
+ });
113904
+ };
113905
+ async function getUserConfiguredKeys() {
113906
+ const keyPath = getAgeKeyPath();
113907
+ const configPath = getEncryptedConfigPath();
113908
+ if (!existsSync14(keyPath) || !existsSync14(configPath)) {
113909
+ return /* @__PURE__ */ new Set();
113910
+ }
113911
+ try {
113912
+ const identity = readFileSync12(keyPath, "utf8").trim();
113913
+ const encrypted = readFileSync12(configPath);
113914
+ const decrypter = new Decrypter4();
113915
+ decrypter.addIdentity(identity);
113916
+ const decrypted = await decrypter.decrypt(encrypted, "text");
113917
+ const keys = /* @__PURE__ */ new Set();
113918
+ for (const line of decrypted.split("\n")) {
113919
+ const trimmed = line.trim();
113920
+ if (!trimmed || trimmed.startsWith("#")) continue;
113921
+ const eqIndex = trimmed.indexOf("=");
113922
+ if (eqIndex > 0) {
113923
+ keys.add(trimmed.substring(0, eqIndex));
113924
+ }
113925
+ }
113926
+ return keys;
113927
+ } catch {
113928
+ return /* @__PURE__ */ new Set();
113929
+ }
113930
+ }
113931
+ async function showKeyStatus(ctx) {
113932
+ const userKeys = await getUserConfiguredKeys();
113933
+ const allKeys = Object.keys(SECRET_REFS);
113934
+ ctx.output.data("\n\u{1F4CB} API Key Status");
113935
+ ctx.output.data("\u2500".repeat(60));
113936
+ const personal = [];
113937
+ const shared = [];
113938
+ const notSet = [];
113939
+ for (const key of allKeys) {
113940
+ const provenance = getKeyProvenance(key);
113941
+ const hasUserKey = userKeys.has(key);
113942
+ const hasEnvValue = !!process.env[key];
113943
+ if (hasUserKey) {
113944
+ personal.push(key);
113945
+ } else if (provenance === "shipped" || hasEnvValue) {
113946
+ shared.push(key);
113947
+ } else {
113948
+ notSet.push(key);
113949
+ }
113950
+ }
113951
+ if (personal.length > 0) {
113952
+ ctx.output.data("\n\u{1F510} Your personal keys:");
113953
+ for (const key of personal) {
113954
+ ctx.output.data(` \u2713 ${key}`);
113955
+ }
113956
+ }
113957
+ if (shared.length > 0) {
113958
+ ctx.output.data("\n\u{1F3E2} Using shared/shipped keys:");
113959
+ for (const key of shared.slice(0, 5)) {
113960
+ ctx.output.data(` \u2022 ${key}`);
113961
+ }
113962
+ if (shared.length > 5) {
113963
+ ctx.output.data(` \u2022 ... and ${shared.length - 5} more`);
113964
+ }
113965
+ }
113966
+ if (notSet.length > 0 && notSet.length < 10) {
113967
+ ctx.output.data("\n\u26A0\uFE0F Not configured:");
113968
+ for (const key of notSet) {
113969
+ ctx.output.data(` \u25CB ${key}`);
113970
+ }
113971
+ }
113972
+ ctx.output.data("");
113973
+ }
113974
+ async function interactiveKeySetup(ctx) {
113975
+ const keyPath = getAgeKeyPath();
113976
+ if (!existsSync14(keyPath)) {
113977
+ ctx.output.data("\n\u{1F511} First time setup - creating your encryption key...\n");
113978
+ await configInitAction(ctx, { json: false });
113979
+ ctx.output.data("");
113980
+ }
113981
+ await showKeyStatus(ctx);
113982
+ ctx.output.data("\u2500".repeat(60));
113983
+ ctx.output.data("");
113984
+ try {
113985
+ const action = await select5({
113986
+ message: "What would you like to do?",
113987
+ choices: [
113988
+ { name: "Add/update a personal API key", value: "add" },
113989
+ { name: "View all available keys", value: "list" },
113990
+ { name: "Exit", value: "exit" }
113991
+ ]
113992
+ });
113993
+ if (action === "exit") {
113994
+ return;
113995
+ }
113996
+ if (action === "list") {
113997
+ ctx.output.data("\n\u{1F4CB} Available API keys you can personalize:\n");
113998
+ const keys = Object.keys(SECRET_REFS);
113999
+ for (const key of keys) {
114000
+ ctx.output.data(` \u2022 ${key}`);
114001
+ }
114002
+ ctx.output.data("\nRun `skill keys add` to set one.");
114003
+ return;
114004
+ }
114005
+ if (action === "add") {
114006
+ const selectedKey = await select5({
114007
+ message: "Which key do you want to set?",
114008
+ choices: Object.keys(SECRET_REFS).map((key) => ({
114009
+ name: key,
114010
+ value: key
114011
+ }))
114012
+ });
114013
+ const value = await password2({
114014
+ message: `Enter your ${selectedKey}:`
114015
+ });
114016
+ if (!value) {
114017
+ ctx.output.data("Cancelled - no value provided.");
114018
+ return;
114019
+ }
114020
+ await configSetAction(ctx, `${selectedKey}=${value}`, { json: false });
114021
+ }
114022
+ } catch (error) {
114023
+ if (error instanceof Error && (error.message.includes("User force closed") || error.message.includes("canceled"))) {
114024
+ ctx.output.data("\nCancelled.");
114025
+ return;
114026
+ }
114027
+ throw error;
114028
+ }
114029
+ }
114030
+ function registerKeysCommands(program3) {
114031
+ const keys = program3.command("keys").description(
114032
+ "Manage your personal API keys\n\n Use your own API keys instead of shared defaults.\n Keys are encrypted and stored in ~/.config/skill/\n\n Examples:\n skill keys Interactive setup\n skill keys status Show which keys are personal vs shared\n skill keys add Add a personal API key"
114033
+ ).action(async (_options, command) => {
114034
+ const ctx = await buildContext4(command, false);
114035
+ if (!process.stdin.isTTY) {
114036
+ ctx.output.error(
114037
+ "Interactive mode requires a TTY. Use `skill keys add KEY=value` for scripting."
114038
+ );
114039
+ return;
114040
+ }
114041
+ await interactiveKeySetup(ctx);
114042
+ });
114043
+ keys.command("status").description("Show which API keys are personal vs shared").option("--json", "Output as JSON").action(async (options, command) => {
114044
+ const ctx = await buildContext4(command, options.json);
114045
+ if (options.json || ctx.format === "json") {
114046
+ const userKeys = await getUserConfiguredKeys();
114047
+ const allKeys = Object.keys(SECRET_REFS);
114048
+ const status = {};
114049
+ for (const key of allKeys) {
114050
+ const provenance = getKeyProvenance(key);
114051
+ if (userKeys.has(key)) {
114052
+ status[key] = "personal";
114053
+ } else if (provenance === "shipped" || process.env[key]) {
114054
+ status[key] = "shared";
114055
+ } else {
114056
+ status[key] = "not_set";
114057
+ }
114058
+ }
114059
+ ctx.output.data({ keys: status });
114060
+ } else {
114061
+ await showKeyStatus(ctx);
114062
+ }
114063
+ });
114064
+ keys.command("add [key-value]").description(
114065
+ "Add a personal API key\n\n Interactive: skill keys add\n Direct: skill keys add LINEAR_API_KEY=lin_xxx"
114066
+ ).option("--json", "Output as JSON").action(async (keyValue, options, command) => {
114067
+ const ctx = await buildContext4(command, options.json);
114068
+ const keyPath = getAgeKeyPath();
114069
+ if (!existsSync14(keyPath)) {
114070
+ if (process.stdin.isTTY && !options.json) {
114071
+ ctx.output.data(
114072
+ "\u{1F511} First time setup - creating your encryption key...\n"
114073
+ );
114074
+ }
114075
+ await configInitAction(ctx, { json: options.json });
114076
+ }
114077
+ await configSetAction(ctx, keyValue, options);
114078
+ });
114079
+ keys.command("list").description("List your personal API keys (names only, values hidden)").option("--show-values", "Show decrypted values").option("--json", "Output as JSON").action(async (options, command) => {
114080
+ const ctx = await buildContext4(command, options.json);
114081
+ const userKeys = await getUserConfiguredKeys();
114082
+ if (options.json || ctx.format === "json") {
114083
+ ctx.output.data({ personalKeys: Array.from(userKeys) });
114084
+ } else {
114085
+ if (userKeys.size === 0) {
114086
+ ctx.output.data("No personal keys configured.");
114087
+ ctx.output.data("\nRun `skill keys add` to set one.");
114088
+ } else {
114089
+ ctx.output.data("\n\u{1F510} Your personal API keys:\n");
114090
+ for (const key of userKeys) {
114091
+ ctx.output.data(` \u2022 ${key}`);
114092
+ }
114093
+ ctx.output.data("");
114094
+ }
114095
+ }
114096
+ });
114097
+ }
114098
+
113898
114099
  // src/commands/linear/index.ts
113899
114100
  init_esm_shims();
113900
114101
 
@@ -113911,7 +114112,7 @@ function requirePersonalKey(keyName) {
113911
114112
  throw new CLIError({
113912
114113
  userMessage: `Write operations require a personal API key for ${keyName}.`,
113913
114114
  exitCode: EXIT_CODES.auth,
113914
- suggestion: "Run 'skill config init' to set up your personal keys.",
114115
+ suggestion: "Run 'skill keys add' to set up your personal keys.",
113915
114116
  debugMessage: `Key provenance for ${keyName}: ${provenance ?? "undefined"}`
113916
114117
  });
113917
114118
  }
@@ -113947,8 +114148,8 @@ function hateoasWrap2(opts) {
113947
114148
  return response;
113948
114149
  }
113949
114150
  var WRITE_ACTION_META = {
113950
- personal_key_hint: "\u26A0\uFE0F Write operations require a personal LINEAR_API_KEY. Run `skill config init` to set up your keys.",
113951
- setup_command: "skill config init"
114151
+ personal_key_hint: "\u26A0\uFE0F Write operations require a personal LINEAR_API_KEY. Run `skill keys add` to set up your keys.",
114152
+ setup_command: "skill keys add"
113952
114153
  };
113953
114154
  function issueLinks(identifier, teamKey) {
113954
114155
  const links = [
@@ -114809,7 +115010,7 @@ async function getIssue(ctx, id) {
114809
115010
  ctx.output.data(` \u2022 Close: skill linear close ${issue.identifier}`);
114810
115011
  ctx.output.data("");
114811
115012
  ctx.output.data(" \u26A0\uFE0F Write operations require a personal LINEAR_API_KEY.");
114812
- ctx.output.data(" Run `skill config init` to set up your keys.");
115013
+ ctx.output.data(" Run `skill keys add` to set up your keys.");
114813
115014
  ctx.output.data("");
114814
115015
  } catch (error) {
114815
115016
  const cliError = error instanceof CLIError ? error : new CLIError({
@@ -116738,7 +116939,7 @@ async function deleteMemory(ctx, id, options) {
116738
116939
  }
116739
116940
 
116740
116941
  // src/commands/memory/index.ts
116741
- var buildContext4 = async (command, json) => {
116942
+ var buildContext5 = async (command, json) => {
116742
116943
  const opts = typeof command.optsWithGlobals === "function" ? command.optsWithGlobals() : {
116743
116944
  ...command.parent?.opts(),
116744
116945
  ...command.opts()
@@ -116752,42 +116953,42 @@ var buildContext4 = async (command, json) => {
116752
116953
  function registerMemoryCommands(program3) {
116753
116954
  const memory = program3.command("memory").description("Manage semantic memory for agent learning");
116754
116955
  memory.command("store").description("Store a new memory").argument("<content>", "Memory content to store").option("--tags <tags>", "Comma-separated tags").option("--collection <collection>", "Collection name (default: learnings)").option("--app <app>", "App slug to associate with memory").option("--json", "Output as JSON").action(async (content, options, command) => {
116755
- const ctx = await buildContext4(command, options.json);
116956
+ const ctx = await buildContext5(command, options.json);
116756
116957
  await store(ctx, content, options);
116757
116958
  });
116758
116959
  memory.command("find").description("Search memories by semantic similarity").argument("<query>", "Search query text").option("--limit <number>", "Max results (1-100, default: 10)").option("--collection <collection>", "Collection name (default: learnings)").option("--app <app>", "Filter by app slug").option(
116759
116960
  "--min-confidence <confidence>",
116760
116961
  "Minimum confidence threshold (0-1, default: 0.5)"
116761
116962
  ).option("--json", "Output as JSON").action(async (query, options, command) => {
116762
- const ctx = await buildContext4(command, options.json);
116963
+ const ctx = await buildContext5(command, options.json);
116763
116964
  await find5(ctx, query, options);
116764
116965
  });
116765
116966
  memory.command("get").description("Get a specific memory by ID").argument("<id>", "Memory ID").option("--collection <collection>", "Collection name (default: learnings)").option("--json", "Output as JSON").action(async (id, options, command) => {
116766
- const ctx = await buildContext4(command, options.json);
116967
+ const ctx = await buildContext5(command, options.json);
116767
116968
  await get2(ctx, id, options);
116768
116969
  });
116769
116970
  memory.command("validate").description("Validate a memory (resets decay clock)").argument("<id>", "Memory ID").option("--collection <collection>", "Collection name (default: learnings)").option("--json", "Output as JSON").action(async (id, options, command) => {
116770
- const ctx = await buildContext4(command, options.json);
116971
+ const ctx = await buildContext5(command, options.json);
116771
116972
  await validate2(ctx, id, options);
116772
116973
  });
116773
116974
  memory.command("upvote").description("Upvote a memory").argument("<id>", "Memory ID").option("--collection <collection>", "Collection name (default: learnings)").option("--reason <reason>", "Optional reason for upvote").option("--json", "Output as JSON").action(async (id, options, command) => {
116774
- const ctx = await buildContext4(command, options.json);
116975
+ const ctx = await buildContext5(command, options.json);
116775
116976
  await upvote(ctx, id, options);
116776
116977
  });
116777
116978
  memory.command("downvote").description("Downvote a memory").argument("<id>", "Memory ID").option("--collection <collection>", "Collection name (default: learnings)").option("--reason <reason>", "Optional reason for downvote").option("--json", "Output as JSON").action(async (id, options, command) => {
116778
- const ctx = await buildContext4(command, options.json);
116979
+ const ctx = await buildContext5(command, options.json);
116779
116980
  await downvote(ctx, id, options);
116780
116981
  });
116781
116982
  memory.command("delete").description("Delete a memory").argument("<id>", "Memory ID").option("--collection <collection>", "Collection name (default: learnings)").option("--json", "Output as JSON").action(async (id, options, command) => {
116782
- const ctx = await buildContext4(command, options.json);
116983
+ const ctx = await buildContext5(command, options.json);
116783
116984
  await deleteMemory(ctx, id, options);
116784
116985
  });
116785
116986
  memory.command("stats").description("Display memory statistics").option("--collection <collection>", "Filter by collection").option("--app <app>", "Filter by app slug").option("--json", "Output as JSON").action(async (options, command) => {
116786
- const ctx = await buildContext4(command, options.json);
116987
+ const ctx = await buildContext5(command, options.json);
116787
116988
  await stats3(ctx, options);
116788
116989
  });
116789
116990
  memory.command("stale").description("List stale memories needing validation").option("--collection <collection>", "Filter by collection").option("--threshold <threshold>", "Confidence threshold (default: 0.25)").option("--json", "Output as JSON").action(async (options, command) => {
116790
- const ctx = await buildContext4(command, options.json);
116991
+ const ctx = await buildContext5(command, options.json);
116791
116992
  await stale(ctx, options);
116792
116993
  });
116793
116994
  }
@@ -117369,7 +117570,7 @@ async function buildValidateDatasetFromProduction(productionResultsPath, outputP
117369
117570
  }
117370
117571
 
117371
117572
  // src/commands/pipeline.ts
117372
- var buildContext5 = async (command, json) => {
117573
+ var buildContext6 = async (command, json) => {
117373
117574
  const opts = typeof command.optsWithGlobals === "function" ? command.optsWithGlobals() : {
117374
117575
  ...command.parent?.opts(),
117375
117576
  ...command.opts()
@@ -117440,7 +117641,7 @@ function registerPipelineCommands(program3) {
117440
117641
  "Model for LLM classification",
117441
117642
  "anthropic/claude-haiku-4-5"
117442
117643
  ).action(async (opts, command) => {
117443
- const ctx = await buildContext5(command, opts.json);
117644
+ const ctx = await buildContext6(command, opts.json);
117444
117645
  try {
117445
117646
  await runClassifyEval2({
117446
117647
  ...opts,
@@ -117451,7 +117652,7 @@ function registerPipelineCommands(program3) {
117451
117652
  }
117452
117653
  });
117453
117654
  pipeline.command("build-classify-dataset").description("Build classify eval dataset from production data").requiredOption("--production <file>", "Production dataset JSON").requiredOption("--output <file>", "Output scenarios JSON").action(async (opts, command) => {
117454
- const ctx = await buildContext5(command);
117655
+ const ctx = await buildContext6(command);
117455
117656
  try {
117456
117657
  await buildClassifyDataset(opts.production, opts.output);
117457
117658
  ctx.output.success(`Dataset written to ${opts.output}`);
@@ -117463,7 +117664,7 @@ function registerPipelineCommands(program3) {
117463
117664
  "--dataset <file>",
117464
117665
  "Path to scenarios JSON (uses built-in if not provided)"
117465
117666
  ).option("--output <file>", "Save results to JSON").option("--verbose", "Show individual failures").option("--json", "JSON output").action(async (opts, command) => {
117466
- const ctx = await buildContext5(command, opts.json);
117667
+ const ctx = await buildContext6(command, opts.json);
117467
117668
  try {
117468
117669
  await runValidateEval2({
117469
117670
  ...opts,
@@ -117474,7 +117675,7 @@ function registerPipelineCommands(program3) {
117474
117675
  }
117475
117676
  });
117476
117677
  pipeline.command("build-validate-dataset").description("Build validate eval dataset from production failures").requiredOption("--production <file>", "Production baseline results JSON").requiredOption("--output <file>", "Output scenarios JSON").action(async (opts, command) => {
117477
- const ctx = await buildContext5(command);
117678
+ const ctx = await buildContext6(command);
117478
117679
  try {
117479
117680
  await buildValidateDatasetFromProduction(opts.production, opts.output);
117480
117681
  ctx.output.success(`Dataset written to ${opts.output}`);
@@ -117487,7 +117688,7 @@ function registerPipelineCommands(program3) {
117487
117688
  "Model for LLM steps",
117488
117689
  "anthropic/claude-haiku-4-5"
117489
117690
  ).action(async (opts, command) => {
117490
- const ctx = await buildContext5(command, opts.json);
117691
+ const ctx = await buildContext6(command, opts.json);
117491
117692
  try {
117492
117693
  await runE2EEval2({ ...opts, json: opts.json ?? ctx.format === "json" });
117493
117694
  } catch (error) {
@@ -117495,7 +117696,7 @@ function registerPipelineCommands(program3) {
117495
117696
  }
117496
117697
  });
117497
117698
  pipeline.command("run").description("Run pipeline on a single message").requiredOption("--subject <text>", "Message subject").requiredOption("--body <text>", "Message body").option("--app <id>", "App ID", "total-typescript").option("--dry-run", "Don't actually send", true).option("--json", "JSON output").action(async (opts, command) => {
117498
- const ctx = await buildContext5(command, opts.json);
117699
+ const ctx = await buildContext6(command, opts.json);
117499
117700
  await runPipelineCommand(ctx, opts);
117500
117701
  });
117501
117702
  }
@@ -117503,10 +117704,10 @@ function registerPipelineCommands(program3) {
117503
117704
  // src/commands/plugin-sync.ts
117504
117705
  init_esm_shims();
117505
117706
  import { homedir as homedir3 } from "os";
117506
- import { dirname as dirname4, join as join13, resolve as resolve6 } from "path";
117707
+ import { dirname as dirname3, join as join13, resolve as resolve6 } from "path";
117507
117708
  import { fileURLToPath } from "url";
117508
117709
  var PLUGIN_SOURCE_DIR = resolve6(
117509
- dirname4(fileURLToPath(import.meta.url)),
117710
+ dirname3(fileURLToPath(import.meta.url)),
117510
117711
  "../../plugin"
117511
117712
  );
117512
117713
  var PLUGIN_MANIFEST_RELATIVE = join13(".claude-plugin", "plugin.json");
@@ -117612,7 +117813,7 @@ var registerPluginSyncCommand = (program3) => {
117612
117813
 
117613
117814
  // src/commands/responses.ts
117614
117815
  init_esm_shims();
117615
- import { writeFileSync as writeFileSync12 } from "fs";
117816
+ import { writeFileSync as writeFileSync11 } from "fs";
117616
117817
  function formatDate3(date) {
117617
117818
  return date.toLocaleString("en-US", {
117618
117819
  month: "short",
@@ -118145,7 +118346,7 @@ async function exportResponses(ctx, options) {
118145
118346
  }
118146
118347
  const outputJson = JSON.stringify(exportData, null, 2);
118147
118348
  if (options.output) {
118148
- writeFileSync12(options.output, outputJson, "utf-8");
118349
+ writeFileSync11(options.output, outputJson, "utf-8");
118149
118350
  if (!outputJsonFormat) {
118150
118351
  ctx.output.success(
118151
118352
  `Exported ${exportData.length} responses to ${options.output}`
@@ -118794,7 +118995,7 @@ init_esm_shims();
118794
118995
  import { spawn } from "child_process";
118795
118996
  import { writeFile as writeFile7 } from "fs/promises";
118796
118997
  import { homedir as homedir4 } from "os";
118797
- import { dirname as dirname5, join as join14 } from "path";
118998
+ import { dirname as dirname4, join as join14 } from "path";
118798
118999
  var CONFIG_DIR_NAME = "skill-cli";
118799
119000
  var AUTO_UPDATE_STATE_FILE = "auto-update.json";
118800
119001
  var DEFAULT_PACKAGE = "@skillrecordings/cli";
@@ -118824,7 +119025,7 @@ var AutoUpdateStore = class {
118824
119025
  }
118825
119026
  async save(state) {
118826
119027
  try {
118827
- await ensureDir(dirname5(this.filePath));
119028
+ await ensureDir(dirname4(this.filePath));
118828
119029
  await writeFile7(this.filePath, JSON.stringify(state, null, 2), "utf-8");
118829
119030
  } catch {
118830
119031
  }
@@ -119030,7 +119231,7 @@ var DEFAULT_HINT_RULES = [
119030
119231
  {
119031
119232
  id: "onboarding.auth",
119032
119233
  audience: "onboarding",
119033
- message: "Set up credentials with `skill auth setup` (requires 1Password).",
119234
+ message: "Set up your own API keys with `skill keys`.",
119034
119235
  showWhen: (state) => state.totalRuns >= 1 && !hasMilestone(state, "auth_configured"),
119035
119236
  retireWhen: (state) => hasMilestone(state, "auth_configured")
119036
119237
  },
@@ -119062,6 +119263,13 @@ var DEFAULT_HINT_RULES = [
119062
119263
  showWhen: (state) => state.totalRuns >= 3 && !hasCommandPrefix(state, "axiom."),
119063
119264
  retireWhen: (state) => hasCommandPrefix(state, "axiom.")
119064
119265
  },
119266
+ {
119267
+ id: "discovery.keys",
119268
+ audience: "discovery",
119269
+ message: "Override shared credentials with your own: `skill keys add`",
119270
+ showWhen: (state) => state.totalRuns >= 3 && !hasCommand(state, "keys") && !hasMilestone(state, "auth_configured"),
119271
+ retireWhen: (state) => hasCommand(state, "keys") || hasCommand(state, "keys.add") || hasMilestone(state, "auth_configured")
119272
+ },
119065
119273
  {
119066
119274
  id: "context.front.triage",
119067
119275
  audience: "contextual",
@@ -119132,10 +119340,10 @@ var writeHints = (hints, stderr) => {
119132
119340
  init_esm_shims();
119133
119341
  import { lstat, readlink, symlink } from "fs/promises";
119134
119342
  import { homedir as homedir5 } from "os";
119135
- import { dirname as dirname6, join as join15, resolve as resolve7 } from "path";
119343
+ import { dirname as dirname5, join as join15, resolve as resolve7 } from "path";
119136
119344
  import { fileURLToPath as fileURLToPath2 } from "url";
119137
119345
  var SKILL_SOURCE_DIR = resolve7(
119138
- dirname6(fileURLToPath2(import.meta.url)),
119346
+ dirname5(fileURLToPath2(import.meta.url)),
119139
119347
  "../../../../.claude/skills/skill-cli"
119140
119348
  );
119141
119349
  var SKILL_TARGET_DIR = join15(homedir5(), ".claude", "skills", "skill-cli");
@@ -119149,7 +119357,7 @@ async function autoLinkSkill() {
119149
119357
  } catch (e) {
119150
119358
  if (e.code === "ENOENT") {
119151
119359
  const { mkdir: mkdir2 } = await import("fs/promises");
119152
- await mkdir2(dirname6(target), { recursive: true });
119360
+ await mkdir2(dirname5(target), { recursive: true });
119153
119361
  await symlink(source, target, "dir");
119154
119362
  return {
119155
119363
  status: "linked",
@@ -119162,7 +119370,7 @@ async function autoLinkSkill() {
119162
119370
  }
119163
119371
  if (stats4.isSymbolicLink()) {
119164
119372
  const linkTarget = await readlink(target);
119165
- const resolvedLinkTarget = resolve7(dirname6(target), linkTarget);
119373
+ const resolvedLinkTarget = resolve7(dirname5(target), linkTarget);
119166
119374
  if (resolvedLinkTarget === source || linkTarget === source) {
119167
119375
  return {
119168
119376
  status: "exists",
@@ -119242,7 +119450,7 @@ async function sendTelemetryEvent(event) {
119242
119450
  init_esm_shims();
119243
119451
  import { writeFile as writeFile8 } from "fs/promises";
119244
119452
  import { homedir as homedir6 } from "os";
119245
- import { dirname as dirname7, join as join16 } from "path";
119453
+ import { dirname as dirname6, join as join16 } from "path";
119246
119454
  var CONFIG_DIR_NAME2 = "skill-cli";
119247
119455
  var USAGE_FILE_NAME = "usage.json";
119248
119456
  function resolveConfigDir2(configDir) {
@@ -119312,7 +119520,7 @@ var UsageTracker = class {
119312
119520
  }
119313
119521
  async saveState(state) {
119314
119522
  try {
119315
- await ensureDir(dirname7(this.filePath));
119523
+ await ensureDir(dirname6(this.filePath));
119316
119524
  await writeFile8(this.filePath, JSON.stringify(state, null, 2), "utf-8");
119317
119525
  } catch {
119318
119526
  }
@@ -119868,8 +120076,8 @@ if (!envLoaded && !process.env.DATABASE_URL) {
119868
120076
  process.env.SKIP_ENV_VALIDATION = "1";
119869
120077
  }
119870
120078
  var runtimeTarget = `bun-${process.platform}-${process.arch}`;
119871
- var buildVersion = "0.15.0".length > 0 ? "0.15.0" : "0.0.0-dev";
119872
- var buildCommit = "73ba4fa".length > 0 ? "73ba4fa" : "dev";
120079
+ var buildVersion = "0.16.0".length > 0 ? "0.16.0" : "0.0.0-dev";
120080
+ var buildCommit = "d96a5e3".length > 0 ? "d96a5e3" : "dev";
119873
120081
  var buildTarget = "node".length > 0 ? "node" : runtimeTarget;
119874
120082
  var isDevBuild = buildVersion.includes("dev") || buildCommit === "dev";
119875
120083
  var versionLabel = `skill v${buildVersion} (${buildCommit}) ${buildTarget}`;
@@ -120088,6 +120296,7 @@ registerDeployCommands(program2);
120088
120296
  registerKbCommands(program2);
120089
120297
  registerAuthCommands(program2, usageState);
120090
120298
  registerConfigCommands(program2);
120299
+ registerKeysCommands(program2);
120091
120300
  registerPluginSyncCommand(program2);
120092
120301
  program2.command("mcp").description(
120093
120302
  "Start MCP server for AI coding agent integration.\n Exposes 9 Front tools over JSON-RPC stdio for Claude Code, Cursor, etc.\n Tools: inbox, conversation, message, assign, reply, tag, archive, search, report\n Usage: skill mcp (then connect your AI editor to stdin/stdout)"