@skillrecordings/cli 0.17.0 → 0.18.1
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/{chunk-IR6KG25Y.js → chunk-LV53JZHC.js} +1 -1
- package/dist/chunk-LV53JZHC.js.map +1 -0
- package/dist/{chunk-J4IC3GC3.js → chunk-ZCWCT4ES.js} +10 -10
- package/dist/chunk-ZCWCT4ES.js.map +1 -0
- package/dist/{config-C7CDVTO7.js → config-6PEJQQJY.js} +2 -2
- package/dist/index.js +700 -215
- package/dist/index.js.map +1 -1
- package/dist/{pipeline-TMFQSA7X.js → pipeline-JPI7ITZN.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-IR6KG25Y.js.map +0 -1
- package/dist/chunk-J4IC3GC3.js.map +0 -1
- /package/dist/{config-C7CDVTO7.js.map → config-6PEJQQJY.js.map} +0 -0
- /package/dist/{pipeline-TMFQSA7X.js.map → pipeline-JPI7ITZN.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
runPipeline,
|
|
21
21
|
validate,
|
|
22
22
|
validateSync
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-ZCWCT4ES.js";
|
|
24
24
|
import "./chunk-HK3PEWFD.js";
|
|
25
25
|
import "./chunk-WYKL32C3.js";
|
|
26
26
|
import {
|
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
getApp,
|
|
41
41
|
getOutcomeHistory,
|
|
42
42
|
getRedis
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-LV53JZHC.js";
|
|
44
44
|
import "./chunk-KEV3QKXP.js";
|
|
45
45
|
import {
|
|
46
46
|
MemoryService,
|
|
@@ -56,8 +56,10 @@ import "./chunk-F4EM72IH.js";
|
|
|
56
56
|
import {
|
|
57
57
|
addShellIntegration,
|
|
58
58
|
autoBootstrapKeychain,
|
|
59
|
+
getFromKeychain,
|
|
59
60
|
getKeychainStatus,
|
|
60
61
|
isKeychainSupported,
|
|
62
|
+
isOpCliAvailable,
|
|
61
63
|
storeInKeychain
|
|
62
64
|
} from "./chunk-7SQU7KCI.js";
|
|
63
65
|
import {
|
|
@@ -74553,7 +74555,7 @@ import { resolve as resolve8 } from "path";
|
|
|
74553
74555
|
|
|
74554
74556
|
// src/core/config-loader.ts
|
|
74555
74557
|
init_esm_shims();
|
|
74556
|
-
import { readFileSync } from "fs";
|
|
74558
|
+
import { existsSync as existsSync2, readFileSync } from "fs";
|
|
74557
74559
|
import { resolve } from "path";
|
|
74558
74560
|
|
|
74559
74561
|
// src/core/user-config.ts
|
|
@@ -74601,6 +74603,13 @@ function getUserConfigDir(configDir) {
|
|
|
74601
74603
|
function getUserConfigPath(fileName, configDir) {
|
|
74602
74604
|
return join(getUserConfigDir(configDir), fileName);
|
|
74603
74605
|
}
|
|
74606
|
+
function getAgeKeyPath(configDir) {
|
|
74607
|
+
const envKey = process.env.AGE_USER_KEY;
|
|
74608
|
+
if (envKey && envKey.trim() !== "") {
|
|
74609
|
+
return envKey;
|
|
74610
|
+
}
|
|
74611
|
+
return getUserConfigPath(USER_CONFIG_PATHS.ageKey, configDir);
|
|
74612
|
+
}
|
|
74604
74613
|
|
|
74605
74614
|
// src/core/config-loader.ts
|
|
74606
74615
|
function parseEnvContent(content) {
|
|
@@ -74618,12 +74627,11 @@ function parseEnvContent(content) {
|
|
|
74618
74627
|
return env;
|
|
74619
74628
|
}
|
|
74620
74629
|
async function decryptEnvFile(encryptedPath) {
|
|
74621
|
-
const { existsSync: existsSync15 } = await import("fs");
|
|
74622
74630
|
const { readFile: readFile10 } = await import("fs/promises");
|
|
74623
|
-
if (!
|
|
74631
|
+
if (!existsSync2(encryptedPath)) {
|
|
74624
74632
|
return {};
|
|
74625
74633
|
}
|
|
74626
|
-
const ageKey = await
|
|
74634
|
+
const ageKey = await getAgeKey();
|
|
74627
74635
|
if (!ageKey) {
|
|
74628
74636
|
return {};
|
|
74629
74637
|
}
|
|
@@ -74636,13 +74644,21 @@ async function decryptEnvFile(encryptedPath) {
|
|
|
74636
74644
|
return {};
|
|
74637
74645
|
}
|
|
74638
74646
|
}
|
|
74639
|
-
async function
|
|
74647
|
+
async function getAgeKey() {
|
|
74640
74648
|
if (process.env.SKILL_AGE_KEY) {
|
|
74641
74649
|
return process.env.SKILL_AGE_KEY;
|
|
74642
74650
|
}
|
|
74643
74651
|
try {
|
|
74644
|
-
const
|
|
74645
|
-
|
|
74652
|
+
const ageKeyPath = getAgeKeyPath();
|
|
74653
|
+
if (existsSync2(ageKeyPath)) {
|
|
74654
|
+
const key = readFileSync(ageKeyPath, "utf8").trim();
|
|
74655
|
+
if (key) return key;
|
|
74656
|
+
}
|
|
74657
|
+
} catch {
|
|
74658
|
+
}
|
|
74659
|
+
try {
|
|
74660
|
+
const { getFromKeychain: getFromKeychain2, storeInKeychain: storeInKeychain2, autoBootstrapKeychain: autoBootstrapKeychain2 } = await import("./keychain-IEZHT5WN.js");
|
|
74661
|
+
const fromKeychain = getFromKeychain2("age-private-key");
|
|
74646
74662
|
if (fromKeychain) return fromKeychain;
|
|
74647
74663
|
let opToken = process.env.OP_SERVICE_ACCOUNT_TOKEN;
|
|
74648
74664
|
if (!opToken) {
|
|
@@ -74750,7 +74766,7 @@ var ROOT_DESCRIPTIONS = {
|
|
|
74750
74766
|
minimal: "Skill Recordings support agent CLI. Try: skill wizard, skill keys, skill front inbox, skill front triage. Use --help for details."
|
|
74751
74767
|
};
|
|
74752
74768
|
var FRONT_DESCRIPTIONS = {
|
|
74753
|
-
full: "Front conversations, inboxes, tags, archival, and reporting.\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.",
|
|
74769
|
+
full: "Front conversations, inboxes, tags, archival, and reporting.\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.\n\n Environment: FRONT_API_TOKEN required. Run `skill doctor` to check.",
|
|
74754
74770
|
abbreviated: "Front API workflows for inbox triage and conversation actions.\n\n Common:\n skill front inbox\n skill front triage\n skill front conversation <id> -m\n skill front reply <id>\n skill front archive <id>",
|
|
74755
74771
|
minimal: "Front API commands (inbox, triage, assign, reply, archive)."
|
|
74756
74772
|
};
|
|
@@ -74760,7 +74776,7 @@ var AUTH_DESCRIPTIONS = {
|
|
|
74760
74776
|
minimal: "Auth status commands (auth status, auth whoami)."
|
|
74761
74777
|
};
|
|
74762
74778
|
var INNGEST_DESCRIPTIONS = {
|
|
74763
|
-
full: "Inngest event and workflow commands.\n\n Debug pipeline runs:\n skill inngest runs --status failed --after 1h Recent failures\n skill inngest events --after 12h Recent events\n skill inngest investigate <run-id> Deep-dive a specific run",
|
|
74779
|
+
full: "Inngest event and workflow commands.\n\n Debug pipeline runs:\n skill inngest runs --status failed --after 1h Recent failures\n skill inngest events --after 12h Recent events\n skill inngest investigate <run-id> Deep-dive a specific run\n\n Environment: INNGEST_SIGNING_KEY required. Run `skill doctor` to check.",
|
|
74764
74780
|
abbreviated: "Inngest events and workflow runs.\n\n Common:\n skill inngest runs --status failed --after 1h\n skill inngest events --after 12h\n skill inngest investigate <run-id>",
|
|
74765
74781
|
minimal: "Inngest events and runs debugging."
|
|
74766
74782
|
};
|
|
@@ -75085,7 +75101,7 @@ async function loginAction(ctx, options) {
|
|
|
75085
75101
|
|
|
75086
75102
|
// src/commands/auth/setup.ts
|
|
75087
75103
|
init_esm_shims();
|
|
75088
|
-
import { existsSync as
|
|
75104
|
+
import { existsSync as existsSync3, writeFileSync } from "fs";
|
|
75089
75105
|
import { resolve as resolve2 } from "path";
|
|
75090
75106
|
import { confirm, select } from "@inquirer/prompts";
|
|
75091
75107
|
|
|
@@ -75434,7 +75450,7 @@ async function authSetupAction(ctx, options = {}) {
|
|
|
75434
75450
|
});
|
|
75435
75451
|
if (persistence === "env") {
|
|
75436
75452
|
const envPath = resolve2(process.cwd(), ".env.local");
|
|
75437
|
-
if (
|
|
75453
|
+
if (existsSync3(envPath)) {
|
|
75438
75454
|
const overwrite = await confirm({
|
|
75439
75455
|
message: `.env.local already exists at ${envPath}. Overwrite?`,
|
|
75440
75456
|
default: false
|
|
@@ -76836,7 +76852,9 @@ async function listApprovals(ctx, options) {
|
|
|
76836
76852
|
}
|
|
76837
76853
|
}
|
|
76838
76854
|
function registerAxiomCommands(program3) {
|
|
76839
|
-
const axiom = program3.command("axiom").description(
|
|
76855
|
+
const axiom = program3.command("axiom").description(
|
|
76856
|
+
"Query Axiom logs and traces.\n Environment: AXIOM_TOKEN required. Run `skill doctor` to check."
|
|
76857
|
+
);
|
|
76840
76858
|
axiom.command("query").description("Run a raw APL query").argument("<apl>", "APL query string").option("-s, --since <time>", "Time range (e.g., 1h, 24h, 7d)", "24h").option("--json", "Output as JSON").action(async (apl, options, command) => {
|
|
76841
76859
|
const opts = typeof command.optsWithGlobals === "function" ? command.optsWithGlobals() : {
|
|
76842
76860
|
...command.parent?.opts(),
|
|
@@ -77074,11 +77092,11 @@ Saved to ${options.output}`);
|
|
|
77074
77092
|
}
|
|
77075
77093
|
}
|
|
77076
77094
|
async function toEvalite(options) {
|
|
77077
|
-
const { readFileSync:
|
|
77095
|
+
const { readFileSync: readFileSync14 } = await import("fs");
|
|
77078
77096
|
const { ctx } = options;
|
|
77079
77097
|
const outputJson = ctx.format === "json";
|
|
77080
77098
|
const data2 = JSON.parse(
|
|
77081
|
-
|
|
77099
|
+
readFileSync14(options.input, "utf-8")
|
|
77082
77100
|
);
|
|
77083
77101
|
const evaliteData = data2.map((d) => ({
|
|
77084
77102
|
input: d.triggerMessage.body,
|
|
@@ -77139,12 +77157,12 @@ init_esm_shims();
|
|
|
77139
77157
|
|
|
77140
77158
|
// src/commands/config/get.ts
|
|
77141
77159
|
init_esm_shims();
|
|
77142
|
-
import { existsSync as
|
|
77160
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
|
|
77143
77161
|
import { Decrypter as Decrypter2 } from "age-encryption";
|
|
77144
77162
|
|
|
77145
77163
|
// src/commands/config/set.ts
|
|
77146
77164
|
init_esm_shims();
|
|
77147
|
-
import { existsSync as
|
|
77165
|
+
import { existsSync as existsSync4, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
77148
77166
|
import { password, select as select2 } from "@inquirer/prompts";
|
|
77149
77167
|
import { Decrypter, Encrypter, identityToRecipient } from "age-encryption";
|
|
77150
77168
|
|
|
@@ -77155,7 +77173,7 @@ import { join as join2 } from "path";
|
|
|
77155
77173
|
function getUserConfigDir2() {
|
|
77156
77174
|
return join2(homedir2(), ".config", "skill");
|
|
77157
77175
|
}
|
|
77158
|
-
function
|
|
77176
|
+
function getAgeKeyPath2() {
|
|
77159
77177
|
return join2(getUserConfigDir2(), "age.key");
|
|
77160
77178
|
}
|
|
77161
77179
|
async function configInitAction(ctx, options = {}) {
|
|
@@ -77193,7 +77211,7 @@ function parseKeyValue(input2) {
|
|
|
77193
77211
|
return { key, value };
|
|
77194
77212
|
}
|
|
77195
77213
|
async function readExistingConfig(identity, configPath) {
|
|
77196
|
-
if (!
|
|
77214
|
+
if (!existsSync4(configPath)) {
|
|
77197
77215
|
return {};
|
|
77198
77216
|
}
|
|
77199
77217
|
try {
|
|
@@ -77219,8 +77237,8 @@ async function readExistingConfig(identity, configPath) {
|
|
|
77219
77237
|
}
|
|
77220
77238
|
async function configSetAction(ctx, keyValue, options = {}) {
|
|
77221
77239
|
const outputJson = options.json === true || ctx.format === "json";
|
|
77222
|
-
const keyPath =
|
|
77223
|
-
if (!
|
|
77240
|
+
const keyPath = getAgeKeyPath2();
|
|
77241
|
+
if (!existsSync4(keyPath)) {
|
|
77224
77242
|
const result = {
|
|
77225
77243
|
success: false,
|
|
77226
77244
|
error: "Age key not found. Run: skill config init"
|
|
@@ -77307,24 +77325,9 @@ async function configSetAction(ctx, keyValue, options = {}) {
|
|
|
77307
77325
|
}
|
|
77308
77326
|
|
|
77309
77327
|
// src/commands/config/get.ts
|
|
77310
|
-
async function getAgeKeyFrom1Password2() {
|
|
77311
|
-
if (!process.env.OP_SERVICE_ACCOUNT_TOKEN) {
|
|
77312
|
-
return null;
|
|
77313
|
-
}
|
|
77314
|
-
try {
|
|
77315
|
-
const { OnePasswordProvider: OnePasswordProvider2 } = await import("./secrets-MGVPGMFJ.js");
|
|
77316
|
-
const op = new OnePasswordProvider2();
|
|
77317
|
-
if (!await op.isAvailable()) {
|
|
77318
|
-
return null;
|
|
77319
|
-
}
|
|
77320
|
-
return await op.resolve("op://Support/skill-cli-age-key/private_key");
|
|
77321
|
-
} catch {
|
|
77322
|
-
return null;
|
|
77323
|
-
}
|
|
77324
|
-
}
|
|
77325
77328
|
async function decryptConfig(identity) {
|
|
77326
77329
|
const configPath = getEncryptedConfigPath();
|
|
77327
|
-
if (!
|
|
77330
|
+
if (!existsSync5(configPath)) {
|
|
77328
77331
|
return {};
|
|
77329
77332
|
}
|
|
77330
77333
|
const encrypted = readFileSync3(configPath);
|
|
@@ -77352,11 +77355,11 @@ async function decryptConfig(identity) {
|
|
|
77352
77355
|
}
|
|
77353
77356
|
async function configGetAction(ctx, key, options = {}) {
|
|
77354
77357
|
const outputJson = options.json === true || ctx.format === "json";
|
|
77355
|
-
const identity = await
|
|
77358
|
+
const identity = await getAgeKey();
|
|
77356
77359
|
if (!identity) {
|
|
77357
77360
|
const result = {
|
|
77358
77361
|
success: false,
|
|
77359
|
-
error: "
|
|
77362
|
+
error: "No age key found. Set SKILL_AGE_KEY, place key at ~/.config/skill/age.key, or configure 1Password."
|
|
77360
77363
|
};
|
|
77361
77364
|
if (outputJson) {
|
|
77362
77365
|
ctx.output.data(result);
|
|
@@ -77409,26 +77412,11 @@ async function configGetAction(ctx, key, options = {}) {
|
|
|
77409
77412
|
|
|
77410
77413
|
// src/commands/config/list.ts
|
|
77411
77414
|
init_esm_shims();
|
|
77412
|
-
import { existsSync as
|
|
77415
|
+
import { existsSync as existsSync6, readFileSync as readFileSync4 } from "fs";
|
|
77413
77416
|
import { Decrypter as Decrypter3 } from "age-encryption";
|
|
77414
|
-
async function getAgeKeyFrom1Password3() {
|
|
77415
|
-
if (!process.env.OP_SERVICE_ACCOUNT_TOKEN) {
|
|
77416
|
-
return null;
|
|
77417
|
-
}
|
|
77418
|
-
try {
|
|
77419
|
-
const { OnePasswordProvider: OnePasswordProvider2 } = await import("./secrets-MGVPGMFJ.js");
|
|
77420
|
-
const op = new OnePasswordProvider2();
|
|
77421
|
-
if (!await op.isAvailable()) {
|
|
77422
|
-
return null;
|
|
77423
|
-
}
|
|
77424
|
-
return await op.resolve("op://Support/skill-cli-age-key/private_key");
|
|
77425
|
-
} catch {
|
|
77426
|
-
return null;
|
|
77427
|
-
}
|
|
77428
|
-
}
|
|
77429
77417
|
async function decryptConfig2(identity) {
|
|
77430
77418
|
const configPath = getEncryptedConfigPath();
|
|
77431
|
-
if (!
|
|
77419
|
+
if (!existsSync6(configPath)) {
|
|
77432
77420
|
return {};
|
|
77433
77421
|
}
|
|
77434
77422
|
const encrypted = readFileSync4(configPath);
|
|
@@ -77456,11 +77444,11 @@ async function decryptConfig2(identity) {
|
|
|
77456
77444
|
}
|
|
77457
77445
|
async function configListAction(ctx, options = {}) {
|
|
77458
77446
|
const outputJson = options.json === true || ctx.format === "json";
|
|
77459
|
-
const identity = await
|
|
77447
|
+
const identity = await getAgeKey();
|
|
77460
77448
|
if (!identity) {
|
|
77461
77449
|
const result = {
|
|
77462
77450
|
success: false,
|
|
77463
|
-
error: "
|
|
77451
|
+
error: "No age key found. Set SKILL_AGE_KEY, place key at ~/.config/skill/age.key, or configure 1Password."
|
|
77464
77452
|
};
|
|
77465
77453
|
if (outputJson) {
|
|
77466
77454
|
ctx.output.data(result);
|
|
@@ -77882,6 +77870,170 @@ function registerDeployCommands(program3) {
|
|
|
77882
77870
|
});
|
|
77883
77871
|
}
|
|
77884
77872
|
|
|
77873
|
+
// src/commands/doctor.ts
|
|
77874
|
+
init_esm_shims();
|
|
77875
|
+
import { execSync as execSync3 } from "child_process";
|
|
77876
|
+
import { existsSync as existsSync7 } from "fs";
|
|
77877
|
+
import { join as join3 } from "path";
|
|
77878
|
+
var REQUIRED_ENV_VARS = [
|
|
77879
|
+
"DATABASE_URL",
|
|
77880
|
+
"INNGEST_SIGNING_KEY",
|
|
77881
|
+
"INNGEST_EVENT_KEY",
|
|
77882
|
+
"FRONT_API_TOKEN",
|
|
77883
|
+
"LINEAR_API_KEY",
|
|
77884
|
+
"AXIOM_TOKEN",
|
|
77885
|
+
"SLACK_BOT_TOKEN",
|
|
77886
|
+
"UPSTASH_REDIS_REST_URL",
|
|
77887
|
+
"UPSTASH_VECTOR_REST_URL"
|
|
77888
|
+
];
|
|
77889
|
+
function checkEnvVars() {
|
|
77890
|
+
return REQUIRED_ENV_VARS.map((varName) => {
|
|
77891
|
+
const value = process.env[varName];
|
|
77892
|
+
return {
|
|
77893
|
+
name: varName,
|
|
77894
|
+
status: value ? "ok" : "warn",
|
|
77895
|
+
message: value ? void 0 : "Not set"
|
|
77896
|
+
};
|
|
77897
|
+
});
|
|
77898
|
+
}
|
|
77899
|
+
function checkKeychain() {
|
|
77900
|
+
const checks = [];
|
|
77901
|
+
const opAvailable = isOpCliAvailable();
|
|
77902
|
+
checks.push({
|
|
77903
|
+
name: "op CLI",
|
|
77904
|
+
status: opAvailable ? "ok" : "warn",
|
|
77905
|
+
message: opAvailable ? void 0 : "Not installed or not authenticated"
|
|
77906
|
+
});
|
|
77907
|
+
const opToken = getFromKeychain("op-service-account-token");
|
|
77908
|
+
checks.push({
|
|
77909
|
+
name: "op-service-account-token",
|
|
77910
|
+
status: opToken ? "ok" : "warn",
|
|
77911
|
+
message: opToken ? void 0 : "Not found in keychain"
|
|
77912
|
+
});
|
|
77913
|
+
const ageKey = getFromKeychain("age-private-key");
|
|
77914
|
+
checks.push({
|
|
77915
|
+
name: "age-private-key",
|
|
77916
|
+
status: ageKey ? "ok" : "warn",
|
|
77917
|
+
message: ageKey ? void 0 : "Not found in keychain"
|
|
77918
|
+
});
|
|
77919
|
+
return checks;
|
|
77920
|
+
}
|
|
77921
|
+
function checkTools() {
|
|
77922
|
+
const checks = [];
|
|
77923
|
+
try {
|
|
77924
|
+
execSync3("gh auth status", { stdio: "pipe", timeout: 3e3 });
|
|
77925
|
+
checks.push({
|
|
77926
|
+
name: "gh CLI",
|
|
77927
|
+
status: "ok"
|
|
77928
|
+
});
|
|
77929
|
+
} catch {
|
|
77930
|
+
checks.push({
|
|
77931
|
+
name: "gh CLI",
|
|
77932
|
+
status: "warn",
|
|
77933
|
+
message: "Not installed or not authenticated"
|
|
77934
|
+
});
|
|
77935
|
+
}
|
|
77936
|
+
return checks;
|
|
77937
|
+
}
|
|
77938
|
+
function checkWorkspace() {
|
|
77939
|
+
const checks = [];
|
|
77940
|
+
const hivePath = join3(process.cwd(), ".hive");
|
|
77941
|
+
const hiveExists = existsSync7(hivePath);
|
|
77942
|
+
checks.push({
|
|
77943
|
+
name: ".hive directory",
|
|
77944
|
+
status: hiveExists ? "ok" : "warn",
|
|
77945
|
+
message: hiveExists ? void 0 : "Not found in current directory"
|
|
77946
|
+
});
|
|
77947
|
+
return checks;
|
|
77948
|
+
}
|
|
77949
|
+
function runHealthChecks() {
|
|
77950
|
+
const categories = [
|
|
77951
|
+
{
|
|
77952
|
+
category: "Environment",
|
|
77953
|
+
checks: checkEnvVars()
|
|
77954
|
+
},
|
|
77955
|
+
{
|
|
77956
|
+
category: "Keychain",
|
|
77957
|
+
checks: checkKeychain()
|
|
77958
|
+
},
|
|
77959
|
+
{
|
|
77960
|
+
category: "Tools",
|
|
77961
|
+
checks: checkTools()
|
|
77962
|
+
},
|
|
77963
|
+
{
|
|
77964
|
+
category: "Workspace",
|
|
77965
|
+
checks: checkWorkspace()
|
|
77966
|
+
}
|
|
77967
|
+
];
|
|
77968
|
+
let total = 0;
|
|
77969
|
+
let ok = 0;
|
|
77970
|
+
let warn = 0;
|
|
77971
|
+
let fail = 0;
|
|
77972
|
+
for (const category of categories) {
|
|
77973
|
+
for (const check of category.checks) {
|
|
77974
|
+
total++;
|
|
77975
|
+
if (check.status === "ok") ok++;
|
|
77976
|
+
else if (check.status === "warn") warn++;
|
|
77977
|
+
else fail++;
|
|
77978
|
+
}
|
|
77979
|
+
}
|
|
77980
|
+
let status;
|
|
77981
|
+
if (fail > 0) {
|
|
77982
|
+
status = "unhealthy";
|
|
77983
|
+
} else if (warn > 3) {
|
|
77984
|
+
status = "degraded";
|
|
77985
|
+
} else {
|
|
77986
|
+
status = "healthy";
|
|
77987
|
+
}
|
|
77988
|
+
return {
|
|
77989
|
+
status,
|
|
77990
|
+
categories,
|
|
77991
|
+
summary: { total, ok, warn, fail }
|
|
77992
|
+
};
|
|
77993
|
+
}
|
|
77994
|
+
function formatTextOutput(results) {
|
|
77995
|
+
console.log("\n\u{1FA7A} Health Check Results\n");
|
|
77996
|
+
for (const category of results.categories) {
|
|
77997
|
+
console.log(`${category.category}:`);
|
|
77998
|
+
for (const check of category.checks) {
|
|
77999
|
+
const symbol = check.status === "ok" ? "\u2713" : check.status === "warn" ? "\u26A0" : "\u2717";
|
|
78000
|
+
const line = check.message ? ` ${symbol} ${check.name} - ${check.message}` : ` ${symbol} ${check.name}`;
|
|
78001
|
+
console.log(line);
|
|
78002
|
+
}
|
|
78003
|
+
console.log("");
|
|
78004
|
+
}
|
|
78005
|
+
console.log("\u2500".repeat(60));
|
|
78006
|
+
console.log(
|
|
78007
|
+
`Summary: ${results.summary.ok}/${results.summary.total} checks passed`
|
|
78008
|
+
);
|
|
78009
|
+
if (results.summary.warn > 0) {
|
|
78010
|
+
console.log(`\u26A0 ${results.summary.warn} warnings`);
|
|
78011
|
+
}
|
|
78012
|
+
if (results.summary.fail > 0) {
|
|
78013
|
+
console.log(`\u2717 ${results.summary.fail} failures`);
|
|
78014
|
+
}
|
|
78015
|
+
console.log(`
|
|
78016
|
+
Overall status: ${results.status.toUpperCase()}`);
|
|
78017
|
+
console.log("");
|
|
78018
|
+
}
|
|
78019
|
+
function registerDoctorCommand(program3) {
|
|
78020
|
+
program3.command("doctor").description(
|
|
78021
|
+
"Run health checks on environment and tools\n\n Checks:\n - Environment variables\n - Keychain secrets\n - CLI tools (gh, op)\n - Workspace setup (.hive)\n\n Examples:\n skill doctor\n skill doctor --json"
|
|
78022
|
+
).option("--json", "Output as JSON").action(async (options, command) => {
|
|
78023
|
+
const ctx = await createContext({
|
|
78024
|
+
format: options.json ? "json" : "text",
|
|
78025
|
+
verbose: command.optsWithGlobals().verbose,
|
|
78026
|
+
quiet: command.optsWithGlobals().quiet
|
|
78027
|
+
});
|
|
78028
|
+
const results = runHealthChecks();
|
|
78029
|
+
if (options.json || ctx.format === "json") {
|
|
78030
|
+
ctx.output.data(results);
|
|
78031
|
+
} else {
|
|
78032
|
+
formatTextOutput(results);
|
|
78033
|
+
}
|
|
78034
|
+
});
|
|
78035
|
+
}
|
|
78036
|
+
|
|
77885
78037
|
// src/commands/eval.ts
|
|
77886
78038
|
init_esm_shims();
|
|
77887
78039
|
import { access, readFile as readFile2 } from "fs/promises";
|
|
@@ -79889,12 +80041,12 @@ async function scoreProduction(ctx, options) {
|
|
|
79889
80041
|
|
|
79890
80042
|
// src/commands/eval-local/seed.ts
|
|
79891
80043
|
init_esm_shims();
|
|
79892
|
-
import { join as
|
|
80044
|
+
import { join as join5 } from "path";
|
|
79893
80045
|
import { glob as glob3 } from "glob";
|
|
79894
80046
|
|
|
79895
80047
|
// src/lib/eval-seed.ts
|
|
79896
80048
|
init_esm_shims();
|
|
79897
|
-
import { join as
|
|
80049
|
+
import { join as join4 } from "path";
|
|
79898
80050
|
import { readFile as readFile5, readdir } from "fs/promises";
|
|
79899
80051
|
import { glob as glob2 } from "glob";
|
|
79900
80052
|
import matter from "gray-matter";
|
|
@@ -79940,7 +80092,7 @@ async function loadJsonFiles(dirPath) {
|
|
|
79940
80092
|
const jsonFiles = files.filter((f) => f.endsWith(".json"));
|
|
79941
80093
|
const items = await Promise.all(
|
|
79942
80094
|
jsonFiles.map(async (file) => {
|
|
79943
|
-
const content = await readFile5(
|
|
80095
|
+
const content = await readFile5(join4(dirPath, file), "utf-8");
|
|
79944
80096
|
return JSON.parse(content);
|
|
79945
80097
|
})
|
|
79946
80098
|
);
|
|
@@ -79950,7 +80102,7 @@ async function loadJsonFiles(dirPath) {
|
|
|
79950
80102
|
}
|
|
79951
80103
|
}
|
|
79952
80104
|
async function loadKnowledgeFiles(basePath) {
|
|
79953
|
-
const files = await glob2(
|
|
80105
|
+
const files = await glob2(join4(basePath, "**/*.md"));
|
|
79954
80106
|
const docs = [];
|
|
79955
80107
|
for (const filePath of files) {
|
|
79956
80108
|
const content = await readFile5(filePath, "utf-8");
|
|
@@ -80140,16 +80292,16 @@ async function seed(ctx, options) {
|
|
|
80140
80292
|
await cleanQdrant();
|
|
80141
80293
|
}
|
|
80142
80294
|
log("\u{1F4E6} Seeding apps...");
|
|
80143
|
-
const apps = await loadJsonFiles(
|
|
80295
|
+
const apps = await loadJsonFiles(join5(fixturesPath, "apps"));
|
|
80144
80296
|
result.apps = await seedApps(connection, apps);
|
|
80145
80297
|
log("\u{1F465} Loading customer fixtures...");
|
|
80146
|
-
const customers = await loadJsonFiles(
|
|
80298
|
+
const customers = await loadJsonFiles(join5(fixturesPath, "customers"));
|
|
80147
80299
|
result.customers = customers.length;
|
|
80148
80300
|
log("\u{1F4DA} Seeding knowledge base...");
|
|
80149
|
-
const knowledge = await loadKnowledgeFiles(
|
|
80301
|
+
const knowledge = await loadKnowledgeFiles(join5(fixturesPath, "knowledge"));
|
|
80150
80302
|
result.knowledge = knowledge.length;
|
|
80151
80303
|
result.embeddings = await seedKnowledgeBase(knowledge, !outputJson);
|
|
80152
|
-
const scenarioFiles = await glob3(
|
|
80304
|
+
const scenarioFiles = await glob3(join5(fixturesPath, "scenarios/**/*.json"));
|
|
80153
80305
|
result.scenarios = scenarioFiles.length;
|
|
80154
80306
|
await connection.end();
|
|
80155
80307
|
if (outputJson) {
|
|
@@ -80225,8 +80377,8 @@ init_esm_shims();
|
|
|
80225
80377
|
// src/commands/eval-pipeline/run.ts
|
|
80226
80378
|
init_esm_shims();
|
|
80227
80379
|
import { createHash as createHash2 } from "crypto";
|
|
80228
|
-
import { existsSync as
|
|
80229
|
-
import { join as
|
|
80380
|
+
import { existsSync as existsSync8, mkdirSync, readFileSync as readFileSync5, rmSync, writeFileSync as writeFileSync4 } from "fs";
|
|
80381
|
+
import { join as join6 } from "path";
|
|
80230
80382
|
import { readFile as readFile6 } from "fs/promises";
|
|
80231
80383
|
import { glob as glob4 } from "glob";
|
|
80232
80384
|
|
|
@@ -80639,11 +80791,11 @@ function getCacheKey(scenarioId, classifySourceHash) {
|
|
|
80639
80791
|
function getClassifySourceHash() {
|
|
80640
80792
|
try {
|
|
80641
80793
|
const possiblePaths = [
|
|
80642
|
-
|
|
80643
|
-
|
|
80794
|
+
join6(process.cwd(), "packages/core/src/pipeline/classify.ts"),
|
|
80795
|
+
join6(process.cwd(), "../core/src/pipeline/classify.ts")
|
|
80644
80796
|
];
|
|
80645
80797
|
for (const path of possiblePaths) {
|
|
80646
|
-
if (
|
|
80798
|
+
if (existsSync8(path)) {
|
|
80647
80799
|
const content = readFileSync5(path, "utf-8");
|
|
80648
80800
|
return createHash2("md5").update(content).digest("hex");
|
|
80649
80801
|
}
|
|
@@ -80653,9 +80805,9 @@ function getClassifySourceHash() {
|
|
|
80653
80805
|
return createHash2("md5").update(Math.floor(Date.now() / 3e5).toString()).digest("hex");
|
|
80654
80806
|
}
|
|
80655
80807
|
function loadCachedClassify(cacheKey) {
|
|
80656
|
-
const cachePath =
|
|
80808
|
+
const cachePath = join6(CACHE_DIR, `${cacheKey}.json`);
|
|
80657
80809
|
try {
|
|
80658
|
-
if (
|
|
80810
|
+
if (existsSync8(cachePath)) {
|
|
80659
80811
|
return JSON.parse(readFileSync5(cachePath, "utf-8"));
|
|
80660
80812
|
}
|
|
80661
80813
|
} catch {
|
|
@@ -80664,17 +80816,17 @@ function loadCachedClassify(cacheKey) {
|
|
|
80664
80816
|
}
|
|
80665
80817
|
function saveCachedClassify(cacheKey, result) {
|
|
80666
80818
|
try {
|
|
80667
|
-
if (!
|
|
80819
|
+
if (!existsSync8(CACHE_DIR)) {
|
|
80668
80820
|
mkdirSync(CACHE_DIR, { recursive: true });
|
|
80669
80821
|
}
|
|
80670
|
-
const cachePath =
|
|
80822
|
+
const cachePath = join6(CACHE_DIR, `${cacheKey}.json`);
|
|
80671
80823
|
writeFileSync4(cachePath, JSON.stringify(result));
|
|
80672
80824
|
} catch {
|
|
80673
80825
|
}
|
|
80674
80826
|
}
|
|
80675
80827
|
function clearClassifyCache() {
|
|
80676
80828
|
try {
|
|
80677
|
-
if (
|
|
80829
|
+
if (existsSync8(CACHE_DIR)) {
|
|
80678
80830
|
rmSync(CACHE_DIR, { recursive: true, force: true });
|
|
80679
80831
|
}
|
|
80680
80832
|
} catch {
|
|
@@ -81346,7 +81498,7 @@ async function runValidateEval(ctx, scenarios, options) {
|
|
|
81346
81498
|
return results;
|
|
81347
81499
|
}
|
|
81348
81500
|
async function runE2EEval(ctx, scenarios, options) {
|
|
81349
|
-
const { runPipeline: runPipeline2 } = await import("./pipeline-
|
|
81501
|
+
const { runPipeline: runPipeline2 } = await import("./pipeline-JPI7ITZN.js");
|
|
81350
81502
|
const concurrency = options.parallel || 1;
|
|
81351
81503
|
let completed = 0;
|
|
81352
81504
|
const outputJson = options.outputJson ?? false;
|
|
@@ -81550,7 +81702,7 @@ Latency: ${avgLatency.toFixed(0)}ms avg`);
|
|
|
81550
81702
|
|
|
81551
81703
|
// src/commands/eval-pipeline/seed.ts
|
|
81552
81704
|
init_esm_shims();
|
|
81553
|
-
import { join as
|
|
81705
|
+
import { join as join7 } from "path";
|
|
81554
81706
|
import { glob as glob5 } from "glob";
|
|
81555
81707
|
async function seed2(ctx, options) {
|
|
81556
81708
|
const fixturesPath = options.fixtures || "fixtures";
|
|
@@ -81581,20 +81733,20 @@ async function seed2(ctx, options) {
|
|
|
81581
81733
|
await cleanQdrant();
|
|
81582
81734
|
}
|
|
81583
81735
|
if (!outputJson) ctx.output.message("\u{1F4E6} Seeding apps...");
|
|
81584
|
-
const apps = await loadJsonFiles(
|
|
81736
|
+
const apps = await loadJsonFiles(join7(fixturesPath, "apps"));
|
|
81585
81737
|
result.apps = await seedApps(connection, apps);
|
|
81586
81738
|
const [trustRows] = await connection.execute(
|
|
81587
81739
|
"SELECT COUNT(*) as count FROM SUPPORT_trust_scores"
|
|
81588
81740
|
);
|
|
81589
81741
|
result.trustScores = trustRows[0].count;
|
|
81590
81742
|
if (!outputJson) ctx.output.message("\u{1F465} Loading customer fixtures...");
|
|
81591
|
-
const customers = await loadJsonFiles(
|
|
81743
|
+
const customers = await loadJsonFiles(join7(fixturesPath, "customers"));
|
|
81592
81744
|
result.customers = customers.length;
|
|
81593
81745
|
if (!outputJson) ctx.output.message("\u{1F4DA} Seeding knowledge base...");
|
|
81594
|
-
const knowledge = await loadKnowledgeFiles(
|
|
81746
|
+
const knowledge = await loadKnowledgeFiles(join7(fixturesPath, "knowledge"));
|
|
81595
81747
|
result.knowledge = knowledge.length;
|
|
81596
81748
|
result.embeddings = await seedKnowledgeBase(knowledge, !outputJson);
|
|
81597
|
-
const scenarioFiles = await glob5(
|
|
81749
|
+
const scenarioFiles = await glob5(join7(fixturesPath, "scenarios/**/*.json"));
|
|
81598
81750
|
result.scenarios = scenarioFiles.length;
|
|
81599
81751
|
await connection.end();
|
|
81600
81752
|
if (outputJson) {
|
|
@@ -81666,7 +81818,7 @@ function registerEvalPipelineCommands(program3) {
|
|
|
81666
81818
|
|
|
81667
81819
|
// src/commands/eval-prompt.ts
|
|
81668
81820
|
init_esm_shims();
|
|
81669
|
-
import { existsSync as
|
|
81821
|
+
import { existsSync as existsSync9, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
|
|
81670
81822
|
import { generateText as generateText2, stepCountIs as stepCountIs2, tool as tool4 } from "ai";
|
|
81671
81823
|
import { z as z5 } from "zod";
|
|
81672
81824
|
var leakPatterns = [
|
|
@@ -81853,7 +82005,7 @@ async function runEval2(ctx, options) {
|
|
|
81853
82005
|
try {
|
|
81854
82006
|
let prompt = SUPPORT_AGENT_PROMPT;
|
|
81855
82007
|
if (promptPath) {
|
|
81856
|
-
if (!
|
|
82008
|
+
if (!existsSync9(promptPath)) {
|
|
81857
82009
|
throw new CLIError({
|
|
81858
82010
|
userMessage: `Prompt file not found: ${promptPath}.`,
|
|
81859
82011
|
suggestion: "Verify the prompt path and try again."
|
|
@@ -81866,7 +82018,7 @@ async function runEval2(ctx, options) {
|
|
|
81866
82018
|
} else if (!outputJson) {
|
|
81867
82019
|
ctx.output.message("Using production prompt");
|
|
81868
82020
|
}
|
|
81869
|
-
if (!
|
|
82021
|
+
if (!existsSync9(datasetPath)) {
|
|
81870
82022
|
throw new CLIError({
|
|
81871
82023
|
userMessage: `Dataset not found: ${datasetPath}.`,
|
|
81872
82024
|
suggestion: "Provide a valid dataset file path."
|
|
@@ -81978,7 +82130,7 @@ async function comparePrompts(ctx, options) {
|
|
|
81978
82130
|
try {
|
|
81979
82131
|
const baselinePrompt = baseline ? readFileSync6(baseline, "utf-8") : SUPPORT_AGENT_PROMPT;
|
|
81980
82132
|
const candidatePrompt = readFileSync6(candidate, "utf-8");
|
|
81981
|
-
if (!
|
|
82133
|
+
if (!existsSync9(datasetPath)) {
|
|
81982
82134
|
throw new CLIError({
|
|
81983
82135
|
userMessage: `Dataset not found: ${datasetPath}.`,
|
|
81984
82136
|
suggestion: "Provide a valid dataset file path."
|
|
@@ -82126,20 +82278,20 @@ init_esm_shims();
|
|
|
82126
82278
|
|
|
82127
82279
|
// src/commands/faq/classify.ts
|
|
82128
82280
|
init_esm_shims();
|
|
82129
|
-
import { appendFileSync, existsSync as
|
|
82130
|
-
import { dirname as dirname2, join as
|
|
82281
|
+
import { appendFileSync, existsSync as existsSync10, mkdirSync as mkdirSync2, readFileSync as readFileSync7 } from "fs";
|
|
82282
|
+
import { dirname as dirname2, join as join8, resolve as resolve3 } from "path";
|
|
82131
82283
|
import { generateObject } from "ai";
|
|
82132
82284
|
import { z as z6 } from "zod";
|
|
82133
82285
|
var PROJECT_ROOT = resolve3(__dirname, "../../../..");
|
|
82134
|
-
var DEFAULT_PARQUET_PATH =
|
|
82286
|
+
var DEFAULT_PARQUET_PATH = join8(
|
|
82135
82287
|
PROJECT_ROOT,
|
|
82136
82288
|
"artifacts/phase-0/embeddings/v2/conversations.parquet"
|
|
82137
82289
|
);
|
|
82138
|
-
var DEFAULT_TAXONOMY_PATH =
|
|
82290
|
+
var DEFAULT_TAXONOMY_PATH = join8(
|
|
82139
82291
|
PROJECT_ROOT,
|
|
82140
82292
|
"artifacts/phase-1/llm-topics/taxonomy.json"
|
|
82141
82293
|
);
|
|
82142
|
-
var DEFAULT_OUTPUT_PATH =
|
|
82294
|
+
var DEFAULT_OUTPUT_PATH = join8(
|
|
82143
82295
|
PROJECT_ROOT,
|
|
82144
82296
|
"artifacts/phase-1/llm-topics/classifications.jsonl"
|
|
82145
82297
|
);
|
|
@@ -82173,7 +82325,7 @@ function createProgressReporter(ctx, total) {
|
|
|
82173
82325
|
};
|
|
82174
82326
|
}
|
|
82175
82327
|
async function loadConversationsFromParquet(parquetPath) {
|
|
82176
|
-
const { execSync:
|
|
82328
|
+
const { execSync: execSync4 } = await import("child_process");
|
|
82177
82329
|
const query = `
|
|
82178
82330
|
SELECT
|
|
82179
82331
|
conversation_id,
|
|
@@ -82184,7 +82336,7 @@ async function loadConversationsFromParquet(parquetPath) {
|
|
|
82184
82336
|
WHERE first_message IS NOT NULL
|
|
82185
82337
|
ORDER BY conversation_id
|
|
82186
82338
|
`;
|
|
82187
|
-
const result =
|
|
82339
|
+
const result = execSync4(`duckdb -json -c "${query.replace(/"/g, '\\"')}"`, {
|
|
82188
82340
|
encoding: "utf-8",
|
|
82189
82341
|
maxBuffer: 100 * 1024 * 1024
|
|
82190
82342
|
// 100MB buffer for large datasets
|
|
@@ -82194,7 +82346,7 @@ async function loadConversationsFromParquet(parquetPath) {
|
|
|
82194
82346
|
}
|
|
82195
82347
|
function loadExistingClassifications(outputPath) {
|
|
82196
82348
|
const classifiedIds = /* @__PURE__ */ new Set();
|
|
82197
|
-
if (!
|
|
82349
|
+
if (!existsSync10(outputPath)) {
|
|
82198
82350
|
return classifiedIds;
|
|
82199
82351
|
}
|
|
82200
82352
|
const content = readFileSync7(outputPath, "utf-8");
|
|
@@ -82312,7 +82464,7 @@ async function faqClassify(ctx, options) {
|
|
|
82312
82464
|
ctx.output.data(` Dry run: ${options.dryRun ?? false}`);
|
|
82313
82465
|
ctx.output.data("");
|
|
82314
82466
|
}
|
|
82315
|
-
if (!
|
|
82467
|
+
if (!existsSync10(parquetPath)) {
|
|
82316
82468
|
handleFaqClassifyError(
|
|
82317
82469
|
ctx,
|
|
82318
82470
|
new CLIError({
|
|
@@ -82323,7 +82475,7 @@ async function faqClassify(ctx, options) {
|
|
|
82323
82475
|
);
|
|
82324
82476
|
return;
|
|
82325
82477
|
}
|
|
82326
|
-
if (!
|
|
82478
|
+
if (!existsSync10(taxonomyPath)) {
|
|
82327
82479
|
handleFaqClassifyError(
|
|
82328
82480
|
ctx,
|
|
82329
82481
|
new CLIError({
|
|
@@ -82335,7 +82487,7 @@ async function faqClassify(ctx, options) {
|
|
|
82335
82487
|
return;
|
|
82336
82488
|
}
|
|
82337
82489
|
const outputDir = dirname2(outputPath);
|
|
82338
|
-
if (!
|
|
82490
|
+
if (!existsSync10(outputDir)) {
|
|
82339
82491
|
mkdirSync2(outputDir, { recursive: true });
|
|
82340
82492
|
}
|
|
82341
82493
|
if (!outputJson) ctx.output.data("\u{1F4DA} Loading taxonomy...");
|
|
@@ -82504,18 +82656,18 @@ function registerFaqClassifyCommands(program3) {
|
|
|
82504
82656
|
|
|
82505
82657
|
// src/commands/faq/cluster.ts
|
|
82506
82658
|
init_esm_shims();
|
|
82507
|
-
import { existsSync as
|
|
82508
|
-
import { join as
|
|
82659
|
+
import { existsSync as existsSync12 } from "fs";
|
|
82660
|
+
import { join as join10, resolve as resolve4 } from "path";
|
|
82509
82661
|
|
|
82510
82662
|
// ../core/src/faq/production-clusterer.ts
|
|
82511
82663
|
init_esm_shims();
|
|
82512
|
-
import { existsSync as
|
|
82513
|
-
import { join as
|
|
82664
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
|
|
82665
|
+
import { join as join9 } from "path";
|
|
82514
82666
|
function readPhase0Assignments(phase0Path) {
|
|
82515
|
-
const assignmentsPath =
|
|
82516
|
-
if (!
|
|
82517
|
-
const latestPath =
|
|
82518
|
-
if (!
|
|
82667
|
+
const assignmentsPath = join9(phase0Path, "clusters/v1/assignments.json");
|
|
82668
|
+
if (!existsSync11(assignmentsPath)) {
|
|
82669
|
+
const latestPath = join9(phase0Path, "clusters/latest/assignments.json");
|
|
82670
|
+
if (!existsSync11(latestPath)) {
|
|
82519
82671
|
throw new Error(`Phase 0 assignments not found at ${assignmentsPath}`);
|
|
82520
82672
|
}
|
|
82521
82673
|
const content2 = readFileSync8(latestPath, "utf-8");
|
|
@@ -82525,10 +82677,10 @@ function readPhase0Assignments(phase0Path) {
|
|
|
82525
82677
|
return JSON.parse(content);
|
|
82526
82678
|
}
|
|
82527
82679
|
function readPhase0Labels(phase0Path) {
|
|
82528
|
-
const labelsPath =
|
|
82529
|
-
if (!
|
|
82530
|
-
const latestPath =
|
|
82531
|
-
if (!
|
|
82680
|
+
const labelsPath = join9(phase0Path, "clusters/v1/labels.json");
|
|
82681
|
+
if (!existsSync11(labelsPath)) {
|
|
82682
|
+
const latestPath = join9(phase0Path, "clusters/latest/labels.json");
|
|
82683
|
+
if (!existsSync11(latestPath)) {
|
|
82532
82684
|
throw new Error(`Phase 0 labels not found at ${labelsPath}`);
|
|
82533
82685
|
}
|
|
82534
82686
|
const content2 = readFileSync8(latestPath, "utf-8");
|
|
@@ -82540,10 +82692,10 @@ function readPhase0Labels(phase0Path) {
|
|
|
82540
82692
|
return parsed.clusters || [];
|
|
82541
82693
|
}
|
|
82542
82694
|
function readPhase0Metrics(phase0Path) {
|
|
82543
|
-
const metricsPath =
|
|
82544
|
-
if (!
|
|
82545
|
-
const latestPath =
|
|
82546
|
-
if (!
|
|
82695
|
+
const metricsPath = join9(phase0Path, "clusters/v1/metrics.json");
|
|
82696
|
+
if (!existsSync11(metricsPath)) {
|
|
82697
|
+
const latestPath = join9(phase0Path, "clusters/latest/metrics.json");
|
|
82698
|
+
if (!existsSync11(latestPath)) {
|
|
82547
82699
|
throw new Error(`Phase 0 metrics not found at ${metricsPath}`);
|
|
82548
82700
|
}
|
|
82549
82701
|
return JSON.parse(readFileSync8(latestPath, "utf-8"));
|
|
@@ -82663,17 +82815,17 @@ async function generateProductionClustering(options) {
|
|
|
82663
82815
|
return result;
|
|
82664
82816
|
}
|
|
82665
82817
|
function writeProductionArtifacts(result, outputPath) {
|
|
82666
|
-
const versionPath =
|
|
82667
|
-
if (!
|
|
82818
|
+
const versionPath = join9(outputPath, result.version);
|
|
82819
|
+
if (!existsSync11(versionPath)) {
|
|
82668
82820
|
mkdirSync3(versionPath, { recursive: true });
|
|
82669
82821
|
}
|
|
82670
|
-
const resultPath =
|
|
82822
|
+
const resultPath = join9(versionPath, "clustering-result.json");
|
|
82671
82823
|
writeFileSync6(resultPath, JSON.stringify(result, null, 2));
|
|
82672
82824
|
console.log(`\u2705 Written: ${resultPath}`);
|
|
82673
|
-
const assignmentsPath =
|
|
82825
|
+
const assignmentsPath = join9(versionPath, "assignments.json");
|
|
82674
82826
|
writeFileSync6(assignmentsPath, JSON.stringify(result.assignments, null, 2));
|
|
82675
82827
|
console.log(`\u2705 Written: ${assignmentsPath}`);
|
|
82676
|
-
const clustersPath =
|
|
82828
|
+
const clustersPath = join9(versionPath, "clusters.json");
|
|
82677
82829
|
writeFileSync6(
|
|
82678
82830
|
clustersPath,
|
|
82679
82831
|
JSON.stringify(
|
|
@@ -82688,7 +82840,7 @@ function writeProductionArtifacts(result, outputPath) {
|
|
|
82688
82840
|
)
|
|
82689
82841
|
);
|
|
82690
82842
|
console.log(`\u2705 Written: ${clustersPath}`);
|
|
82691
|
-
const summaryPath =
|
|
82843
|
+
const summaryPath = join9(versionPath, "summary.json");
|
|
82692
82844
|
const summary = {
|
|
82693
82845
|
version: result.version,
|
|
82694
82846
|
generatedAt: result.generatedAt,
|
|
@@ -82702,8 +82854,8 @@ function writeProductionArtifacts(result, outputPath) {
|
|
|
82702
82854
|
};
|
|
82703
82855
|
writeFileSync6(summaryPath, JSON.stringify(summary, null, 2));
|
|
82704
82856
|
console.log(`\u2705 Written: ${summaryPath}`);
|
|
82705
|
-
const latestPath =
|
|
82706
|
-
if (
|
|
82857
|
+
const latestPath = join9(outputPath, "latest");
|
|
82858
|
+
if (existsSync11(latestPath)) {
|
|
82707
82859
|
const { rmSync: rmSync2 } = __require("fs");
|
|
82708
82860
|
rmSync2(latestPath, { recursive: true, force: true });
|
|
82709
82861
|
}
|
|
@@ -82714,8 +82866,8 @@ function writeProductionArtifacts(result, outputPath) {
|
|
|
82714
82866
|
"clusters.json",
|
|
82715
82867
|
"summary.json"
|
|
82716
82868
|
]) {
|
|
82717
|
-
const src =
|
|
82718
|
-
const dst =
|
|
82869
|
+
const src = join9(versionPath, file);
|
|
82870
|
+
const dst = join9(latestPath, file);
|
|
82719
82871
|
writeFileSync6(dst, readFileSync8(src));
|
|
82720
82872
|
}
|
|
82721
82873
|
console.log(`\u2705 Updated: ${latestPath}`);
|
|
@@ -82768,25 +82920,25 @@ function displayClusteringSummary(result) {
|
|
|
82768
82920
|
|
|
82769
82921
|
// src/commands/faq/cluster.ts
|
|
82770
82922
|
var PROJECT_ROOT2 = resolve4(__dirname, "../../../..");
|
|
82771
|
-
var DEFAULT_PHASE0_PATH =
|
|
82772
|
-
var DEFAULT_OUTPUT_PATH2 =
|
|
82923
|
+
var DEFAULT_PHASE0_PATH = join10(PROJECT_ROOT2, "artifacts/phase-0");
|
|
82924
|
+
var DEFAULT_OUTPUT_PATH2 = join10(PROJECT_ROOT2, "artifacts/phase-1/clustering");
|
|
82773
82925
|
function validatePaths(phase0Path) {
|
|
82774
|
-
const assignmentsPath =
|
|
82775
|
-
const labelsPath =
|
|
82776
|
-
const metricsPath =
|
|
82777
|
-
if (!
|
|
82926
|
+
const assignmentsPath = join10(phase0Path, "clusters/v1/assignments.json");
|
|
82927
|
+
const labelsPath = join10(phase0Path, "clusters/v1/labels.json");
|
|
82928
|
+
const metricsPath = join10(phase0Path, "clusters/v1/metrics.json");
|
|
82929
|
+
if (!existsSync12(assignmentsPath)) {
|
|
82778
82930
|
throw new CLIError({
|
|
82779
82931
|
userMessage: `Phase 0 assignments not found at ${assignmentsPath}.`,
|
|
82780
82932
|
suggestion: "Run Phase 0 clustering first or specify the correct --phase0-path."
|
|
82781
82933
|
});
|
|
82782
82934
|
}
|
|
82783
|
-
if (!
|
|
82935
|
+
if (!existsSync12(labelsPath)) {
|
|
82784
82936
|
throw new CLIError({
|
|
82785
82937
|
userMessage: `Phase 0 labels not found at ${labelsPath}.`,
|
|
82786
82938
|
suggestion: "Verify the --phase0-path points to valid artifacts."
|
|
82787
82939
|
});
|
|
82788
82940
|
}
|
|
82789
|
-
if (!
|
|
82941
|
+
if (!existsSync12(metricsPath)) {
|
|
82790
82942
|
throw new CLIError({
|
|
82791
82943
|
userMessage: `Phase 0 metrics not found at ${metricsPath}.`,
|
|
82792
82944
|
suggestion: "Verify the --phase0-path points to valid artifacts."
|
|
@@ -82824,7 +82976,7 @@ async function faqCluster(ctx, options) {
|
|
|
82824
82976
|
writeProductionArtifacts(result, outputPath);
|
|
82825
82977
|
if (!outputJson) {
|
|
82826
82978
|
ctx.output.data("\n\u2705 Production clustering complete!");
|
|
82827
|
-
ctx.output.data(` Artifacts written to: ${
|
|
82979
|
+
ctx.output.data(` Artifacts written to: ${join10(outputPath, version)}`);
|
|
82828
82980
|
}
|
|
82829
82981
|
} else {
|
|
82830
82982
|
if (!outputJson) ctx.output.data("\n\u{1F9EA} Dry run - no artifacts written");
|
|
@@ -82867,13 +83019,13 @@ function registerFaqClusterCommands(program3) {
|
|
|
82867
83019
|
|
|
82868
83020
|
// src/commands/faq/extract.ts
|
|
82869
83021
|
init_esm_shims();
|
|
82870
|
-
import { existsSync as
|
|
82871
|
-
import { join as
|
|
83022
|
+
import { existsSync as existsSync14 } from "fs";
|
|
83023
|
+
import { join as join12, resolve as resolve5 } from "path";
|
|
82872
83024
|
|
|
82873
83025
|
// ../core/src/faq/extractor.ts
|
|
82874
83026
|
init_esm_shims();
|
|
82875
|
-
import { existsSync as
|
|
82876
|
-
import { join as
|
|
83027
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync4, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
|
|
83028
|
+
import { join as join11 } from "path";
|
|
82877
83029
|
|
|
82878
83030
|
// ../core/src/faq/review.ts
|
|
82879
83031
|
init_esm_shims();
|
|
@@ -83487,14 +83639,14 @@ async function extractFaqCandidates(options) {
|
|
|
83487
83639
|
return result;
|
|
83488
83640
|
}
|
|
83489
83641
|
function writeExtractionArtifacts(result, outputPath) {
|
|
83490
|
-
const versionPath =
|
|
83491
|
-
if (!
|
|
83642
|
+
const versionPath = join11(outputPath, result.version);
|
|
83643
|
+
if (!existsSync13(versionPath)) {
|
|
83492
83644
|
mkdirSync4(versionPath, { recursive: true });
|
|
83493
83645
|
}
|
|
83494
|
-
const resultPath =
|
|
83646
|
+
const resultPath = join11(versionPath, "extraction-result.json");
|
|
83495
83647
|
writeFileSync7(resultPath, JSON.stringify(result, null, 2));
|
|
83496
83648
|
console.log(`\u2705 Written: ${resultPath}`);
|
|
83497
|
-
const candidatesPath =
|
|
83649
|
+
const candidatesPath = join11(versionPath, "candidates.json");
|
|
83498
83650
|
const candidatesData = {
|
|
83499
83651
|
version: result.version,
|
|
83500
83652
|
extractedAt: result.extractedAt,
|
|
@@ -83514,7 +83666,7 @@ function writeExtractionArtifacts(result, outputPath) {
|
|
|
83514
83666
|
};
|
|
83515
83667
|
writeFileSync7(candidatesPath, JSON.stringify(candidatesData, null, 2));
|
|
83516
83668
|
console.log(`\u2705 Written: ${candidatesPath}`);
|
|
83517
|
-
const statsPath =
|
|
83669
|
+
const statsPath = join11(versionPath, "stats.json");
|
|
83518
83670
|
writeFileSync7(
|
|
83519
83671
|
statsPath,
|
|
83520
83672
|
JSON.stringify(
|
|
@@ -83528,8 +83680,8 @@ function writeExtractionArtifacts(result, outputPath) {
|
|
|
83528
83680
|
)
|
|
83529
83681
|
);
|
|
83530
83682
|
console.log(`\u2705 Written: ${statsPath}`);
|
|
83531
|
-
const latestPath =
|
|
83532
|
-
if (
|
|
83683
|
+
const latestPath = join11(outputPath, "latest");
|
|
83684
|
+
if (existsSync13(latestPath)) {
|
|
83533
83685
|
const { rmSync: rmSync2 } = __require("fs");
|
|
83534
83686
|
rmSync2(latestPath, { recursive: true, force: true });
|
|
83535
83687
|
}
|
|
@@ -83539,9 +83691,9 @@ function writeExtractionArtifacts(result, outputPath) {
|
|
|
83539
83691
|
"candidates.json",
|
|
83540
83692
|
"stats.json"
|
|
83541
83693
|
]) {
|
|
83542
|
-
const src =
|
|
83543
|
-
const dst =
|
|
83544
|
-
if (
|
|
83694
|
+
const src = join11(versionPath, file);
|
|
83695
|
+
const dst = join11(latestPath, file);
|
|
83696
|
+
if (existsSync13(src)) {
|
|
83545
83697
|
writeFileSync7(dst, readFileSync9(src));
|
|
83546
83698
|
}
|
|
83547
83699
|
}
|
|
@@ -83595,24 +83747,24 @@ ${i + 1}. [${confPct}%]${golden} ${candidate.suggestedCategory}`
|
|
|
83595
83747
|
|
|
83596
83748
|
// src/commands/faq/extract.ts
|
|
83597
83749
|
var PROJECT_ROOT3 = resolve5(__dirname, "../../../..");
|
|
83598
|
-
var DEFAULT_CLUSTERING_PATH =
|
|
83750
|
+
var DEFAULT_CLUSTERING_PATH = join12(
|
|
83599
83751
|
PROJECT_ROOT3,
|
|
83600
83752
|
"artifacts/phase-1/clustering/v1/clustering-result.json"
|
|
83601
83753
|
);
|
|
83602
|
-
var DEFAULT_GOLDEN_PATH =
|
|
83754
|
+
var DEFAULT_GOLDEN_PATH = join12(
|
|
83603
83755
|
PROJECT_ROOT3,
|
|
83604
83756
|
"artifacts/phase-0/golden/latest/responses.json"
|
|
83605
83757
|
);
|
|
83606
|
-
var DEFAULT_OUTPUT_PATH3 =
|
|
83758
|
+
var DEFAULT_OUTPUT_PATH3 = join12(PROJECT_ROOT3, "artifacts/phase-1/extraction");
|
|
83607
83759
|
var DEFAULT_CACHE_PATH = `${process.env.HOME}/skill/data/front-cache.db`;
|
|
83608
83760
|
function validatePaths2(ctx, clusteringPath, goldenPath, outputJson) {
|
|
83609
|
-
if (!
|
|
83761
|
+
if (!existsSync14(clusteringPath)) {
|
|
83610
83762
|
throw new CLIError({
|
|
83611
83763
|
userMessage: `Clustering result not found at ${clusteringPath}.`,
|
|
83612
83764
|
suggestion: "Run `bun src/index.ts faq cluster` first to generate clustering."
|
|
83613
83765
|
});
|
|
83614
83766
|
}
|
|
83615
|
-
if (goldenPath && !
|
|
83767
|
+
if (goldenPath && !existsSync14(goldenPath)) {
|
|
83616
83768
|
if (!outputJson) {
|
|
83617
83769
|
ctx.output.warn(`Golden responses not found at ${goldenPath}`);
|
|
83618
83770
|
ctx.output.warn("Golden matching will be disabled.");
|
|
@@ -83641,7 +83793,7 @@ async function faqExtract(ctx, options) {
|
|
|
83641
83793
|
ctx.output.data("");
|
|
83642
83794
|
}
|
|
83643
83795
|
validatePaths2(ctx, clusteringPath, goldenPath, outputJson);
|
|
83644
|
-
if (!
|
|
83796
|
+
if (!existsSync14(cachePath)) {
|
|
83645
83797
|
const cliError = new CLIError({
|
|
83646
83798
|
userMessage: `DuckDB cache not found at ${cachePath}.`,
|
|
83647
83799
|
suggestion: "Run `bun src/index.ts front-cache sync` first to populate cache."
|
|
@@ -83663,7 +83815,7 @@ async function faqExtract(ctx, options) {
|
|
|
83663
83815
|
}
|
|
83664
83816
|
const extractionOptions = {
|
|
83665
83817
|
clusteringPath,
|
|
83666
|
-
goldenPath:
|
|
83818
|
+
goldenPath: existsSync14(goldenPath) ? goldenPath : void 0,
|
|
83667
83819
|
source,
|
|
83668
83820
|
outputPath,
|
|
83669
83821
|
version,
|
|
@@ -83708,7 +83860,7 @@ async function faqExtract(ctx, options) {
|
|
|
83708
83860
|
if (!options.dryRun) {
|
|
83709
83861
|
ctx.output.data(`
|
|
83710
83862
|
\u2705 Extraction complete!`);
|
|
83711
|
-
ctx.output.data(` Artifacts written to: ${
|
|
83863
|
+
ctx.output.data(` Artifacts written to: ${join12(outputPath, version)}`);
|
|
83712
83864
|
if (options.pushRedis && options.app) {
|
|
83713
83865
|
ctx.output.data(
|
|
83714
83866
|
` Candidates pushed to Redis queue: faq:pending:${options.app}`
|
|
@@ -92737,9 +92889,9 @@ function registerFaqMineCommands(program3) {
|
|
|
92737
92889
|
// src/commands/faq/review.ts
|
|
92738
92890
|
init_esm_shims();
|
|
92739
92891
|
import { spawnSync } from "child_process";
|
|
92740
|
-
import { existsSync as
|
|
92892
|
+
import { existsSync as existsSync15, readFileSync as readFileSync10, unlinkSync, writeFileSync as writeFileSync9 } from "fs";
|
|
92741
92893
|
import { tmpdir } from "os";
|
|
92742
|
-
import { join as
|
|
92894
|
+
import { join as join13 } from "path";
|
|
92743
92895
|
import { confirm as confirm2, select as select3 } from "@inquirer/prompts";
|
|
92744
92896
|
var COLORS2 = {
|
|
92745
92897
|
reset: "\x1B[0m",
|
|
@@ -92800,7 +92952,7 @@ function getEditor() {
|
|
|
92800
92952
|
}
|
|
92801
92953
|
function editInEditor(ctx, question, answer) {
|
|
92802
92954
|
const editor = getEditor();
|
|
92803
|
-
const tmpFile =
|
|
92955
|
+
const tmpFile = join13(tmpdir(), `faq-edit-${Date.now()}.md`);
|
|
92804
92956
|
const content = `# FAQ Edit
|
|
92805
92957
|
|
|
92806
92958
|
## Question
|
|
@@ -92843,7 +92995,7 @@ The sections are separated by "## Question" and "## Answer" headers.
|
|
|
92843
92995
|
answer: editedAnswer
|
|
92844
92996
|
};
|
|
92845
92997
|
} finally {
|
|
92846
|
-
if (
|
|
92998
|
+
if (existsSync15(tmpFile)) {
|
|
92847
92999
|
unlinkSync(tmpFile);
|
|
92848
93000
|
}
|
|
92849
93001
|
}
|
|
@@ -97795,6 +97947,154 @@ function registerInvestigateCommands(inngest) {
|
|
|
97795
97947
|
});
|
|
97796
97948
|
}
|
|
97797
97949
|
|
|
97950
|
+
// src/commands/inngest/patterns.ts
|
|
97951
|
+
init_esm_shims();
|
|
97952
|
+
async function patterns(ctx, options) {
|
|
97953
|
+
const outputJson = options.json === true || ctx.format === "json";
|
|
97954
|
+
try {
|
|
97955
|
+
const client = new InngestClient({ dev: options.dev });
|
|
97956
|
+
const params = { limit: 100 };
|
|
97957
|
+
if (options.after) {
|
|
97958
|
+
params.received_after = parseTimeArg(options.after);
|
|
97959
|
+
}
|
|
97960
|
+
const events = outputJson ? await client.listEvents(params) : await withSpinner("Fetching events...", () => client.listEvents(params));
|
|
97961
|
+
const byName = {};
|
|
97962
|
+
const byFunction = {};
|
|
97963
|
+
for (const event of events.data) {
|
|
97964
|
+
byName[event.name] = (byName[event.name] || 0) + 1;
|
|
97965
|
+
if (event.name === "inngest/function.finished") {
|
|
97966
|
+
const data2 = event.data;
|
|
97967
|
+
const functionId = data2?.function_id;
|
|
97968
|
+
if (!functionId) continue;
|
|
97969
|
+
if (!byFunction[functionId]) {
|
|
97970
|
+
byFunction[functionId] = { success: 0, failed: 0 };
|
|
97971
|
+
}
|
|
97972
|
+
if (data2.error || data2._inngest?.status === "Failed") {
|
|
97973
|
+
byFunction[functionId].failed++;
|
|
97974
|
+
} else {
|
|
97975
|
+
byFunction[functionId].success++;
|
|
97976
|
+
}
|
|
97977
|
+
}
|
|
97978
|
+
}
|
|
97979
|
+
const timeRangeHours = options.after ? parseTimeWindow(options.after) : 24;
|
|
97980
|
+
const topEvents = Object.entries(byName).map(([name, count]) => ({
|
|
97981
|
+
name,
|
|
97982
|
+
count,
|
|
97983
|
+
frequency_per_hour: count / timeRangeHours
|
|
97984
|
+
})).sort((a, b) => b.count - a.count).slice(0, 10);
|
|
97985
|
+
const functionStats = {};
|
|
97986
|
+
for (const [functionId, stats4] of Object.entries(byFunction)) {
|
|
97987
|
+
const total = stats4.success + stats4.failed;
|
|
97988
|
+
functionStats[functionId] = {
|
|
97989
|
+
success: stats4.success,
|
|
97990
|
+
failed: stats4.failed,
|
|
97991
|
+
success_rate: total > 0 ? stats4.success / total : 0
|
|
97992
|
+
};
|
|
97993
|
+
}
|
|
97994
|
+
const output = {
|
|
97995
|
+
time_range: options.after || "24h",
|
|
97996
|
+
total_events: events.data.length,
|
|
97997
|
+
events_by_name: byName,
|
|
97998
|
+
by_function: functionStats,
|
|
97999
|
+
top_events: topEvents
|
|
98000
|
+
};
|
|
98001
|
+
if (outputJson) {
|
|
98002
|
+
ctx.output.data(output);
|
|
98003
|
+
} else {
|
|
98004
|
+
const lines = [];
|
|
98005
|
+
lines.push("\nEvent Patterns\n");
|
|
98006
|
+
lines.push(`Time range: ${output.time_range}`);
|
|
98007
|
+
lines.push(`Total events: ${output.total_events}
|
|
98008
|
+
`);
|
|
98009
|
+
lines.push("Top Events:");
|
|
98010
|
+
lines.push(
|
|
98011
|
+
"\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"
|
|
98012
|
+
);
|
|
98013
|
+
lines.push(
|
|
98014
|
+
"\u2502 Event Name \u2502 Count \u2502 Per Hour \u2502"
|
|
98015
|
+
);
|
|
98016
|
+
lines.push(
|
|
98017
|
+
"\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"
|
|
98018
|
+
);
|
|
98019
|
+
for (const event of topEvents) {
|
|
98020
|
+
const name = event.name.padEnd(38).slice(0, 38);
|
|
98021
|
+
const count = String(event.count).padStart(5);
|
|
98022
|
+
const freq = event.frequency_per_hour.toFixed(2).padStart(12);
|
|
98023
|
+
lines.push(`\u2502 ${name} \u2502 ${count} \u2502 ${freq} \u2502`);
|
|
98024
|
+
}
|
|
98025
|
+
lines.push(
|
|
98026
|
+
"\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n"
|
|
98027
|
+
);
|
|
98028
|
+
if (Object.keys(functionStats).length > 0) {
|
|
98029
|
+
lines.push("Function Stats:");
|
|
98030
|
+
lines.push(
|
|
98031
|
+
"\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"
|
|
98032
|
+
);
|
|
98033
|
+
lines.push(
|
|
98034
|
+
"\u2502 Function \u2502 Success \u2502 Failed \u2502 Success % \u2502"
|
|
98035
|
+
);
|
|
98036
|
+
lines.push(
|
|
98037
|
+
"\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"
|
|
98038
|
+
);
|
|
98039
|
+
for (const [functionId, stats4] of Object.entries(functionStats)) {
|
|
98040
|
+
const name = functionId.padEnd(38).slice(0, 38);
|
|
98041
|
+
const success = String(stats4.success).padStart(7);
|
|
98042
|
+
const failed = String(stats4.failed).padStart(6);
|
|
98043
|
+
const rate = `${(stats4.success_rate * 100).toFixed(1)}%`.padStart(11);
|
|
98044
|
+
lines.push(`\u2502 ${name} \u2502 ${success} \u2502 ${failed} \u2502 ${rate} \u2502`);
|
|
98045
|
+
}
|
|
98046
|
+
lines.push(
|
|
98047
|
+
"\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n"
|
|
98048
|
+
);
|
|
98049
|
+
}
|
|
98050
|
+
lines.push(
|
|
98051
|
+
"Use `skill inngest failures` for detailed failure analysis.\n"
|
|
98052
|
+
);
|
|
98053
|
+
ctx.output.data(lines.join("\n"));
|
|
98054
|
+
}
|
|
98055
|
+
} catch (error) {
|
|
98056
|
+
const cliError = error instanceof CLIError ? error : new CLIError({
|
|
98057
|
+
userMessage: "Failed to analyze Inngest patterns.",
|
|
98058
|
+
suggestion: "Verify INNGEST_SIGNING_KEY and time window.",
|
|
98059
|
+
cause: error
|
|
98060
|
+
});
|
|
98061
|
+
ctx.output.error(formatError(cliError));
|
|
98062
|
+
process.exitCode = cliError.exitCode;
|
|
98063
|
+
}
|
|
98064
|
+
}
|
|
98065
|
+
function parseTimeWindow(input2) {
|
|
98066
|
+
const match = input2.match(/^(\d+)([hmd])$/);
|
|
98067
|
+
if (!match) return 24;
|
|
98068
|
+
const [, num, unit] = match;
|
|
98069
|
+
const value = Number.parseInt(num ?? "24", 10);
|
|
98070
|
+
switch (unit) {
|
|
98071
|
+
case "h":
|
|
98072
|
+
return value;
|
|
98073
|
+
case "d":
|
|
98074
|
+
return value * 24;
|
|
98075
|
+
case "m":
|
|
98076
|
+
return value / 60;
|
|
98077
|
+
default:
|
|
98078
|
+
return 24;
|
|
98079
|
+
}
|
|
98080
|
+
}
|
|
98081
|
+
function registerPatternsCommand(inngest) {
|
|
98082
|
+
inngest.command("patterns").description(
|
|
98083
|
+
"Aggregate event analysis (event distribution, function success rates)"
|
|
98084
|
+
).option("--after <time>", 'Time window (e.g., "2h", "1d")', "24h").option("--json", "Output as JSON").option("--dev", "Use dev server").action(async (options, command) => {
|
|
98085
|
+
const opts = typeof command.optsWithGlobals === "function" ? command.optsWithGlobals() : {
|
|
98086
|
+
...command.parent?.opts(),
|
|
98087
|
+
...command.opts()
|
|
98088
|
+
};
|
|
98089
|
+
const ctx = await createContext({
|
|
98090
|
+
format: options.json ? "json" : opts.format,
|
|
98091
|
+
verbose: opts.verbose,
|
|
98092
|
+
quiet: opts.quiet
|
|
98093
|
+
});
|
|
98094
|
+
await patterns(ctx, options);
|
|
98095
|
+
});
|
|
98096
|
+
}
|
|
98097
|
+
|
|
97798
98098
|
// src/commands/inngest/runs.ts
|
|
97799
98099
|
init_esm_shims();
|
|
97800
98100
|
import { confirm as confirm4 } from "@inquirer/prompts";
|
|
@@ -97984,11 +98284,16 @@ function registerSignalCommand(inngest) {
|
|
|
97984
98284
|
|
|
97985
98285
|
// src/commands/inngest/index.ts
|
|
97986
98286
|
function registerInngestCommands(program3, usageState2) {
|
|
97987
|
-
const
|
|
98287
|
+
const baseDescription = getInngestAdaptiveDescription(usageState2);
|
|
98288
|
+
const descriptionWithEnv = `${baseDescription}
|
|
98289
|
+
|
|
98290
|
+
Environment: INNGEST_SIGNING_KEY required. Run \`skill doctor\` to check.`;
|
|
98291
|
+
const inngest = program3.command("inngest").description(descriptionWithEnv);
|
|
97988
98292
|
registerEventsCommands(inngest);
|
|
97989
98293
|
registerRunsCommands(inngest);
|
|
97990
98294
|
registerSignalCommand(inngest);
|
|
97991
98295
|
registerInvestigateCommands(inngest);
|
|
98296
|
+
registerPatternsCommand(inngest);
|
|
97992
98297
|
}
|
|
97993
98298
|
|
|
97994
98299
|
// src/commands/kb-sync.ts
|
|
@@ -114017,7 +114322,7 @@ function registerKbCommands(program3) {
|
|
|
114017
114322
|
|
|
114018
114323
|
// src/commands/keys/index.ts
|
|
114019
114324
|
init_esm_shims();
|
|
114020
|
-
import { existsSync as
|
|
114325
|
+
import { existsSync as existsSync16, readFileSync as readFileSync12 } from "fs";
|
|
114021
114326
|
import { password as password2, select as select5 } from "@inquirer/prompts";
|
|
114022
114327
|
import { Decrypter as Decrypter4 } from "age-encryption";
|
|
114023
114328
|
var buildContext4 = async (command, json) => {
|
|
@@ -114032,9 +114337,9 @@ var buildContext4 = async (command, json) => {
|
|
|
114032
114337
|
});
|
|
114033
114338
|
};
|
|
114034
114339
|
async function getUserConfiguredKeys() {
|
|
114035
|
-
const keyPath =
|
|
114340
|
+
const keyPath = getAgeKeyPath2();
|
|
114036
114341
|
const configPath = getEncryptedConfigPath();
|
|
114037
|
-
if (!
|
|
114342
|
+
if (!existsSync16(keyPath) || !existsSync16(configPath)) {
|
|
114038
114343
|
return /* @__PURE__ */ new Set();
|
|
114039
114344
|
}
|
|
114040
114345
|
try {
|
|
@@ -114101,8 +114406,8 @@ async function showKeyStatus(ctx) {
|
|
|
114101
114406
|
ctx.output.data("");
|
|
114102
114407
|
}
|
|
114103
114408
|
async function interactiveKeySetup(ctx) {
|
|
114104
|
-
const keyPath =
|
|
114105
|
-
if (!
|
|
114409
|
+
const keyPath = getAgeKeyPath2();
|
|
114410
|
+
if (!existsSync16(keyPath)) {
|
|
114106
114411
|
ctx.output.data("\n\u{1F511} First time setup - creating your encryption key...\n");
|
|
114107
114412
|
await configInitAction(ctx, { json: false });
|
|
114108
114413
|
ctx.output.data("");
|
|
@@ -114194,8 +114499,8 @@ function registerKeysCommands(program3) {
|
|
|
114194
114499
|
"Add a personal API key\n\n Interactive: skill keys add\n Direct: skill keys add LINEAR_API_KEY=lin_xxx"
|
|
114195
114500
|
).option("--json", "Output as JSON").action(async (keyValue, options, command) => {
|
|
114196
114501
|
const ctx = await buildContext4(command, options.json);
|
|
114197
|
-
const keyPath =
|
|
114198
|
-
if (!
|
|
114502
|
+
const keyPath = getAgeKeyPath2();
|
|
114503
|
+
if (!existsSync16(keyPath)) {
|
|
114199
114504
|
if (process.stdin.isTTY && !options.json) {
|
|
114200
114505
|
ctx.output.data(
|
|
114201
114506
|
"\u{1F511} First time setup - creating your encryption key...\n"
|
|
@@ -114244,8 +114549,8 @@ function registerKeysCommands(program3) {
|
|
|
114244
114549
|
steps.push("\u2713 OP token from env");
|
|
114245
114550
|
}
|
|
114246
114551
|
if (!opToken) {
|
|
114247
|
-
const { getFromKeychain } = await import("./keychain-IEZHT5WN.js");
|
|
114248
|
-
opToken =
|
|
114552
|
+
const { getFromKeychain: getFromKeychain2 } = await import("./keychain-IEZHT5WN.js");
|
|
114553
|
+
opToken = getFromKeychain2("op-service-account-token");
|
|
114249
114554
|
if (opToken) steps.push("\u2713 OP token from keychain");
|
|
114250
114555
|
}
|
|
114251
114556
|
if (!opToken && status.opCliAvailable) {
|
|
@@ -114265,8 +114570,8 @@ function registerKeysCommands(program3) {
|
|
|
114265
114570
|
steps.push("\u2713 Age key from env");
|
|
114266
114571
|
}
|
|
114267
114572
|
if (!ageKey) {
|
|
114268
|
-
const { getFromKeychain } = await import("./keychain-IEZHT5WN.js");
|
|
114269
|
-
ageKey =
|
|
114573
|
+
const { getFromKeychain: getFromKeychain2 } = await import("./keychain-IEZHT5WN.js");
|
|
114574
|
+
ageKey = getFromKeychain2("age-private-key");
|
|
114270
114575
|
if (ageKey) steps.push("\u2713 Age key from keychain");
|
|
114271
114576
|
}
|
|
114272
114577
|
if (!ageKey && opToken) {
|
|
@@ -115637,6 +115942,25 @@ var PRIORITY_EMOJI2 = {
|
|
|
115637
115942
|
3: "\u{1F7E2}",
|
|
115638
115943
|
4: "\u26AA"
|
|
115639
115944
|
};
|
|
115945
|
+
function parseRelativeTime(timeStr) {
|
|
115946
|
+
const match = timeStr.match(/^(\d+)(d|w|h|m)$/);
|
|
115947
|
+
if (!match || !match[1] || !match[2]) {
|
|
115948
|
+
throw new CLIError({
|
|
115949
|
+
userMessage: `Invalid time format: ${timeStr}`,
|
|
115950
|
+
suggestion: "Use format like 90d, 2w, 24h, or 3m"
|
|
115951
|
+
});
|
|
115952
|
+
}
|
|
115953
|
+
const value = parseInt(match[1], 10);
|
|
115954
|
+
const unit = match[2];
|
|
115955
|
+
const msMap = {
|
|
115956
|
+
h: 60 * 60 * 1e3,
|
|
115957
|
+
d: 24 * 60 * 60 * 1e3,
|
|
115958
|
+
w: 7 * 24 * 60 * 60 * 1e3,
|
|
115959
|
+
m: 30 * 24 * 60 * 60 * 1e3
|
|
115960
|
+
};
|
|
115961
|
+
const ms = value * msMap[unit];
|
|
115962
|
+
return new Date(Date.now() - ms);
|
|
115963
|
+
}
|
|
115640
115964
|
async function listIssues(ctx, options = {}) {
|
|
115641
115965
|
const limit2 = options.limit || 20;
|
|
115642
115966
|
try {
|
|
@@ -115648,6 +115972,10 @@ async function listIssues(ctx, options = {}) {
|
|
|
115648
115972
|
}
|
|
115649
115973
|
}
|
|
115650
115974
|
};
|
|
115975
|
+
if (options.olderThan) {
|
|
115976
|
+
const date = parseRelativeTime(options.olderThan);
|
|
115977
|
+
filter4.updatedAt = { lt: date };
|
|
115978
|
+
}
|
|
115651
115979
|
let teamKey;
|
|
115652
115980
|
if (options.team) {
|
|
115653
115981
|
const teams = await client.teams();
|
|
@@ -115709,28 +116037,57 @@ async function listIssues(ctx, options = {}) {
|
|
|
115709
116037
|
});
|
|
115710
116038
|
const issues = response.nodes || [];
|
|
115711
116039
|
const issuesWithDetails = await Promise.all(
|
|
115712
|
-
issues.map(async (issue) =>
|
|
115713
|
-
issue
|
|
115714
|
-
|
|
115715
|
-
|
|
115716
|
-
|
|
115717
|
-
|
|
116040
|
+
issues.map(async (issue) => {
|
|
116041
|
+
const labels = options.export ? await issue.labels() : null;
|
|
116042
|
+
const comments = options.export ? await issue.comments() : null;
|
|
116043
|
+
return {
|
|
116044
|
+
issue,
|
|
116045
|
+
state: await issue.state,
|
|
116046
|
+
assignee: await issue.assignee,
|
|
116047
|
+
team: await issue.team,
|
|
116048
|
+
labels: labels?.nodes || null,
|
|
116049
|
+
comments: comments?.nodes || null
|
|
116050
|
+
};
|
|
116051
|
+
})
|
|
115718
116052
|
);
|
|
115719
116053
|
if (ctx.format === "json") {
|
|
115720
|
-
const issueData =
|
|
115721
|
-
(
|
|
115722
|
-
|
|
115723
|
-
|
|
115724
|
-
|
|
115725
|
-
|
|
115726
|
-
|
|
115727
|
-
|
|
115728
|
-
|
|
115729
|
-
|
|
115730
|
-
|
|
115731
|
-
|
|
115732
|
-
|
|
115733
|
-
|
|
116054
|
+
const issueData = await Promise.all(
|
|
116055
|
+
issuesWithDetails.map(
|
|
116056
|
+
async ({ issue, state, assignee, team, labels, comments }) => {
|
|
116057
|
+
const baseData = {
|
|
116058
|
+
id: issue.id,
|
|
116059
|
+
identifier: issue.identifier,
|
|
116060
|
+
title: issue.title,
|
|
116061
|
+
state: state?.name || null,
|
|
116062
|
+
stateType: state?.type || null,
|
|
116063
|
+
priority: issue.priority,
|
|
116064
|
+
assignee: assignee ? {
|
|
116065
|
+
id: assignee.id,
|
|
116066
|
+
name: assignee.name,
|
|
116067
|
+
email: assignee.email
|
|
116068
|
+
} : null,
|
|
116069
|
+
team: team ? { key: team.key, name: team.name } : null,
|
|
116070
|
+
url: issue.url,
|
|
116071
|
+
createdAt: issue.createdAt,
|
|
116072
|
+
updatedAt: issue.updatedAt
|
|
116073
|
+
};
|
|
116074
|
+
if (options.export) {
|
|
116075
|
+
return {
|
|
116076
|
+
...baseData,
|
|
116077
|
+
description: issue.description,
|
|
116078
|
+
labels: labels ? labels.map((l) => l.name) : [],
|
|
116079
|
+
comments: comments ? await Promise.all(
|
|
116080
|
+
comments.map(async (c) => ({
|
|
116081
|
+
body: c.body,
|
|
116082
|
+
user: (await c.user)?.name || "Unknown",
|
|
116083
|
+
createdAt: c.createdAt
|
|
116084
|
+
}))
|
|
116085
|
+
) : []
|
|
116086
|
+
};
|
|
116087
|
+
}
|
|
116088
|
+
return baseData;
|
|
116089
|
+
}
|
|
116090
|
+
)
|
|
115734
116091
|
);
|
|
115735
116092
|
ctx.output.data(
|
|
115736
116093
|
JSON.stringify(
|
|
@@ -115778,7 +116135,14 @@ async function listIssues(ctx, options = {}) {
|
|
|
115778
116135
|
ctx.output.data("");
|
|
115779
116136
|
return;
|
|
115780
116137
|
}
|
|
115781
|
-
for (const {
|
|
116138
|
+
for (const {
|
|
116139
|
+
issue,
|
|
116140
|
+
state,
|
|
116141
|
+
assignee,
|
|
116142
|
+
team,
|
|
116143
|
+
labels,
|
|
116144
|
+
comments
|
|
116145
|
+
} of issuesWithDetails) {
|
|
115782
116146
|
const emoji = PRIORITY_EMOJI2[issue.priority] || "\u26AA";
|
|
115783
116147
|
const assigneeName = assignee ? `@${assignee.name}` : "";
|
|
115784
116148
|
const teamBadge = team ? `[${team.key}]` : "";
|
|
@@ -115789,6 +116153,19 @@ async function listIssues(ctx, options = {}) {
|
|
|
115789
116153
|
ctx.output.data(
|
|
115790
116154
|
` Status: ${state?.name || "unknown"}${assigneeName ? ` | Assignee: ${assigneeName}` : ""}`
|
|
115791
116155
|
);
|
|
116156
|
+
if (options.export) {
|
|
116157
|
+
if (issue.description) {
|
|
116158
|
+
ctx.output.data(` Description: ${issue.description}`);
|
|
116159
|
+
}
|
|
116160
|
+
if (labels && labels.length > 0) {
|
|
116161
|
+
ctx.output.data(
|
|
116162
|
+
` Labels: ${labels.map((l) => l.name).join(", ")}`
|
|
116163
|
+
);
|
|
116164
|
+
}
|
|
116165
|
+
if (comments && comments.length > 0) {
|
|
116166
|
+
ctx.output.data(` Comments: ${comments.length}`);
|
|
116167
|
+
}
|
|
116168
|
+
}
|
|
115792
116169
|
}
|
|
115793
116170
|
ctx.output.data("");
|
|
115794
116171
|
ctx.output.data(" Use `skill linear issue <ID> --json` for full details.");
|
|
@@ -116582,6 +116959,13 @@ Quick start:
|
|
|
116582
116959
|
skill linear create "Title" Create issue
|
|
116583
116960
|
skill linear search "query" Search issues
|
|
116584
116961
|
|
|
116962
|
+
Bulk queries:
|
|
116963
|
+
skill linear issues --older-than 90d Stale issues
|
|
116964
|
+
skill linear issues --older-than 2w --export Full data export
|
|
116965
|
+
|
|
116966
|
+
Environment:
|
|
116967
|
+
LINEAR_API_KEY required. Run 'skill doctor' to check.
|
|
116968
|
+
|
|
116585
116969
|
All commands support --json for machine-readable output.
|
|
116586
116970
|
|
|
116587
116971
|
\u26A0\uFE0F Write operations require personal LINEAR_API_KEY (run 'skill keys add').`
|
|
@@ -116594,8 +116978,10 @@ Examples:
|
|
|
116594
116978
|
skill linear issues --team ENG Filter by team
|
|
116595
116979
|
skill linear issues --state "In Progress" Filter by state
|
|
116596
116980
|
skill linear issues --assignee me Your issues
|
|
116597
|
-
skill linear issues --priority 0 Urgent only
|
|
116598
|
-
|
|
116981
|
+
skill linear issues --priority 0 Urgent only
|
|
116982
|
+
skill linear issues --older-than 90d Stale issues (90+ days)
|
|
116983
|
+
skill linear issues --older-than 2w --export Full export`
|
|
116984
|
+
).option("--limit <number>", "Maximum results (default: 20)", "20").option("--team <key>", "Filter by team key (e.g., ENG)").option("--state <name>", "Filter by state name").option("--assignee <email>", 'Filter by assignee (or "me")').option("--project <name>", "Filter by project name").option("--priority <0-4>", "Filter by priority (0=urgent)").option("--older-than <time>", "Filter by last update (90d, 2w, 24h, 3m)").option("--export", "Include full details (description, labels, comments)").option("--json", "Output as JSON with HATEOAS links").action(async (options, command) => {
|
|
116599
116985
|
const ctx = await contextFromCommand2(command, options);
|
|
116600
116986
|
await listIssues(ctx, {
|
|
116601
116987
|
limit: parseInt(options.limit || "20", 10),
|
|
@@ -116603,7 +116989,9 @@ Examples:
|
|
|
116603
116989
|
state: options.state,
|
|
116604
116990
|
assignee: options.assignee,
|
|
116605
116991
|
project: options.project,
|
|
116606
|
-
priority: options.priority !== void 0 ? parseInt(options.priority, 10) : void 0
|
|
116992
|
+
priority: options.priority !== void 0 ? parseInt(options.priority, 10) : void 0,
|
|
116993
|
+
olderThan: options.olderThan,
|
|
116994
|
+
export: options.export
|
|
116607
116995
|
});
|
|
116608
116996
|
});
|
|
116609
116997
|
linear.command("my").description(
|
|
@@ -116850,6 +117238,101 @@ Examples:
|
|
|
116850
117238
|
});
|
|
116851
117239
|
}
|
|
116852
117240
|
|
|
117241
|
+
// src/commands/list.ts
|
|
117242
|
+
init_esm_shims();
|
|
117243
|
+
import { existsSync as existsSync17, readFileSync as readFileSync13, readdirSync, statSync } from "fs";
|
|
117244
|
+
import { join as join14 } from "path";
|
|
117245
|
+
function discoverSkills(skillsDir) {
|
|
117246
|
+
if (!existsSync17(skillsDir)) {
|
|
117247
|
+
return [];
|
|
117248
|
+
}
|
|
117249
|
+
const skills = [];
|
|
117250
|
+
try {
|
|
117251
|
+
const entries = readdirSync(skillsDir);
|
|
117252
|
+
for (const entry of entries) {
|
|
117253
|
+
const entryPath = join14(skillsDir, entry);
|
|
117254
|
+
const stat = statSync(entryPath);
|
|
117255
|
+
if (!stat.isDirectory()) continue;
|
|
117256
|
+
const skillPath = join14(entryPath, "SKILL.md");
|
|
117257
|
+
if (!existsSync17(skillPath)) continue;
|
|
117258
|
+
const content = readFileSync13(skillPath, "utf8");
|
|
117259
|
+
const description = extractDescription(content);
|
|
117260
|
+
skills.push({
|
|
117261
|
+
name: entry,
|
|
117262
|
+
description,
|
|
117263
|
+
path: skillPath
|
|
117264
|
+
});
|
|
117265
|
+
}
|
|
117266
|
+
} catch {
|
|
117267
|
+
return [];
|
|
117268
|
+
}
|
|
117269
|
+
return skills.sort((a, b) => a.name.localeCompare(b.name));
|
|
117270
|
+
}
|
|
117271
|
+
function extractDescription(markdown) {
|
|
117272
|
+
const lines = markdown.split("\n");
|
|
117273
|
+
let inFrontmatter = false;
|
|
117274
|
+
let foundHeading = false;
|
|
117275
|
+
const descriptionLines = [];
|
|
117276
|
+
for (const line of lines) {
|
|
117277
|
+
const trimmed = line.trim();
|
|
117278
|
+
if (trimmed === "---") {
|
|
117279
|
+
if (!inFrontmatter && !foundHeading) {
|
|
117280
|
+
inFrontmatter = true;
|
|
117281
|
+
continue;
|
|
117282
|
+
} else if (inFrontmatter) {
|
|
117283
|
+
inFrontmatter = false;
|
|
117284
|
+
continue;
|
|
117285
|
+
}
|
|
117286
|
+
}
|
|
117287
|
+
if (inFrontmatter) continue;
|
|
117288
|
+
if (trimmed.startsWith("# ")) {
|
|
117289
|
+
foundHeading = true;
|
|
117290
|
+
continue;
|
|
117291
|
+
}
|
|
117292
|
+
if (foundHeading && trimmed.startsWith("#")) {
|
|
117293
|
+
break;
|
|
117294
|
+
}
|
|
117295
|
+
if (foundHeading) {
|
|
117296
|
+
if (trimmed === "") {
|
|
117297
|
+
if (descriptionLines.length > 0) {
|
|
117298
|
+
break;
|
|
117299
|
+
}
|
|
117300
|
+
continue;
|
|
117301
|
+
}
|
|
117302
|
+
descriptionLines.push(trimmed);
|
|
117303
|
+
}
|
|
117304
|
+
}
|
|
117305
|
+
return descriptionLines.join(" ").trim();
|
|
117306
|
+
}
|
|
117307
|
+
async function listAction(options, command) {
|
|
117308
|
+
const ctx = await createContext({
|
|
117309
|
+
format: options.json ? "json" : command.optsWithGlobals().format,
|
|
117310
|
+
verbose: command.optsWithGlobals().verbose,
|
|
117311
|
+
quiet: command.optsWithGlobals().quiet
|
|
117312
|
+
});
|
|
117313
|
+
const skillsDir = join14(process.cwd(), ".claude", "skills");
|
|
117314
|
+
const skills = discoverSkills(skillsDir);
|
|
117315
|
+
if (options.json) {
|
|
117316
|
+
ctx.output.data({ skills });
|
|
117317
|
+
return;
|
|
117318
|
+
}
|
|
117319
|
+
if (skills.length === 0) {
|
|
117320
|
+
ctx.output.message("No skills found in .claude/skills/");
|
|
117321
|
+
return;
|
|
117322
|
+
}
|
|
117323
|
+
ctx.output.data(`
|
|
117324
|
+
\u{1F4DA} Available Skills (${skills.length})`);
|
|
117325
|
+
ctx.output.data("\u2500".repeat(80));
|
|
117326
|
+
const rows = skills.map((skill) => ({
|
|
117327
|
+
Name: skill.name,
|
|
117328
|
+
Description: skill.description || "(no description)"
|
|
117329
|
+
}));
|
|
117330
|
+
ctx.output.table(rows);
|
|
117331
|
+
}
|
|
117332
|
+
function registerListCommand(program3) {
|
|
117333
|
+
program3.command("list").description("List available CLI skills for programmatic discovery").option("--json", "Output as JSON").action(listAction);
|
|
117334
|
+
}
|
|
117335
|
+
|
|
116853
117336
|
// src/commands/memory/index.ts
|
|
116854
117337
|
init_esm_shims();
|
|
116855
117338
|
|
|
@@ -117426,7 +117909,7 @@ async function runE2EEval2(options) {
|
|
|
117426
117909
|
verbose,
|
|
117427
117910
|
json,
|
|
117428
117911
|
limit: limit2,
|
|
117429
|
-
model = "anthropic/claude-
|
|
117912
|
+
model = "anthropic/claude-sonnet-4-5"
|
|
117430
117913
|
} = options;
|
|
117431
117914
|
const content = await readFile8(dataset, "utf-8");
|
|
117432
117915
|
let scenarios = JSON.parse(content);
|
|
@@ -117868,7 +118351,7 @@ var handlePipelineError = (ctx, error, message, suggestion = "Verify inputs and
|
|
|
117868
118351
|
async function runPipelineCommand(ctx, opts) {
|
|
117869
118352
|
const outputJson = opts.json === true || ctx.format === "json";
|
|
117870
118353
|
try {
|
|
117871
|
-
const { runPipeline: runPipeline2 } = await import("./pipeline-
|
|
118354
|
+
const { runPipeline: runPipeline2 } = await import("./pipeline-JPI7ITZN.js");
|
|
117872
118355
|
const result = await runPipeline2({
|
|
117873
118356
|
message: {
|
|
117874
118357
|
subject: opts.subject,
|
|
@@ -117979,16 +118462,16 @@ function registerPipelineCommands(program3) {
|
|
|
117979
118462
|
// src/commands/plugin-sync.ts
|
|
117980
118463
|
init_esm_shims();
|
|
117981
118464
|
import { homedir as homedir3 } from "os";
|
|
117982
|
-
import { dirname as dirname3, join as
|
|
118465
|
+
import { dirname as dirname3, join as join15, resolve as resolve6 } from "path";
|
|
117983
118466
|
import { fileURLToPath } from "url";
|
|
117984
118467
|
var PLUGIN_SOURCE_DIR = resolve6(
|
|
117985
118468
|
dirname3(fileURLToPath(import.meta.url)),
|
|
117986
118469
|
"../../plugin"
|
|
117987
118470
|
);
|
|
117988
|
-
var PLUGIN_MANIFEST_RELATIVE =
|
|
118471
|
+
var PLUGIN_MANIFEST_RELATIVE = join15(".claude-plugin", "plugin.json");
|
|
117989
118472
|
var resolveTargetDir = (global2) => {
|
|
117990
|
-
const base =
|
|
117991
|
-
return
|
|
118473
|
+
const base = join15(homedir3(), ".claude", global2 ? "skills" : "plugins");
|
|
118474
|
+
return join15(base, "skill-cli");
|
|
117992
118475
|
};
|
|
117993
118476
|
var readManifest = async (path) => {
|
|
117994
118477
|
const manifest = await readJson(path);
|
|
@@ -118017,7 +118500,7 @@ var writeResult4 = (ctx, payload) => {
|
|
|
118017
118500
|
};
|
|
118018
118501
|
async function executePluginSync(ctx, options) {
|
|
118019
118502
|
try {
|
|
118020
|
-
const sourceManifestPath =
|
|
118503
|
+
const sourceManifestPath = join15(PLUGIN_SOURCE_DIR, PLUGIN_MANIFEST_RELATIVE);
|
|
118021
118504
|
const sourceExists = await pathExists(sourceManifestPath);
|
|
118022
118505
|
if (!sourceExists) {
|
|
118023
118506
|
throw new CLIError({
|
|
@@ -118027,7 +118510,7 @@ async function executePluginSync(ctx, options) {
|
|
|
118027
118510
|
}
|
|
118028
118511
|
const sourceManifest = await readManifest(sourceManifestPath);
|
|
118029
118512
|
const targetDir = resolveTargetDir(options.global);
|
|
118030
|
-
const targetManifestPath =
|
|
118513
|
+
const targetManifestPath = join15(targetDir, PLUGIN_MANIFEST_RELATIVE);
|
|
118031
118514
|
const targetExists = await pathExists(targetManifestPath);
|
|
118032
118515
|
if (targetExists && !options.force) {
|
|
118033
118516
|
const targetManifest = await readManifest(targetManifestPath);
|
|
@@ -119270,7 +119753,7 @@ init_esm_shims();
|
|
|
119270
119753
|
import { spawn } from "child_process";
|
|
119271
119754
|
import { writeFile as writeFile7 } from "fs/promises";
|
|
119272
119755
|
import { homedir as homedir4 } from "os";
|
|
119273
|
-
import { dirname as dirname4, join as
|
|
119756
|
+
import { dirname as dirname4, join as join16 } from "path";
|
|
119274
119757
|
var CONFIG_DIR_NAME = "skill-cli";
|
|
119275
119758
|
var AUTO_UPDATE_STATE_FILE = "auto-update.json";
|
|
119276
119759
|
var DEFAULT_PACKAGE = "@skillrecordings/cli";
|
|
@@ -119282,7 +119765,7 @@ var AutoUpdateStore = class {
|
|
|
119282
119765
|
now;
|
|
119283
119766
|
constructor(options = {}) {
|
|
119284
119767
|
const configDir = resolveConfigDir(options.configDir);
|
|
119285
|
-
this.filePath =
|
|
119768
|
+
this.filePath = join16(configDir, AUTO_UPDATE_STATE_FILE);
|
|
119286
119769
|
this.now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
119287
119770
|
}
|
|
119288
119771
|
getNow() {
|
|
@@ -119310,9 +119793,9 @@ function resolveConfigDir(configDir) {
|
|
|
119310
119793
|
if (configDir) return configDir;
|
|
119311
119794
|
const xdgConfigHome = process.env.XDG_CONFIG_HOME;
|
|
119312
119795
|
if (xdgConfigHome && xdgConfigHome.trim() !== "") {
|
|
119313
|
-
return
|
|
119796
|
+
return join16(xdgConfigHome, CONFIG_DIR_NAME);
|
|
119314
119797
|
}
|
|
119315
|
-
return
|
|
119798
|
+
return join16(homedir4(), ".config", CONFIG_DIR_NAME);
|
|
119316
119799
|
}
|
|
119317
119800
|
function isAutoUpdateState(value) {
|
|
119318
119801
|
if (!value || typeof value !== "object") return false;
|
|
@@ -119609,13 +120092,13 @@ var writeHints = (hints, stderr) => {
|
|
|
119609
120092
|
init_esm_shims();
|
|
119610
120093
|
import { lstat, readlink, symlink } from "fs/promises";
|
|
119611
120094
|
import { homedir as homedir5 } from "os";
|
|
119612
|
-
import { dirname as dirname5, join as
|
|
120095
|
+
import { dirname as dirname5, join as join17, resolve as resolve7 } from "path";
|
|
119613
120096
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
119614
120097
|
var SKILL_SOURCE_DIR = resolve7(
|
|
119615
120098
|
dirname5(fileURLToPath2(import.meta.url)),
|
|
119616
120099
|
"../../../../.claude/skills/skill-cli"
|
|
119617
120100
|
);
|
|
119618
|
-
var SKILL_TARGET_DIR =
|
|
120101
|
+
var SKILL_TARGET_DIR = join17(homedir5(), ".claude", "skills", "skill-cli");
|
|
119619
120102
|
async function autoLinkSkill() {
|
|
119620
120103
|
const source = SKILL_SOURCE_DIR;
|
|
119621
120104
|
const target = SKILL_TARGET_DIR;
|
|
@@ -119719,16 +120202,16 @@ async function sendTelemetryEvent(event) {
|
|
|
119719
120202
|
init_esm_shims();
|
|
119720
120203
|
import { writeFile as writeFile8 } from "fs/promises";
|
|
119721
120204
|
import { homedir as homedir6 } from "os";
|
|
119722
|
-
import { dirname as dirname6, join as
|
|
120205
|
+
import { dirname as dirname6, join as join18 } from "path";
|
|
119723
120206
|
var CONFIG_DIR_NAME2 = "skill-cli";
|
|
119724
120207
|
var USAGE_FILE_NAME = "usage.json";
|
|
119725
120208
|
function resolveConfigDir2(configDir) {
|
|
119726
120209
|
if (configDir) return configDir;
|
|
119727
120210
|
const xdgConfigHome = process.env.XDG_CONFIG_HOME;
|
|
119728
120211
|
if (xdgConfigHome && xdgConfigHome.trim() !== "") {
|
|
119729
|
-
return
|
|
120212
|
+
return join18(xdgConfigHome, CONFIG_DIR_NAME2);
|
|
119730
120213
|
}
|
|
119731
|
-
return
|
|
120214
|
+
return join18(homedir6(), ".config", CONFIG_DIR_NAME2);
|
|
119732
120215
|
}
|
|
119733
120216
|
function createDefaultState(now) {
|
|
119734
120217
|
return {
|
|
@@ -119766,7 +120249,7 @@ var UsageTracker = class {
|
|
|
119766
120249
|
statePromise;
|
|
119767
120250
|
constructor(options = {}) {
|
|
119768
120251
|
const configDir = resolveConfigDir2(options.configDir);
|
|
119769
|
-
this.filePath =
|
|
120252
|
+
this.filePath = join18(configDir, USAGE_FILE_NAME);
|
|
119770
120253
|
this.now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
119771
120254
|
}
|
|
119772
120255
|
async loadState() {
|
|
@@ -120345,8 +120828,8 @@ if (!envLoaded && !process.env.DATABASE_URL) {
|
|
|
120345
120828
|
process.env.SKIP_ENV_VALIDATION = "1";
|
|
120346
120829
|
}
|
|
120347
120830
|
var runtimeTarget = `bun-${process.platform}-${process.arch}`;
|
|
120348
|
-
var buildVersion = "0.
|
|
120349
|
-
var buildCommit = "
|
|
120831
|
+
var buildVersion = "0.18.1".length > 0 ? "0.18.1" : "0.0.0-dev";
|
|
120832
|
+
var buildCommit = "e9e5214".length > 0 ? "e9e5214" : "dev";
|
|
120350
120833
|
var buildTarget = "node".length > 0 ? "node" : runtimeTarget;
|
|
120351
120834
|
var isDevBuild = buildVersion.includes("dev") || buildCommit === "dev";
|
|
120352
120835
|
var versionLabel = `skill v${buildVersion} (${buildCommit}) ${buildTarget}`;
|
|
@@ -120551,6 +121034,8 @@ registerKbCommands(program2);
|
|
|
120551
121034
|
registerAuthCommands(program2, usageState);
|
|
120552
121035
|
registerConfigCommands(program2);
|
|
120553
121036
|
registerKeysCommands(program2);
|
|
121037
|
+
registerDoctorCommand(program2);
|
|
121038
|
+
registerListCommand(program2);
|
|
120554
121039
|
registerPluginSyncCommand(program2);
|
|
120555
121040
|
program2.command("mcp").description(
|
|
120556
121041
|
"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)"
|