@skillrecordings/cli 0.14.3 → 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 +431 -197
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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,
|
|
1482
|
+
module.exports.setThePassword = function(url, password3) {
|
|
1483
1483
|
url.password = "";
|
|
1484
|
-
const decoded = punycode.ucs2.decode(
|
|
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, 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 &&
|
|
16752
|
-
this[kProxyHeaders]["proxy-authorization"] = `Basic ${Buffer.from(`${decodeURIComponent(username)}:${decodeURIComponent(
|
|
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:
|
|
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(
|
|
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 } = requestCurrentURL(httpRequest);
|
|
26410
|
-
authorizationValue = `Basic ${Buffer.from(`${username}:${
|
|
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
|
|
74718
|
-
abbreviated: "Skill Recordings support agent CLI \u2014 triage and investigate support conversations.\n\n Start here:\n skill
|
|
74719
|
-
minimal: "Skill Recordings support agent CLI. Try: skill
|
|
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:
|
|
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
|
-
|
|
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
|
|
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,67 +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
|
|
77040
|
-
|
|
77041
|
-
|
|
77042
|
-
|
|
77043
|
-
|
|
77044
|
-
|
|
77045
|
-
|
|
77046
|
-
|
|
77047
|
-
|
|
77048
|
-
|
|
77049
|
-
|
|
77050
|
-
|
|
77051
|
-
To
|
|
77052
|
-
|
|
77053
|
-
|
|
77054
|
-
|
|
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 { Decrypter, Encrypter, identityToRecipient as identityToRecipient2 } from "age-encryption";
|
|
77100
77064
|
function getEncryptedConfigPath() {
|
|
77101
77065
|
return `${getUserConfigDir2()}/.env.user.encrypted`;
|
|
77102
77066
|
}
|
|
@@ -77109,7 +77073,7 @@ function parseKeyValue(input2) {
|
|
|
77109
77073
|
return { key, value };
|
|
77110
77074
|
}
|
|
77111
77075
|
async function readExistingConfig(identity, configPath) {
|
|
77112
|
-
if (!
|
|
77076
|
+
if (!existsSync3(configPath)) {
|
|
77113
77077
|
return {};
|
|
77114
77078
|
}
|
|
77115
77079
|
try {
|
|
@@ -77136,7 +77100,7 @@ async function readExistingConfig(identity, configPath) {
|
|
|
77136
77100
|
async function configSetAction(ctx, keyValue, options = {}) {
|
|
77137
77101
|
const outputJson = options.json === true || ctx.format === "json";
|
|
77138
77102
|
const keyPath = getAgeKeyPath();
|
|
77139
|
-
if (!
|
|
77103
|
+
if (!existsSync3(keyPath)) {
|
|
77140
77104
|
const result = {
|
|
77141
77105
|
success: false,
|
|
77142
77106
|
error: "Age key not found. Run: skill config init"
|
|
@@ -77149,7 +77113,29 @@ async function configSetAction(ctx, keyValue, options = {}) {
|
|
|
77149
77113
|
process.exitCode = EXIT_CODES.usage;
|
|
77150
77114
|
return;
|
|
77151
77115
|
}
|
|
77152
|
-
|
|
77116
|
+
let finalKeyValue = keyValue;
|
|
77117
|
+
if (!finalKeyValue && process.stdin.isTTY && !outputJson) {
|
|
77118
|
+
try {
|
|
77119
|
+
const selectedKey = await select2({
|
|
77120
|
+
message: "Select a secret key to set:",
|
|
77121
|
+
choices: Object.keys(SECRET_REFS).map((key) => ({
|
|
77122
|
+
name: key,
|
|
77123
|
+
value: key
|
|
77124
|
+
}))
|
|
77125
|
+
});
|
|
77126
|
+
const secretValue = await password({
|
|
77127
|
+
message: `Enter value for ${selectedKey}:`
|
|
77128
|
+
});
|
|
77129
|
+
finalKeyValue = `${selectedKey}=${secretValue}`;
|
|
77130
|
+
} catch (error) {
|
|
77131
|
+
if (error instanceof Error && (error.message.includes("User force closed") || error.message.includes("canceled"))) {
|
|
77132
|
+
ctx.output.data("Cancelled");
|
|
77133
|
+
return;
|
|
77134
|
+
}
|
|
77135
|
+
throw error;
|
|
77136
|
+
}
|
|
77137
|
+
}
|
|
77138
|
+
const parsed = parseKeyValue(finalKeyValue || "");
|
|
77153
77139
|
if (!parsed) {
|
|
77154
77140
|
const result = {
|
|
77155
77141
|
success: false,
|
|
@@ -77166,7 +77152,7 @@ async function configSetAction(ctx, keyValue, options = {}) {
|
|
|
77166
77152
|
}
|
|
77167
77153
|
try {
|
|
77168
77154
|
const identity = readFileSync2(keyPath, "utf8").trim();
|
|
77169
|
-
const recipient = await
|
|
77155
|
+
const recipient = await identityToRecipient(identity);
|
|
77170
77156
|
const configPath = getEncryptedConfigPath();
|
|
77171
77157
|
const config = await readExistingConfig(identity, configPath);
|
|
77172
77158
|
config[parsed.key] = parsed.value;
|
|
@@ -77174,7 +77160,7 @@ async function configSetAction(ctx, keyValue, options = {}) {
|
|
|
77174
77160
|
const encrypter = new Encrypter();
|
|
77175
77161
|
encrypter.addRecipient(recipient);
|
|
77176
77162
|
const encrypted = await encrypter.encrypt(envContent + "\n");
|
|
77177
|
-
|
|
77163
|
+
writeFileSync3(configPath, Buffer.from(encrypted));
|
|
77178
77164
|
const result = {
|
|
77179
77165
|
success: true,
|
|
77180
77166
|
key: parsed.key,
|
|
@@ -77201,9 +77187,24 @@ async function configSetAction(ctx, keyValue, options = {}) {
|
|
|
77201
77187
|
}
|
|
77202
77188
|
|
|
77203
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
|
+
}
|
|
77204
77205
|
async function decryptConfig(identity) {
|
|
77205
77206
|
const configPath = getEncryptedConfigPath();
|
|
77206
|
-
if (!
|
|
77207
|
+
if (!existsSync4(configPath)) {
|
|
77207
77208
|
return {};
|
|
77208
77209
|
}
|
|
77209
77210
|
const encrypted = readFileSync3(configPath);
|
|
@@ -77231,11 +77232,11 @@ async function decryptConfig(identity) {
|
|
|
77231
77232
|
}
|
|
77232
77233
|
async function configGetAction(ctx, key, options = {}) {
|
|
77233
77234
|
const outputJson = options.json === true || ctx.format === "json";
|
|
77234
|
-
const
|
|
77235
|
-
if (!
|
|
77235
|
+
const identity = await getAgeKeyFrom1Password2();
|
|
77236
|
+
if (!identity) {
|
|
77236
77237
|
const result = {
|
|
77237
77238
|
success: false,
|
|
77238
|
-
error: "
|
|
77239
|
+
error: "OP_SERVICE_ACCOUNT_TOKEN not set. Required for encrypted config."
|
|
77239
77240
|
};
|
|
77240
77241
|
if (outputJson) {
|
|
77241
77242
|
ctx.output.data(result);
|
|
@@ -77246,7 +77247,6 @@ async function configGetAction(ctx, key, options = {}) {
|
|
|
77246
77247
|
return;
|
|
77247
77248
|
}
|
|
77248
77249
|
try {
|
|
77249
|
-
const identity = readFileSync3(keyPath, "utf8").trim();
|
|
77250
77250
|
const config = await decryptConfig(identity);
|
|
77251
77251
|
if (!(key in config)) {
|
|
77252
77252
|
const result2 = {
|
|
@@ -77289,11 +77289,26 @@ async function configGetAction(ctx, key, options = {}) {
|
|
|
77289
77289
|
|
|
77290
77290
|
// src/commands/config/list.ts
|
|
77291
77291
|
init_esm_shims();
|
|
77292
|
-
import { existsSync as
|
|
77292
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
|
|
77293
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
|
+
}
|
|
77294
77309
|
async function decryptConfig2(identity) {
|
|
77295
77310
|
const configPath = getEncryptedConfigPath();
|
|
77296
|
-
if (!
|
|
77311
|
+
if (!existsSync5(configPath)) {
|
|
77297
77312
|
return {};
|
|
77298
77313
|
}
|
|
77299
77314
|
const encrypted = readFileSync4(configPath);
|
|
@@ -77321,11 +77336,11 @@ async function decryptConfig2(identity) {
|
|
|
77321
77336
|
}
|
|
77322
77337
|
async function configListAction(ctx, options = {}) {
|
|
77323
77338
|
const outputJson = options.json === true || ctx.format === "json";
|
|
77324
|
-
const
|
|
77325
|
-
if (!
|
|
77339
|
+
const identity = await getAgeKeyFrom1Password3();
|
|
77340
|
+
if (!identity) {
|
|
77326
77341
|
const result = {
|
|
77327
77342
|
success: false,
|
|
77328
|
-
error: "
|
|
77343
|
+
error: "OP_SERVICE_ACCOUNT_TOKEN not set. Required for encrypted config."
|
|
77329
77344
|
};
|
|
77330
77345
|
if (outputJson) {
|
|
77331
77346
|
ctx.output.data(result);
|
|
@@ -77336,7 +77351,6 @@ async function configListAction(ctx, options = {}) {
|
|
|
77336
77351
|
return;
|
|
77337
77352
|
}
|
|
77338
77353
|
try {
|
|
77339
|
-
const identity = readFileSync4(keyPath, "utf8").trim();
|
|
77340
77354
|
const config = await decryptConfig2(identity);
|
|
77341
77355
|
const keys = Object.keys(config);
|
|
77342
77356
|
if (keys.length === 0) {
|
|
@@ -77401,11 +77415,13 @@ var buildContext2 = async (command, json) => {
|
|
|
77401
77415
|
};
|
|
77402
77416
|
function registerConfigCommands(program3) {
|
|
77403
77417
|
const config = program3.command("config").description("Manage user-specific config overrides (encrypted)");
|
|
77404
|
-
config.command("init").description("
|
|
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) => {
|
|
77405
77419
|
const ctx = await buildContext2(command, options.json);
|
|
77406
77420
|
await configInitAction(ctx, options);
|
|
77407
77421
|
});
|
|
77408
|
-
config.command("set
|
|
77422
|
+
config.command("set [key-value]").description(
|
|
77423
|
+
"Set encrypted config value (format: KEY=value or interactive)"
|
|
77424
|
+
).option("--json", "Output as JSON").action(async (keyValue, options, command) => {
|
|
77409
77425
|
const ctx = await buildContext2(command, options.json);
|
|
77410
77426
|
await configSetAction(ctx, keyValue, options);
|
|
77411
77427
|
});
|
|
@@ -80089,7 +80105,7 @@ init_esm_shims();
|
|
|
80089
80105
|
// src/commands/eval-pipeline/run.ts
|
|
80090
80106
|
init_esm_shims();
|
|
80091
80107
|
import { createHash as createHash2 } from "crypto";
|
|
80092
|
-
import { existsSync as
|
|
80108
|
+
import { existsSync as existsSync6, mkdirSync, readFileSync as readFileSync5, rmSync, writeFileSync as writeFileSync4 } from "fs";
|
|
80093
80109
|
import { join as join5 } from "path";
|
|
80094
80110
|
import { readFile as readFile6 } from "fs/promises";
|
|
80095
80111
|
import { glob as glob4 } from "glob";
|
|
@@ -80507,7 +80523,7 @@ function getClassifySourceHash() {
|
|
|
80507
80523
|
join5(process.cwd(), "../core/src/pipeline/classify.ts")
|
|
80508
80524
|
];
|
|
80509
80525
|
for (const path of possiblePaths) {
|
|
80510
|
-
if (
|
|
80526
|
+
if (existsSync6(path)) {
|
|
80511
80527
|
const content = readFileSync5(path, "utf-8");
|
|
80512
80528
|
return createHash2("md5").update(content).digest("hex");
|
|
80513
80529
|
}
|
|
@@ -80519,7 +80535,7 @@ function getClassifySourceHash() {
|
|
|
80519
80535
|
function loadCachedClassify(cacheKey) {
|
|
80520
80536
|
const cachePath = join5(CACHE_DIR, `${cacheKey}.json`);
|
|
80521
80537
|
try {
|
|
80522
|
-
if (
|
|
80538
|
+
if (existsSync6(cachePath)) {
|
|
80523
80539
|
return JSON.parse(readFileSync5(cachePath, "utf-8"));
|
|
80524
80540
|
}
|
|
80525
80541
|
} catch {
|
|
@@ -80528,17 +80544,17 @@ function loadCachedClassify(cacheKey) {
|
|
|
80528
80544
|
}
|
|
80529
80545
|
function saveCachedClassify(cacheKey, result) {
|
|
80530
80546
|
try {
|
|
80531
|
-
if (!
|
|
80532
|
-
|
|
80547
|
+
if (!existsSync6(CACHE_DIR)) {
|
|
80548
|
+
mkdirSync(CACHE_DIR, { recursive: true });
|
|
80533
80549
|
}
|
|
80534
80550
|
const cachePath = join5(CACHE_DIR, `${cacheKey}.json`);
|
|
80535
|
-
|
|
80551
|
+
writeFileSync4(cachePath, JSON.stringify(result));
|
|
80536
80552
|
} catch {
|
|
80537
80553
|
}
|
|
80538
80554
|
}
|
|
80539
80555
|
function clearClassifyCache() {
|
|
80540
80556
|
try {
|
|
80541
|
-
if (
|
|
80557
|
+
if (existsSync6(CACHE_DIR)) {
|
|
80542
80558
|
rmSync(CACHE_DIR, { recursive: true, force: true });
|
|
80543
80559
|
}
|
|
80544
80560
|
} catch {
|
|
@@ -81530,7 +81546,7 @@ function registerEvalPipelineCommands(program3) {
|
|
|
81530
81546
|
|
|
81531
81547
|
// src/commands/eval-prompt.ts
|
|
81532
81548
|
init_esm_shims();
|
|
81533
|
-
import { existsSync as
|
|
81549
|
+
import { existsSync as existsSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
|
|
81534
81550
|
import { generateText as generateText2, stepCountIs as stepCountIs2, tool as tool4 } from "ai";
|
|
81535
81551
|
import { z as z5 } from "zod";
|
|
81536
81552
|
var leakPatterns = [
|
|
@@ -81717,7 +81733,7 @@ async function runEval2(ctx, options) {
|
|
|
81717
81733
|
try {
|
|
81718
81734
|
let prompt = SUPPORT_AGENT_PROMPT;
|
|
81719
81735
|
if (promptPath) {
|
|
81720
|
-
if (!
|
|
81736
|
+
if (!existsSync7(promptPath)) {
|
|
81721
81737
|
throw new CLIError({
|
|
81722
81738
|
userMessage: `Prompt file not found: ${promptPath}.`,
|
|
81723
81739
|
suggestion: "Verify the prompt path and try again."
|
|
@@ -81730,7 +81746,7 @@ async function runEval2(ctx, options) {
|
|
|
81730
81746
|
} else if (!outputJson) {
|
|
81731
81747
|
ctx.output.message("Using production prompt");
|
|
81732
81748
|
}
|
|
81733
|
-
if (!
|
|
81749
|
+
if (!existsSync7(datasetPath)) {
|
|
81734
81750
|
throw new CLIError({
|
|
81735
81751
|
userMessage: `Dataset not found: ${datasetPath}.`,
|
|
81736
81752
|
suggestion: "Provide a valid dataset file path."
|
|
@@ -81813,7 +81829,7 @@ async function runEval2(ctx, options) {
|
|
|
81813
81829
|
});
|
|
81814
81830
|
}
|
|
81815
81831
|
if (outputPath) {
|
|
81816
|
-
|
|
81832
|
+
writeFileSync5(outputPath, JSON.stringify(results, null, 2));
|
|
81817
81833
|
if (!outputJson) {
|
|
81818
81834
|
ctx.output.success(`Saved results to ${outputPath}`);
|
|
81819
81835
|
}
|
|
@@ -81842,7 +81858,7 @@ async function comparePrompts(ctx, options) {
|
|
|
81842
81858
|
try {
|
|
81843
81859
|
const baselinePrompt = baseline ? readFileSync6(baseline, "utf-8") : SUPPORT_AGENT_PROMPT;
|
|
81844
81860
|
const candidatePrompt = readFileSync6(candidate, "utf-8");
|
|
81845
|
-
if (!
|
|
81861
|
+
if (!existsSync7(datasetPath)) {
|
|
81846
81862
|
throw new CLIError({
|
|
81847
81863
|
userMessage: `Dataset not found: ${datasetPath}.`,
|
|
81848
81864
|
suggestion: "Provide a valid dataset file path."
|
|
@@ -81990,8 +82006,8 @@ init_esm_shims();
|
|
|
81990
82006
|
|
|
81991
82007
|
// src/commands/faq/classify.ts
|
|
81992
82008
|
init_esm_shims();
|
|
81993
|
-
import { appendFileSync, existsSync as
|
|
81994
|
-
import { dirname as
|
|
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";
|
|
81995
82011
|
import { generateObject } from "ai";
|
|
81996
82012
|
import { z as z6 } from "zod";
|
|
81997
82013
|
var PROJECT_ROOT = resolve3(__dirname, "../../../..");
|
|
@@ -82058,7 +82074,7 @@ async function loadConversationsFromParquet(parquetPath) {
|
|
|
82058
82074
|
}
|
|
82059
82075
|
function loadExistingClassifications(outputPath) {
|
|
82060
82076
|
const classifiedIds = /* @__PURE__ */ new Set();
|
|
82061
|
-
if (!
|
|
82077
|
+
if (!existsSync8(outputPath)) {
|
|
82062
82078
|
return classifiedIds;
|
|
82063
82079
|
}
|
|
82064
82080
|
const content = readFileSync7(outputPath, "utf-8");
|
|
@@ -82176,7 +82192,7 @@ async function faqClassify(ctx, options) {
|
|
|
82176
82192
|
ctx.output.data(` Dry run: ${options.dryRun ?? false}`);
|
|
82177
82193
|
ctx.output.data("");
|
|
82178
82194
|
}
|
|
82179
|
-
if (!
|
|
82195
|
+
if (!existsSync8(parquetPath)) {
|
|
82180
82196
|
handleFaqClassifyError(
|
|
82181
82197
|
ctx,
|
|
82182
82198
|
new CLIError({
|
|
@@ -82187,7 +82203,7 @@ async function faqClassify(ctx, options) {
|
|
|
82187
82203
|
);
|
|
82188
82204
|
return;
|
|
82189
82205
|
}
|
|
82190
|
-
if (!
|
|
82206
|
+
if (!existsSync8(taxonomyPath)) {
|
|
82191
82207
|
handleFaqClassifyError(
|
|
82192
82208
|
ctx,
|
|
82193
82209
|
new CLIError({
|
|
@@ -82198,9 +82214,9 @@ async function faqClassify(ctx, options) {
|
|
|
82198
82214
|
);
|
|
82199
82215
|
return;
|
|
82200
82216
|
}
|
|
82201
|
-
const outputDir =
|
|
82202
|
-
if (!
|
|
82203
|
-
|
|
82217
|
+
const outputDir = dirname2(outputPath);
|
|
82218
|
+
if (!existsSync8(outputDir)) {
|
|
82219
|
+
mkdirSync2(outputDir, { recursive: true });
|
|
82204
82220
|
}
|
|
82205
82221
|
if (!outputJson) ctx.output.data("\u{1F4DA} Loading taxonomy...");
|
|
82206
82222
|
const taxonomy = JSON.parse(readFileSync7(taxonomyPath, "utf-8"));
|
|
@@ -82368,18 +82384,18 @@ function registerFaqClassifyCommands(program3) {
|
|
|
82368
82384
|
|
|
82369
82385
|
// src/commands/faq/cluster.ts
|
|
82370
82386
|
init_esm_shims();
|
|
82371
|
-
import { existsSync as
|
|
82387
|
+
import { existsSync as existsSync10 } from "fs";
|
|
82372
82388
|
import { join as join9, resolve as resolve4 } from "path";
|
|
82373
82389
|
|
|
82374
82390
|
// ../core/src/faq/production-clusterer.ts
|
|
82375
82391
|
init_esm_shims();
|
|
82376
|
-
import { existsSync as
|
|
82392
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
|
|
82377
82393
|
import { join as join8 } from "path";
|
|
82378
82394
|
function readPhase0Assignments(phase0Path) {
|
|
82379
82395
|
const assignmentsPath = join8(phase0Path, "clusters/v1/assignments.json");
|
|
82380
|
-
if (!
|
|
82396
|
+
if (!existsSync9(assignmentsPath)) {
|
|
82381
82397
|
const latestPath = join8(phase0Path, "clusters/latest/assignments.json");
|
|
82382
|
-
if (!
|
|
82398
|
+
if (!existsSync9(latestPath)) {
|
|
82383
82399
|
throw new Error(`Phase 0 assignments not found at ${assignmentsPath}`);
|
|
82384
82400
|
}
|
|
82385
82401
|
const content2 = readFileSync8(latestPath, "utf-8");
|
|
@@ -82390,9 +82406,9 @@ function readPhase0Assignments(phase0Path) {
|
|
|
82390
82406
|
}
|
|
82391
82407
|
function readPhase0Labels(phase0Path) {
|
|
82392
82408
|
const labelsPath = join8(phase0Path, "clusters/v1/labels.json");
|
|
82393
|
-
if (!
|
|
82409
|
+
if (!existsSync9(labelsPath)) {
|
|
82394
82410
|
const latestPath = join8(phase0Path, "clusters/latest/labels.json");
|
|
82395
|
-
if (!
|
|
82411
|
+
if (!existsSync9(latestPath)) {
|
|
82396
82412
|
throw new Error(`Phase 0 labels not found at ${labelsPath}`);
|
|
82397
82413
|
}
|
|
82398
82414
|
const content2 = readFileSync8(latestPath, "utf-8");
|
|
@@ -82405,9 +82421,9 @@ function readPhase0Labels(phase0Path) {
|
|
|
82405
82421
|
}
|
|
82406
82422
|
function readPhase0Metrics(phase0Path) {
|
|
82407
82423
|
const metricsPath = join8(phase0Path, "clusters/v1/metrics.json");
|
|
82408
|
-
if (!
|
|
82424
|
+
if (!existsSync9(metricsPath)) {
|
|
82409
82425
|
const latestPath = join8(phase0Path, "clusters/latest/metrics.json");
|
|
82410
|
-
if (!
|
|
82426
|
+
if (!existsSync9(latestPath)) {
|
|
82411
82427
|
throw new Error(`Phase 0 metrics not found at ${metricsPath}`);
|
|
82412
82428
|
}
|
|
82413
82429
|
return JSON.parse(readFileSync8(latestPath, "utf-8"));
|
|
@@ -82528,17 +82544,17 @@ async function generateProductionClustering(options) {
|
|
|
82528
82544
|
}
|
|
82529
82545
|
function writeProductionArtifacts(result, outputPath) {
|
|
82530
82546
|
const versionPath = join8(outputPath, result.version);
|
|
82531
|
-
if (!
|
|
82532
|
-
|
|
82547
|
+
if (!existsSync9(versionPath)) {
|
|
82548
|
+
mkdirSync3(versionPath, { recursive: true });
|
|
82533
82549
|
}
|
|
82534
82550
|
const resultPath = join8(versionPath, "clustering-result.json");
|
|
82535
|
-
|
|
82551
|
+
writeFileSync6(resultPath, JSON.stringify(result, null, 2));
|
|
82536
82552
|
console.log(`\u2705 Written: ${resultPath}`);
|
|
82537
82553
|
const assignmentsPath = join8(versionPath, "assignments.json");
|
|
82538
|
-
|
|
82554
|
+
writeFileSync6(assignmentsPath, JSON.stringify(result.assignments, null, 2));
|
|
82539
82555
|
console.log(`\u2705 Written: ${assignmentsPath}`);
|
|
82540
82556
|
const clustersPath = join8(versionPath, "clusters.json");
|
|
82541
|
-
|
|
82557
|
+
writeFileSync6(
|
|
82542
82558
|
clustersPath,
|
|
82543
82559
|
JSON.stringify(
|
|
82544
82560
|
{
|
|
@@ -82564,14 +82580,14 @@ function writeProductionArtifacts(result, outputPath) {
|
|
|
82564
82580
|
priorityTier: c.priorityTier
|
|
82565
82581
|
}))
|
|
82566
82582
|
};
|
|
82567
|
-
|
|
82583
|
+
writeFileSync6(summaryPath, JSON.stringify(summary, null, 2));
|
|
82568
82584
|
console.log(`\u2705 Written: ${summaryPath}`);
|
|
82569
82585
|
const latestPath = join8(outputPath, "latest");
|
|
82570
|
-
if (
|
|
82586
|
+
if (existsSync9(latestPath)) {
|
|
82571
82587
|
const { rmSync: rmSync2 } = __require("fs");
|
|
82572
82588
|
rmSync2(latestPath, { recursive: true, force: true });
|
|
82573
82589
|
}
|
|
82574
|
-
|
|
82590
|
+
mkdirSync3(latestPath, { recursive: true });
|
|
82575
82591
|
for (const file of [
|
|
82576
82592
|
"clustering-result.json",
|
|
82577
82593
|
"assignments.json",
|
|
@@ -82580,7 +82596,7 @@ function writeProductionArtifacts(result, outputPath) {
|
|
|
82580
82596
|
]) {
|
|
82581
82597
|
const src = join8(versionPath, file);
|
|
82582
82598
|
const dst = join8(latestPath, file);
|
|
82583
|
-
|
|
82599
|
+
writeFileSync6(dst, readFileSync8(src));
|
|
82584
82600
|
}
|
|
82585
82601
|
console.log(`\u2705 Updated: ${latestPath}`);
|
|
82586
82602
|
}
|
|
@@ -82638,19 +82654,19 @@ function validatePaths(phase0Path) {
|
|
|
82638
82654
|
const assignmentsPath = join9(phase0Path, "clusters/v1/assignments.json");
|
|
82639
82655
|
const labelsPath = join9(phase0Path, "clusters/v1/labels.json");
|
|
82640
82656
|
const metricsPath = join9(phase0Path, "clusters/v1/metrics.json");
|
|
82641
|
-
if (!
|
|
82657
|
+
if (!existsSync10(assignmentsPath)) {
|
|
82642
82658
|
throw new CLIError({
|
|
82643
82659
|
userMessage: `Phase 0 assignments not found at ${assignmentsPath}.`,
|
|
82644
82660
|
suggestion: "Run Phase 0 clustering first or specify the correct --phase0-path."
|
|
82645
82661
|
});
|
|
82646
82662
|
}
|
|
82647
|
-
if (!
|
|
82663
|
+
if (!existsSync10(labelsPath)) {
|
|
82648
82664
|
throw new CLIError({
|
|
82649
82665
|
userMessage: `Phase 0 labels not found at ${labelsPath}.`,
|
|
82650
82666
|
suggestion: "Verify the --phase0-path points to valid artifacts."
|
|
82651
82667
|
});
|
|
82652
82668
|
}
|
|
82653
|
-
if (!
|
|
82669
|
+
if (!existsSync10(metricsPath)) {
|
|
82654
82670
|
throw new CLIError({
|
|
82655
82671
|
userMessage: `Phase 0 metrics not found at ${metricsPath}.`,
|
|
82656
82672
|
suggestion: "Verify the --phase0-path points to valid artifacts."
|
|
@@ -82731,12 +82747,12 @@ function registerFaqClusterCommands(program3) {
|
|
|
82731
82747
|
|
|
82732
82748
|
// src/commands/faq/extract.ts
|
|
82733
82749
|
init_esm_shims();
|
|
82734
|
-
import { existsSync as
|
|
82750
|
+
import { existsSync as existsSync12 } from "fs";
|
|
82735
82751
|
import { join as join11, resolve as resolve5 } from "path";
|
|
82736
82752
|
|
|
82737
82753
|
// ../core/src/faq/extractor.ts
|
|
82738
82754
|
init_esm_shims();
|
|
82739
|
-
import { existsSync as
|
|
82755
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync4, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
|
|
82740
82756
|
import { join as join10 } from "path";
|
|
82741
82757
|
|
|
82742
82758
|
// ../core/src/faq/review.ts
|
|
@@ -83352,11 +83368,11 @@ async function extractFaqCandidates(options) {
|
|
|
83352
83368
|
}
|
|
83353
83369
|
function writeExtractionArtifacts(result, outputPath) {
|
|
83354
83370
|
const versionPath = join10(outputPath, result.version);
|
|
83355
|
-
if (!
|
|
83356
|
-
|
|
83371
|
+
if (!existsSync11(versionPath)) {
|
|
83372
|
+
mkdirSync4(versionPath, { recursive: true });
|
|
83357
83373
|
}
|
|
83358
83374
|
const resultPath = join10(versionPath, "extraction-result.json");
|
|
83359
|
-
|
|
83375
|
+
writeFileSync7(resultPath, JSON.stringify(result, null, 2));
|
|
83360
83376
|
console.log(`\u2705 Written: ${resultPath}`);
|
|
83361
83377
|
const candidatesPath = join10(versionPath, "candidates.json");
|
|
83362
83378
|
const candidatesData = {
|
|
@@ -83376,10 +83392,10 @@ function writeExtractionArtifacts(result, outputPath) {
|
|
|
83376
83392
|
sourceConversations: c.sourceConversations.slice(0, 5)
|
|
83377
83393
|
}))
|
|
83378
83394
|
};
|
|
83379
|
-
|
|
83395
|
+
writeFileSync7(candidatesPath, JSON.stringify(candidatesData, null, 2));
|
|
83380
83396
|
console.log(`\u2705 Written: ${candidatesPath}`);
|
|
83381
83397
|
const statsPath = join10(versionPath, "stats.json");
|
|
83382
|
-
|
|
83398
|
+
writeFileSync7(
|
|
83383
83399
|
statsPath,
|
|
83384
83400
|
JSON.stringify(
|
|
83385
83401
|
{
|
|
@@ -83393,11 +83409,11 @@ function writeExtractionArtifacts(result, outputPath) {
|
|
|
83393
83409
|
);
|
|
83394
83410
|
console.log(`\u2705 Written: ${statsPath}`);
|
|
83395
83411
|
const latestPath = join10(outputPath, "latest");
|
|
83396
|
-
if (
|
|
83412
|
+
if (existsSync11(latestPath)) {
|
|
83397
83413
|
const { rmSync: rmSync2 } = __require("fs");
|
|
83398
83414
|
rmSync2(latestPath, { recursive: true, force: true });
|
|
83399
83415
|
}
|
|
83400
|
-
|
|
83416
|
+
mkdirSync4(latestPath, { recursive: true });
|
|
83401
83417
|
for (const file of [
|
|
83402
83418
|
"extraction-result.json",
|
|
83403
83419
|
"candidates.json",
|
|
@@ -83405,8 +83421,8 @@ function writeExtractionArtifacts(result, outputPath) {
|
|
|
83405
83421
|
]) {
|
|
83406
83422
|
const src = join10(versionPath, file);
|
|
83407
83423
|
const dst = join10(latestPath, file);
|
|
83408
|
-
if (
|
|
83409
|
-
|
|
83424
|
+
if (existsSync11(src)) {
|
|
83425
|
+
writeFileSync7(dst, readFileSync9(src));
|
|
83410
83426
|
}
|
|
83411
83427
|
}
|
|
83412
83428
|
console.log(`\u2705 Updated: ${latestPath}`);
|
|
@@ -83470,13 +83486,13 @@ var DEFAULT_GOLDEN_PATH = join11(
|
|
|
83470
83486
|
var DEFAULT_OUTPUT_PATH3 = join11(PROJECT_ROOT3, "artifacts/phase-1/extraction");
|
|
83471
83487
|
var DEFAULT_CACHE_PATH = `${process.env.HOME}/skill/data/front-cache.db`;
|
|
83472
83488
|
function validatePaths2(ctx, clusteringPath, goldenPath, outputJson) {
|
|
83473
|
-
if (!
|
|
83489
|
+
if (!existsSync12(clusteringPath)) {
|
|
83474
83490
|
throw new CLIError({
|
|
83475
83491
|
userMessage: `Clustering result not found at ${clusteringPath}.`,
|
|
83476
83492
|
suggestion: "Run `bun src/index.ts faq cluster` first to generate clustering."
|
|
83477
83493
|
});
|
|
83478
83494
|
}
|
|
83479
|
-
if (goldenPath && !
|
|
83495
|
+
if (goldenPath && !existsSync12(goldenPath)) {
|
|
83480
83496
|
if (!outputJson) {
|
|
83481
83497
|
ctx.output.warn(`Golden responses not found at ${goldenPath}`);
|
|
83482
83498
|
ctx.output.warn("Golden matching will be disabled.");
|
|
@@ -83505,7 +83521,7 @@ async function faqExtract(ctx, options) {
|
|
|
83505
83521
|
ctx.output.data("");
|
|
83506
83522
|
}
|
|
83507
83523
|
validatePaths2(ctx, clusteringPath, goldenPath, outputJson);
|
|
83508
|
-
if (!
|
|
83524
|
+
if (!existsSync12(cachePath)) {
|
|
83509
83525
|
const cliError = new CLIError({
|
|
83510
83526
|
userMessage: `DuckDB cache not found at ${cachePath}.`,
|
|
83511
83527
|
suggestion: "Run `bun src/index.ts front-cache sync` first to populate cache."
|
|
@@ -83527,7 +83543,7 @@ async function faqExtract(ctx, options) {
|
|
|
83527
83543
|
}
|
|
83528
83544
|
const extractionOptions = {
|
|
83529
83545
|
clusteringPath,
|
|
83530
|
-
goldenPath:
|
|
83546
|
+
goldenPath: existsSync12(goldenPath) ? goldenPath : void 0,
|
|
83531
83547
|
source,
|
|
83532
83548
|
outputPath,
|
|
83533
83549
|
version,
|
|
@@ -83647,7 +83663,7 @@ function registerFaqExtractCommands(program3) {
|
|
|
83647
83663
|
|
|
83648
83664
|
// src/commands/faq/mine.ts
|
|
83649
83665
|
init_esm_shims();
|
|
83650
|
-
import { writeFileSync as
|
|
83666
|
+
import { writeFileSync as writeFileSync8 } from "fs";
|
|
83651
83667
|
|
|
83652
83668
|
// ../core/src/faq/index.ts
|
|
83653
83669
|
init_esm_shims();
|
|
@@ -92464,7 +92480,7 @@ async function faqMine(ctx, options) {
|
|
|
92464
92480
|
}))
|
|
92465
92481
|
};
|
|
92466
92482
|
if (options.export) {
|
|
92467
|
-
|
|
92483
|
+
writeFileSync8(options.export, JSON.stringify(rawData, null, 2), "utf-8");
|
|
92468
92484
|
if (outputJson) {
|
|
92469
92485
|
ctx.output.data({
|
|
92470
92486
|
success: true,
|
|
@@ -92538,7 +92554,7 @@ async function faqMine(ctx, options) {
|
|
|
92538
92554
|
generatedAt: c.generatedAt.toISOString()
|
|
92539
92555
|
}))
|
|
92540
92556
|
};
|
|
92541
|
-
|
|
92557
|
+
writeFileSync8(
|
|
92542
92558
|
options.export,
|
|
92543
92559
|
JSON.stringify(exportData, null, 2),
|
|
92544
92560
|
"utf-8"
|
|
@@ -92601,10 +92617,10 @@ function registerFaqMineCommands(program3) {
|
|
|
92601
92617
|
// src/commands/faq/review.ts
|
|
92602
92618
|
init_esm_shims();
|
|
92603
92619
|
import { spawnSync } from "child_process";
|
|
92604
|
-
import { existsSync as
|
|
92620
|
+
import { existsSync as existsSync13, readFileSync as readFileSync10, unlinkSync, writeFileSync as writeFileSync9 } from "fs";
|
|
92605
92621
|
import { tmpdir } from "os";
|
|
92606
92622
|
import { join as join12 } from "path";
|
|
92607
|
-
import { confirm as confirm2, select as
|
|
92623
|
+
import { confirm as confirm2, select as select3 } from "@inquirer/prompts";
|
|
92608
92624
|
var COLORS2 = {
|
|
92609
92625
|
reset: "\x1B[0m",
|
|
92610
92626
|
green: "\x1B[32m",
|
|
@@ -92679,7 +92695,7 @@ Save and close the editor when done.
|
|
|
92679
92695
|
The sections are separated by "## Question" and "## Answer" headers.
|
|
92680
92696
|
-->
|
|
92681
92697
|
`;
|
|
92682
|
-
|
|
92698
|
+
writeFileSync9(tmpFile, content, "utf-8");
|
|
92683
92699
|
try {
|
|
92684
92700
|
const result = spawnSync(editor, [tmpFile], {
|
|
92685
92701
|
stdio: "inherit",
|
|
@@ -92707,7 +92723,7 @@ The sections are separated by "## Question" and "## Answer" headers.
|
|
|
92707
92723
|
answer: editedAnswer
|
|
92708
92724
|
};
|
|
92709
92725
|
} finally {
|
|
92710
|
-
if (
|
|
92726
|
+
if (existsSync13(tmpFile)) {
|
|
92711
92727
|
unlinkSync(tmpFile);
|
|
92712
92728
|
}
|
|
92713
92729
|
}
|
|
@@ -92738,7 +92754,7 @@ ${COLORS2.bold}\u{1F4CB} FAQ Review Session${COLORS2.reset}`);
|
|
|
92738
92754
|
for (let i = 0; i < candidates.length; i++) {
|
|
92739
92755
|
const candidate = candidates[i];
|
|
92740
92756
|
displayCandidate(ctx, candidate, i, candidates.length);
|
|
92741
|
-
const action = await
|
|
92757
|
+
const action = await select3({
|
|
92742
92758
|
message: "Action:",
|
|
92743
92759
|
choices: [
|
|
92744
92760
|
{
|
|
@@ -94902,7 +94918,7 @@ function registerInboxCommand(front) {
|
|
|
94902
94918
|
|
|
94903
94919
|
// src/commands/front/pull-conversations.ts
|
|
94904
94920
|
init_esm_shims();
|
|
94905
|
-
import { writeFileSync as
|
|
94921
|
+
import { writeFileSync as writeFileSync10 } from "fs";
|
|
94906
94922
|
async function pullConversations(ctx, options) {
|
|
94907
94923
|
const { inbox, limit: limit2 = 50, output, filter: filter4 } = options;
|
|
94908
94924
|
const outputJson = options.json === true || ctx.format === "json";
|
|
@@ -95035,7 +95051,7 @@ Built ${samples.length} eval samples`);
|
|
|
95035
95051
|
ctx.output.data(` ${cat}: ${count}`);
|
|
95036
95052
|
}
|
|
95037
95053
|
if (output) {
|
|
95038
|
-
|
|
95054
|
+
writeFileSync10(output, JSON.stringify(samples, null, 2));
|
|
95039
95055
|
ctx.output.data(`
|
|
95040
95056
|
Saved to ${output}`);
|
|
95041
95057
|
} else if (outputJson) {
|
|
@@ -103216,7 +103232,7 @@ var compile3 = wrapCompile(compile2);
|
|
|
103216
103232
|
var _compileUnsafe = wrapCompile(compileUnsafe);
|
|
103217
103233
|
var _compileToken = wrapCompile(compileToken);
|
|
103218
103234
|
function getSelectorFunc(searchFunc) {
|
|
103219
|
-
return function
|
|
103235
|
+
return function select7(query, elements, options) {
|
|
103220
103236
|
const opts = convertOptionFormats(options);
|
|
103221
103237
|
if (typeof query !== "function") {
|
|
103222
103238
|
query = compileUnsafe(query, opts, elements);
|
|
@@ -103403,7 +103419,7 @@ function filterBySelector(selector, elements, options) {
|
|
|
103403
103419
|
}
|
|
103404
103420
|
return findFilterElements(elements, selector, options, false, elements.length);
|
|
103405
103421
|
}
|
|
103406
|
-
function
|
|
103422
|
+
function select4(selector, root2, options = {}, limit2 = Infinity) {
|
|
103407
103423
|
if (typeof selector === "function") {
|
|
103408
103424
|
return find3(root2, selector);
|
|
103409
103425
|
}
|
|
@@ -103508,7 +103524,7 @@ function _findBySelector(selector, limit2) {
|
|
|
103508
103524
|
pseudos: this.options.pseudos,
|
|
103509
103525
|
quirksMode: this.options.quirksMode
|
|
103510
103526
|
};
|
|
103511
|
-
return this._make(
|
|
103527
|
+
return this._make(select4(selector, elems, options, limit2));
|
|
103512
103528
|
}
|
|
103513
103529
|
function _getMatcher(matchMap) {
|
|
103514
103530
|
return function(fn, ...postFns) {
|
|
@@ -113870,6 +113886,216 @@ function registerKbCommands(program3) {
|
|
|
113870
113886
|
});
|
|
113871
113887
|
}
|
|
113872
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
|
+
|
|
113873
114099
|
// src/commands/linear/index.ts
|
|
113874
114100
|
init_esm_shims();
|
|
113875
114101
|
|
|
@@ -113886,7 +114112,7 @@ function requirePersonalKey(keyName) {
|
|
|
113886
114112
|
throw new CLIError({
|
|
113887
114113
|
userMessage: `Write operations require a personal API key for ${keyName}.`,
|
|
113888
114114
|
exitCode: EXIT_CODES.auth,
|
|
113889
|
-
suggestion: "Run 'skill
|
|
114115
|
+
suggestion: "Run 'skill keys add' to set up your personal keys.",
|
|
113890
114116
|
debugMessage: `Key provenance for ${keyName}: ${provenance ?? "undefined"}`
|
|
113891
114117
|
});
|
|
113892
114118
|
}
|
|
@@ -113922,8 +114148,8 @@ function hateoasWrap2(opts) {
|
|
|
113922
114148
|
return response;
|
|
113923
114149
|
}
|
|
113924
114150
|
var WRITE_ACTION_META = {
|
|
113925
|
-
personal_key_hint: "\u26A0\uFE0F Write operations require a personal LINEAR_API_KEY. Run `skill
|
|
113926
|
-
setup_command: "skill
|
|
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"
|
|
113927
114153
|
};
|
|
113928
114154
|
function issueLinks(identifier, teamKey) {
|
|
113929
114155
|
const links = [
|
|
@@ -114784,7 +115010,7 @@ async function getIssue(ctx, id) {
|
|
|
114784
115010
|
ctx.output.data(` \u2022 Close: skill linear close ${issue.identifier}`);
|
|
114785
115011
|
ctx.output.data("");
|
|
114786
115012
|
ctx.output.data(" \u26A0\uFE0F Write operations require a personal LINEAR_API_KEY.");
|
|
114787
|
-
ctx.output.data(" Run `skill
|
|
115013
|
+
ctx.output.data(" Run `skill keys add` to set up your keys.");
|
|
114788
115014
|
ctx.output.data("");
|
|
114789
115015
|
} catch (error) {
|
|
114790
115016
|
const cliError = error instanceof CLIError ? error : new CLIError({
|
|
@@ -116713,7 +116939,7 @@ async function deleteMemory(ctx, id, options) {
|
|
|
116713
116939
|
}
|
|
116714
116940
|
|
|
116715
116941
|
// src/commands/memory/index.ts
|
|
116716
|
-
var
|
|
116942
|
+
var buildContext5 = async (command, json) => {
|
|
116717
116943
|
const opts = typeof command.optsWithGlobals === "function" ? command.optsWithGlobals() : {
|
|
116718
116944
|
...command.parent?.opts(),
|
|
116719
116945
|
...command.opts()
|
|
@@ -116727,42 +116953,42 @@ var buildContext4 = async (command, json) => {
|
|
|
116727
116953
|
function registerMemoryCommands(program3) {
|
|
116728
116954
|
const memory = program3.command("memory").description("Manage semantic memory for agent learning");
|
|
116729
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) => {
|
|
116730
|
-
const ctx = await
|
|
116956
|
+
const ctx = await buildContext5(command, options.json);
|
|
116731
116957
|
await store(ctx, content, options);
|
|
116732
116958
|
});
|
|
116733
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(
|
|
116734
116960
|
"--min-confidence <confidence>",
|
|
116735
116961
|
"Minimum confidence threshold (0-1, default: 0.5)"
|
|
116736
116962
|
).option("--json", "Output as JSON").action(async (query, options, command) => {
|
|
116737
|
-
const ctx = await
|
|
116963
|
+
const ctx = await buildContext5(command, options.json);
|
|
116738
116964
|
await find5(ctx, query, options);
|
|
116739
116965
|
});
|
|
116740
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) => {
|
|
116741
|
-
const ctx = await
|
|
116967
|
+
const ctx = await buildContext5(command, options.json);
|
|
116742
116968
|
await get2(ctx, id, options);
|
|
116743
116969
|
});
|
|
116744
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) => {
|
|
116745
|
-
const ctx = await
|
|
116971
|
+
const ctx = await buildContext5(command, options.json);
|
|
116746
116972
|
await validate2(ctx, id, options);
|
|
116747
116973
|
});
|
|
116748
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) => {
|
|
116749
|
-
const ctx = await
|
|
116975
|
+
const ctx = await buildContext5(command, options.json);
|
|
116750
116976
|
await upvote(ctx, id, options);
|
|
116751
116977
|
});
|
|
116752
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) => {
|
|
116753
|
-
const ctx = await
|
|
116979
|
+
const ctx = await buildContext5(command, options.json);
|
|
116754
116980
|
await downvote(ctx, id, options);
|
|
116755
116981
|
});
|
|
116756
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) => {
|
|
116757
|
-
const ctx = await
|
|
116983
|
+
const ctx = await buildContext5(command, options.json);
|
|
116758
116984
|
await deleteMemory(ctx, id, options);
|
|
116759
116985
|
});
|
|
116760
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) => {
|
|
116761
|
-
const ctx = await
|
|
116987
|
+
const ctx = await buildContext5(command, options.json);
|
|
116762
116988
|
await stats3(ctx, options);
|
|
116763
116989
|
});
|
|
116764
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) => {
|
|
116765
|
-
const ctx = await
|
|
116991
|
+
const ctx = await buildContext5(command, options.json);
|
|
116766
116992
|
await stale(ctx, options);
|
|
116767
116993
|
});
|
|
116768
116994
|
}
|
|
@@ -117344,7 +117570,7 @@ async function buildValidateDatasetFromProduction(productionResultsPath, outputP
|
|
|
117344
117570
|
}
|
|
117345
117571
|
|
|
117346
117572
|
// src/commands/pipeline.ts
|
|
117347
|
-
var
|
|
117573
|
+
var buildContext6 = async (command, json) => {
|
|
117348
117574
|
const opts = typeof command.optsWithGlobals === "function" ? command.optsWithGlobals() : {
|
|
117349
117575
|
...command.parent?.opts(),
|
|
117350
117576
|
...command.opts()
|
|
@@ -117415,7 +117641,7 @@ function registerPipelineCommands(program3) {
|
|
|
117415
117641
|
"Model for LLM classification",
|
|
117416
117642
|
"anthropic/claude-haiku-4-5"
|
|
117417
117643
|
).action(async (opts, command) => {
|
|
117418
|
-
const ctx = await
|
|
117644
|
+
const ctx = await buildContext6(command, opts.json);
|
|
117419
117645
|
try {
|
|
117420
117646
|
await runClassifyEval2({
|
|
117421
117647
|
...opts,
|
|
@@ -117426,7 +117652,7 @@ function registerPipelineCommands(program3) {
|
|
|
117426
117652
|
}
|
|
117427
117653
|
});
|
|
117428
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) => {
|
|
117429
|
-
const ctx = await
|
|
117655
|
+
const ctx = await buildContext6(command);
|
|
117430
117656
|
try {
|
|
117431
117657
|
await buildClassifyDataset(opts.production, opts.output);
|
|
117432
117658
|
ctx.output.success(`Dataset written to ${opts.output}`);
|
|
@@ -117438,7 +117664,7 @@ function registerPipelineCommands(program3) {
|
|
|
117438
117664
|
"--dataset <file>",
|
|
117439
117665
|
"Path to scenarios JSON (uses built-in if not provided)"
|
|
117440
117666
|
).option("--output <file>", "Save results to JSON").option("--verbose", "Show individual failures").option("--json", "JSON output").action(async (opts, command) => {
|
|
117441
|
-
const ctx = await
|
|
117667
|
+
const ctx = await buildContext6(command, opts.json);
|
|
117442
117668
|
try {
|
|
117443
117669
|
await runValidateEval2({
|
|
117444
117670
|
...opts,
|
|
@@ -117449,7 +117675,7 @@ function registerPipelineCommands(program3) {
|
|
|
117449
117675
|
}
|
|
117450
117676
|
});
|
|
117451
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) => {
|
|
117452
|
-
const ctx = await
|
|
117678
|
+
const ctx = await buildContext6(command);
|
|
117453
117679
|
try {
|
|
117454
117680
|
await buildValidateDatasetFromProduction(opts.production, opts.output);
|
|
117455
117681
|
ctx.output.success(`Dataset written to ${opts.output}`);
|
|
@@ -117462,7 +117688,7 @@ function registerPipelineCommands(program3) {
|
|
|
117462
117688
|
"Model for LLM steps",
|
|
117463
117689
|
"anthropic/claude-haiku-4-5"
|
|
117464
117690
|
).action(async (opts, command) => {
|
|
117465
|
-
const ctx = await
|
|
117691
|
+
const ctx = await buildContext6(command, opts.json);
|
|
117466
117692
|
try {
|
|
117467
117693
|
await runE2EEval2({ ...opts, json: opts.json ?? ctx.format === "json" });
|
|
117468
117694
|
} catch (error) {
|
|
@@ -117470,7 +117696,7 @@ function registerPipelineCommands(program3) {
|
|
|
117470
117696
|
}
|
|
117471
117697
|
});
|
|
117472
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) => {
|
|
117473
|
-
const ctx = await
|
|
117699
|
+
const ctx = await buildContext6(command, opts.json);
|
|
117474
117700
|
await runPipelineCommand(ctx, opts);
|
|
117475
117701
|
});
|
|
117476
117702
|
}
|
|
@@ -117478,10 +117704,10 @@ function registerPipelineCommands(program3) {
|
|
|
117478
117704
|
// src/commands/plugin-sync.ts
|
|
117479
117705
|
init_esm_shims();
|
|
117480
117706
|
import { homedir as homedir3 } from "os";
|
|
117481
|
-
import { dirname as
|
|
117707
|
+
import { dirname as dirname3, join as join13, resolve as resolve6 } from "path";
|
|
117482
117708
|
import { fileURLToPath } from "url";
|
|
117483
117709
|
var PLUGIN_SOURCE_DIR = resolve6(
|
|
117484
|
-
|
|
117710
|
+
dirname3(fileURLToPath(import.meta.url)),
|
|
117485
117711
|
"../../plugin"
|
|
117486
117712
|
);
|
|
117487
117713
|
var PLUGIN_MANIFEST_RELATIVE = join13(".claude-plugin", "plugin.json");
|
|
@@ -117587,7 +117813,7 @@ var registerPluginSyncCommand = (program3) => {
|
|
|
117587
117813
|
|
|
117588
117814
|
// src/commands/responses.ts
|
|
117589
117815
|
init_esm_shims();
|
|
117590
|
-
import { writeFileSync as
|
|
117816
|
+
import { writeFileSync as writeFileSync11 } from "fs";
|
|
117591
117817
|
function formatDate3(date) {
|
|
117592
117818
|
return date.toLocaleString("en-US", {
|
|
117593
117819
|
month: "short",
|
|
@@ -118120,7 +118346,7 @@ async function exportResponses(ctx, options) {
|
|
|
118120
118346
|
}
|
|
118121
118347
|
const outputJson = JSON.stringify(exportData, null, 2);
|
|
118122
118348
|
if (options.output) {
|
|
118123
|
-
|
|
118349
|
+
writeFileSync11(options.output, outputJson, "utf-8");
|
|
118124
118350
|
if (!outputJsonFormat) {
|
|
118125
118351
|
ctx.output.success(
|
|
118126
118352
|
`Exported ${exportData.length} responses to ${options.output}`
|
|
@@ -118769,7 +118995,7 @@ init_esm_shims();
|
|
|
118769
118995
|
import { spawn } from "child_process";
|
|
118770
118996
|
import { writeFile as writeFile7 } from "fs/promises";
|
|
118771
118997
|
import { homedir as homedir4 } from "os";
|
|
118772
|
-
import { dirname as
|
|
118998
|
+
import { dirname as dirname4, join as join14 } from "path";
|
|
118773
118999
|
var CONFIG_DIR_NAME = "skill-cli";
|
|
118774
119000
|
var AUTO_UPDATE_STATE_FILE = "auto-update.json";
|
|
118775
119001
|
var DEFAULT_PACKAGE = "@skillrecordings/cli";
|
|
@@ -118799,7 +119025,7 @@ var AutoUpdateStore = class {
|
|
|
118799
119025
|
}
|
|
118800
119026
|
async save(state) {
|
|
118801
119027
|
try {
|
|
118802
|
-
await ensureDir(
|
|
119028
|
+
await ensureDir(dirname4(this.filePath));
|
|
118803
119029
|
await writeFile7(this.filePath, JSON.stringify(state, null, 2), "utf-8");
|
|
118804
119030
|
} catch {
|
|
118805
119031
|
}
|
|
@@ -119005,7 +119231,7 @@ var DEFAULT_HINT_RULES = [
|
|
|
119005
119231
|
{
|
|
119006
119232
|
id: "onboarding.auth",
|
|
119007
119233
|
audience: "onboarding",
|
|
119008
|
-
message: "
|
|
119234
|
+
message: "Set up your own API keys with `skill keys`.",
|
|
119009
119235
|
showWhen: (state) => state.totalRuns >= 1 && !hasMilestone(state, "auth_configured"),
|
|
119010
119236
|
retireWhen: (state) => hasMilestone(state, "auth_configured")
|
|
119011
119237
|
},
|
|
@@ -119037,6 +119263,13 @@ var DEFAULT_HINT_RULES = [
|
|
|
119037
119263
|
showWhen: (state) => state.totalRuns >= 3 && !hasCommandPrefix(state, "axiom."),
|
|
119038
119264
|
retireWhen: (state) => hasCommandPrefix(state, "axiom.")
|
|
119039
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
|
+
},
|
|
119040
119273
|
{
|
|
119041
119274
|
id: "context.front.triage",
|
|
119042
119275
|
audience: "contextual",
|
|
@@ -119107,10 +119340,10 @@ var writeHints = (hints, stderr) => {
|
|
|
119107
119340
|
init_esm_shims();
|
|
119108
119341
|
import { lstat, readlink, symlink } from "fs/promises";
|
|
119109
119342
|
import { homedir as homedir5 } from "os";
|
|
119110
|
-
import { dirname as
|
|
119343
|
+
import { dirname as dirname5, join as join15, resolve as resolve7 } from "path";
|
|
119111
119344
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
119112
119345
|
var SKILL_SOURCE_DIR = resolve7(
|
|
119113
|
-
|
|
119346
|
+
dirname5(fileURLToPath2(import.meta.url)),
|
|
119114
119347
|
"../../../../.claude/skills/skill-cli"
|
|
119115
119348
|
);
|
|
119116
119349
|
var SKILL_TARGET_DIR = join15(homedir5(), ".claude", "skills", "skill-cli");
|
|
@@ -119124,7 +119357,7 @@ async function autoLinkSkill() {
|
|
|
119124
119357
|
} catch (e) {
|
|
119125
119358
|
if (e.code === "ENOENT") {
|
|
119126
119359
|
const { mkdir: mkdir2 } = await import("fs/promises");
|
|
119127
|
-
await mkdir2(
|
|
119360
|
+
await mkdir2(dirname5(target), { recursive: true });
|
|
119128
119361
|
await symlink(source, target, "dir");
|
|
119129
119362
|
return {
|
|
119130
119363
|
status: "linked",
|
|
@@ -119137,7 +119370,7 @@ async function autoLinkSkill() {
|
|
|
119137
119370
|
}
|
|
119138
119371
|
if (stats4.isSymbolicLink()) {
|
|
119139
119372
|
const linkTarget = await readlink(target);
|
|
119140
|
-
const resolvedLinkTarget = resolve7(
|
|
119373
|
+
const resolvedLinkTarget = resolve7(dirname5(target), linkTarget);
|
|
119141
119374
|
if (resolvedLinkTarget === source || linkTarget === source) {
|
|
119142
119375
|
return {
|
|
119143
119376
|
status: "exists",
|
|
@@ -119217,7 +119450,7 @@ async function sendTelemetryEvent(event) {
|
|
|
119217
119450
|
init_esm_shims();
|
|
119218
119451
|
import { writeFile as writeFile8 } from "fs/promises";
|
|
119219
119452
|
import { homedir as homedir6 } from "os";
|
|
119220
|
-
import { dirname as
|
|
119453
|
+
import { dirname as dirname6, join as join16 } from "path";
|
|
119221
119454
|
var CONFIG_DIR_NAME2 = "skill-cli";
|
|
119222
119455
|
var USAGE_FILE_NAME = "usage.json";
|
|
119223
119456
|
function resolveConfigDir2(configDir) {
|
|
@@ -119287,7 +119520,7 @@ var UsageTracker = class {
|
|
|
119287
119520
|
}
|
|
119288
119521
|
async saveState(state) {
|
|
119289
119522
|
try {
|
|
119290
|
-
await ensureDir(
|
|
119523
|
+
await ensureDir(dirname6(this.filePath));
|
|
119291
119524
|
await writeFile8(this.filePath, JSON.stringify(state, null, 2), "utf-8");
|
|
119292
119525
|
} catch {
|
|
119293
119526
|
}
|
|
@@ -119843,8 +120076,8 @@ if (!envLoaded && !process.env.DATABASE_URL) {
|
|
|
119843
120076
|
process.env.SKIP_ENV_VALIDATION = "1";
|
|
119844
120077
|
}
|
|
119845
120078
|
var runtimeTarget = `bun-${process.platform}-${process.arch}`;
|
|
119846
|
-
var buildVersion = "0.
|
|
119847
|
-
var buildCommit = "
|
|
120079
|
+
var buildVersion = "0.16.0".length > 0 ? "0.16.0" : "0.0.0-dev";
|
|
120080
|
+
var buildCommit = "d96a5e3".length > 0 ? "d96a5e3" : "dev";
|
|
119848
120081
|
var buildTarget = "node".length > 0 ? "node" : runtimeTarget;
|
|
119849
120082
|
var isDevBuild = buildVersion.includes("dev") || buildCommit === "dev";
|
|
119850
120083
|
var versionLabel = `skill v${buildVersion} (${buildCommit}) ${buildTarget}`;
|
|
@@ -119889,7 +120122,7 @@ var resolveMilestones = (commandName) => {
|
|
|
119889
120122
|
case "wizard":
|
|
119890
120123
|
return ["wizard_completed"];
|
|
119891
120124
|
case "auth.setup":
|
|
119892
|
-
case "init":
|
|
120125
|
+
case "config.init":
|
|
119893
120126
|
return ["auth_configured"];
|
|
119894
120127
|
default:
|
|
119895
120128
|
return [];
|
|
@@ -120063,6 +120296,7 @@ registerDeployCommands(program2);
|
|
|
120063
120296
|
registerKbCommands(program2);
|
|
120064
120297
|
registerAuthCommands(program2, usageState);
|
|
120065
120298
|
registerConfigCommands(program2);
|
|
120299
|
+
registerKeysCommands(program2);
|
|
120066
120300
|
registerPluginSyncCommand(program2);
|
|
120067
120301
|
program2.command("mcp").description(
|
|
120068
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)"
|