@skill-map/cli 0.43.0 → 0.44.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/cli/tutorial/sm-master/SKILL.md +7 -9
- package/dist/cli/tutorial/sm-master/references/fixture-templates.md +1 -1
- package/dist/cli/tutorial/sm-master/references/tour-plugins.md +10 -9
- package/dist/cli/tutorial/sm-master/references/tour-settings.md +4 -4
- package/dist/cli/tutorial/sm-tutorial/SKILL.md +216 -299
- package/dist/cli.js +736 -221
- package/dist/cli.js.map +1 -1
- package/dist/index.js +21 -15
- package/dist/index.js.map +1 -1
- package/dist/kernel/index.d.ts +8 -6
- package/dist/kernel/index.js +21 -15
- package/dist/kernel/index.js.map +1 -1
- package/dist/ui/chunk-27WQPOXP.js +1 -0
- package/dist/ui/{chunk-DZBSELHN.js → chunk-43S72FTV.js} +1 -1
- package/dist/ui/chunk-555ST76V.js +1 -0
- package/dist/ui/{chunk-JPYAASHN.js → chunk-5AD5ZV4I.js} +3 -3
- package/dist/ui/{chunk-CFJBTDAA.js → chunk-5ITZXW3A.js} +1 -1
- package/dist/ui/chunk-A7PRWMQD.js +1021 -0
- package/dist/ui/chunk-DL5EA245.js +123 -0
- package/dist/ui/chunk-F7I6KMHX.js +1 -0
- package/dist/ui/{chunk-77J7XU3Y.js → chunk-I5AX4U2N.js} +28 -28
- package/dist/ui/chunk-IUZRAD7S.js +1 -0
- package/dist/ui/{chunk-XOHD5XWA.js → chunk-IYM26L3O.js} +1 -1
- package/dist/ui/{chunk-SBCO7ZSP.js → chunk-LGFABCIA.js} +1 -1
- package/dist/ui/{chunk-IUDL3NDH.js → chunk-MFLFIA7C.js} +1 -1
- package/dist/ui/chunk-MS6B7344.js +315 -0
- package/dist/ui/chunk-P3SNMV4X.js +2 -0
- package/dist/ui/chunk-PZQHB7GS.js +4 -0
- package/dist/ui/chunk-QDUSFOBE.js +1 -0
- package/dist/ui/{chunk-YCR3XCIW.js → chunk-QNTAOR2L.js} +5 -5
- package/dist/ui/{chunk-CR3AANNX.js → chunk-S4S5ZMXJ.js} +1 -1
- package/dist/ui/{chunk-5WJRN3LD.js → chunk-T3IVIRRJ.js} +1 -1
- package/dist/ui/{chunk-HP375T2O.js → chunk-VGPYYAVI.js} +1 -1
- package/dist/ui/chunk-X227ITGS.js +499 -0
- package/dist/ui/index.html +1 -1
- package/dist/ui/main-O3CWFYKV.js +3 -0
- package/package.json +10 -9
- package/dist/ui/chunk-2IF446BS.js +0 -1
- package/dist/ui/chunk-DIKPNZUZ.js +0 -315
- package/dist/ui/chunk-KGCJINI6.js +0 -1
- package/dist/ui/chunk-PPE3P2JD.js +0 -1
- package/dist/ui/chunk-UOCACZLI.js +0 -123
- package/dist/ui/chunk-YL6SWAFJ.js +0 -1024
- package/dist/ui/main-VHFB7Q2D.js +0 -3
- /package/dist/ui/{chunk-C2YUQODZ.js → chunk-4SG4352Z.js} +0 -0
- /package/dist/ui/{chunk-VB56BUGO.js → chunk-WCABR6TI.js} +0 -0
package/dist/cli.js
CHANGED
|
@@ -912,75 +912,77 @@ var antigravityProvider = {
|
|
|
912
912
|
classify() {
|
|
913
913
|
return null;
|
|
914
914
|
},
|
|
915
|
-
//
|
|
916
|
-
//
|
|
917
|
-
//
|
|
918
|
-
//
|
|
919
|
-
//
|
|
920
|
-
//
|
|
921
|
-
//
|
|
922
|
-
//
|
|
923
|
-
//
|
|
924
|
-
//
|
|
925
|
-
//
|
|
926
|
-
//
|
|
927
|
-
//
|
|
915
|
+
// Built-in slash-command catalog, captured verbatim from `agy /help`
|
|
916
|
+
// (Antigravity CLI v1.0.3). This REPLACES the earlier provisional list
|
|
917
|
+
// that mirrored Gemini CLI's verbs: `agy` ships its own surface. It
|
|
918
|
+
// DROPPED Gemini-only verbs (`vim`, `theme`, `terminal-setup`,
|
|
919
|
+
// `setup-github`, `bashes`, `shells`, `policies`, `extensions`, `about`,
|
|
920
|
+
// `auth`, `bug`, `chat`, `compress`, `docs`, `editor`, `ide`, `init`,
|
|
921
|
+
// `memory`, `restore`, `stats`, `tools`, `upgrade`, `?`, `dir`) and
|
|
922
|
+
// ADDED agent-first ones (`goal`, `grill-me`, `schedule`, `fast`, `btw`,
|
|
923
|
+
// `artifact`, `context`, `diff`, `fork`, `tasks`, `add-dir`, `credits`,
|
|
924
|
+
// `feedback`, `logout`, `open`, `planning`, `rename`, `statusline`,
|
|
925
|
+
// `title`, `usage`). Both the 35 primary verbs and the 8 documented
|
|
926
|
+
// aliases (`new`, `settings`, `quit`, `branch`, `switch`, `conversation`,
|
|
927
|
+
// `undo`, `quota`) are reserved: a user skill named after either is
|
|
928
|
+
// silently shadowed by the built-in once the catalog activates.
|
|
928
929
|
//
|
|
929
|
-
//
|
|
930
|
-
//
|
|
931
|
-
//
|
|
932
|
-
//
|
|
933
|
-
//
|
|
934
|
-
//
|
|
930
|
+
// Declared under the `skill` kind (NOT `command`): Antigravity has no
|
|
931
|
+
// vendor-specific command directory, its user slash-commands are skills
|
|
932
|
+
// (`.agents/skills/<name>/SKILL.md`, owned by the universal `agent-skills`
|
|
933
|
+
// Provider). The catalog is ACTIVE via the LENS SCOPE in
|
|
934
|
+
// `buildReservedNodePaths` (spec/architecture.md §Provider ·
|
|
935
|
+
// reservedNames): when `activeProvider === 'antigravity'` the orchestrator
|
|
936
|
+
// lends this `skill` catalog to `agent-skills` skill nodes, so a user
|
|
937
|
+
// `.agents/skills/goal/SKILL.md` is flagged because `/goal` is built-in.
|
|
935
938
|
//
|
|
936
|
-
// **Reconciliation marker**:
|
|
937
|
-
//
|
|
938
|
-
// reference, replace this comment + array with the official list (and
|
|
939
|
-
// bump the file's leading docblock to cite the new source URL).
|
|
939
|
+
// **Reconciliation marker**: re-capture from `agy /help` on each major
|
|
940
|
+
// Antigravity CLI release and bump the cited version above.
|
|
940
941
|
reservedNames: {
|
|
941
|
-
|
|
942
|
-
"
|
|
943
|
-
"about",
|
|
942
|
+
skill: [
|
|
943
|
+
"add-dir",
|
|
944
944
|
"agents",
|
|
945
|
-
"
|
|
946
|
-
"
|
|
947
|
-
"
|
|
948
|
-
"
|
|
945
|
+
"artifact",
|
|
946
|
+
"branch",
|
|
947
|
+
"btw",
|
|
948
|
+
"changelog",
|
|
949
949
|
"clear",
|
|
950
|
-
"
|
|
951
|
-
"
|
|
950
|
+
"config",
|
|
951
|
+
"context",
|
|
952
|
+
"conversation",
|
|
952
953
|
"copy",
|
|
953
|
-
"
|
|
954
|
-
"
|
|
955
|
-
"docs",
|
|
956
|
-
"editor",
|
|
954
|
+
"credits",
|
|
955
|
+
"diff",
|
|
957
956
|
"exit",
|
|
958
|
-
"
|
|
957
|
+
"fast",
|
|
958
|
+
"feedback",
|
|
959
|
+
"fork",
|
|
960
|
+
"goal",
|
|
961
|
+
"grill-me",
|
|
959
962
|
"help",
|
|
960
963
|
"hooks",
|
|
961
|
-
"
|
|
962
|
-
"
|
|
964
|
+
"keybindings",
|
|
965
|
+
"logout",
|
|
963
966
|
"mcp",
|
|
964
|
-
"memory",
|
|
965
967
|
"model",
|
|
968
|
+
"new",
|
|
969
|
+
"open",
|
|
966
970
|
"permissions",
|
|
967
|
-
"
|
|
968
|
-
"policies",
|
|
969
|
-
"privacy",
|
|
971
|
+
"planning",
|
|
970
972
|
"quit",
|
|
971
|
-
"
|
|
973
|
+
"quota",
|
|
974
|
+
"rename",
|
|
972
975
|
"resume",
|
|
973
976
|
"rewind",
|
|
977
|
+
"schedule",
|
|
974
978
|
"settings",
|
|
975
|
-
"setup-github",
|
|
976
|
-
"shells",
|
|
977
979
|
"skills",
|
|
978
|
-
"
|
|
979
|
-
"
|
|
980
|
-
"
|
|
981
|
-
"
|
|
982
|
-
"
|
|
983
|
-
"
|
|
980
|
+
"statusline",
|
|
981
|
+
"switch",
|
|
982
|
+
"tasks",
|
|
983
|
+
"title",
|
|
984
|
+
"undo",
|
|
985
|
+
"usage"
|
|
984
986
|
]
|
|
985
987
|
}
|
|
986
988
|
};
|
|
@@ -3946,7 +3948,7 @@ var UPDATE_CHECK_TEXTS = {
|
|
|
3946
3948
|
// package.json
|
|
3947
3949
|
var package_default = {
|
|
3948
3950
|
name: "@skill-map/cli",
|
|
3949
|
-
version: "0.
|
|
3951
|
+
version: "0.44.0",
|
|
3950
3952
|
description: "skill-map reference implementation \u2014 kernel + CLI + adapters.",
|
|
3951
3953
|
license: "MIT",
|
|
3952
3954
|
type: "module",
|
|
@@ -3997,25 +3999,25 @@ var package_default = {
|
|
|
3997
3999
|
typecheck: "tsc --noEmit",
|
|
3998
4000
|
lint: "eslint .",
|
|
3999
4001
|
"lint:fix": "eslint . --fix",
|
|
4000
|
-
reference: "node scripts/build-reference.js",
|
|
4001
|
-
"reference:check": "node scripts/build-reference.js --check",
|
|
4002
4002
|
"build-built-ins": "node ../scripts/generate-built-ins.js",
|
|
4003
4003
|
"built-ins:check": "node ../scripts/generate-built-ins.js --check",
|
|
4004
4004
|
prebuild: "pnpm build-built-ins",
|
|
4005
4005
|
validate: "pnpm validate:compile && pnpm validate:test",
|
|
4006
|
-
"validate:compile": "pnpm typecheck && pnpm lint && pnpm build && pnpm
|
|
4006
|
+
"validate:compile": "pnpm typecheck && pnpm lint && pnpm build && pnpm built-ins:check",
|
|
4007
4007
|
"validate:test": "pnpm test:ci",
|
|
4008
4008
|
pretest: "tsup",
|
|
4009
4009
|
"pretest:coverage": "tsup",
|
|
4010
4010
|
"pretest:coverage:html": "tsup",
|
|
4011
|
-
test: "tsc --noEmit && node --import tsx --test --test-reporter=
|
|
4012
|
-
"test:ci": "node --import tsx --test '__tests__/**/*.spec.ts' 'kernel/**/__tests__/**/*.spec.ts' 'cli/**/__tests__/**/*.spec.ts' 'server/**/__tests__/**/*.spec.ts' 'plugins/**/__tests__/**/*.spec.ts' 'core/**/__tests__/**/*.spec.ts' 'conformance/**/__tests__/**/*.spec.ts'",
|
|
4013
|
-
"test:
|
|
4014
|
-
"test:coverage
|
|
4011
|
+
test: "tsc --noEmit && SKILL_MAP_TELEMETRY=0 node --import tsx --test --test-reporter=./scripts/test-reporter.js --test-reporter-destination=stdout '__tests__/**/*.spec.ts' 'kernel/**/__tests__/**/*.spec.ts' 'cli/**/__tests__/**/*.spec.ts' 'server/**/__tests__/**/*.spec.ts' 'plugins/**/__tests__/**/*.spec.ts' 'core/**/__tests__/**/*.spec.ts' 'conformance/**/__tests__/**/*.spec.ts'",
|
|
4012
|
+
"test:ci": "FORCE_COLOR=1 SKILL_MAP_TELEMETRY=0 node --import tsx --test --test-reporter=./scripts/test-reporter.js --test-reporter-destination=stdout '__tests__/**/*.spec.ts' 'kernel/**/__tests__/**/*.spec.ts' 'cli/**/__tests__/**/*.spec.ts' 'server/**/__tests__/**/*.spec.ts' 'plugins/**/__tests__/**/*.spec.ts' 'core/**/__tests__/**/*.spec.ts' 'conformance/**/__tests__/**/*.spec.ts'",
|
|
4013
|
+
"test:spec": "SKILL_MAP_TELEMETRY=0 node --import tsx --test --test-reporter=spec '__tests__/**/*.spec.ts' 'kernel/**/__tests__/**/*.spec.ts' 'cli/**/__tests__/**/*.spec.ts' 'server/**/__tests__/**/*.spec.ts' 'plugins/**/__tests__/**/*.spec.ts' 'core/**/__tests__/**/*.spec.ts' 'conformance/**/__tests__/**/*.spec.ts'",
|
|
4014
|
+
"test:coverage": "tsc --noEmit && SKILL_MAP_TELEMETRY=0 SKILL_MAP_SKIP_BENCHMARK=1 node --experimental-default-config-file --import tsx --test --experimental-test-coverage '__tests__/**/*.spec.ts' 'kernel/**/__tests__/**/*.spec.ts' 'cli/**/__tests__/**/*.spec.ts' 'server/**/__tests__/**/*.spec.ts' 'plugins/**/__tests__/**/*.spec.ts' 'core/**/__tests__/**/*.spec.ts' 'conformance/**/__tests__/**/*.spec.ts'",
|
|
4015
|
+
"test:coverage:html": "tsc --noEmit && SKILL_MAP_TELEMETRY=0 SKILL_MAP_SKIP_BENCHMARK=1 c8 node --import tsx --test '__tests__/**/*.spec.ts' 'kernel/**/__tests__/**/*.spec.ts' 'cli/**/__tests__/**/*.spec.ts' 'server/**/__tests__/**/*.spec.ts' 'plugins/**/__tests__/**/*.spec.ts' 'core/**/__tests__/**/*.spec.ts' 'conformance/**/__tests__/**/*.spec.ts'",
|
|
4015
4016
|
clean: "rm -rf dist coverage"
|
|
4016
4017
|
},
|
|
4017
4018
|
dependencies: {
|
|
4018
4019
|
"@hono/node-server": "2.0.1",
|
|
4020
|
+
"@sentry/node": "10.55.0",
|
|
4019
4021
|
"@skill-map/spec": "workspace:*",
|
|
4020
4022
|
ajv: "8.18.0",
|
|
4021
4023
|
"ajv-formats": "3.0.1",
|
|
@@ -4026,6 +4028,7 @@ var package_default = {
|
|
|
4026
4028
|
"js-tiktoken": "1.0.21",
|
|
4027
4029
|
"js-yaml": "4.1.1",
|
|
4028
4030
|
kysely: "0.28.17",
|
|
4031
|
+
"posthog-node": "5.35.6",
|
|
4029
4032
|
semver: "7.7.4",
|
|
4030
4033
|
"smol-toml": "1.6.1",
|
|
4031
4034
|
typanion: "3.14.0",
|
|
@@ -4096,6 +4099,7 @@ function ansiFor(opts) {
|
|
|
4096
4099
|
}
|
|
4097
4100
|
|
|
4098
4101
|
// cli/util/user-settings-store.ts
|
|
4102
|
+
import { randomUUID } from "crypto";
|
|
4099
4103
|
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync5 } from "fs";
|
|
4100
4104
|
import { homedir } from "os";
|
|
4101
4105
|
import { join as join2 } from "path";
|
|
@@ -4204,13 +4208,13 @@ function userSettingsFilePath() {
|
|
|
4204
4208
|
return join2(homedir(), SKILL_MAP_DIR, FILENAME);
|
|
4205
4209
|
}
|
|
4206
4210
|
function defaultSettings() {
|
|
4207
|
-
return { schemaVersion: SCHEMA_VERSION, updateCheck: {} };
|
|
4211
|
+
return { schemaVersion: SCHEMA_VERSION, updateCheck: {}, telemetry: {} };
|
|
4208
4212
|
}
|
|
4209
4213
|
function readUserSettings() {
|
|
4210
4214
|
const parsed = readParsedFile();
|
|
4211
4215
|
if (parsed === null) return defaultSettings();
|
|
4212
4216
|
const validated = validateOrDefault(parsed);
|
|
4213
|
-
return
|
|
4217
|
+
return backfillSubObjects(validated);
|
|
4214
4218
|
}
|
|
4215
4219
|
function readParsedFile() {
|
|
4216
4220
|
const path = userSettingsFilePath();
|
|
@@ -4232,11 +4236,12 @@ function validateOrDefault(parsed) {
|
|
|
4232
4236
|
if (!result.ok) return defaultSettings();
|
|
4233
4237
|
return result.data;
|
|
4234
4238
|
}
|
|
4235
|
-
function
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4239
|
+
function backfillSubObjects(settings) {
|
|
4240
|
+
return {
|
|
4241
|
+
...settings,
|
|
4242
|
+
updateCheck: settings.updateCheck ?? {},
|
|
4243
|
+
telemetry: settings.telemetry ?? {}
|
|
4244
|
+
};
|
|
4240
4245
|
}
|
|
4241
4246
|
function writeUserSettings(patch) {
|
|
4242
4247
|
const dir = join2(homedir(), SKILL_MAP_DIR);
|
|
@@ -4258,14 +4263,49 @@ function isUpdateCheckEnabled() {
|
|
|
4258
4263
|
const settings = readUserSettings();
|
|
4259
4264
|
return settings.updateCheck?.enabled !== false;
|
|
4260
4265
|
}
|
|
4266
|
+
function isErrorTelemetryEnabled() {
|
|
4267
|
+
const settings = readUserSettings();
|
|
4268
|
+
return settings.telemetry?.errorsEnabled === true;
|
|
4269
|
+
}
|
|
4270
|
+
function isUsageCliTelemetryEnabled() {
|
|
4271
|
+
const settings = readUserSettings();
|
|
4272
|
+
return settings.telemetry?.usageCliEnabled === true;
|
|
4273
|
+
}
|
|
4274
|
+
function isUsageUiTelemetryEnabled() {
|
|
4275
|
+
const settings = readUserSettings();
|
|
4276
|
+
return settings.telemetry?.usageUiEnabled === true;
|
|
4277
|
+
}
|
|
4278
|
+
function readAnonymousId() {
|
|
4279
|
+
const settings = readUserSettings();
|
|
4280
|
+
return settings.telemetry?.anonymousId ?? null;
|
|
4281
|
+
}
|
|
4282
|
+
function ensureAnonymousId(generate = () => randomUUID()) {
|
|
4283
|
+
const existing = readAnonymousId();
|
|
4284
|
+
if (existing !== null && existing !== "") return existing;
|
|
4285
|
+
const id = generate();
|
|
4286
|
+
writeUserSettings({ telemetry: { anonymousId: id } });
|
|
4287
|
+
return id;
|
|
4288
|
+
}
|
|
4289
|
+
function hasTelemetryPromptBeenShown() {
|
|
4290
|
+
const settings = readUserSettings();
|
|
4291
|
+
return typeof settings.telemetry?.promptedAt === "number";
|
|
4292
|
+
}
|
|
4293
|
+
function hasSeenFirstRun() {
|
|
4294
|
+
const settings = readUserSettings();
|
|
4295
|
+
return typeof settings.telemetry?.firstRunAt === "number";
|
|
4296
|
+
}
|
|
4261
4297
|
function mergeSettings(current, patch) {
|
|
4262
4298
|
const merged = {
|
|
4263
4299
|
schemaVersion: SCHEMA_VERSION,
|
|
4264
|
-
updateCheck: { ...current.updateCheck ?? {} }
|
|
4300
|
+
updateCheck: { ...current.updateCheck ?? {} },
|
|
4301
|
+
telemetry: { ...current.telemetry ?? {} }
|
|
4265
4302
|
};
|
|
4266
4303
|
if (patch.updateCheck) {
|
|
4267
4304
|
merged.updateCheck = { ...merged.updateCheck, ...patch.updateCheck };
|
|
4268
4305
|
}
|
|
4306
|
+
if (patch.telemetry) {
|
|
4307
|
+
merged.telemetry = { ...merged.telemetry, ...patch.telemetry };
|
|
4308
|
+
}
|
|
4269
4309
|
return merged;
|
|
4270
4310
|
}
|
|
4271
4311
|
function tryLoadValidators() {
|
|
@@ -4378,40 +4418,40 @@ var updateCheckHook = {
|
|
|
4378
4418
|
};
|
|
4379
4419
|
|
|
4380
4420
|
// plugins/built-ins.ts
|
|
4381
|
-
var claudeProvider2 = { ...claudeProvider, pluginId: "claude", version: "0.
|
|
4382
|
-
var atDirectiveExtractor2 = { ...atDirectiveExtractor, pluginId: "claude", version: "0.
|
|
4383
|
-
var slashCommandExtractor2 = { ...slashCommandExtractor, pluginId: "claude", version: "0.
|
|
4384
|
-
var antigravityProvider2 = { ...antigravityProvider, pluginId: "antigravity", version: "0.
|
|
4385
|
-
var openaiProvider2 = { ...openaiProvider, pluginId: "openai", version: "0.
|
|
4386
|
-
var agentSkillsProvider2 = { ...agentSkillsProvider, pluginId: "agent-skills", version: "0.
|
|
4387
|
-
var coreMarkdownProvider2 = { ...coreMarkdownProvider, pluginId: "core", version: "0.
|
|
4388
|
-
var annotationsExtractor2 = { ...annotationsExtractor, pluginId: "core", version: "0.
|
|
4389
|
-
var externalUrlCounterExtractor2 = { ...externalUrlCounterExtractor, pluginId: "core", version: "0.
|
|
4390
|
-
var markdownLinkExtractor2 = { ...markdownLinkExtractor, pluginId: "core", version: "0.
|
|
4391
|
-
var mcpToolsExtractor2 = { ...mcpToolsExtractor, pluginId: "core", version: "0.
|
|
4392
|
-
var toolsCounterExtractor2 = { ...toolsCounterExtractor, pluginId: "core", version: "0.
|
|
4393
|
-
var annotationFieldUnknownAnalyzer2 = { ...annotationFieldUnknownAnalyzer, pluginId: "core", version: "0.
|
|
4394
|
-
var annotationOrphanAnalyzer2 = { ...annotationOrphanAnalyzer, pluginId: "core", version: "0.
|
|
4395
|
-
var annotationStaleAnalyzer2 = { ...annotationStaleAnalyzer, pluginId: "core", version: "0.
|
|
4396
|
-
var contributionOrphanAnalyzer2 = { ...contributionOrphanAnalyzer, pluginId: "core", version: "0.
|
|
4397
|
-
var issueCounterAnalyzer2 = { ...issueCounterAnalyzer, pluginId: "core", version: "0.
|
|
4398
|
-
var jobFileOrphanAnalyzer2 = { ...jobFileOrphanAnalyzer, pluginId: "core", version: "0.
|
|
4399
|
-
var linkConflictAnalyzer2 = { ...linkConflictAnalyzer, pluginId: "core", version: "0.
|
|
4400
|
-
var linkCounterAnalyzer2 = { ...linkCounterAnalyzer, pluginId: "core", version: "0.
|
|
4401
|
-
var linkSelfLoopAnalyzer2 = { ...linkSelfLoopAnalyzer, pluginId: "core", version: "0.
|
|
4402
|
-
var nameReservedAnalyzer2 = { ...nameReservedAnalyzer, pluginId: "core", version: "0.
|
|
4403
|
-
var nodeStabilityAnalyzer2 = { ...nodeStabilityAnalyzer, pluginId: "core", version: "0.
|
|
4404
|
-
var nodeSupersededAnalyzer2 = { ...nodeSupersededAnalyzer, pluginId: "core", version: "0.
|
|
4405
|
-
var referenceBrokenAnalyzer2 = { ...referenceBrokenAnalyzer, pluginId: "core", version: "0.
|
|
4406
|
-
var referenceRedundantAnalyzer2 = { ...referenceRedundantAnalyzer, pluginId: "core", version: "0.
|
|
4407
|
-
var schemaViolationAnalyzer2 = { ...schemaViolationAnalyzer, pluginId: "core", version: "0.
|
|
4408
|
-
var signalCollisionAnalyzer2 = { ...signalCollisionAnalyzer, pluginId: "core", version: "0.
|
|
4409
|
-
var triggerCollisionAnalyzer2 = { ...triggerCollisionAnalyzer, pluginId: "core", version: "0.
|
|
4410
|
-
var asciiFormatter2 = { ...asciiFormatter, pluginId: "core", version: "0.
|
|
4411
|
-
var jsonFormatter2 = { ...jsonFormatter, pluginId: "core", version: "0.
|
|
4412
|
-
var nodeBumpAction2 = { ...nodeBumpAction, pluginId: "core", version: "0.
|
|
4413
|
-
var nodeSupersedeAction2 = { ...nodeSupersedeAction, pluginId: "core", version: "0.
|
|
4414
|
-
var updateCheckHook2 = { ...updateCheckHook, pluginId: "core", version: "0.
|
|
4421
|
+
var claudeProvider2 = { ...claudeProvider, pluginId: "claude", version: "0.44.0" };
|
|
4422
|
+
var atDirectiveExtractor2 = { ...atDirectiveExtractor, pluginId: "claude", version: "0.44.0" };
|
|
4423
|
+
var slashCommandExtractor2 = { ...slashCommandExtractor, pluginId: "claude", version: "0.44.0" };
|
|
4424
|
+
var antigravityProvider2 = { ...antigravityProvider, pluginId: "antigravity", version: "0.44.0" };
|
|
4425
|
+
var openaiProvider2 = { ...openaiProvider, pluginId: "openai", version: "0.44.0" };
|
|
4426
|
+
var agentSkillsProvider2 = { ...agentSkillsProvider, pluginId: "agent-skills", version: "0.44.0" };
|
|
4427
|
+
var coreMarkdownProvider2 = { ...coreMarkdownProvider, pluginId: "core", version: "0.44.0" };
|
|
4428
|
+
var annotationsExtractor2 = { ...annotationsExtractor, pluginId: "core", version: "0.44.0" };
|
|
4429
|
+
var externalUrlCounterExtractor2 = { ...externalUrlCounterExtractor, pluginId: "core", version: "0.44.0" };
|
|
4430
|
+
var markdownLinkExtractor2 = { ...markdownLinkExtractor, pluginId: "core", version: "0.44.0" };
|
|
4431
|
+
var mcpToolsExtractor2 = { ...mcpToolsExtractor, pluginId: "core", version: "0.44.0" };
|
|
4432
|
+
var toolsCounterExtractor2 = { ...toolsCounterExtractor, pluginId: "core", version: "0.44.0" };
|
|
4433
|
+
var annotationFieldUnknownAnalyzer2 = { ...annotationFieldUnknownAnalyzer, pluginId: "core", version: "0.44.0" };
|
|
4434
|
+
var annotationOrphanAnalyzer2 = { ...annotationOrphanAnalyzer, pluginId: "core", version: "0.44.0" };
|
|
4435
|
+
var annotationStaleAnalyzer2 = { ...annotationStaleAnalyzer, pluginId: "core", version: "0.44.0" };
|
|
4436
|
+
var contributionOrphanAnalyzer2 = { ...contributionOrphanAnalyzer, pluginId: "core", version: "0.44.0" };
|
|
4437
|
+
var issueCounterAnalyzer2 = { ...issueCounterAnalyzer, pluginId: "core", version: "0.44.0" };
|
|
4438
|
+
var jobFileOrphanAnalyzer2 = { ...jobFileOrphanAnalyzer, pluginId: "core", version: "0.44.0" };
|
|
4439
|
+
var linkConflictAnalyzer2 = { ...linkConflictAnalyzer, pluginId: "core", version: "0.44.0" };
|
|
4440
|
+
var linkCounterAnalyzer2 = { ...linkCounterAnalyzer, pluginId: "core", version: "0.44.0" };
|
|
4441
|
+
var linkSelfLoopAnalyzer2 = { ...linkSelfLoopAnalyzer, pluginId: "core", version: "0.44.0" };
|
|
4442
|
+
var nameReservedAnalyzer2 = { ...nameReservedAnalyzer, pluginId: "core", version: "0.44.0" };
|
|
4443
|
+
var nodeStabilityAnalyzer2 = { ...nodeStabilityAnalyzer, pluginId: "core", version: "0.44.0" };
|
|
4444
|
+
var nodeSupersededAnalyzer2 = { ...nodeSupersededAnalyzer, pluginId: "core", version: "0.44.0" };
|
|
4445
|
+
var referenceBrokenAnalyzer2 = { ...referenceBrokenAnalyzer, pluginId: "core", version: "0.44.0" };
|
|
4446
|
+
var referenceRedundantAnalyzer2 = { ...referenceRedundantAnalyzer, pluginId: "core", version: "0.44.0" };
|
|
4447
|
+
var schemaViolationAnalyzer2 = { ...schemaViolationAnalyzer, pluginId: "core", version: "0.44.0" };
|
|
4448
|
+
var signalCollisionAnalyzer2 = { ...signalCollisionAnalyzer, pluginId: "core", version: "0.44.0" };
|
|
4449
|
+
var triggerCollisionAnalyzer2 = { ...triggerCollisionAnalyzer, pluginId: "core", version: "0.44.0" };
|
|
4450
|
+
var asciiFormatter2 = { ...asciiFormatter, pluginId: "core", version: "0.44.0" };
|
|
4451
|
+
var jsonFormatter2 = { ...jsonFormatter, pluginId: "core", version: "0.44.0" };
|
|
4452
|
+
var nodeBumpAction2 = { ...nodeBumpAction, pluginId: "core", version: "0.44.0" };
|
|
4453
|
+
var nodeSupersedeAction2 = { ...nodeSupersedeAction, pluginId: "core", version: "0.44.0" };
|
|
4454
|
+
var updateCheckHook2 = { ...updateCheckHook, pluginId: "core", version: "0.44.0" };
|
|
4415
4455
|
var builtInBundles = [
|
|
4416
4456
|
{
|
|
4417
4457
|
id: "claude",
|
|
@@ -4943,6 +4983,341 @@ function defaultRuntimeContext() {
|
|
|
4943
4983
|
return { cwd: process.cwd() };
|
|
4944
4984
|
}
|
|
4945
4985
|
|
|
4986
|
+
// cli/telemetry/first-run-prompt.ts
|
|
4987
|
+
import { createInterface } from "readline/promises";
|
|
4988
|
+
|
|
4989
|
+
// cli/i18n/telemetry.texts.ts
|
|
4990
|
+
var TELEMETRY_PROMPT_TEXTS = {
|
|
4991
|
+
// Header + body of the one-time question (glyph `ℹ` added by the renderer).
|
|
4992
|
+
title: "Anonymous error and usage reporting",
|
|
4993
|
+
intro: [
|
|
4994
|
+
"skill-map can send anonymous reports to help fix bugs and decide what to",
|
|
4995
|
+
"build next. No personal information is ever sent: not your files or their",
|
|
4996
|
+
"contents, not your folder or home paths, not your settings."
|
|
4997
|
+
],
|
|
4998
|
+
question: "Enable anonymous error and usage reporting?",
|
|
4999
|
+
answerYes: "[Y]es",
|
|
5000
|
+
answerNo: "[n]o",
|
|
5001
|
+
answerDetails: "[d]etails",
|
|
5002
|
+
// Disclosure shown on `[d]etails`, then the question is re-asked.
|
|
5003
|
+
detailsSentTitle: "Sent, only if you turn this on",
|
|
5004
|
+
detailsSent: [
|
|
5005
|
+
"crashes: error name, code, message, and a path-stripped stack trace",
|
|
5006
|
+
"usage: the command you ran and its flag names (never their values)",
|
|
5007
|
+
"usage: which built-in extractors ran, and which UI views you opened",
|
|
5008
|
+
"cli version, node major, os, arch, and a random anonymous id"
|
|
5009
|
+
],
|
|
5010
|
+
detailsNeverTitle: "Never sent",
|
|
5011
|
+
detailsNever: [
|
|
5012
|
+
"your files, their contents, frontmatter, annotations",
|
|
5013
|
+
"absolute paths, hostname, your username, ip address",
|
|
5014
|
+
"your settings values or any flag values"
|
|
5015
|
+
],
|
|
5016
|
+
detailsHint: "Turn error reports, CLI usage, and UI usage on or off independently in Settings, or force everything off with SKILL_MAP_TELEMETRY=0.",
|
|
5017
|
+
// Confirmation lines (glyph added by the renderer).
|
|
5018
|
+
enabled: "Telemetry on. Thanks. Turn error reports, CLI usage, and UI usage off independently in Settings.",
|
|
5019
|
+
disabled: "Telemetry off. You can turn any of it on later in Settings."
|
|
5020
|
+
};
|
|
5021
|
+
|
|
5022
|
+
// public-config.ts
|
|
5023
|
+
var SENTRY_DSN_NODE = "https://8b73dbb2563da4b77def12ce5ee46e75@o4511475590037504.ingest.de.sentry.io/4511475708002384";
|
|
5024
|
+
var POSTHOG_KEY_NODE = "phc_vMX3PcNeDsacWNg2hYEbKVXDijSWcjKFzabCkzU7RNEr";
|
|
5025
|
+
var POSTHOG_HOST = "https://eu.i.posthog.com";
|
|
5026
|
+
|
|
5027
|
+
// core/telemetry/scrub.ts
|
|
5028
|
+
var HOME_PLACEHOLDER = "<HOME>";
|
|
5029
|
+
var STRIPPED_ENVELOPE_KEYS = ["server_name", "user"];
|
|
5030
|
+
var HOME_PATTERNS = [
|
|
5031
|
+
// Windows: drive + Users + one user segment (back- or forward-slash).
|
|
5032
|
+
/[A-Za-z]:[\\/]Users[\\/][^\\/\s:*?"<>|]+/g,
|
|
5033
|
+
// POSIX user homes: /home/<user> or macOS /Users/<user>.
|
|
5034
|
+
/\/(?:home|Users)\/[^/\s:]+/g,
|
|
5035
|
+
// Root account home.
|
|
5036
|
+
/\/root(?=\/|\b)/g
|
|
5037
|
+
];
|
|
5038
|
+
function scrubString(value) {
|
|
5039
|
+
let out = value;
|
|
5040
|
+
for (const pattern of HOME_PATTERNS) {
|
|
5041
|
+
out = out.replace(pattern, HOME_PLACEHOLDER);
|
|
5042
|
+
}
|
|
5043
|
+
return out;
|
|
5044
|
+
}
|
|
5045
|
+
function scrubEvent(event) {
|
|
5046
|
+
const walked = walk(event);
|
|
5047
|
+
if (walked !== null && typeof walked === "object" && !Array.isArray(walked)) {
|
|
5048
|
+
const record = walked;
|
|
5049
|
+
for (const key of STRIPPED_ENVELOPE_KEYS) {
|
|
5050
|
+
if (key in record) delete record[key];
|
|
5051
|
+
}
|
|
5052
|
+
}
|
|
5053
|
+
return walked;
|
|
5054
|
+
}
|
|
5055
|
+
function walk(value) {
|
|
5056
|
+
if (typeof value === "string") return scrubString(value);
|
|
5057
|
+
if (Array.isArray(value)) return value.map((item) => walk(item));
|
|
5058
|
+
if (value !== null && typeof value === "object") {
|
|
5059
|
+
const out = {};
|
|
5060
|
+
for (const [key, child] of Object.entries(value)) {
|
|
5061
|
+
out[key] = walk(child);
|
|
5062
|
+
}
|
|
5063
|
+
return out;
|
|
5064
|
+
}
|
|
5065
|
+
return value;
|
|
5066
|
+
}
|
|
5067
|
+
|
|
5068
|
+
// cli/telemetry/telemetry-env.ts
|
|
5069
|
+
var TELEMETRY_ENV_VAR = "SKILL_MAP_TELEMETRY_ENV";
|
|
5070
|
+
function resolveTelemetryEnv() {
|
|
5071
|
+
const raw = process.env[TELEMETRY_ENV_VAR];
|
|
5072
|
+
if (raw === void 0 || raw.trim() === "" || raw === "prod" || raw === "production") {
|
|
5073
|
+
return "prod";
|
|
5074
|
+
}
|
|
5075
|
+
return "dev";
|
|
5076
|
+
}
|
|
5077
|
+
|
|
5078
|
+
// cli/telemetry/sentry-init.ts
|
|
5079
|
+
var KILL_SWITCH_ENV = "SKILL_MAP_TELEMETRY";
|
|
5080
|
+
var sdk = null;
|
|
5081
|
+
function isCliDsnConfigured() {
|
|
5082
|
+
return SENTRY_DSN_NODE !== "";
|
|
5083
|
+
}
|
|
5084
|
+
function isTelemetryForcedOff() {
|
|
5085
|
+
return process.env[KILL_SWITCH_ENV] === "0";
|
|
5086
|
+
}
|
|
5087
|
+
function isTelemetryActive(dsn) {
|
|
5088
|
+
if (isTelemetryForcedOff()) return false;
|
|
5089
|
+
if (dsn === "") return false;
|
|
5090
|
+
return isErrorTelemetryEnabled();
|
|
5091
|
+
}
|
|
5092
|
+
async function initSentryCli(version, loadSdk = () => import("@sentry/node")) {
|
|
5093
|
+
if (sdk) return;
|
|
5094
|
+
if (!isTelemetryActive(SENTRY_DSN_NODE)) return;
|
|
5095
|
+
const Sentry = await loadSdk();
|
|
5096
|
+
Sentry.init({
|
|
5097
|
+
dsn: SENTRY_DSN_NODE,
|
|
5098
|
+
release: `@skill-map/cli@${version}`,
|
|
5099
|
+
environment: resolveTelemetryEnv(),
|
|
5100
|
+
// CLI and BFF share one Sentry project; the `surface` tag tells their
|
|
5101
|
+
// events apart in the shared issue stream.
|
|
5102
|
+
initialScope: { tags: { surface: "cli" } },
|
|
5103
|
+
// Errors only: do NOT register the OpenTelemetry ESM loader hooks. We
|
|
5104
|
+
// run no tracing / auto-instrumentation, and the hook calls the
|
|
5105
|
+
// deprecated `module.register()` (a `DEP0205` warning on Node >= 26 that
|
|
5106
|
+
// would print on every telemetry-on invocation). Disabling it keeps
|
|
5107
|
+
// stderr clean and skips the loader's startup cost.
|
|
5108
|
+
registerEsmLoaderHooks: false,
|
|
5109
|
+
defaultIntegrations: false,
|
|
5110
|
+
integrations: [
|
|
5111
|
+
Sentry.onUncaughtExceptionIntegration(),
|
|
5112
|
+
Sentry.onUnhandledRejectionIntegration()
|
|
5113
|
+
],
|
|
5114
|
+
tracesSampleRate: 0,
|
|
5115
|
+
sendDefaultPii: false,
|
|
5116
|
+
beforeSend: (event) => scrubEvent(event)
|
|
5117
|
+
});
|
|
5118
|
+
sdk = Sentry;
|
|
5119
|
+
}
|
|
5120
|
+
function setTelemetryVerbTag(verb) {
|
|
5121
|
+
if (!sdk || verb === void 0 || verb === "") return;
|
|
5122
|
+
sdk.setTag("verb", verb);
|
|
5123
|
+
}
|
|
5124
|
+
async function closeSentryCli(timeoutMs = 2e3) {
|
|
5125
|
+
if (!sdk) return;
|
|
5126
|
+
try {
|
|
5127
|
+
await sdk.close(timeoutMs);
|
|
5128
|
+
} catch {
|
|
5129
|
+
}
|
|
5130
|
+
}
|
|
5131
|
+
|
|
5132
|
+
// cli/telemetry/usage-collector.ts
|
|
5133
|
+
var BUILT_IN_PLUGIN_IDS = /* @__PURE__ */ new Set([
|
|
5134
|
+
"claude",
|
|
5135
|
+
"antigravity",
|
|
5136
|
+
"openai",
|
|
5137
|
+
"agent-skills",
|
|
5138
|
+
"core"
|
|
5139
|
+
]);
|
|
5140
|
+
var EXTERNAL_PLUGIN_PLACEHOLDER = "external_plugin";
|
|
5141
|
+
function qualifyExtensionForUsage(qualifiedId2) {
|
|
5142
|
+
const slash = qualifiedId2.indexOf("/");
|
|
5143
|
+
if (slash <= 0) return EXTERNAL_PLUGIN_PLACEHOLDER;
|
|
5144
|
+
const pluginId = qualifiedId2.slice(0, slash);
|
|
5145
|
+
return BUILT_IN_PLUGIN_IDS.has(pluginId) ? qualifiedId2 : EXTERNAL_PLUGIN_PLACEHOLDER;
|
|
5146
|
+
}
|
|
5147
|
+
function buildScanExtensionSet(executedExtensionIds) {
|
|
5148
|
+
const out = /* @__PURE__ */ new Set();
|
|
5149
|
+
for (const id of executedExtensionIds) {
|
|
5150
|
+
out.add(qualifyExtensionForUsage(id));
|
|
5151
|
+
}
|
|
5152
|
+
return [...out].sort();
|
|
5153
|
+
}
|
|
5154
|
+
function extractFlagNames(args2) {
|
|
5155
|
+
const out = /* @__PURE__ */ new Set();
|
|
5156
|
+
for (const arg of args2) {
|
|
5157
|
+
if (!arg.startsWith("-")) continue;
|
|
5158
|
+
const name = arg.replace(/^-+/, "").split("=")[0];
|
|
5159
|
+
if (name !== void 0 && name !== "") out.add(name);
|
|
5160
|
+
}
|
|
5161
|
+
return [...out].sort();
|
|
5162
|
+
}
|
|
5163
|
+
function cliVerbEventName(verb, knownVerbs) {
|
|
5164
|
+
return `cli.${knownVerbs.has(verb) ? verb : "unknown"}`;
|
|
5165
|
+
}
|
|
5166
|
+
function buildCliVerbProperties(flagNames, extensions) {
|
|
5167
|
+
const flags = [...new Set(flagNames)].sort();
|
|
5168
|
+
return extensions ? { flags, extensions } : { flags };
|
|
5169
|
+
}
|
|
5170
|
+
function envUsageProps(cliVersion) {
|
|
5171
|
+
return {
|
|
5172
|
+
cli_version: cliVersion,
|
|
5173
|
+
node_major: Number.parseInt(process.versions.node.split(".")[0] ?? "0", 10),
|
|
5174
|
+
os: process.platform,
|
|
5175
|
+
arch: process.arch,
|
|
5176
|
+
environment: resolveTelemetryEnv()
|
|
5177
|
+
};
|
|
5178
|
+
}
|
|
5179
|
+
|
|
5180
|
+
// cli/telemetry/posthog-init.ts
|
|
5181
|
+
var client = null;
|
|
5182
|
+
function isUsageKeyConfigured() {
|
|
5183
|
+
return POSTHOG_KEY_NODE !== "";
|
|
5184
|
+
}
|
|
5185
|
+
function isUsageCliTelemetryActive(key) {
|
|
5186
|
+
if (isTelemetryForcedOff()) return false;
|
|
5187
|
+
if (key === "") return false;
|
|
5188
|
+
return isUsageCliTelemetryEnabled();
|
|
5189
|
+
}
|
|
5190
|
+
function scrubUsageEvent(event) {
|
|
5191
|
+
return event === null ? null : scrubEvent(event);
|
|
5192
|
+
}
|
|
5193
|
+
async function initUsageCli(loadSdk = () => import("posthog-node")) {
|
|
5194
|
+
if (client) return;
|
|
5195
|
+
if (!isUsageCliTelemetryActive(POSTHOG_KEY_NODE)) return;
|
|
5196
|
+
const { PostHog } = await loadSdk();
|
|
5197
|
+
client = new PostHog(POSTHOG_KEY_NODE, {
|
|
5198
|
+
host: POSTHOG_HOST,
|
|
5199
|
+
// Second line of defense behind the project-level IP drop: the client
|
|
5200
|
+
// never attaches an IP or geo, and never autocaptures.
|
|
5201
|
+
disableGeoip: true,
|
|
5202
|
+
before_send: scrubUsageEvent
|
|
5203
|
+
});
|
|
5204
|
+
}
|
|
5205
|
+
function captureUsage(event, properties) {
|
|
5206
|
+
if (client === null) return;
|
|
5207
|
+
const distinctId = readAnonymousId();
|
|
5208
|
+
if (distinctId === null) return;
|
|
5209
|
+
client.capture({
|
|
5210
|
+
distinctId,
|
|
5211
|
+
event,
|
|
5212
|
+
properties: { ...envUsageProps(VERSION), ...properties }
|
|
5213
|
+
});
|
|
5214
|
+
}
|
|
5215
|
+
var pendingScanExtensions = null;
|
|
5216
|
+
function setScanExtensions(extensions) {
|
|
5217
|
+
pendingScanExtensions = extensions;
|
|
5218
|
+
}
|
|
5219
|
+
function captureCliInvocation(verb, flagNames, knownVerbs) {
|
|
5220
|
+
const extensions = pendingScanExtensions;
|
|
5221
|
+
pendingScanExtensions = null;
|
|
5222
|
+
captureUsage(cliVerbEventName(verb, knownVerbs), buildCliVerbProperties(flagNames, extensions));
|
|
5223
|
+
}
|
|
5224
|
+
async function flushUsageCli(timeoutMs = 2e3) {
|
|
5225
|
+
if (client === null) return;
|
|
5226
|
+
try {
|
|
5227
|
+
await client.shutdown(timeoutMs);
|
|
5228
|
+
} catch {
|
|
5229
|
+
}
|
|
5230
|
+
}
|
|
5231
|
+
|
|
5232
|
+
// cli/telemetry/first-run-prompt.ts
|
|
5233
|
+
function interpretConsentAnswer(raw) {
|
|
5234
|
+
const value = raw.trim().toLowerCase();
|
|
5235
|
+
if (value === "n" || value === "no") return "no";
|
|
5236
|
+
if (value === "d" || value === "details") return "details";
|
|
5237
|
+
return "yes";
|
|
5238
|
+
}
|
|
5239
|
+
function isPromptEligible(opts) {
|
|
5240
|
+
return opts.dsnConfigured && opts.isTTY && !opts.isCI && !opts.forcedOff && !opts.alreadyPrompted;
|
|
5241
|
+
}
|
|
5242
|
+
function liveGateInputs(stdout) {
|
|
5243
|
+
return {
|
|
5244
|
+
dsnConfigured: isCliDsnConfigured() || isUsageKeyConfigured(),
|
|
5245
|
+
isTTY: stdout.isTTY === true,
|
|
5246
|
+
isCI: Boolean(process.env["CI"]),
|
|
5247
|
+
forcedOff: isTelemetryForcedOff(),
|
|
5248
|
+
alreadyPrompted: hasTelemetryPromptBeenShown()
|
|
5249
|
+
};
|
|
5250
|
+
}
|
|
5251
|
+
function renderConsent(ansi) {
|
|
5252
|
+
const t = TELEMETRY_PROMPT_TEXTS;
|
|
5253
|
+
const answerLine = ` ${t.question} ${ansi.bold(t.answerYes)} ${t.answerNo} ${ansi.dim(t.answerDetails)} `;
|
|
5254
|
+
return {
|
|
5255
|
+
question: [
|
|
5256
|
+
` ${ansi.cyan("\u2139")} ${ansi.bold(t.title)}`,
|
|
5257
|
+
...t.intro.map((line) => ` ${line}`),
|
|
5258
|
+
"",
|
|
5259
|
+
answerLine
|
|
5260
|
+
].join("\n"),
|
|
5261
|
+
reprompt: answerLine,
|
|
5262
|
+
details: [
|
|
5263
|
+
"",
|
|
5264
|
+
` ${t.detailsSentTitle}`,
|
|
5265
|
+
...t.detailsSent.map((line) => ` ${ansi.dim("\u2192")} ${line}`),
|
|
5266
|
+
` ${t.detailsNeverTitle}`,
|
|
5267
|
+
...t.detailsNever.map((line) => ` ${ansi.red("\u2715")} ${line}`),
|
|
5268
|
+
"",
|
|
5269
|
+
` ${ansi.dim(t.detailsHint)}`,
|
|
5270
|
+
""
|
|
5271
|
+
].join("\n"),
|
|
5272
|
+
enabled: ` ${ansi.green("\u2713")} ${t.enabled}
|
|
5273
|
+
`,
|
|
5274
|
+
disabled: ` ${ansi.cyan("\u2139")} ${t.disabled}
|
|
5275
|
+
`
|
|
5276
|
+
};
|
|
5277
|
+
}
|
|
5278
|
+
async function readConsentDecision(rl, stdout, rendered) {
|
|
5279
|
+
let answer = interpretConsentAnswer(await rl.question(rendered.question));
|
|
5280
|
+
while (answer === "details") {
|
|
5281
|
+
stdout.write(rendered.details);
|
|
5282
|
+
answer = interpretConsentAnswer(await rl.question(rendered.reprompt));
|
|
5283
|
+
}
|
|
5284
|
+
return answer === "yes";
|
|
5285
|
+
}
|
|
5286
|
+
async function runConsentPrompt(stdin, stdout, nowMs) {
|
|
5287
|
+
const rendered = renderConsent(
|
|
5288
|
+
ansiFor({ isTTY: stdout.isTTY === true, noColorFlag: false })
|
|
5289
|
+
);
|
|
5290
|
+
const rl = createInterface({ input: stdin, output: stdout });
|
|
5291
|
+
try {
|
|
5292
|
+
const consented = await readConsentDecision(rl, stdout, rendered);
|
|
5293
|
+
writeUserSettings({
|
|
5294
|
+
telemetry: {
|
|
5295
|
+
errorsEnabled: consented,
|
|
5296
|
+
usageCliEnabled: consented,
|
|
5297
|
+
usageUiEnabled: consented,
|
|
5298
|
+
promptedAt: nowMs
|
|
5299
|
+
}
|
|
5300
|
+
});
|
|
5301
|
+
if (consented) ensureAnonymousId();
|
|
5302
|
+
stdout.write(consented ? rendered.enabled : rendered.disabled);
|
|
5303
|
+
} catch {
|
|
5304
|
+
} finally {
|
|
5305
|
+
rl.close();
|
|
5306
|
+
}
|
|
5307
|
+
}
|
|
5308
|
+
async function maybeRunFirstRunPrompt({
|
|
5309
|
+
stdin = process.stdin,
|
|
5310
|
+
stdout = process.stdout,
|
|
5311
|
+
nowMs = Date.now()
|
|
5312
|
+
} = {}) {
|
|
5313
|
+
if (!isPromptEligible(liveGateInputs(stdout))) return;
|
|
5314
|
+
if (!hasSeenFirstRun()) {
|
|
5315
|
+
writeUserSettings({ telemetry: { firstRunAt: nowMs } });
|
|
5316
|
+
return;
|
|
5317
|
+
}
|
|
5318
|
+
await runConsentPrompt(stdin, stdout, nowMs);
|
|
5319
|
+
}
|
|
5320
|
+
|
|
4946
5321
|
// cli/commands/bump.ts
|
|
4947
5322
|
import { Command as Command2, Option as Option2 } from "clipanion";
|
|
4948
5323
|
|
|
@@ -5625,13 +6000,13 @@ var CONSENT_TEXTS = {
|
|
|
5625
6000
|
};
|
|
5626
6001
|
|
|
5627
6002
|
// cli/util/confirm.ts
|
|
5628
|
-
import { createInterface } from "readline";
|
|
6003
|
+
import { createInterface as createInterface2 } from "readline";
|
|
5629
6004
|
var YES_PATTERN = new RegExp(UTIL_TEXTS.confirmYesPatternSource, "i");
|
|
5630
6005
|
var NO_PATTERN = new RegExp(UTIL_TEXTS.confirmNoPatternSource, "i");
|
|
5631
6006
|
async function confirm(question, streams, opts) {
|
|
5632
6007
|
const defaultAnswer = opts?.defaultAnswer ?? "no";
|
|
5633
6008
|
const suffix = defaultAnswer === "yes" ? UTIL_TEXTS.confirmPromptSuffixDefaultYes : UTIL_TEXTS.confirmPromptSuffix;
|
|
5634
|
-
const rl =
|
|
6009
|
+
const rl = createInterface2({ input: streams.stdin, output: streams.stderr });
|
|
5635
6010
|
try {
|
|
5636
6011
|
const answer = await new Promise(
|
|
5637
6012
|
(resolveP) => rl.question(`${question}${suffix}`, resolveP)
|
|
@@ -7904,7 +8279,7 @@ var SqliteStorageAdapter = class {
|
|
|
7904
8279
|
/**
|
|
7905
8280
|
* Access the underlying Kysely instance.
|
|
7906
8281
|
*
|
|
7907
|
-
* Test-only escape hatch (per
|
|
8282
|
+
* Test-only escape hatch (per context/kernel.md §Kernel boundaries, tests
|
|
7908
8283
|
* are the documented exception). CLI commands MUST consume the
|
|
7909
8284
|
* adapter through the namespaced port surfaces (`port.<namespace>.*`
|
|
7910
8285
|
* or `port.transaction(...)`); reaching for this getter from a
|
|
@@ -10243,8 +10618,8 @@ var DEFAULT_READ_CONFIG = Object.freeze({
|
|
|
10243
10618
|
});
|
|
10244
10619
|
function resolveProviderWalk(provider) {
|
|
10245
10620
|
if (provider.walk) {
|
|
10246
|
-
const
|
|
10247
|
-
return
|
|
10621
|
+
const walk3 = provider.walk.bind(provider);
|
|
10622
|
+
return walk3;
|
|
10248
10623
|
}
|
|
10249
10624
|
const read = provider.read ?? DEFAULT_READ_CONFIG;
|
|
10250
10625
|
return (roots, options) => {
|
|
@@ -13870,8 +14245,7 @@ var HelpCommand = class extends Command15 {
|
|
|
13870
14245
|
|
|
13871
14246
|
Formats:
|
|
13872
14247
|
human (default): pretty terminal output.
|
|
13873
|
-
md : canonical markdown
|
|
13874
|
-
regenerated from this and CI fails on drift.
|
|
14248
|
+
md : canonical markdown for documentation.
|
|
13875
14249
|
json : structured surface dump per spec/cli-contract.md.
|
|
13876
14250
|
`
|
|
13877
14251
|
});
|
|
@@ -15508,11 +15882,11 @@ import { join as join13, relative as relative4, sep as sep4 } from "path";
|
|
|
15508
15882
|
function discoverOrphanSidecars(roots, shouldSkip) {
|
|
15509
15883
|
const out = [];
|
|
15510
15884
|
for (const root of roots) {
|
|
15511
|
-
|
|
15885
|
+
walk2(root, root, shouldSkip ?? (() => false), out);
|
|
15512
15886
|
}
|
|
15513
15887
|
return out;
|
|
15514
15888
|
}
|
|
15515
|
-
function
|
|
15889
|
+
function walk2(root, current, shouldSkip, out) {
|
|
15516
15890
|
let entries;
|
|
15517
15891
|
try {
|
|
15518
15892
|
entries = readdirSync7(current, { withFileTypes: true, encoding: "utf8" });
|
|
@@ -15525,7 +15899,7 @@ function walk(root, current, shouldSkip, out) {
|
|
|
15525
15899
|
if (shouldSkip(rel)) continue;
|
|
15526
15900
|
if (entry.isSymbolicLink()) continue;
|
|
15527
15901
|
if (entry.isDirectory()) {
|
|
15528
|
-
|
|
15902
|
+
walk2(root, full, shouldSkip, out);
|
|
15529
15903
|
continue;
|
|
15530
15904
|
}
|
|
15531
15905
|
if (!entry.isFile()) continue;
|
|
@@ -16149,7 +16523,8 @@ function buildPostWalkTransformCtx(providers, nodes, activeProvider) {
|
|
|
16149
16523
|
const reservedNodePaths = buildReservedNodePaths(
|
|
16150
16524
|
nodes,
|
|
16151
16525
|
kindRegistry,
|
|
16152
|
-
reservedNamesByProviderKind
|
|
16526
|
+
reservedNamesByProviderKind,
|
|
16527
|
+
activeProvider
|
|
16153
16528
|
);
|
|
16154
16529
|
return { kindRegistry, providerResolution, activeProvider, reservedNodePaths };
|
|
16155
16530
|
}
|
|
@@ -16180,19 +16555,23 @@ function indexReservedNames(provider, out) {
|
|
|
16180
16555
|
}
|
|
16181
16556
|
}
|
|
16182
16557
|
}
|
|
16183
|
-
function buildReservedNodePaths(nodes, kindRegistry, reservedNamesByProviderKind) {
|
|
16558
|
+
function buildReservedNodePaths(nodes, kindRegistry, reservedNamesByProviderKind, activeProvider) {
|
|
16184
16559
|
const out = /* @__PURE__ */ new Set();
|
|
16185
16560
|
for (const node of nodes) {
|
|
16186
|
-
const
|
|
16187
|
-
const
|
|
16188
|
-
|
|
16189
|
-
|
|
16190
|
-
|
|
16561
|
+
const selfKey = `${node.provider}/${node.kind}`;
|
|
16562
|
+
const selfReserved = reservedNamesByProviderKind.get(selfKey);
|
|
16563
|
+
const lensReserved = activeProvider && activeProvider !== node.provider ? reservedNamesByProviderKind.get(`${activeProvider}/${node.kind}`) : void 0;
|
|
16564
|
+
if (!hasEntries(selfReserved) && !hasEntries(lensReserved)) continue;
|
|
16565
|
+
const ids = deriveNodeIdentifiers(node, kindRegistry.get(selfKey));
|
|
16566
|
+
if (ids.some((id) => selfReserved?.has(id) === true || lensReserved?.has(id) === true)) {
|
|
16191
16567
|
out.add(node.path);
|
|
16192
16568
|
}
|
|
16193
16569
|
}
|
|
16194
16570
|
return out;
|
|
16195
16571
|
}
|
|
16572
|
+
function hasEntries(set) {
|
|
16573
|
+
return set !== void 0 && set.size > 0;
|
|
16574
|
+
}
|
|
16196
16575
|
function buildScanSetup(options) {
|
|
16197
16576
|
const start = Date.now();
|
|
16198
16577
|
const emitter = options.emitter ?? new InMemoryProgressEmitter();
|
|
@@ -16754,7 +17133,7 @@ function safeStat(path) {
|
|
|
16754
17133
|
}
|
|
16755
17134
|
|
|
16756
17135
|
// core/runtime/active-provider-bootstrap.ts
|
|
16757
|
-
import { createInterface as
|
|
17136
|
+
import { createInterface as createInterface3 } from "readline";
|
|
16758
17137
|
import { isAbsolute as isAbsolute9, join as join16 } from "path";
|
|
16759
17138
|
async function bootstrapActiveProvider(opts) {
|
|
16760
17139
|
const fromCwd = resolveActiveProvider(opts.cwd, opts.providers);
|
|
@@ -16910,7 +17289,7 @@ async function promptForLens(detected, stdin, stderr, warnGlyph) {
|
|
|
16910
17289
|
);
|
|
16911
17290
|
}
|
|
16912
17291
|
stderr.write(lines.join("\n") + "\n");
|
|
16913
|
-
const rl =
|
|
17292
|
+
const rl = createInterface3({ input: stdin, output: stderr });
|
|
16914
17293
|
try {
|
|
16915
17294
|
const answer = await new Promise(
|
|
16916
17295
|
(resolveP) => rl.question(SCAN_RUNNER_TEXTS.activeProviderPromptInput, resolveP)
|
|
@@ -16929,7 +17308,7 @@ async function promptForLens(detected, stdin, stderr, warnGlyph) {
|
|
|
16929
17308
|
|
|
16930
17309
|
// core/sqlite/db-drift-reset.ts
|
|
16931
17310
|
import { existsSync as existsSync23 } from "fs";
|
|
16932
|
-
import { createInterface as
|
|
17311
|
+
import { createInterface as createInterface4 } from "readline";
|
|
16933
17312
|
import { DatabaseSync as DatabaseSync7 } from "node:sqlite";
|
|
16934
17313
|
|
|
16935
17314
|
// core/sqlite/i18n/db-drift.texts.ts
|
|
@@ -16996,7 +17375,7 @@ async function askDriftReset(dbVersion, policy) {
|
|
|
16996
17375
|
hint: dim(DB_DRIFT_TEXTS.driftPromptHint)
|
|
16997
17376
|
})
|
|
16998
17377
|
);
|
|
16999
|
-
const rl =
|
|
17378
|
+
const rl = createInterface4({ input: policy.stdin, output: policy.stderr });
|
|
17000
17379
|
try {
|
|
17001
17380
|
const answer = await new Promise(
|
|
17002
17381
|
(resolveP) => rl.question(DB_DRIFT_TEXTS.driftPromptQuestion, resolveP)
|
|
@@ -17032,9 +17411,9 @@ async function runScanForCommand(opts) {
|
|
|
17032
17411
|
const { cfg, ignoreFilter, strict, effectiveRoots } = scanInputs;
|
|
17033
17412
|
let referenceablePaths;
|
|
17034
17413
|
if (cfg.scan.referencePaths.length > 0) {
|
|
17035
|
-
const
|
|
17036
|
-
referenceablePaths =
|
|
17037
|
-
emitReferenceWalkAdvisory(
|
|
17414
|
+
const walk3 = walkReferencePaths(cfg.scan.referencePaths, ctx.cwd);
|
|
17415
|
+
referenceablePaths = walk3.paths;
|
|
17416
|
+
emitReferenceWalkAdvisory(walk3, opts);
|
|
17038
17417
|
}
|
|
17039
17418
|
const loadPrior = makePriorLoader(opts.noBuiltIns, strict);
|
|
17040
17419
|
const jobsDir = defaultProjectJobsDir(ctx);
|
|
@@ -17096,11 +17475,11 @@ async function resolveActiveLens(opts, ctx, effectiveRoots, pluginRuntime, provi
|
|
|
17096
17475
|
});
|
|
17097
17476
|
return { kind: "ok", activeProvider: bootstrap.activeProvider };
|
|
17098
17477
|
}
|
|
17099
|
-
function emitReferenceWalkAdvisory(
|
|
17100
|
-
if (
|
|
17478
|
+
function emitReferenceWalkAdvisory(walk3, opts) {
|
|
17479
|
+
if (walk3.truncated) {
|
|
17101
17480
|
opts.printer.warn(SCAN_RUNNER_TEXTS.referenceWalkTruncated);
|
|
17102
17481
|
}
|
|
17103
|
-
for (const missing of
|
|
17482
|
+
for (const missing of walk3.missingRoots) {
|
|
17104
17483
|
opts.printer.warn(
|
|
17105
17484
|
tx(SCAN_RUNNER_TEXTS.referenceWalkMissingRoot, { path: missing })
|
|
17106
17485
|
);
|
|
@@ -17279,7 +17658,8 @@ async function runPersistPath(opts, dbPath, jobsDir, strict, loadPrior, runScanW
|
|
|
17279
17658
|
renameOps: outcome.renameOps,
|
|
17280
17659
|
persistedTo: dbPath,
|
|
17281
17660
|
dbPath,
|
|
17282
|
-
strict
|
|
17661
|
+
strict,
|
|
17662
|
+
executedExtensionIds: outcome.extractorRuns.map((run) => run.extractorId)
|
|
17283
17663
|
};
|
|
17284
17664
|
}
|
|
17285
17665
|
async function runEphemeralPath(opts, dbPath, strict, loadPrior, runScanWith) {
|
|
@@ -17297,7 +17677,8 @@ async function runEphemeralPath(opts, dbPath, strict, loadPrior, runScanWith) {
|
|
|
17297
17677
|
renameOps: scanned.renameOps,
|
|
17298
17678
|
persistedTo: null,
|
|
17299
17679
|
dbPath,
|
|
17300
|
-
strict
|
|
17680
|
+
strict,
|
|
17681
|
+
executedExtensionIds: scanned.extractorRuns.map((run) => run.extractorId)
|
|
17301
17682
|
};
|
|
17302
17683
|
} catch (err) {
|
|
17303
17684
|
return { kind: "scan-error", message: formatErrorMessage(err) };
|
|
@@ -20221,6 +20602,8 @@ var TogglePluginsBase = class extends SmCommand {
|
|
|
20221
20602
|
targets = lockError;
|
|
20222
20603
|
const keys = expandToKeys(targets);
|
|
20223
20604
|
await this.#persistKeys(keys, enabled);
|
|
20605
|
+
const set = buildScanExtensionSet(keys);
|
|
20606
|
+
captureUsage("plugin.apply", enabled ? { enabled: set, disabled: [] } : { enabled: [], disabled: set });
|
|
20224
20607
|
this.#renderSuccess(keys, enabled);
|
|
20225
20608
|
return ExitCode.Ok;
|
|
20226
20609
|
}
|
|
@@ -21183,6 +21566,29 @@ function stripFrontmatterFence(text) {
|
|
|
21183
21566
|
}
|
|
21184
21567
|
var REFRESH_COMMANDS = [RefreshCommand];
|
|
21185
21568
|
|
|
21569
|
+
// cli/i18n/intentional-fail.texts.ts
|
|
21570
|
+
var INTENTIONAL_FAIL_TEXTS = {
|
|
21571
|
+
triggering: "Triggering an intentional uncaught error to exercise Sentry error reporting...",
|
|
21572
|
+
errorMessage: "skill-map intentional failure (Sentry self-test)"
|
|
21573
|
+
};
|
|
21574
|
+
|
|
21575
|
+
// cli/commands/intentional-fail.ts
|
|
21576
|
+
var IntentionalFailCommand = class extends SmCommand {
|
|
21577
|
+
static paths = [["intentional-fail"]];
|
|
21578
|
+
// No `static usage` on purpose: that is what keeps the verb out of every
|
|
21579
|
+
// help / reference surface Clipanion drives from command definitions.
|
|
21580
|
+
// A self-test crash has no meaningful "done in <...>" line.
|
|
21581
|
+
emitElapsed = false;
|
|
21582
|
+
async run() {
|
|
21583
|
+
this.printer.warn(INTENTIONAL_FAIL_TEXTS.triggering);
|
|
21584
|
+
setTimeout(() => {
|
|
21585
|
+
throw new Error(INTENTIONAL_FAIL_TEXTS.errorMessage);
|
|
21586
|
+
}, 0);
|
|
21587
|
+
await new Promise((resolve40) => setTimeout(resolve40, 5e3));
|
|
21588
|
+
return 1;
|
|
21589
|
+
}
|
|
21590
|
+
};
|
|
21591
|
+
|
|
21186
21592
|
// cli/commands/scan.ts
|
|
21187
21593
|
import { Command as Command31, Option as Option29 } from "clipanion";
|
|
21188
21594
|
|
|
@@ -21414,9 +21820,9 @@ function createWatcherRuntime(opts) {
|
|
|
21414
21820
|
overrideMaxNodes: opts.maxNodesOverride ?? null
|
|
21415
21821
|
};
|
|
21416
21822
|
if (cfg.scan.referencePaths.length > 0) {
|
|
21417
|
-
const
|
|
21418
|
-
if (
|
|
21419
|
-
runOptions.referenceablePaths =
|
|
21823
|
+
const walk3 = walkReferencePaths(cfg.scan.referencePaths, cwd);
|
|
21824
|
+
if (walk3.paths.size > 0) {
|
|
21825
|
+
runOptions.referenceablePaths = walk3.paths;
|
|
21420
21826
|
runOptions.cwd = cwd;
|
|
21421
21827
|
}
|
|
21422
21828
|
}
|
|
@@ -21994,7 +22400,11 @@ var ScanCommand = class extends SmCommand {
|
|
|
21994
22400
|
style,
|
|
21995
22401
|
...parsedMaxNodes.value !== void 0 ? { maxNodes: parsedMaxNodes.value } : {}
|
|
21996
22402
|
});
|
|
21997
|
-
|
|
22403
|
+
if (outcome.kind === "ok") {
|
|
22404
|
+
setScanExtensions(buildScanExtensionSet(outcome.executedExtensionIds));
|
|
22405
|
+
return this.renderOutcome(outcome.result, outcome.persistedTo, outcome.dbPath, outcome.strict);
|
|
22406
|
+
}
|
|
22407
|
+
return this.renderFailure(outcome);
|
|
21998
22408
|
}
|
|
21999
22409
|
/**
|
|
22000
22410
|
* Parse `--max-nodes <N>`. Returns either the integer value (or
|
|
@@ -22512,7 +22922,7 @@ import { WebSocketServer } from "ws";
|
|
|
22512
22922
|
// server/app.ts
|
|
22513
22923
|
import { Hono } from "hono";
|
|
22514
22924
|
import { bodyLimit } from "hono/body-limit";
|
|
22515
|
-
import { HTTPException as
|
|
22925
|
+
import { HTTPException as HTTPException16 } from "hono/http-exception";
|
|
22516
22926
|
|
|
22517
22927
|
// core/config/service.ts
|
|
22518
22928
|
var ConfigService = class {
|
|
@@ -22749,6 +23159,10 @@ var SERVER_TEXTS = {
|
|
|
22749
23159
|
preferencesBodyEmpty: "Request body must contain at least one known preference (e.g. `updateCheck.enabled`).",
|
|
22750
23160
|
preferencesUpdateCheckNotObject: '`updateCheck` must be an object (e.g. `{"updateCheck": {"enabled": false}}`).',
|
|
22751
23161
|
preferencesUpdateCheckEnabledNotBoolean: "`updateCheck.enabled` must be a boolean.",
|
|
23162
|
+
preferencesTelemetryNotObject: '`telemetry` must be an object (e.g. `{"telemetry": {"errorsEnabled": true}}`).',
|
|
23163
|
+
preferencesTelemetryErrorsEnabledNotBoolean: "`telemetry.errorsEnabled` must be a boolean.",
|
|
23164
|
+
preferencesTelemetryUsageCliEnabledNotBoolean: "`telemetry.usageCliEnabled` must be a boolean.",
|
|
23165
|
+
preferencesTelemetryUsageUiEnabledNotBoolean: "`telemetry.usageUiEnabled` must be a boolean.",
|
|
22752
23166
|
preferencesPersistFailed: "Could not persist preferences: {{message}}",
|
|
22753
23167
|
// ---- project-preferences route (routes/project-preferences.ts) ----------
|
|
22754
23168
|
//
|
|
@@ -22908,6 +23322,53 @@ function createSecurityHeaders() {
|
|
|
22908
23322
|
};
|
|
22909
23323
|
}
|
|
22910
23324
|
|
|
23325
|
+
// server/telemetry/sentry.ts
|
|
23326
|
+
import { HTTPException } from "hono/http-exception";
|
|
23327
|
+
var sdk2 = null;
|
|
23328
|
+
async function initSentryBff(version, loadSdk = () => import("@sentry/node")) {
|
|
23329
|
+
if (sdk2) return;
|
|
23330
|
+
if (!isTelemetryActive(SENTRY_DSN_NODE)) return;
|
|
23331
|
+
const Sentry = await loadSdk();
|
|
23332
|
+
Sentry.init({
|
|
23333
|
+
dsn: SENTRY_DSN_NODE,
|
|
23334
|
+
release: `@skill-map/cli@${version}`,
|
|
23335
|
+
environment: resolveTelemetryEnv(),
|
|
23336
|
+
// Shared project with the CLI; the `surface` tag separates the two.
|
|
23337
|
+
initialScope: { tags: { surface: "bff" } },
|
|
23338
|
+
// Errors only: skip the OpenTelemetry ESM loader hooks (we run no
|
|
23339
|
+
// tracing). They call the deprecated `module.register()` (a Node >= 26
|
|
23340
|
+
// DEP0205 warning) and add startup cost for nothing here.
|
|
23341
|
+
registerEsmLoaderHooks: false,
|
|
23342
|
+
defaultIntegrations: false,
|
|
23343
|
+
integrations: [],
|
|
23344
|
+
tracesSampleRate: 0,
|
|
23345
|
+
sendDefaultPii: false,
|
|
23346
|
+
beforeSend: (event) => scrubEvent(event)
|
|
23347
|
+
});
|
|
23348
|
+
sdk2 = Sentry;
|
|
23349
|
+
}
|
|
23350
|
+
function shouldCaptureError(err) {
|
|
23351
|
+
if (err instanceof HTTPException) return err.status >= 500;
|
|
23352
|
+
return true;
|
|
23353
|
+
}
|
|
23354
|
+
function createSentryRequestCapture() {
|
|
23355
|
+
return async function sentryRequestCapture(c, next) {
|
|
23356
|
+
try {
|
|
23357
|
+
await next();
|
|
23358
|
+
} catch (err) {
|
|
23359
|
+
const client2 = sdk2;
|
|
23360
|
+
if (client2 && shouldCaptureError(err)) {
|
|
23361
|
+
client2.withScope((scope) => {
|
|
23362
|
+
scope.setTag("route", c.req.routePath ?? c.req.path);
|
|
23363
|
+
scope.setTag("method", c.req.method);
|
|
23364
|
+
client2.captureException(err);
|
|
23365
|
+
});
|
|
23366
|
+
}
|
|
23367
|
+
throw err;
|
|
23368
|
+
}
|
|
23369
|
+
};
|
|
23370
|
+
}
|
|
23371
|
+
|
|
22911
23372
|
// server/routes/annotations.ts
|
|
22912
23373
|
var ENVELOPE_KIND = "annotations.registered";
|
|
22913
23374
|
function registerAnnotationsRoute(app, deps) {
|
|
@@ -22924,10 +23385,10 @@ function registerAnnotationsRoute(app, deps) {
|
|
|
22924
23385
|
}
|
|
22925
23386
|
|
|
22926
23387
|
// server/routes/contributions.ts
|
|
22927
|
-
import { HTTPException as
|
|
23388
|
+
import { HTTPException as HTTPException3 } from "hono/http-exception";
|
|
22928
23389
|
|
|
22929
23390
|
// server/util/parse-query.ts
|
|
22930
|
-
import { HTTPException } from "hono/http-exception";
|
|
23391
|
+
import { HTTPException as HTTPException2 } from "hono/http-exception";
|
|
22931
23392
|
function parseCsv(value) {
|
|
22932
23393
|
if (value === void 0) return [];
|
|
22933
23394
|
return value.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
@@ -22936,7 +23397,7 @@ function parsePagination(query, defaults) {
|
|
|
22936
23397
|
const offset = parseNonNegativeInt(query.offset, "offset", 0);
|
|
22937
23398
|
const limit = parseNonNegativeInt(query.limit, "limit", defaults.limit);
|
|
22938
23399
|
if (limit > defaults.max) {
|
|
22939
|
-
throw new
|
|
23400
|
+
throw new HTTPException2(400, {
|
|
22940
23401
|
message: tx(SERVER_TEXTS.paginationLimitTooLarge, {
|
|
22941
23402
|
value: limit,
|
|
22942
23403
|
max: defaults.max
|
|
@@ -22950,7 +23411,7 @@ function parseBooleanFlag(value) {
|
|
|
22950
23411
|
}
|
|
22951
23412
|
function parseRequiredString(value, name) {
|
|
22952
23413
|
if (typeof value !== "string" || value.length === 0) {
|
|
22953
|
-
throw new
|
|
23414
|
+
throw new HTTPException2(400, {
|
|
22954
23415
|
message: tx(SERVER_TEXTS.queryRequiredString, { name })
|
|
22955
23416
|
});
|
|
22956
23417
|
}
|
|
@@ -22961,7 +23422,7 @@ function parseNonNegativeInt(raw, name, fallback) {
|
|
|
22961
23422
|
const trimmed = raw.trim();
|
|
22962
23423
|
const parsed = Number.parseInt(trimmed, 10);
|
|
22963
23424
|
if (!Number.isInteger(parsed) || parsed < 0 || String(parsed) !== trimmed) {
|
|
22964
|
-
throw new
|
|
23425
|
+
throw new HTTPException2(400, {
|
|
22965
23426
|
message: tx(SERVER_TEXTS.paginationInvalidInteger, { name, value: raw })
|
|
22966
23427
|
});
|
|
22967
23428
|
}
|
|
@@ -22972,7 +23433,7 @@ function parseNonNegativeInt(raw, name, fallback) {
|
|
|
22972
23433
|
var QUALIFIED_ID_SEGMENT = /^[A-Za-z0-9._-]+$/;
|
|
22973
23434
|
function parseQualifiedIdSegment(value, name) {
|
|
22974
23435
|
if (!QUALIFIED_ID_SEGMENT.test(value)) {
|
|
22975
|
-
throw new
|
|
23436
|
+
throw new HTTPException3(400, {
|
|
22976
23437
|
message: tx(SERVER_TEXTS.qualifiedIdMalformed, {
|
|
22977
23438
|
name,
|
|
22978
23439
|
value: sanitizeForTerminal(value)
|
|
@@ -23002,7 +23463,7 @@ function registerContributionsRoutes(app, deps) {
|
|
|
23002
23463
|
(e) => e.pluginId === pluginId && e.extensionId === extensionId && e.contributionId === contributionId
|
|
23003
23464
|
);
|
|
23004
23465
|
if (!catalogEntry) {
|
|
23005
|
-
throw new
|
|
23466
|
+
throw new HTTPException3(404, {
|
|
23006
23467
|
message: tx(SERVER_TEXTS.contributionUnknown, {
|
|
23007
23468
|
pluginId: sanitizeForTerminal(pluginId),
|
|
23008
23469
|
extensionId: sanitizeForTerminal(extensionId),
|
|
@@ -23033,7 +23494,7 @@ function registerContributionsRoutes(app, deps) {
|
|
|
23033
23494
|
}
|
|
23034
23495
|
|
|
23035
23496
|
// server/routes/config.ts
|
|
23036
|
-
import { HTTPException as
|
|
23497
|
+
import { HTTPException as HTTPException4 } from "hono/http-exception";
|
|
23037
23498
|
|
|
23038
23499
|
// server/envelope.ts
|
|
23039
23500
|
var REST_ENVELOPE_SCHEMA_VERSION = "1";
|
|
@@ -23072,7 +23533,7 @@ function registerConfigRoute(app, deps) {
|
|
|
23072
23533
|
try {
|
|
23073
23534
|
loaded = deps.configService.get();
|
|
23074
23535
|
} catch (err) {
|
|
23075
|
-
throw new
|
|
23536
|
+
throw new HTTPException4(500, { message: formatErrorMessage(err) });
|
|
23076
23537
|
}
|
|
23077
23538
|
for (const warn of loaded.warnings) {
|
|
23078
23539
|
log.warn(sanitizeForTerminal(warn));
|
|
@@ -23090,7 +23551,7 @@ function registerConfigRoute(app, deps) {
|
|
|
23090
23551
|
}
|
|
23091
23552
|
|
|
23092
23553
|
// server/routes/favorites.ts
|
|
23093
|
-
import { HTTPException as
|
|
23554
|
+
import { HTTPException as HTTPException5 } from "hono/http-exception";
|
|
23094
23555
|
|
|
23095
23556
|
// server/path-codec.ts
|
|
23096
23557
|
var PathCodecError = class extends Error {
|
|
@@ -23130,7 +23591,7 @@ function registerFavoritesRoutes(app, deps) {
|
|
|
23130
23591
|
}
|
|
23131
23592
|
);
|
|
23132
23593
|
if (!result || !result.found) {
|
|
23133
|
-
throw new
|
|
23594
|
+
throw new HTTPException5(404, {
|
|
23134
23595
|
message: tx(SERVER_TEXTS.nodeNotFound, { path: sanitizeForTerminal(nodePath) })
|
|
23135
23596
|
});
|
|
23136
23597
|
}
|
|
@@ -23150,14 +23611,14 @@ function decodePath(pathB64) {
|
|
|
23150
23611
|
return decodeNodePath(pathB64);
|
|
23151
23612
|
} catch (err) {
|
|
23152
23613
|
if (err instanceof PathCodecError) {
|
|
23153
|
-
throw new
|
|
23614
|
+
throw new HTTPException5(404, { message: SERVER_TEXTS.pathB64Malformed });
|
|
23154
23615
|
}
|
|
23155
23616
|
throw err;
|
|
23156
23617
|
}
|
|
23157
23618
|
}
|
|
23158
23619
|
|
|
23159
23620
|
// server/routes/graph.ts
|
|
23160
|
-
import { HTTPException as
|
|
23621
|
+
import { HTTPException as HTTPException6 } from "hono/http-exception";
|
|
23161
23622
|
var DEFAULT_FORMAT2 = "ascii";
|
|
23162
23623
|
var FORMAT_ID_PATTERN = /^[a-z0-9-]+$/;
|
|
23163
23624
|
var FORMAT_ID_MAX = 32;
|
|
@@ -23165,7 +23626,7 @@ function registerGraphRoute(app, deps) {
|
|
|
23165
23626
|
app.get("/api/graph", async (c) => {
|
|
23166
23627
|
const format = c.req.query("format") ?? DEFAULT_FORMAT2;
|
|
23167
23628
|
if (format.length > FORMAT_ID_MAX || !FORMAT_ID_PATTERN.test(format)) {
|
|
23168
|
-
throw new
|
|
23629
|
+
throw new HTTPException6(400, {
|
|
23169
23630
|
// Sanitize defensively, the regex above already rejects ANSI
|
|
23170
23631
|
// and control bytes, but the message interpolates user input
|
|
23171
23632
|
// and the BFF mirrors error envelopes into the server log.
|
|
@@ -23181,7 +23642,7 @@ function registerGraphRoute(app, deps) {
|
|
|
23181
23642
|
const formatter = formatters.find((f) => f.formatId === format);
|
|
23182
23643
|
if (!formatter) {
|
|
23183
23644
|
const available = formatters.map((f) => f.formatId).sort().join(", ");
|
|
23184
|
-
throw new
|
|
23645
|
+
throw new HTTPException6(400, {
|
|
23185
23646
|
message: tx(SERVER_TEXTS.graphUnknownFormat, {
|
|
23186
23647
|
format,
|
|
23187
23648
|
available: available || "(none)"
|
|
@@ -23354,7 +23815,7 @@ function registerLinksRoute(app, deps) {
|
|
|
23354
23815
|
}
|
|
23355
23816
|
|
|
23356
23817
|
// server/routes/nodes.ts
|
|
23357
|
-
import { HTTPException as
|
|
23818
|
+
import { HTTPException as HTTPException7 } from "hono/http-exception";
|
|
23358
23819
|
|
|
23359
23820
|
// server/node-body.ts
|
|
23360
23821
|
import { constants as fsConstants2 } from "fs";
|
|
@@ -23465,7 +23926,7 @@ function registerNodesRoutes(app, deps) {
|
|
|
23465
23926
|
nodePath = decodeNodePath(pathB64);
|
|
23466
23927
|
} catch (err) {
|
|
23467
23928
|
if (err instanceof PathCodecError) {
|
|
23468
|
-
throw new
|
|
23929
|
+
throw new HTTPException7(404, { message: SERVER_TEXTS.pathB64Malformed });
|
|
23469
23930
|
}
|
|
23470
23931
|
throw err;
|
|
23471
23932
|
}
|
|
@@ -23497,7 +23958,7 @@ function registerNodesRoutes(app, deps) {
|
|
|
23497
23958
|
const contributions = result?.contributions ?? [];
|
|
23498
23959
|
const tags = result?.tags ?? [];
|
|
23499
23960
|
if (!bundle) {
|
|
23500
|
-
throw new
|
|
23961
|
+
throw new HTTPException7(404, {
|
|
23501
23962
|
message: tx(SERVER_TEXTS.nodeNotFound, { path: nodePath })
|
|
23502
23963
|
});
|
|
23503
23964
|
}
|
|
@@ -23607,11 +24068,11 @@ async function groupContributionsByPath(rows) {
|
|
|
23607
24068
|
}
|
|
23608
24069
|
|
|
23609
24070
|
// server/routes/plugins.ts
|
|
23610
|
-
import { HTTPException as
|
|
24071
|
+
import { HTTPException as HTTPException9 } from "hono/http-exception";
|
|
23611
24072
|
|
|
23612
24073
|
// server/util/parse-body.ts
|
|
23613
24074
|
import { Ajv2020 as Ajv20207 } from "ajv/dist/2020.js";
|
|
23614
|
-
import { HTTPException as
|
|
24075
|
+
import { HTTPException as HTTPException8 } from "hono/http-exception";
|
|
23615
24076
|
function makeBodyValidator(schema, messages) {
|
|
23616
24077
|
const ajv = new Ajv20207({ strict: false, allErrors: false });
|
|
23617
24078
|
const validate = ajv.compile(schema);
|
|
@@ -23620,16 +24081,16 @@ function makeBodyValidator(schema, messages) {
|
|
|
23620
24081
|
try {
|
|
23621
24082
|
raw = await req.json();
|
|
23622
24083
|
} catch {
|
|
23623
|
-
throw new
|
|
24084
|
+
throw new HTTPException8(400, { message: messages.notJson });
|
|
23624
24085
|
}
|
|
23625
24086
|
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
|
|
23626
|
-
throw new
|
|
24087
|
+
throw new HTTPException8(400, { message: messages.notObject });
|
|
23627
24088
|
}
|
|
23628
24089
|
if (validate(raw)) {
|
|
23629
24090
|
return raw;
|
|
23630
24091
|
}
|
|
23631
24092
|
const message = resolveErrorMessage(validate.errors, messages);
|
|
23632
|
-
throw new
|
|
24093
|
+
throw new HTTPException8(400, { message });
|
|
23633
24094
|
};
|
|
23634
24095
|
}
|
|
23635
24096
|
function resolveErrorMessage(errors, messages) {
|
|
@@ -23730,18 +24191,18 @@ function registerPluginsRoute(app, deps) {
|
|
|
23730
24191
|
app.patch("/api/plugins/:id", async (c) => {
|
|
23731
24192
|
const id = c.req.param("id");
|
|
23732
24193
|
if (id.includes("/")) {
|
|
23733
|
-
throw new
|
|
24194
|
+
throw new HTTPException9(400, {
|
|
23734
24195
|
message: tx(SERVER_TEXTS.pluginsCascadeRouteQualifiedRejected, { id })
|
|
23735
24196
|
});
|
|
23736
24197
|
}
|
|
23737
24198
|
const handle = findHandle(id, deps);
|
|
23738
24199
|
if (!handle) {
|
|
23739
|
-
throw new
|
|
24200
|
+
throw new HTTPException9(404, {
|
|
23740
24201
|
message: tx(SERVER_TEXTS.pluginsUnknown, { id })
|
|
23741
24202
|
});
|
|
23742
24203
|
}
|
|
23743
24204
|
if (isPluginLocked(id)) {
|
|
23744
|
-
throw new
|
|
24205
|
+
throw new HTTPException9(403, {
|
|
23745
24206
|
message: tx(SERVER_TEXTS.pluginsLocked, { id })
|
|
23746
24207
|
});
|
|
23747
24208
|
}
|
|
@@ -23755,18 +24216,18 @@ function registerPluginsRoute(app, deps) {
|
|
|
23755
24216
|
const extensionId = c.req.param("extensionId");
|
|
23756
24217
|
const handle = findHandle(bundleId, deps);
|
|
23757
24218
|
if (!handle) {
|
|
23758
|
-
throw new
|
|
24219
|
+
throw new HTTPException9(404, {
|
|
23759
24220
|
message: tx(SERVER_TEXTS.pluginsUnknown, { id: bundleId })
|
|
23760
24221
|
});
|
|
23761
24222
|
}
|
|
23762
24223
|
if (!hasExtension(handle, extensionId)) {
|
|
23763
|
-
throw new
|
|
24224
|
+
throw new HTTPException9(404, {
|
|
23764
24225
|
message: tx(SERVER_TEXTS.pluginsExtensionUnknown, { bundleId, extensionId })
|
|
23765
24226
|
});
|
|
23766
24227
|
}
|
|
23767
24228
|
const qualified = qualifiedExtensionId(bundleId, extensionId);
|
|
23768
24229
|
if (isPluginLocked(qualified) || isPluginLocked(bundleId)) {
|
|
23769
|
-
throw new
|
|
24230
|
+
throw new HTTPException9(403, {
|
|
23770
24231
|
message: tx(SERVER_TEXTS.pluginsExtensionLocked, { bundleId, extensionId })
|
|
23771
24232
|
});
|
|
23772
24233
|
}
|
|
@@ -24042,7 +24503,7 @@ function hasExtension(handle, extensionId) {
|
|
|
24042
24503
|
}
|
|
24043
24504
|
|
|
24044
24505
|
// server/routes/preferences.ts
|
|
24045
|
-
import { HTTPException as
|
|
24506
|
+
import { HTTPException as HTTPException10 } from "hono/http-exception";
|
|
24046
24507
|
function registerPreferencesRoute(app, _deps) {
|
|
24047
24508
|
app.get("/api/preferences", (c) => {
|
|
24048
24509
|
return c.json(buildEnvelope());
|
|
@@ -24055,20 +24516,43 @@ function registerPreferencesRoute(app, _deps) {
|
|
|
24055
24516
|
}
|
|
24056
24517
|
function buildEnvelope() {
|
|
24057
24518
|
return {
|
|
24058
|
-
updateCheck: { enabled: isUpdateCheckEnabled() }
|
|
24519
|
+
updateCheck: { enabled: isUpdateCheckEnabled() },
|
|
24520
|
+
telemetry: {
|
|
24521
|
+
errorsEnabled: isErrorTelemetryEnabled(),
|
|
24522
|
+
usageCliEnabled: isUsageCliTelemetryEnabled(),
|
|
24523
|
+
usageUiEnabled: isUsageUiTelemetryEnabled(),
|
|
24524
|
+
anonymousId: readAnonymousId(),
|
|
24525
|
+
environment: resolveTelemetryEnv()
|
|
24526
|
+
}
|
|
24059
24527
|
};
|
|
24060
24528
|
}
|
|
24061
24529
|
function applyPatch(body) {
|
|
24062
|
-
|
|
24063
|
-
|
|
24530
|
+
try {
|
|
24531
|
+
if (body.updateCheck && typeof body.updateCheck.enabled === "boolean") {
|
|
24064
24532
|
writeUserSettings({ updateCheck: { enabled: body.updateCheck.enabled } });
|
|
24065
|
-
} catch (err) {
|
|
24066
|
-
throw new HTTPException9(400, {
|
|
24067
|
-
message: tx(SERVER_TEXTS.preferencesPersistFailed, {
|
|
24068
|
-
message: formatErrorMessage(err)
|
|
24069
|
-
})
|
|
24070
|
-
});
|
|
24071
24533
|
}
|
|
24534
|
+
if (body.telemetry) {
|
|
24535
|
+
applyTelemetryPatch(body.telemetry);
|
|
24536
|
+
}
|
|
24537
|
+
} catch (err) {
|
|
24538
|
+
throw new HTTPException10(400, {
|
|
24539
|
+
message: tx(SERVER_TEXTS.preferencesPersistFailed, {
|
|
24540
|
+
message: formatErrorMessage(err)
|
|
24541
|
+
})
|
|
24542
|
+
});
|
|
24543
|
+
}
|
|
24544
|
+
}
|
|
24545
|
+
function applyTelemetryPatch(t) {
|
|
24546
|
+
if (typeof t.errorsEnabled === "boolean") {
|
|
24547
|
+
writeUserSettings({ telemetry: { errorsEnabled: t.errorsEnabled } });
|
|
24548
|
+
}
|
|
24549
|
+
if (typeof t.usageCliEnabled === "boolean") {
|
|
24550
|
+
writeUserSettings({ telemetry: { usageCliEnabled: t.usageCliEnabled } });
|
|
24551
|
+
if (t.usageCliEnabled) ensureAnonymousId();
|
|
24552
|
+
}
|
|
24553
|
+
if (typeof t.usageUiEnabled === "boolean") {
|
|
24554
|
+
writeUserSettings({ telemetry: { usageUiEnabled: t.usageUiEnabled } });
|
|
24555
|
+
if (t.usageUiEnabled) ensureAnonymousId();
|
|
24072
24556
|
}
|
|
24073
24557
|
}
|
|
24074
24558
|
var PATCH_BODY_SCHEMA = {
|
|
@@ -24082,6 +24566,15 @@ var PATCH_BODY_SCHEMA = {
|
|
|
24082
24566
|
properties: {
|
|
24083
24567
|
enabled: { type: "boolean" }
|
|
24084
24568
|
}
|
|
24569
|
+
},
|
|
24570
|
+
telemetry: {
|
|
24571
|
+
type: "object",
|
|
24572
|
+
additionalProperties: false,
|
|
24573
|
+
properties: {
|
|
24574
|
+
errorsEnabled: { type: "boolean" },
|
|
24575
|
+
usageCliEnabled: { type: "boolean" },
|
|
24576
|
+
usageUiEnabled: { type: "boolean" }
|
|
24577
|
+
}
|
|
24085
24578
|
}
|
|
24086
24579
|
}
|
|
24087
24580
|
};
|
|
@@ -24092,12 +24585,16 @@ var parsePatchBody2 = makeBodyValidator(PATCH_BODY_SCHEMA, {
|
|
|
24092
24585
|
mapping: {
|
|
24093
24586
|
":minProperties": SERVER_TEXTS.preferencesBodyEmpty,
|
|
24094
24587
|
"/updateCheck:type:object": SERVER_TEXTS.preferencesUpdateCheckNotObject,
|
|
24095
|
-
"/updateCheck/enabled:type:boolean": SERVER_TEXTS.preferencesUpdateCheckEnabledNotBoolean
|
|
24588
|
+
"/updateCheck/enabled:type:boolean": SERVER_TEXTS.preferencesUpdateCheckEnabledNotBoolean,
|
|
24589
|
+
"/telemetry:type:object": SERVER_TEXTS.preferencesTelemetryNotObject,
|
|
24590
|
+
"/telemetry/errorsEnabled:type:boolean": SERVER_TEXTS.preferencesTelemetryErrorsEnabledNotBoolean,
|
|
24591
|
+
"/telemetry/usageCliEnabled:type:boolean": SERVER_TEXTS.preferencesTelemetryUsageCliEnabledNotBoolean,
|
|
24592
|
+
"/telemetry/usageUiEnabled:type:boolean": SERVER_TEXTS.preferencesTelemetryUsageUiEnabledNotBoolean
|
|
24096
24593
|
}
|
|
24097
24594
|
});
|
|
24098
24595
|
|
|
24099
24596
|
// server/routes/project-ignore.ts
|
|
24100
|
-
import { HTTPException as
|
|
24597
|
+
import { HTTPException as HTTPException11 } from "hono/http-exception";
|
|
24101
24598
|
|
|
24102
24599
|
// server/util/skillmapignore-io.ts
|
|
24103
24600
|
import { existsSync as existsSync26, readFileSync as readFileSync17, writeFileSync as writeFileSync2 } from "fs";
|
|
@@ -24184,12 +24681,12 @@ async function applyPatch2(deps, body) {
|
|
|
24184
24681
|
for (const raw of body.patterns) {
|
|
24185
24682
|
const t = raw.trim();
|
|
24186
24683
|
if (t.length === 0) {
|
|
24187
|
-
throw new
|
|
24684
|
+
throw new HTTPException11(400, {
|
|
24188
24685
|
message: SERVER_TEXTS.projectIgnorePatternEmpty
|
|
24189
24686
|
});
|
|
24190
24687
|
}
|
|
24191
24688
|
if (seen.has(t)) {
|
|
24192
|
-
throw new
|
|
24689
|
+
throw new HTTPException11(400, {
|
|
24193
24690
|
message: tx(SERVER_TEXTS.projectIgnorePatternDuplicate, { pattern: t })
|
|
24194
24691
|
});
|
|
24195
24692
|
}
|
|
@@ -24200,7 +24697,7 @@ async function applyPatch2(deps, body) {
|
|
|
24200
24697
|
try {
|
|
24201
24698
|
writePatterns(cwd, trimmed);
|
|
24202
24699
|
} catch (err) {
|
|
24203
|
-
throw new
|
|
24700
|
+
throw new HTTPException11(400, {
|
|
24204
24701
|
message: tx(SERVER_TEXTS.projectIgnorePersistFailed, {
|
|
24205
24702
|
message: formatErrorMessage(err)
|
|
24206
24703
|
})
|
|
@@ -24278,7 +24775,7 @@ var parsePatchBody3 = makeBodyValidator(PATCH_BODY_SCHEMA2, {
|
|
|
24278
24775
|
|
|
24279
24776
|
// server/routes/project-preferences.ts
|
|
24280
24777
|
import { statSync as statSync9 } from "fs";
|
|
24281
|
-
import { HTTPException as
|
|
24778
|
+
import { HTTPException as HTTPException12 } from "hono/http-exception";
|
|
24282
24779
|
function registerProjectPreferencesRoute(app, deps) {
|
|
24283
24780
|
app.get("/api/project-preferences", (c) => {
|
|
24284
24781
|
return c.json(buildEnvelope3(deps));
|
|
@@ -24306,7 +24803,7 @@ async function applyPatch3(deps, body) {
|
|
|
24306
24803
|
const cwd = deps.runtimeContext.cwd;
|
|
24307
24804
|
const missingPaths = collectMissingPaths(writes, cwd);
|
|
24308
24805
|
if (missingPaths.length > 0) {
|
|
24309
|
-
throw new
|
|
24806
|
+
throw new HTTPException12(400, {
|
|
24310
24807
|
message: tx(SERVER_TEXTS.projectPrefsPathNotFound, {
|
|
24311
24808
|
paths: missingPaths.join(", ")
|
|
24312
24809
|
})
|
|
@@ -24315,7 +24812,7 @@ async function applyPatch3(deps, body) {
|
|
|
24315
24812
|
const exposures = writes.map((w) => projectPathExposure({ key: w.key, value: w.value, cwd })).filter((e) => e.expandsSurface);
|
|
24316
24813
|
if (exposures.length > 0 && body.confirm !== true) {
|
|
24317
24814
|
const exposed = exposures.flatMap((e) => e.exposedPaths);
|
|
24318
|
-
throw new
|
|
24815
|
+
throw new HTTPException12(412, {
|
|
24319
24816
|
message: tx(SERVER_TEXTS.projectPrefsConfirmRequired, {
|
|
24320
24817
|
paths: exposed.join(", ")
|
|
24321
24818
|
})
|
|
@@ -24367,7 +24864,7 @@ function runWrite(w, cwd) {
|
|
|
24367
24864
|
try {
|
|
24368
24865
|
writeConfigValue(w.key, w.value, { target: "project-local", cwd });
|
|
24369
24866
|
} catch (err) {
|
|
24370
|
-
throw new
|
|
24867
|
+
throw new HTTPException12(400, {
|
|
24371
24868
|
message: tx(SERVER_TEXTS.projectPrefsPersistFailed, {
|
|
24372
24869
|
key: w.key,
|
|
24373
24870
|
message: formatErrorMessage(err)
|
|
@@ -24467,7 +24964,7 @@ var parsePatchBody4 = makeBodyValidator(PATCH_BODY_SCHEMA3, {
|
|
|
24467
24964
|
|
|
24468
24965
|
// server/routes/active-provider.ts
|
|
24469
24966
|
import { existsSync as existsSync27 } from "fs";
|
|
24470
|
-
import { HTTPException as
|
|
24967
|
+
import { HTTPException as HTTPException13 } from "hono/http-exception";
|
|
24471
24968
|
function registerActiveProviderRoute(app, deps) {
|
|
24472
24969
|
app.get("/api/active-provider", (c) => {
|
|
24473
24970
|
return c.json(buildEnvelope4(deps));
|
|
@@ -24492,7 +24989,7 @@ function applyLensSwitch(deps, newValue) {
|
|
|
24492
24989
|
try {
|
|
24493
24990
|
writeConfigValue("activeProvider", newValue, { target: "project", cwd });
|
|
24494
24991
|
} catch (err) {
|
|
24495
|
-
throw new
|
|
24992
|
+
throw new HTTPException13(400, {
|
|
24496
24993
|
message: tx(SERVER_TEXTS.activeProviderPersistFailed, {
|
|
24497
24994
|
message: formatErrorMessage(err)
|
|
24498
24995
|
})
|
|
@@ -24528,7 +25025,7 @@ var parsePatchBody5 = makeBodyValidator(PATCH_BODY_SCHEMA4, {
|
|
|
24528
25025
|
});
|
|
24529
25026
|
|
|
24530
25027
|
// server/routes/scan.ts
|
|
24531
|
-
import { HTTPException as
|
|
25028
|
+
import { HTTPException as HTTPException14 } from "hono/http-exception";
|
|
24532
25029
|
|
|
24533
25030
|
// server/scan-mutex.ts
|
|
24534
25031
|
var inFlight = null;
|
|
@@ -24694,7 +25191,7 @@ function registerScanRoute(app, deps) {
|
|
|
24694
25191
|
}
|
|
24695
25192
|
async function runPersistedScan(c, deps) {
|
|
24696
25193
|
if (deps.options.noBuiltIns || deps.options.noPlugins) {
|
|
24697
|
-
throw new
|
|
25194
|
+
throw new HTTPException14(400, { message: SERVER_TEXTS.scanPostRequiresFullPipeline });
|
|
24698
25195
|
}
|
|
24699
25196
|
const dbExists = await tryWithSqlite(
|
|
24700
25197
|
{ databasePath: deps.options.dbPath, autoBackup: false },
|
|
@@ -24731,7 +25228,7 @@ async function runPersistedScan(c, deps) {
|
|
|
24731
25228
|
...deps.options.maxNodes !== void 0 ? { maxNodes: deps.options.maxNodes } : {}
|
|
24732
25229
|
});
|
|
24733
25230
|
if (outcome.kind !== "ok") {
|
|
24734
|
-
throw new
|
|
25231
|
+
throw new HTTPException14(500, {
|
|
24735
25232
|
message: outcome.kind === "guard-trip" ? tx(SERVER_TEXTS.scanGuardTrip, { existing: outcome.existing }) : outcome.message
|
|
24736
25233
|
});
|
|
24737
25234
|
}
|
|
@@ -24739,7 +25236,7 @@ async function runPersistedScan(c, deps) {
|
|
|
24739
25236
|
});
|
|
24740
25237
|
} catch (err) {
|
|
24741
25238
|
if (err instanceof ScanBusyError) {
|
|
24742
|
-
throw new
|
|
25239
|
+
throw new HTTPException14(409, { message: SERVER_TEXTS.scanPostBusy });
|
|
24743
25240
|
}
|
|
24744
25241
|
throw err;
|
|
24745
25242
|
}
|
|
@@ -24800,7 +25297,7 @@ function groupTagsByPath2(rows) {
|
|
|
24800
25297
|
}
|
|
24801
25298
|
async function runFreshScan(deps) {
|
|
24802
25299
|
if (deps.options.noBuiltIns || deps.options.noPlugins) {
|
|
24803
|
-
throw new
|
|
25300
|
+
throw new HTTPException14(400, { message: SERVER_TEXTS.freshScanRequiresPipeline });
|
|
24804
25301
|
}
|
|
24805
25302
|
const resolveEnabledOverride = await buildBffResolverOverride(deps);
|
|
24806
25303
|
const outcome = await runScanForCommand({
|
|
@@ -24835,7 +25332,7 @@ async function runFreshScan(deps) {
|
|
|
24835
25332
|
...deps.options.maxNodes !== void 0 ? { maxNodes: deps.options.maxNodes } : {}
|
|
24836
25333
|
});
|
|
24837
25334
|
if (outcome.kind !== "ok") {
|
|
24838
|
-
throw new
|
|
25335
|
+
throw new HTTPException14(500, {
|
|
24839
25336
|
message: outcome.kind === "guard-trip" ? tx(SERVER_TEXTS.freshScanGuardTrip, { existing: outcome.existing }) : outcome.message
|
|
24840
25337
|
});
|
|
24841
25338
|
}
|
|
@@ -24875,7 +25372,7 @@ function emptyScanResult() {
|
|
|
24875
25372
|
}
|
|
24876
25373
|
|
|
24877
25374
|
// server/routes/sidecar.ts
|
|
24878
|
-
import { HTTPException as
|
|
25375
|
+
import { HTTPException as HTTPException15 } from "hono/http-exception";
|
|
24879
25376
|
import { resolve as resolve36 } from "path";
|
|
24880
25377
|
var STATUS_FRESH = "fresh";
|
|
24881
25378
|
var ENVELOPE_KIND2 = "sidecar.bumped";
|
|
@@ -24912,11 +25409,11 @@ function registerSidecarRoutes(app, deps) {
|
|
|
24912
25409
|
assertContained(deps.runtimeContext.cwd, node.path);
|
|
24913
25410
|
absPath = resolve36(deps.runtimeContext.cwd, node.path);
|
|
24914
25411
|
} catch (err) {
|
|
24915
|
-
throw new
|
|
25412
|
+
throw new HTTPException15(400, { message: formatErrorMessage(err) });
|
|
24916
25413
|
}
|
|
24917
25414
|
const result = invokeBump2(node, absPath, body);
|
|
24918
25415
|
if (result.report.ok === false && result.report.reason === "fresh") {
|
|
24919
|
-
throw new
|
|
25416
|
+
throw new HTTPException15(409, { message: SERVER_TEXTS.sidecarFreshRefusal });
|
|
24920
25417
|
}
|
|
24921
25418
|
if (result.report.ok === true && result.report.noop === true) {
|
|
24922
25419
|
const envelope2 = {
|
|
@@ -24943,7 +25440,7 @@ function registerSidecarRoutes(app, deps) {
|
|
|
24943
25440
|
}
|
|
24944
25441
|
} catch (err) {
|
|
24945
25442
|
if (err instanceof EConsentRequiredError) throw err;
|
|
24946
|
-
throw new
|
|
25443
|
+
throw new HTTPException15(500, { message: formatErrorMessage(err) });
|
|
24947
25444
|
}
|
|
24948
25445
|
if (body.confirm === true) {
|
|
24949
25446
|
deps.configService.reload();
|
|
@@ -24980,7 +25477,7 @@ async function loadNode(deps, nodePath) {
|
|
|
24980
25477
|
);
|
|
24981
25478
|
const node = persisted?.nodes.find((n) => n.path === nodePath);
|
|
24982
25479
|
if (!node) {
|
|
24983
|
-
throw new
|
|
25480
|
+
throw new HTTPException15(404, {
|
|
24984
25481
|
message: tx(SERVER_TEXTS.nodeNotFound, { path: sanitizeForTerminal(nodePath) })
|
|
24985
25482
|
});
|
|
24986
25483
|
}
|
|
@@ -24988,7 +25485,7 @@ async function loadNode(deps, nodePath) {
|
|
|
24988
25485
|
}
|
|
24989
25486
|
function invokeBump2(node, absPath, body) {
|
|
24990
25487
|
if (!nodeBumpAction.invoke) {
|
|
24991
|
-
throw new
|
|
25488
|
+
throw new HTTPException15(500, { message: SERVER_TEXTS.sidecarBumpInvokeMissing });
|
|
24992
25489
|
}
|
|
24993
25490
|
const input = {};
|
|
24994
25491
|
if (body.force === true) input.force = true;
|
|
@@ -25175,13 +25672,13 @@ function attachBroadcasterRoute(app, broadcaster) {
|
|
|
25175
25672
|
|
|
25176
25673
|
// server/app.ts
|
|
25177
25674
|
var BODY_LIMIT_BYTES = 1024 * 1024;
|
|
25178
|
-
var DbMissingError = class extends
|
|
25675
|
+
var DbMissingError = class extends HTTPException16 {
|
|
25179
25676
|
constructor(message) {
|
|
25180
25677
|
super(500, { message });
|
|
25181
25678
|
this.name = "DbMissingError";
|
|
25182
25679
|
}
|
|
25183
25680
|
};
|
|
25184
|
-
var BulkValidationError = class extends
|
|
25681
|
+
var BulkValidationError = class extends HTTPException16 {
|
|
25185
25682
|
id;
|
|
25186
25683
|
code;
|
|
25187
25684
|
constructor(init) {
|
|
@@ -25191,7 +25688,7 @@ var BulkValidationError = class extends HTTPException15 {
|
|
|
25191
25688
|
this.code = init.code;
|
|
25192
25689
|
}
|
|
25193
25690
|
};
|
|
25194
|
-
var LoopbackGateError = class extends
|
|
25691
|
+
var LoopbackGateError = class extends HTTPException16 {
|
|
25195
25692
|
code;
|
|
25196
25693
|
constructor(init) {
|
|
25197
25694
|
super(403, { message: init.message });
|
|
@@ -25204,6 +25701,7 @@ function createApp(deps) {
|
|
|
25204
25701
|
const configService = new ConfigService({
|
|
25205
25702
|
cwd: deps.runtimeContext.cwd
|
|
25206
25703
|
});
|
|
25704
|
+
app.use("*", createSentryRequestCapture());
|
|
25207
25705
|
app.use("*", createLoopbackGate({ port: deps.options.port }));
|
|
25208
25706
|
app.use("*", createSecurityHeaders());
|
|
25209
25707
|
app.use(
|
|
@@ -25211,7 +25709,7 @@ function createApp(deps) {
|
|
|
25211
25709
|
bodyLimit({
|
|
25212
25710
|
maxSize: BODY_LIMIT_BYTES,
|
|
25213
25711
|
onError: () => {
|
|
25214
|
-
throw new
|
|
25712
|
+
throw new HTTPException16(413, { message: tx(SERVER_TEXTS.bodyTooLarge, { maxBytes: String(BODY_LIMIT_BYTES) }) });
|
|
25215
25713
|
}
|
|
25216
25714
|
})
|
|
25217
25715
|
);
|
|
@@ -25257,7 +25755,7 @@ function createApp(deps) {
|
|
|
25257
25755
|
registerActiveProviderRoute(app, routeDeps);
|
|
25258
25756
|
registerProjectIgnoreRoute(app, routeDeps);
|
|
25259
25757
|
app.all("/api/*", (c) => {
|
|
25260
|
-
throw new
|
|
25758
|
+
throw new HTTPException16(404, {
|
|
25261
25759
|
message: tx(SERVER_TEXTS.unknownApiEndpoint, { path: sanitizeForTerminal(c.req.path) })
|
|
25262
25760
|
});
|
|
25263
25761
|
});
|
|
@@ -25265,7 +25763,7 @@ function createApp(deps) {
|
|
|
25265
25763
|
app.use("*", createStaticHandler({ uiDist: deps.options.uiDist, noUi: deps.options.noUi }));
|
|
25266
25764
|
app.get("*", createSpaFallback({ uiDist: deps.options.uiDist, noUi: deps.options.noUi }));
|
|
25267
25765
|
app.notFound((c) => {
|
|
25268
|
-
throw new
|
|
25766
|
+
throw new HTTPException16(404, {
|
|
25269
25767
|
message: tx(SERVER_TEXTS.unknownPath, { path: sanitizeForTerminal(c.req.path) })
|
|
25270
25768
|
});
|
|
25271
25769
|
});
|
|
@@ -25320,7 +25818,7 @@ function formatError2(err, c) {
|
|
|
25320
25818
|
};
|
|
25321
25819
|
return c.json(envelope, 403);
|
|
25322
25820
|
}
|
|
25323
|
-
if (err instanceof
|
|
25821
|
+
if (err instanceof HTTPException16) {
|
|
25324
25822
|
const status = err.status;
|
|
25325
25823
|
const envelope = {
|
|
25326
25824
|
ok: false,
|
|
@@ -25419,7 +25917,7 @@ var WsBroadcaster = class {
|
|
|
25419
25917
|
* stop the rest from receiving the event. A failing socket is closed
|
|
25420
25918
|
* + unregistered so the next broadcast doesn't waste cycles on it.
|
|
25421
25919
|
*
|
|
25422
|
-
* Backpressure check (per
|
|
25920
|
+
* Backpressure check (per context/kernel.md §Kernel boundaries): if a
|
|
25423
25921
|
* client's `bufferedAmount` exceeds `MAX_BUFFERED_BYTES`, it's evicted
|
|
25424
25922
|
* with close code 1009. The check runs BEFORE `send` so the threshold
|
|
25425
25923
|
* acts as an admission gate, not a post-mortem.
|
|
@@ -25439,8 +25937,8 @@ var WsBroadcaster = class {
|
|
|
25439
25937
|
return;
|
|
25440
25938
|
}
|
|
25441
25939
|
const snapshot = Array.from(this.#clients);
|
|
25442
|
-
for (const
|
|
25443
|
-
this.#deliver(
|
|
25940
|
+
for (const client2 of snapshot) {
|
|
25941
|
+
this.#deliver(client2, payload);
|
|
25444
25942
|
}
|
|
25445
25943
|
}
|
|
25446
25944
|
/**
|
|
@@ -25454,9 +25952,9 @@ var WsBroadcaster = class {
|
|
|
25454
25952
|
this.#shutDown = true;
|
|
25455
25953
|
const snapshot = Array.from(this.#clients);
|
|
25456
25954
|
this.#clients.clear();
|
|
25457
|
-
for (const
|
|
25955
|
+
for (const client2 of snapshot) {
|
|
25458
25956
|
try {
|
|
25459
|
-
|
|
25957
|
+
client2.close(CLOSE_CODE_GOING_AWAY, "server shutdown");
|
|
25460
25958
|
} catch {
|
|
25461
25959
|
}
|
|
25462
25960
|
}
|
|
@@ -25465,31 +25963,31 @@ var WsBroadcaster = class {
|
|
|
25465
25963
|
* Per-client delivery: backpressure check, then `send()`. Eviction +
|
|
25466
25964
|
* unregistration on either failure mode.
|
|
25467
25965
|
*/
|
|
25468
|
-
#deliver(
|
|
25469
|
-
if (
|
|
25470
|
-
this.#clients.delete(
|
|
25966
|
+
#deliver(client2, payload) {
|
|
25967
|
+
if (client2.readyState !== READY_STATE_OPEN) {
|
|
25968
|
+
this.#clients.delete(client2);
|
|
25471
25969
|
return;
|
|
25472
25970
|
}
|
|
25473
|
-
if (
|
|
25474
|
-
this.#clients.delete(
|
|
25971
|
+
if (client2.bufferedAmount > MAX_BUFFERED_BYTES) {
|
|
25972
|
+
this.#clients.delete(client2);
|
|
25475
25973
|
try {
|
|
25476
|
-
|
|
25974
|
+
client2.close(CLOSE_CODE_MESSAGE_TOO_BIG, "backpressure exceeded");
|
|
25477
25975
|
} catch {
|
|
25478
25976
|
}
|
|
25479
25977
|
log.warn(
|
|
25480
25978
|
tx(SERVER_TEXTS.wsBackpressureEvicted, {
|
|
25481
|
-
buffered: String(
|
|
25979
|
+
buffered: String(client2.bufferedAmount),
|
|
25482
25980
|
threshold: String(MAX_BUFFERED_BYTES)
|
|
25483
25981
|
})
|
|
25484
25982
|
);
|
|
25485
25983
|
return;
|
|
25486
25984
|
}
|
|
25487
25985
|
try {
|
|
25488
|
-
|
|
25986
|
+
client2.send(payload);
|
|
25489
25987
|
} catch (err) {
|
|
25490
|
-
this.#clients.delete(
|
|
25988
|
+
this.#clients.delete(client2);
|
|
25491
25989
|
try {
|
|
25492
|
-
|
|
25990
|
+
client2.close();
|
|
25493
25991
|
} catch {
|
|
25494
25992
|
}
|
|
25495
25993
|
const message = formatErrorMessage(err);
|
|
@@ -26250,7 +26748,7 @@ var ServeCommand = class extends SmCommand {
|
|
|
26250
26748
|
emitElapsed = false;
|
|
26251
26749
|
// CLI orchestrator with multi-flag handling, each `if (this.flag)`
|
|
26252
26750
|
// branch is one cyclomatic point. Splitting per branch scatters the
|
|
26253
|
-
// validation away from the flag it gates. Per
|
|
26751
|
+
// validation away from the flag it gates. Per context/lint.md
|
|
26254
26752
|
// category 1 ("CLI orchestrators with multi-flag handling").
|
|
26255
26753
|
// eslint-disable-next-line complexity
|
|
26256
26754
|
async run() {
|
|
@@ -26353,6 +26851,7 @@ var ServeCommand = class extends SmCommand {
|
|
|
26353
26851
|
this.printer.info(formatValidationError(validation.error, stderrAnsi));
|
|
26354
26852
|
return ExitCode.Error;
|
|
26355
26853
|
}
|
|
26854
|
+
await initSentryBff(VERSION);
|
|
26356
26855
|
let handle;
|
|
26357
26856
|
try {
|
|
26358
26857
|
handle = await createServer(validation.options);
|
|
@@ -27822,6 +28321,7 @@ cli.register(RootHelpCommand);
|
|
|
27822
28321
|
cli.register(HelpCommand);
|
|
27823
28322
|
cli.register(InitCommand);
|
|
27824
28323
|
cli.register(TutorialCommand);
|
|
28324
|
+
cli.register(IntentionalFailCommand);
|
|
27825
28325
|
cli.register(ScanCommand);
|
|
27826
28326
|
cli.register(ScanCompareCommand);
|
|
27827
28327
|
cli.register(ServeCommand);
|
|
@@ -27855,6 +28355,13 @@ var logLevel = resolveLogLevel({
|
|
|
27855
28355
|
configureLogger(new Logger({ level: logLevel, stream: process.stderr }));
|
|
27856
28356
|
var bareArgs = resolveBareInvocation(args);
|
|
27857
28357
|
var routedArgs = routeHelpArgs(bareArgs ?? args, cli);
|
|
28358
|
+
var telemetryVerb = routedArgs[0];
|
|
28359
|
+
await maybeRunFirstRunPrompt();
|
|
28360
|
+
if (telemetryVerb !== "serve") {
|
|
28361
|
+
await initSentryCli(VERSION);
|
|
28362
|
+
setTelemetryVerbTag(telemetryVerb);
|
|
28363
|
+
await initUsageCli();
|
|
28364
|
+
}
|
|
27858
28365
|
var lifecycleDispatcher = makeHookDispatcher(
|
|
27859
28366
|
builtIns().hooks ?? [],
|
|
27860
28367
|
new InMemoryProgressEmitter()
|
|
@@ -27891,10 +28398,18 @@ var exitCode = await cli.run(routedArgs, {
|
|
|
27891
28398
|
stdout: process.stdout,
|
|
27892
28399
|
stderr: process.stderr
|
|
27893
28400
|
});
|
|
28401
|
+
if (telemetryVerb !== void 0 && telemetryVerb !== "") {
|
|
28402
|
+
const knownVerbs = new Set(
|
|
28403
|
+
registeredVerbPaths(cli).map((path) => path[0]).filter((token) => token !== void 0)
|
|
28404
|
+
);
|
|
28405
|
+
captureCliInvocation(telemetryVerb, extractFlagNames(routedArgs.slice(1)), knownVerbs);
|
|
28406
|
+
}
|
|
27894
28407
|
await lifecycleDispatcher.dispatch(
|
|
27895
28408
|
"shutdown",
|
|
27896
28409
|
makeEvent("shutdown", { exitCode })
|
|
27897
28410
|
);
|
|
28411
|
+
await closeSentryCli();
|
|
28412
|
+
await flushUsageCli();
|
|
27898
28413
|
process.exit(exitCode);
|
|
27899
28414
|
function resolveBareInvocation(rawArgs) {
|
|
27900
28415
|
if (rawArgs.length === 0) return resolveBareDefault();
|