@massu/core 1.15.1 → 1.15.3
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/CHANGELOG.md +25 -0
- package/dist/cli.js +977 -572
- package/dist/hooks/auto-learning-pipeline.js +90 -19
- package/dist/hooks/classify-failure.js +112 -43
- package/dist/hooks/cost-tracker.js +108 -39
- package/dist/hooks/fix-detector.js +95 -24
- package/dist/hooks/incident-pipeline.js +114 -45
- package/dist/hooks/post-edit-context.js +105 -36
- package/dist/hooks/post-tool-use.js +137 -68
- package/dist/hooks/pre-compact.js +108 -39
- package/dist/hooks/pre-delete-check.js +107 -38
- package/dist/hooks/pre-tool-use-gate.js +113 -44
- package/dist/hooks/quality-event.js +108 -39
- package/dist/hooks/rule-enforcement-pipeline.js +92 -21
- package/dist/hooks/session-end.js +126 -57
- package/dist/hooks/session-start.js +165 -96
- package/dist/hooks/user-prompt.js +124 -55
- package/package.json +1 -1
|
@@ -4,12 +4,12 @@ import{createRequire as __cr}from"module";const require=__cr(import.meta.url);
|
|
|
4
4
|
// src/memory-db.ts
|
|
5
5
|
import Database from "better-sqlite3";
|
|
6
6
|
import { dirname as dirname2, basename } from "path";
|
|
7
|
-
import { existsSync as
|
|
7
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2 } from "fs";
|
|
8
8
|
|
|
9
9
|
// src/config.ts
|
|
10
|
-
import { resolve, dirname } from "path";
|
|
11
|
-
import { existsSync, readFileSync } from "fs";
|
|
12
|
-
import { homedir } from "os";
|
|
10
|
+
import { resolve as resolve2, dirname } from "path";
|
|
11
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
12
|
+
import { homedir as homedir2 } from "os";
|
|
13
13
|
import { parse as parseYaml } from "yaml";
|
|
14
14
|
import { z } from "zod";
|
|
15
15
|
|
|
@@ -18,6 +18,68 @@ function encodeMemoryDirName(projectRoot) {
|
|
|
18
18
|
return projectRoot.replace(/\//g, "-");
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
// src/credentials.ts
|
|
22
|
+
import { homedir } from "os";
|
|
23
|
+
import { resolve } from "path";
|
|
24
|
+
import {
|
|
25
|
+
existsSync,
|
|
26
|
+
readFileSync,
|
|
27
|
+
writeFileSync,
|
|
28
|
+
mkdirSync,
|
|
29
|
+
rmSync,
|
|
30
|
+
chmodSync
|
|
31
|
+
} from "fs";
|
|
32
|
+
var MASSU_ENV_API_KEY = "MASSU_API_KEY";
|
|
33
|
+
var MASSU_ENV_CLOUD_ENDPOINT = "MASSU_CLOUD_ENDPOINT";
|
|
34
|
+
var DEFAULT_CLOUD_ENDPOINT = "https://api.massu.ai/v1";
|
|
35
|
+
function credentialsDir(home = homedir()) {
|
|
36
|
+
return resolve(home, ".massu");
|
|
37
|
+
}
|
|
38
|
+
function credentialsPath(home = homedir()) {
|
|
39
|
+
return resolve(credentialsDir(home), "credentials");
|
|
40
|
+
}
|
|
41
|
+
function readUserCredentials(home = homedir()) {
|
|
42
|
+
try {
|
|
43
|
+
const p = credentialsPath(home);
|
|
44
|
+
if (!existsSync(p)) return void 0;
|
|
45
|
+
const parsed = JSON.parse(readFileSync(p, "utf-8"));
|
|
46
|
+
const key = typeof parsed?.apiKey === "string" ? parsed.apiKey.trim() : "";
|
|
47
|
+
return key.length > 0 ? key : void 0;
|
|
48
|
+
} catch {
|
|
49
|
+
return void 0;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function isUnresolvedLiteral(v) {
|
|
53
|
+
return /^\$\{[^}]+\}$/.test(v);
|
|
54
|
+
}
|
|
55
|
+
function resolveApiKey(opts = {}) {
|
|
56
|
+
const env = opts.env ?? process.env;
|
|
57
|
+
const home = opts.home ?? homedir();
|
|
58
|
+
const cfg = typeof opts.configApiKey === "string" ? opts.configApiKey.trim() : "";
|
|
59
|
+
if (cfg.length > 0 && !isUnresolvedLiteral(cfg)) {
|
|
60
|
+
return { apiKey: cfg, source: "config" };
|
|
61
|
+
}
|
|
62
|
+
const envRaw = env[MASSU_ENV_API_KEY];
|
|
63
|
+
const envKey = typeof envRaw === "string" ? envRaw.trim() : "";
|
|
64
|
+
if (envKey.length > 0) {
|
|
65
|
+
return { apiKey: envKey, source: "env" };
|
|
66
|
+
}
|
|
67
|
+
const fileKey = readUserCredentials(home);
|
|
68
|
+
if (fileKey) {
|
|
69
|
+
return { apiKey: fileKey, source: "user-file" };
|
|
70
|
+
}
|
|
71
|
+
return { source: "none" };
|
|
72
|
+
}
|
|
73
|
+
function resolveEndpoint(opts = {}) {
|
|
74
|
+
const env = opts.env ?? process.env;
|
|
75
|
+
const cfg = typeof opts.configEndpoint === "string" ? opts.configEndpoint.trim() : "";
|
|
76
|
+
if (cfg.length > 0) return cfg;
|
|
77
|
+
const envRaw = env[MASSU_ENV_CLOUD_ENDPOINT];
|
|
78
|
+
const envEp = typeof envRaw === "string" ? envRaw.trim() : "";
|
|
79
|
+
if (envEp.length > 0) return envEp;
|
|
80
|
+
return DEFAULT_CLOUD_ENDPOINT;
|
|
81
|
+
}
|
|
82
|
+
|
|
21
83
|
// src/config.ts
|
|
22
84
|
var DomainConfigSchema = z.object({
|
|
23
85
|
name: z.string().default("Unknown"),
|
|
@@ -400,12 +462,13 @@ var RawConfigSchema = z.object({
|
|
|
400
462
|
lsp: LSPConfigSchema.optional()
|
|
401
463
|
}).passthrough();
|
|
402
464
|
var _config = null;
|
|
465
|
+
var _resolvedApiKeySource = "none";
|
|
403
466
|
var _projectRoot = null;
|
|
404
467
|
function findProjectRoot() {
|
|
405
468
|
const cwd = process.cwd();
|
|
406
469
|
let dir = cwd;
|
|
407
470
|
while (true) {
|
|
408
|
-
if (
|
|
471
|
+
if (existsSync2(resolve2(dir, "massu.config.yaml"))) {
|
|
409
472
|
return dir;
|
|
410
473
|
}
|
|
411
474
|
const parent = dirname(dir);
|
|
@@ -414,10 +477,10 @@ function findProjectRoot() {
|
|
|
414
477
|
}
|
|
415
478
|
dir = cwd;
|
|
416
479
|
while (true) {
|
|
417
|
-
if (
|
|
480
|
+
if (existsSync2(resolve2(dir, "package.json"))) {
|
|
418
481
|
return dir;
|
|
419
482
|
}
|
|
420
|
-
if (
|
|
483
|
+
if (existsSync2(resolve2(dir, ".git"))) {
|
|
421
484
|
return dir;
|
|
422
485
|
}
|
|
423
486
|
const parent = dirname(dir);
|
|
@@ -435,10 +498,10 @@ function getProjectRoot() {
|
|
|
435
498
|
function getConfig() {
|
|
436
499
|
if (_config) return _config;
|
|
437
500
|
const root = getProjectRoot();
|
|
438
|
-
const configPath =
|
|
501
|
+
const configPath = resolve2(root, "massu.config.yaml");
|
|
439
502
|
let rawYaml = {};
|
|
440
|
-
if (
|
|
441
|
-
const content =
|
|
503
|
+
if (existsSync2(configPath)) {
|
|
504
|
+
const content = readFileSync2(configPath, "utf-8");
|
|
442
505
|
rawYaml = parseYaml(content) ?? {};
|
|
443
506
|
}
|
|
444
507
|
const result = RawConfigSchema.safeParse(rawYaml);
|
|
@@ -455,7 +518,7 @@ Hint: run \`massu config refresh\` to regenerate a valid config or fix the liste
|
|
|
455
518
|
);
|
|
456
519
|
}
|
|
457
520
|
const parsed = result.data;
|
|
458
|
-
const projectRoot = parsed.project.root === "auto" || !parsed.project.root ? root :
|
|
521
|
+
const projectRoot = parsed.project.root === "auto" || !parsed.project.root ? root : resolve2(root, parsed.project.root);
|
|
459
522
|
const fw = parsed.framework;
|
|
460
523
|
let router = fw.router;
|
|
461
524
|
let orm = fw.orm;
|
|
@@ -513,13 +576,19 @@ Hint: run \`massu config refresh\` to regenerate a valid config or fix the liste
|
|
|
513
576
|
telemetry: parsed.telemetry,
|
|
514
577
|
lsp: parsed.lsp
|
|
515
578
|
};
|
|
516
|
-
|
|
579
|
+
const resolvedKey = resolveApiKey({ configApiKey: _config.cloud?.apiKey });
|
|
580
|
+
_resolvedApiKeySource = resolvedKey.source;
|
|
581
|
+
const resolvedEndpoint = resolveEndpoint({ configEndpoint: _config.cloud?.endpoint });
|
|
582
|
+
if (resolvedKey.apiKey) {
|
|
517
583
|
_config.cloud = {
|
|
518
584
|
enabled: true,
|
|
519
585
|
sync: { memory: true, analytics: true, audit: true },
|
|
520
586
|
..._config.cloud,
|
|
521
|
-
apiKey:
|
|
587
|
+
apiKey: resolvedKey.apiKey,
|
|
588
|
+
endpoint: resolvedEndpoint
|
|
522
589
|
};
|
|
590
|
+
} else if (_config.cloud) {
|
|
591
|
+
_config.cloud = { ..._config.cloud, endpoint: _config.cloud.endpoint ?? resolvedEndpoint };
|
|
523
592
|
}
|
|
524
593
|
return _config;
|
|
525
594
|
}
|
|
@@ -528,34 +597,34 @@ function getResolvedPaths() {
|
|
|
528
597
|
const root = getProjectRoot();
|
|
529
598
|
const claudeDirName = config.conventions?.claudeDirName ?? ".claude";
|
|
530
599
|
return {
|
|
531
|
-
codegraphDbPath:
|
|
532
|
-
dataDbPath:
|
|
533
|
-
prismaSchemaPath:
|
|
534
|
-
rootRouterPath:
|
|
535
|
-
routersDir:
|
|
536
|
-
srcDir:
|
|
600
|
+
codegraphDbPath: resolve2(root, ".codegraph/codegraph.db"),
|
|
601
|
+
dataDbPath: resolve2(root, ".massu/data.db"),
|
|
602
|
+
prismaSchemaPath: resolve2(root, config.paths.schema ?? "prisma/schema.prisma"),
|
|
603
|
+
rootRouterPath: resolve2(root, config.paths.routerRoot ?? "src/server/api/root.ts"),
|
|
604
|
+
routersDir: resolve2(root, config.paths.routers ?? "src/server/api/routers"),
|
|
605
|
+
srcDir: resolve2(root, config.paths.source),
|
|
537
606
|
pathAlias: Object.fromEntries(
|
|
538
607
|
Object.entries(config.paths.aliases).map(([alias, target]) => [
|
|
539
608
|
alias,
|
|
540
|
-
|
|
609
|
+
resolve2(root, target)
|
|
541
610
|
])
|
|
542
611
|
),
|
|
543
612
|
extensions: [".ts", ".tsx", ".js", ".jsx"],
|
|
544
613
|
indexFiles: ["index.ts", "index.tsx", "index.js", "index.jsx"],
|
|
545
|
-
patternsDir:
|
|
546
|
-
claudeMdPath:
|
|
547
|
-
docsMapPath:
|
|
548
|
-
helpSitePath:
|
|
549
|
-
memoryDbPath:
|
|
550
|
-
knowledgeDbPath:
|
|
551
|
-
plansDir:
|
|
552
|
-
docsDir:
|
|
553
|
-
claudeDir:
|
|
554
|
-
memoryDir:
|
|
555
|
-
sessionStatePath:
|
|
556
|
-
sessionArchivePath:
|
|
557
|
-
mcpJsonPath:
|
|
558
|
-
settingsLocalPath:
|
|
614
|
+
patternsDir: resolve2(root, claudeDirName, "patterns"),
|
|
615
|
+
claudeMdPath: resolve2(root, claudeDirName, "CLAUDE.md"),
|
|
616
|
+
docsMapPath: resolve2(root, ".massu/docs-map.json"),
|
|
617
|
+
helpSitePath: resolve2(root, "../" + config.project.name + "-help"),
|
|
618
|
+
memoryDbPath: resolve2(root, ".massu/memory.db"),
|
|
619
|
+
knowledgeDbPath: resolve2(root, ".massu/knowledge.db"),
|
|
620
|
+
plansDir: resolve2(root, "docs/plans"),
|
|
621
|
+
docsDir: resolve2(root, "docs"),
|
|
622
|
+
claudeDir: resolve2(root, claudeDirName),
|
|
623
|
+
memoryDir: resolve2(homedir2(), claudeDirName, "projects", encodeMemoryDirName(root), "memory"),
|
|
624
|
+
sessionStatePath: resolve2(root, config.conventions?.sessionStatePath ?? `${claudeDirName}/session-state/CURRENT.md`),
|
|
625
|
+
sessionArchivePath: resolve2(root, config.conventions?.sessionArchivePath ?? `${claudeDirName}/session-state/archive`),
|
|
626
|
+
mcpJsonPath: resolve2(root, ".mcp.json"),
|
|
627
|
+
settingsLocalPath: resolve2(root, claudeDirName, "settings.local.json")
|
|
559
628
|
};
|
|
560
629
|
}
|
|
561
630
|
|
|
@@ -563,8 +632,8 @@ function getResolvedPaths() {
|
|
|
563
632
|
function getMemoryDb() {
|
|
564
633
|
const dbPath = getResolvedPaths().memoryDbPath;
|
|
565
634
|
const dir = dirname2(dbPath);
|
|
566
|
-
if (!
|
|
567
|
-
|
|
635
|
+
if (!existsSync3(dir)) {
|
|
636
|
+
mkdirSync2(dir, { recursive: true });
|
|
568
637
|
}
|
|
569
638
|
const db = new Database(dbPath);
|
|
570
639
|
db.pragma("journal_mode = WAL");
|
|
@@ -1274,14 +1343,14 @@ async function main() {
|
|
|
1274
1343
|
process.exit(0);
|
|
1275
1344
|
}
|
|
1276
1345
|
function readStdin() {
|
|
1277
|
-
return new Promise((
|
|
1346
|
+
return new Promise((resolve4) => {
|
|
1278
1347
|
let data = "";
|
|
1279
1348
|
process.stdin.setEncoding("utf-8");
|
|
1280
1349
|
process.stdin.on("data", (chunk) => {
|
|
1281
1350
|
data += chunk;
|
|
1282
1351
|
});
|
|
1283
|
-
process.stdin.on("end", () =>
|
|
1284
|
-
setTimeout(() =>
|
|
1352
|
+
process.stdin.on("end", () => resolve4(data));
|
|
1353
|
+
setTimeout(() => resolve4(data), 3e3);
|
|
1285
1354
|
});
|
|
1286
1355
|
}
|
|
1287
1356
|
main();
|
|
@@ -2,14 +2,78 @@
|
|
|
2
2
|
import{createRequire as __cr}from"module";const require=__cr(import.meta.url);
|
|
3
3
|
|
|
4
4
|
// src/hooks/rule-enforcement-pipeline.ts
|
|
5
|
-
import { existsSync as
|
|
6
|
-
import { basename, resolve as
|
|
5
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, readdirSync } from "fs";
|
|
6
|
+
import { basename, resolve as resolve3 } from "path";
|
|
7
7
|
|
|
8
8
|
// src/config.ts
|
|
9
|
-
import { resolve, dirname } from "path";
|
|
10
|
-
import { existsSync, readFileSync } from "fs";
|
|
9
|
+
import { resolve as resolve2, dirname } from "path";
|
|
10
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
11
11
|
import { parse as parseYaml } from "yaml";
|
|
12
12
|
import { z } from "zod";
|
|
13
|
+
|
|
14
|
+
// src/credentials.ts
|
|
15
|
+
import { homedir } from "os";
|
|
16
|
+
import { resolve } from "path";
|
|
17
|
+
import {
|
|
18
|
+
existsSync,
|
|
19
|
+
readFileSync,
|
|
20
|
+
writeFileSync,
|
|
21
|
+
mkdirSync,
|
|
22
|
+
rmSync,
|
|
23
|
+
chmodSync
|
|
24
|
+
} from "fs";
|
|
25
|
+
var MASSU_ENV_API_KEY = "MASSU_API_KEY";
|
|
26
|
+
var MASSU_ENV_CLOUD_ENDPOINT = "MASSU_CLOUD_ENDPOINT";
|
|
27
|
+
var DEFAULT_CLOUD_ENDPOINT = "https://api.massu.ai/v1";
|
|
28
|
+
function credentialsDir(home = homedir()) {
|
|
29
|
+
return resolve(home, ".massu");
|
|
30
|
+
}
|
|
31
|
+
function credentialsPath(home = homedir()) {
|
|
32
|
+
return resolve(credentialsDir(home), "credentials");
|
|
33
|
+
}
|
|
34
|
+
function readUserCredentials(home = homedir()) {
|
|
35
|
+
try {
|
|
36
|
+
const p = credentialsPath(home);
|
|
37
|
+
if (!existsSync(p)) return void 0;
|
|
38
|
+
const parsed = JSON.parse(readFileSync(p, "utf-8"));
|
|
39
|
+
const key = typeof parsed?.apiKey === "string" ? parsed.apiKey.trim() : "";
|
|
40
|
+
return key.length > 0 ? key : void 0;
|
|
41
|
+
} catch {
|
|
42
|
+
return void 0;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function isUnresolvedLiteral(v) {
|
|
46
|
+
return /^\$\{[^}]+\}$/.test(v);
|
|
47
|
+
}
|
|
48
|
+
function resolveApiKey(opts = {}) {
|
|
49
|
+
const env = opts.env ?? process.env;
|
|
50
|
+
const home = opts.home ?? homedir();
|
|
51
|
+
const cfg = typeof opts.configApiKey === "string" ? opts.configApiKey.trim() : "";
|
|
52
|
+
if (cfg.length > 0 && !isUnresolvedLiteral(cfg)) {
|
|
53
|
+
return { apiKey: cfg, source: "config" };
|
|
54
|
+
}
|
|
55
|
+
const envRaw = env[MASSU_ENV_API_KEY];
|
|
56
|
+
const envKey = typeof envRaw === "string" ? envRaw.trim() : "";
|
|
57
|
+
if (envKey.length > 0) {
|
|
58
|
+
return { apiKey: envKey, source: "env" };
|
|
59
|
+
}
|
|
60
|
+
const fileKey = readUserCredentials(home);
|
|
61
|
+
if (fileKey) {
|
|
62
|
+
return { apiKey: fileKey, source: "user-file" };
|
|
63
|
+
}
|
|
64
|
+
return { source: "none" };
|
|
65
|
+
}
|
|
66
|
+
function resolveEndpoint(opts = {}) {
|
|
67
|
+
const env = opts.env ?? process.env;
|
|
68
|
+
const cfg = typeof opts.configEndpoint === "string" ? opts.configEndpoint.trim() : "";
|
|
69
|
+
if (cfg.length > 0) return cfg;
|
|
70
|
+
const envRaw = env[MASSU_ENV_CLOUD_ENDPOINT];
|
|
71
|
+
const envEp = typeof envRaw === "string" ? envRaw.trim() : "";
|
|
72
|
+
if (envEp.length > 0) return envEp;
|
|
73
|
+
return DEFAULT_CLOUD_ENDPOINT;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// src/config.ts
|
|
13
77
|
var DomainConfigSchema = z.object({
|
|
14
78
|
name: z.string().default("Unknown"),
|
|
15
79
|
routers: z.array(z.string()).default([]),
|
|
@@ -391,12 +455,13 @@ var RawConfigSchema = z.object({
|
|
|
391
455
|
lsp: LSPConfigSchema.optional()
|
|
392
456
|
}).passthrough();
|
|
393
457
|
var _config = null;
|
|
458
|
+
var _resolvedApiKeySource = "none";
|
|
394
459
|
var _projectRoot = null;
|
|
395
460
|
function findProjectRoot() {
|
|
396
461
|
const cwd = process.cwd();
|
|
397
462
|
let dir = cwd;
|
|
398
463
|
while (true) {
|
|
399
|
-
if (
|
|
464
|
+
if (existsSync2(resolve2(dir, "massu.config.yaml"))) {
|
|
400
465
|
return dir;
|
|
401
466
|
}
|
|
402
467
|
const parent = dirname(dir);
|
|
@@ -405,10 +470,10 @@ function findProjectRoot() {
|
|
|
405
470
|
}
|
|
406
471
|
dir = cwd;
|
|
407
472
|
while (true) {
|
|
408
|
-
if (
|
|
473
|
+
if (existsSync2(resolve2(dir, "package.json"))) {
|
|
409
474
|
return dir;
|
|
410
475
|
}
|
|
411
|
-
if (
|
|
476
|
+
if (existsSync2(resolve2(dir, ".git"))) {
|
|
412
477
|
return dir;
|
|
413
478
|
}
|
|
414
479
|
const parent = dirname(dir);
|
|
@@ -426,10 +491,10 @@ function getProjectRoot() {
|
|
|
426
491
|
function getConfig() {
|
|
427
492
|
if (_config) return _config;
|
|
428
493
|
const root = getProjectRoot();
|
|
429
|
-
const configPath =
|
|
494
|
+
const configPath = resolve2(root, "massu.config.yaml");
|
|
430
495
|
let rawYaml = {};
|
|
431
|
-
if (
|
|
432
|
-
const content =
|
|
496
|
+
if (existsSync2(configPath)) {
|
|
497
|
+
const content = readFileSync2(configPath, "utf-8");
|
|
433
498
|
rawYaml = parseYaml(content) ?? {};
|
|
434
499
|
}
|
|
435
500
|
const result = RawConfigSchema.safeParse(rawYaml);
|
|
@@ -446,7 +511,7 @@ Hint: run \`massu config refresh\` to regenerate a valid config or fix the liste
|
|
|
446
511
|
);
|
|
447
512
|
}
|
|
448
513
|
const parsed = result.data;
|
|
449
|
-
const projectRoot = parsed.project.root === "auto" || !parsed.project.root ? root :
|
|
514
|
+
const projectRoot = parsed.project.root === "auto" || !parsed.project.root ? root : resolve2(root, parsed.project.root);
|
|
450
515
|
const fw = parsed.framework;
|
|
451
516
|
let router = fw.router;
|
|
452
517
|
let orm = fw.orm;
|
|
@@ -504,13 +569,19 @@ Hint: run \`massu config refresh\` to regenerate a valid config or fix the liste
|
|
|
504
569
|
telemetry: parsed.telemetry,
|
|
505
570
|
lsp: parsed.lsp
|
|
506
571
|
};
|
|
507
|
-
|
|
572
|
+
const resolvedKey = resolveApiKey({ configApiKey: _config.cloud?.apiKey });
|
|
573
|
+
_resolvedApiKeySource = resolvedKey.source;
|
|
574
|
+
const resolvedEndpoint = resolveEndpoint({ configEndpoint: _config.cloud?.endpoint });
|
|
575
|
+
if (resolvedKey.apiKey) {
|
|
508
576
|
_config.cloud = {
|
|
509
577
|
enabled: true,
|
|
510
578
|
sync: { memory: true, analytics: true, audit: true },
|
|
511
579
|
..._config.cloud,
|
|
512
|
-
apiKey:
|
|
580
|
+
apiKey: resolvedKey.apiKey,
|
|
581
|
+
endpoint: resolvedEndpoint
|
|
513
582
|
};
|
|
583
|
+
} else if (_config.cloud) {
|
|
584
|
+
_config.cloud = { ..._config.cloud, endpoint: _config.cloud.endpoint ?? resolvedEndpoint };
|
|
514
585
|
}
|
|
515
586
|
return _config;
|
|
516
587
|
}
|
|
@@ -549,7 +620,7 @@ async function main() {
|
|
|
549
620
|
process.exit(0);
|
|
550
621
|
return;
|
|
551
622
|
}
|
|
552
|
-
if (!
|
|
623
|
+
if (!existsSync3(filePath)) {
|
|
553
624
|
process.exit(0);
|
|
554
625
|
return;
|
|
555
626
|
}
|
|
@@ -557,18 +628,18 @@ async function main() {
|
|
|
557
628
|
process.exit(0);
|
|
558
629
|
return;
|
|
559
630
|
}
|
|
560
|
-
const content =
|
|
631
|
+
const content = readFileSync3(filePath, "utf-8");
|
|
561
632
|
const nameMatch = content.match(/^name:\s*(.+)/m);
|
|
562
633
|
const descMatch = content.match(/^description:\s*(.+)/m);
|
|
563
634
|
const ruleName = nameMatch?.[1]?.trim() ?? fileName;
|
|
564
635
|
const ruleDesc = descMatch?.[1]?.trim() ?? "";
|
|
565
|
-
const enforcementDirAbs =
|
|
636
|
+
const enforcementDirAbs = resolve3(root, enforcementDir);
|
|
566
637
|
let hasEnforcement = false;
|
|
567
|
-
if (
|
|
638
|
+
if (existsSync3(enforcementDirAbs)) {
|
|
568
639
|
const hookFiles = readdirSync(enforcementDirAbs).filter((f) => f.endsWith(".sh") || f.endsWith(".ts") || f.endsWith(".js"));
|
|
569
640
|
for (const hookFile of hookFiles) {
|
|
570
641
|
try {
|
|
571
|
-
const hookContent =
|
|
642
|
+
const hookContent = readFileSync3(resolve3(enforcementDirAbs, hookFile), "utf-8");
|
|
572
643
|
if (hookContent.includes(fileName)) {
|
|
573
644
|
hasEnforcement = true;
|
|
574
645
|
break;
|
|
@@ -624,14 +695,14 @@ async function main() {
|
|
|
624
695
|
process.exit(0);
|
|
625
696
|
}
|
|
626
697
|
function readStdin() {
|
|
627
|
-
return new Promise((
|
|
698
|
+
return new Promise((resolve4) => {
|
|
628
699
|
let data = "";
|
|
629
700
|
process.stdin.setEncoding("utf-8");
|
|
630
701
|
process.stdin.on("data", (chunk) => {
|
|
631
702
|
data += chunk;
|
|
632
703
|
});
|
|
633
|
-
process.stdin.on("end", () =>
|
|
634
|
-
setTimeout(() =>
|
|
704
|
+
process.stdin.on("end", () => resolve4(data));
|
|
705
|
+
setTimeout(() => resolve4(data), 3e3);
|
|
635
706
|
});
|
|
636
707
|
}
|
|
637
708
|
main();
|