@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
|
@@ -3,12 +3,12 @@ import{createRequire as __cr}from"module";const require=__cr(import.meta.url);
|
|
|
3
3
|
|
|
4
4
|
// src/hooks/pre-delete-check.ts
|
|
5
5
|
import Database2 from "better-sqlite3";
|
|
6
|
-
import { existsSync as
|
|
6
|
+
import { existsSync as existsSync3 } from "fs";
|
|
7
7
|
|
|
8
8
|
// src/config.ts
|
|
9
|
-
import { resolve, dirname } from "path";
|
|
10
|
-
import { existsSync, readFileSync } from "fs";
|
|
11
|
-
import { homedir } from "os";
|
|
9
|
+
import { resolve as resolve2, dirname } from "path";
|
|
10
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
11
|
+
import { homedir as homedir2 } from "os";
|
|
12
12
|
import { parse as parseYaml } from "yaml";
|
|
13
13
|
import { z } from "zod";
|
|
14
14
|
|
|
@@ -17,6 +17,68 @@ function encodeMemoryDirName(projectRoot) {
|
|
|
17
17
|
return projectRoot.replace(/\//g, "-");
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
// src/credentials.ts
|
|
21
|
+
import { homedir } from "os";
|
|
22
|
+
import { resolve } from "path";
|
|
23
|
+
import {
|
|
24
|
+
existsSync,
|
|
25
|
+
readFileSync,
|
|
26
|
+
writeFileSync,
|
|
27
|
+
mkdirSync,
|
|
28
|
+
rmSync,
|
|
29
|
+
chmodSync
|
|
30
|
+
} from "fs";
|
|
31
|
+
var MASSU_ENV_API_KEY = "MASSU_API_KEY";
|
|
32
|
+
var MASSU_ENV_CLOUD_ENDPOINT = "MASSU_CLOUD_ENDPOINT";
|
|
33
|
+
var DEFAULT_CLOUD_ENDPOINT = "https://api.massu.ai/v1";
|
|
34
|
+
function credentialsDir(home = homedir()) {
|
|
35
|
+
return resolve(home, ".massu");
|
|
36
|
+
}
|
|
37
|
+
function credentialsPath(home = homedir()) {
|
|
38
|
+
return resolve(credentialsDir(home), "credentials");
|
|
39
|
+
}
|
|
40
|
+
function readUserCredentials(home = homedir()) {
|
|
41
|
+
try {
|
|
42
|
+
const p = credentialsPath(home);
|
|
43
|
+
if (!existsSync(p)) return void 0;
|
|
44
|
+
const parsed = JSON.parse(readFileSync(p, "utf-8"));
|
|
45
|
+
const key = typeof parsed?.apiKey === "string" ? parsed.apiKey.trim() : "";
|
|
46
|
+
return key.length > 0 ? key : void 0;
|
|
47
|
+
} catch {
|
|
48
|
+
return void 0;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function isUnresolvedLiteral(v) {
|
|
52
|
+
return /^\$\{[^}]+\}$/.test(v);
|
|
53
|
+
}
|
|
54
|
+
function resolveApiKey(opts = {}) {
|
|
55
|
+
const env = opts.env ?? process.env;
|
|
56
|
+
const home = opts.home ?? homedir();
|
|
57
|
+
const cfg = typeof opts.configApiKey === "string" ? opts.configApiKey.trim() : "";
|
|
58
|
+
if (cfg.length > 0 && !isUnresolvedLiteral(cfg)) {
|
|
59
|
+
return { apiKey: cfg, source: "config" };
|
|
60
|
+
}
|
|
61
|
+
const envRaw = env[MASSU_ENV_API_KEY];
|
|
62
|
+
const envKey = typeof envRaw === "string" ? envRaw.trim() : "";
|
|
63
|
+
if (envKey.length > 0) {
|
|
64
|
+
return { apiKey: envKey, source: "env" };
|
|
65
|
+
}
|
|
66
|
+
const fileKey = readUserCredentials(home);
|
|
67
|
+
if (fileKey) {
|
|
68
|
+
return { apiKey: fileKey, source: "user-file" };
|
|
69
|
+
}
|
|
70
|
+
return { source: "none" };
|
|
71
|
+
}
|
|
72
|
+
function resolveEndpoint(opts = {}) {
|
|
73
|
+
const env = opts.env ?? process.env;
|
|
74
|
+
const cfg = typeof opts.configEndpoint === "string" ? opts.configEndpoint.trim() : "";
|
|
75
|
+
if (cfg.length > 0) return cfg;
|
|
76
|
+
const envRaw = env[MASSU_ENV_CLOUD_ENDPOINT];
|
|
77
|
+
const envEp = typeof envRaw === "string" ? envRaw.trim() : "";
|
|
78
|
+
if (envEp.length > 0) return envEp;
|
|
79
|
+
return DEFAULT_CLOUD_ENDPOINT;
|
|
80
|
+
}
|
|
81
|
+
|
|
20
82
|
// src/config.ts
|
|
21
83
|
var DomainConfigSchema = z.object({
|
|
22
84
|
name: z.string().default("Unknown"),
|
|
@@ -399,12 +461,13 @@ var RawConfigSchema = z.object({
|
|
|
399
461
|
lsp: LSPConfigSchema.optional()
|
|
400
462
|
}).passthrough();
|
|
401
463
|
var _config = null;
|
|
464
|
+
var _resolvedApiKeySource = "none";
|
|
402
465
|
var _projectRoot = null;
|
|
403
466
|
function findProjectRoot() {
|
|
404
467
|
const cwd = process.cwd();
|
|
405
468
|
let dir = cwd;
|
|
406
469
|
while (true) {
|
|
407
|
-
if (
|
|
470
|
+
if (existsSync2(resolve2(dir, "massu.config.yaml"))) {
|
|
408
471
|
return dir;
|
|
409
472
|
}
|
|
410
473
|
const parent = dirname(dir);
|
|
@@ -413,10 +476,10 @@ function findProjectRoot() {
|
|
|
413
476
|
}
|
|
414
477
|
dir = cwd;
|
|
415
478
|
while (true) {
|
|
416
|
-
if (
|
|
479
|
+
if (existsSync2(resolve2(dir, "package.json"))) {
|
|
417
480
|
return dir;
|
|
418
481
|
}
|
|
419
|
-
if (
|
|
482
|
+
if (existsSync2(resolve2(dir, ".git"))) {
|
|
420
483
|
return dir;
|
|
421
484
|
}
|
|
422
485
|
const parent = dirname(dir);
|
|
@@ -434,10 +497,10 @@ function getProjectRoot() {
|
|
|
434
497
|
function getConfig() {
|
|
435
498
|
if (_config) return _config;
|
|
436
499
|
const root = getProjectRoot();
|
|
437
|
-
const configPath =
|
|
500
|
+
const configPath = resolve2(root, "massu.config.yaml");
|
|
438
501
|
let rawYaml = {};
|
|
439
|
-
if (
|
|
440
|
-
const content =
|
|
502
|
+
if (existsSync2(configPath)) {
|
|
503
|
+
const content = readFileSync2(configPath, "utf-8");
|
|
441
504
|
rawYaml = parseYaml(content) ?? {};
|
|
442
505
|
}
|
|
443
506
|
const result = RawConfigSchema.safeParse(rawYaml);
|
|
@@ -454,7 +517,7 @@ Hint: run \`massu config refresh\` to regenerate a valid config or fix the liste
|
|
|
454
517
|
);
|
|
455
518
|
}
|
|
456
519
|
const parsed = result.data;
|
|
457
|
-
const projectRoot = parsed.project.root === "auto" || !parsed.project.root ? root :
|
|
520
|
+
const projectRoot = parsed.project.root === "auto" || !parsed.project.root ? root : resolve2(root, parsed.project.root);
|
|
458
521
|
const fw = parsed.framework;
|
|
459
522
|
let router = fw.router;
|
|
460
523
|
let orm = fw.orm;
|
|
@@ -512,13 +575,19 @@ Hint: run \`massu config refresh\` to regenerate a valid config or fix the liste
|
|
|
512
575
|
telemetry: parsed.telemetry,
|
|
513
576
|
lsp: parsed.lsp
|
|
514
577
|
};
|
|
515
|
-
|
|
578
|
+
const resolvedKey = resolveApiKey({ configApiKey: _config.cloud?.apiKey });
|
|
579
|
+
_resolvedApiKeySource = resolvedKey.source;
|
|
580
|
+
const resolvedEndpoint = resolveEndpoint({ configEndpoint: _config.cloud?.endpoint });
|
|
581
|
+
if (resolvedKey.apiKey) {
|
|
516
582
|
_config.cloud = {
|
|
517
583
|
enabled: true,
|
|
518
584
|
sync: { memory: true, analytics: true, audit: true },
|
|
519
585
|
..._config.cloud,
|
|
520
|
-
apiKey:
|
|
586
|
+
apiKey: resolvedKey.apiKey,
|
|
587
|
+
endpoint: resolvedEndpoint
|
|
521
588
|
};
|
|
589
|
+
} else if (_config.cloud) {
|
|
590
|
+
_config.cloud = { ..._config.cloud, endpoint: _config.cloud.endpoint ?? resolvedEndpoint };
|
|
522
591
|
}
|
|
523
592
|
return _config;
|
|
524
593
|
}
|
|
@@ -527,34 +596,34 @@ function getResolvedPaths() {
|
|
|
527
596
|
const root = getProjectRoot();
|
|
528
597
|
const claudeDirName = config.conventions?.claudeDirName ?? ".claude";
|
|
529
598
|
return {
|
|
530
|
-
codegraphDbPath:
|
|
531
|
-
dataDbPath:
|
|
532
|
-
prismaSchemaPath:
|
|
533
|
-
rootRouterPath:
|
|
534
|
-
routersDir:
|
|
535
|
-
srcDir:
|
|
599
|
+
codegraphDbPath: resolve2(root, ".codegraph/codegraph.db"),
|
|
600
|
+
dataDbPath: resolve2(root, ".massu/data.db"),
|
|
601
|
+
prismaSchemaPath: resolve2(root, config.paths.schema ?? "prisma/schema.prisma"),
|
|
602
|
+
rootRouterPath: resolve2(root, config.paths.routerRoot ?? "src/server/api/root.ts"),
|
|
603
|
+
routersDir: resolve2(root, config.paths.routers ?? "src/server/api/routers"),
|
|
604
|
+
srcDir: resolve2(root, config.paths.source),
|
|
536
605
|
pathAlias: Object.fromEntries(
|
|
537
606
|
Object.entries(config.paths.aliases).map(([alias, target]) => [
|
|
538
607
|
alias,
|
|
539
|
-
|
|
608
|
+
resolve2(root, target)
|
|
540
609
|
])
|
|
541
610
|
),
|
|
542
611
|
extensions: [".ts", ".tsx", ".js", ".jsx"],
|
|
543
612
|
indexFiles: ["index.ts", "index.tsx", "index.js", "index.jsx"],
|
|
544
|
-
patternsDir:
|
|
545
|
-
claudeMdPath:
|
|
546
|
-
docsMapPath:
|
|
547
|
-
helpSitePath:
|
|
548
|
-
memoryDbPath:
|
|
549
|
-
knowledgeDbPath:
|
|
550
|
-
plansDir:
|
|
551
|
-
docsDir:
|
|
552
|
-
claudeDir:
|
|
553
|
-
memoryDir:
|
|
554
|
-
sessionStatePath:
|
|
555
|
-
sessionArchivePath:
|
|
556
|
-
mcpJsonPath:
|
|
557
|
-
settingsLocalPath:
|
|
613
|
+
patternsDir: resolve2(root, claudeDirName, "patterns"),
|
|
614
|
+
claudeMdPath: resolve2(root, claudeDirName, "CLAUDE.md"),
|
|
615
|
+
docsMapPath: resolve2(root, ".massu/docs-map.json"),
|
|
616
|
+
helpSitePath: resolve2(root, "../" + config.project.name + "-help"),
|
|
617
|
+
memoryDbPath: resolve2(root, ".massu/memory.db"),
|
|
618
|
+
knowledgeDbPath: resolve2(root, ".massu/knowledge.db"),
|
|
619
|
+
plansDir: resolve2(root, "docs/plans"),
|
|
620
|
+
docsDir: resolve2(root, "docs"),
|
|
621
|
+
claudeDir: resolve2(root, claudeDirName),
|
|
622
|
+
memoryDir: resolve2(homedir2(), claudeDirName, "projects", encodeMemoryDirName(root), "memory"),
|
|
623
|
+
sessionStatePath: resolve2(root, config.conventions?.sessionStatePath ?? `${claudeDirName}/session-state/CURRENT.md`),
|
|
624
|
+
sessionArchivePath: resolve2(root, config.conventions?.sessionArchivePath ?? `${claudeDirName}/session-state/archive`),
|
|
625
|
+
mcpJsonPath: resolve2(root, ".mcp.json"),
|
|
626
|
+
settingsLocalPath: resolve2(root, claudeDirName, "settings.local.json")
|
|
558
627
|
};
|
|
559
628
|
}
|
|
560
629
|
|
|
@@ -662,7 +731,7 @@ var KNOWLEDGE_PROTECTED_FILES = [
|
|
|
662
731
|
];
|
|
663
732
|
function getDataDb() {
|
|
664
733
|
const dbPath = getResolvedPaths().dataDbPath;
|
|
665
|
-
if (!
|
|
734
|
+
if (!existsSync3(dbPath)) return null;
|
|
666
735
|
try {
|
|
667
736
|
const db = new Database2(dbPath, { readonly: true });
|
|
668
737
|
db.pragma("journal_mode = WAL");
|
|
@@ -803,14 +872,14 @@ async function main() {
|
|
|
803
872
|
process.exit(0);
|
|
804
873
|
}
|
|
805
874
|
function readStdin() {
|
|
806
|
-
return new Promise((
|
|
875
|
+
return new Promise((resolve3) => {
|
|
807
876
|
let data = "";
|
|
808
877
|
process.stdin.setEncoding("utf-8");
|
|
809
878
|
process.stdin.on("data", (chunk) => {
|
|
810
879
|
data += chunk;
|
|
811
880
|
});
|
|
812
|
-
process.stdin.on("end", () =>
|
|
813
|
-
setTimeout(() =>
|
|
881
|
+
process.stdin.on("end", () => resolve3(data));
|
|
882
|
+
setTimeout(() => resolve3(data), 400);
|
|
814
883
|
});
|
|
815
884
|
}
|
|
816
885
|
if (process.argv[1]?.endsWith("pre-delete-check.js") || process.argv[1]?.endsWith("pre-delete-check")) {
|
|
@@ -119,14 +119,14 @@ async function main() {
|
|
|
119
119
|
process.exit(0);
|
|
120
120
|
}
|
|
121
121
|
function readStdin() {
|
|
122
|
-
return new Promise((
|
|
122
|
+
return new Promise((resolve3) => {
|
|
123
123
|
let data = "";
|
|
124
124
|
process.stdin.setEncoding("utf-8");
|
|
125
125
|
process.stdin.on("data", (chunk) => {
|
|
126
126
|
data += chunk;
|
|
127
127
|
});
|
|
128
|
-
process.stdin.on("end", () =>
|
|
129
|
-
setTimeout(() =>
|
|
128
|
+
process.stdin.on("end", () => resolve3(data));
|
|
129
|
+
setTimeout(() => resolve3(data), 400);
|
|
130
130
|
});
|
|
131
131
|
}
|
|
132
132
|
if (process.argv[1]?.endsWith("security-gate.js") || process.argv[1]?.endsWith("security-gate")) {
|
|
@@ -135,12 +135,12 @@ if (process.argv[1]?.endsWith("security-gate.js") || process.argv[1]?.endsWith("
|
|
|
135
135
|
|
|
136
136
|
// src/hooks/pre-delete-check.ts
|
|
137
137
|
import Database2 from "better-sqlite3";
|
|
138
|
-
import { existsSync as
|
|
138
|
+
import { existsSync as existsSync3 } from "fs";
|
|
139
139
|
|
|
140
140
|
// src/config.ts
|
|
141
|
-
import { resolve, dirname } from "path";
|
|
142
|
-
import { existsSync, readFileSync } from "fs";
|
|
143
|
-
import { homedir } from "os";
|
|
141
|
+
import { resolve as resolve2, dirname } from "path";
|
|
142
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
143
|
+
import { homedir as homedir2 } from "os";
|
|
144
144
|
import { parse as parseYaml } from "yaml";
|
|
145
145
|
import { z } from "zod";
|
|
146
146
|
|
|
@@ -149,6 +149,68 @@ function encodeMemoryDirName(projectRoot) {
|
|
|
149
149
|
return projectRoot.replace(/\//g, "-");
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
+
// src/credentials.ts
|
|
153
|
+
import { homedir } from "os";
|
|
154
|
+
import { resolve } from "path";
|
|
155
|
+
import {
|
|
156
|
+
existsSync,
|
|
157
|
+
readFileSync,
|
|
158
|
+
writeFileSync,
|
|
159
|
+
mkdirSync,
|
|
160
|
+
rmSync,
|
|
161
|
+
chmodSync
|
|
162
|
+
} from "fs";
|
|
163
|
+
var MASSU_ENV_API_KEY = "MASSU_API_KEY";
|
|
164
|
+
var MASSU_ENV_CLOUD_ENDPOINT = "MASSU_CLOUD_ENDPOINT";
|
|
165
|
+
var DEFAULT_CLOUD_ENDPOINT = "https://api.massu.ai/v1";
|
|
166
|
+
function credentialsDir(home = homedir()) {
|
|
167
|
+
return resolve(home, ".massu");
|
|
168
|
+
}
|
|
169
|
+
function credentialsPath(home = homedir()) {
|
|
170
|
+
return resolve(credentialsDir(home), "credentials");
|
|
171
|
+
}
|
|
172
|
+
function readUserCredentials(home = homedir()) {
|
|
173
|
+
try {
|
|
174
|
+
const p = credentialsPath(home);
|
|
175
|
+
if (!existsSync(p)) return void 0;
|
|
176
|
+
const parsed = JSON.parse(readFileSync(p, "utf-8"));
|
|
177
|
+
const key = typeof parsed?.apiKey === "string" ? parsed.apiKey.trim() : "";
|
|
178
|
+
return key.length > 0 ? key : void 0;
|
|
179
|
+
} catch {
|
|
180
|
+
return void 0;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function isUnresolvedLiteral(v) {
|
|
184
|
+
return /^\$\{[^}]+\}$/.test(v);
|
|
185
|
+
}
|
|
186
|
+
function resolveApiKey(opts = {}) {
|
|
187
|
+
const env = opts.env ?? process.env;
|
|
188
|
+
const home = opts.home ?? homedir();
|
|
189
|
+
const cfg = typeof opts.configApiKey === "string" ? opts.configApiKey.trim() : "";
|
|
190
|
+
if (cfg.length > 0 && !isUnresolvedLiteral(cfg)) {
|
|
191
|
+
return { apiKey: cfg, source: "config" };
|
|
192
|
+
}
|
|
193
|
+
const envRaw = env[MASSU_ENV_API_KEY];
|
|
194
|
+
const envKey = typeof envRaw === "string" ? envRaw.trim() : "";
|
|
195
|
+
if (envKey.length > 0) {
|
|
196
|
+
return { apiKey: envKey, source: "env" };
|
|
197
|
+
}
|
|
198
|
+
const fileKey = readUserCredentials(home);
|
|
199
|
+
if (fileKey) {
|
|
200
|
+
return { apiKey: fileKey, source: "user-file" };
|
|
201
|
+
}
|
|
202
|
+
return { source: "none" };
|
|
203
|
+
}
|
|
204
|
+
function resolveEndpoint(opts = {}) {
|
|
205
|
+
const env = opts.env ?? process.env;
|
|
206
|
+
const cfg = typeof opts.configEndpoint === "string" ? opts.configEndpoint.trim() : "";
|
|
207
|
+
if (cfg.length > 0) return cfg;
|
|
208
|
+
const envRaw = env[MASSU_ENV_CLOUD_ENDPOINT];
|
|
209
|
+
const envEp = typeof envRaw === "string" ? envRaw.trim() : "";
|
|
210
|
+
if (envEp.length > 0) return envEp;
|
|
211
|
+
return DEFAULT_CLOUD_ENDPOINT;
|
|
212
|
+
}
|
|
213
|
+
|
|
152
214
|
// src/config.ts
|
|
153
215
|
var DomainConfigSchema = z.object({
|
|
154
216
|
name: z.string().default("Unknown"),
|
|
@@ -531,12 +593,13 @@ var RawConfigSchema = z.object({
|
|
|
531
593
|
lsp: LSPConfigSchema.optional()
|
|
532
594
|
}).passthrough();
|
|
533
595
|
var _config = null;
|
|
596
|
+
var _resolvedApiKeySource = "none";
|
|
534
597
|
var _projectRoot = null;
|
|
535
598
|
function findProjectRoot() {
|
|
536
599
|
const cwd = process.cwd();
|
|
537
600
|
let dir = cwd;
|
|
538
601
|
while (true) {
|
|
539
|
-
if (
|
|
602
|
+
if (existsSync2(resolve2(dir, "massu.config.yaml"))) {
|
|
540
603
|
return dir;
|
|
541
604
|
}
|
|
542
605
|
const parent = dirname(dir);
|
|
@@ -545,10 +608,10 @@ function findProjectRoot() {
|
|
|
545
608
|
}
|
|
546
609
|
dir = cwd;
|
|
547
610
|
while (true) {
|
|
548
|
-
if (
|
|
611
|
+
if (existsSync2(resolve2(dir, "package.json"))) {
|
|
549
612
|
return dir;
|
|
550
613
|
}
|
|
551
|
-
if (
|
|
614
|
+
if (existsSync2(resolve2(dir, ".git"))) {
|
|
552
615
|
return dir;
|
|
553
616
|
}
|
|
554
617
|
const parent = dirname(dir);
|
|
@@ -566,10 +629,10 @@ function getProjectRoot() {
|
|
|
566
629
|
function getConfig() {
|
|
567
630
|
if (_config) return _config;
|
|
568
631
|
const root = getProjectRoot();
|
|
569
|
-
const configPath =
|
|
632
|
+
const configPath = resolve2(root, "massu.config.yaml");
|
|
570
633
|
let rawYaml = {};
|
|
571
|
-
if (
|
|
572
|
-
const content =
|
|
634
|
+
if (existsSync2(configPath)) {
|
|
635
|
+
const content = readFileSync2(configPath, "utf-8");
|
|
573
636
|
rawYaml = parseYaml(content) ?? {};
|
|
574
637
|
}
|
|
575
638
|
const result = RawConfigSchema.safeParse(rawYaml);
|
|
@@ -586,7 +649,7 @@ Hint: run \`massu config refresh\` to regenerate a valid config or fix the liste
|
|
|
586
649
|
);
|
|
587
650
|
}
|
|
588
651
|
const parsed = result.data;
|
|
589
|
-
const projectRoot = parsed.project.root === "auto" || !parsed.project.root ? root :
|
|
652
|
+
const projectRoot = parsed.project.root === "auto" || !parsed.project.root ? root : resolve2(root, parsed.project.root);
|
|
590
653
|
const fw = parsed.framework;
|
|
591
654
|
let router = fw.router;
|
|
592
655
|
let orm = fw.orm;
|
|
@@ -644,13 +707,19 @@ Hint: run \`massu config refresh\` to regenerate a valid config or fix the liste
|
|
|
644
707
|
telemetry: parsed.telemetry,
|
|
645
708
|
lsp: parsed.lsp
|
|
646
709
|
};
|
|
647
|
-
|
|
710
|
+
const resolvedKey = resolveApiKey({ configApiKey: _config.cloud?.apiKey });
|
|
711
|
+
_resolvedApiKeySource = resolvedKey.source;
|
|
712
|
+
const resolvedEndpoint = resolveEndpoint({ configEndpoint: _config.cloud?.endpoint });
|
|
713
|
+
if (resolvedKey.apiKey) {
|
|
648
714
|
_config.cloud = {
|
|
649
715
|
enabled: true,
|
|
650
716
|
sync: { memory: true, analytics: true, audit: true },
|
|
651
717
|
..._config.cloud,
|
|
652
|
-
apiKey:
|
|
718
|
+
apiKey: resolvedKey.apiKey,
|
|
719
|
+
endpoint: resolvedEndpoint
|
|
653
720
|
};
|
|
721
|
+
} else if (_config.cloud) {
|
|
722
|
+
_config.cloud = { ..._config.cloud, endpoint: _config.cloud.endpoint ?? resolvedEndpoint };
|
|
654
723
|
}
|
|
655
724
|
return _config;
|
|
656
725
|
}
|
|
@@ -659,34 +728,34 @@ function getResolvedPaths() {
|
|
|
659
728
|
const root = getProjectRoot();
|
|
660
729
|
const claudeDirName = config.conventions?.claudeDirName ?? ".claude";
|
|
661
730
|
return {
|
|
662
|
-
codegraphDbPath:
|
|
663
|
-
dataDbPath:
|
|
664
|
-
prismaSchemaPath:
|
|
665
|
-
rootRouterPath:
|
|
666
|
-
routersDir:
|
|
667
|
-
srcDir:
|
|
731
|
+
codegraphDbPath: resolve2(root, ".codegraph/codegraph.db"),
|
|
732
|
+
dataDbPath: resolve2(root, ".massu/data.db"),
|
|
733
|
+
prismaSchemaPath: resolve2(root, config.paths.schema ?? "prisma/schema.prisma"),
|
|
734
|
+
rootRouterPath: resolve2(root, config.paths.routerRoot ?? "src/server/api/root.ts"),
|
|
735
|
+
routersDir: resolve2(root, config.paths.routers ?? "src/server/api/routers"),
|
|
736
|
+
srcDir: resolve2(root, config.paths.source),
|
|
668
737
|
pathAlias: Object.fromEntries(
|
|
669
738
|
Object.entries(config.paths.aliases).map(([alias, target]) => [
|
|
670
739
|
alias,
|
|
671
|
-
|
|
740
|
+
resolve2(root, target)
|
|
672
741
|
])
|
|
673
742
|
),
|
|
674
743
|
extensions: [".ts", ".tsx", ".js", ".jsx"],
|
|
675
744
|
indexFiles: ["index.ts", "index.tsx", "index.js", "index.jsx"],
|
|
676
|
-
patternsDir:
|
|
677
|
-
claudeMdPath:
|
|
678
|
-
docsMapPath:
|
|
679
|
-
helpSitePath:
|
|
680
|
-
memoryDbPath:
|
|
681
|
-
knowledgeDbPath:
|
|
682
|
-
plansDir:
|
|
683
|
-
docsDir:
|
|
684
|
-
claudeDir:
|
|
685
|
-
memoryDir:
|
|
686
|
-
sessionStatePath:
|
|
687
|
-
sessionArchivePath:
|
|
688
|
-
mcpJsonPath:
|
|
689
|
-
settingsLocalPath:
|
|
745
|
+
patternsDir: resolve2(root, claudeDirName, "patterns"),
|
|
746
|
+
claudeMdPath: resolve2(root, claudeDirName, "CLAUDE.md"),
|
|
747
|
+
docsMapPath: resolve2(root, ".massu/docs-map.json"),
|
|
748
|
+
helpSitePath: resolve2(root, "../" + config.project.name + "-help"),
|
|
749
|
+
memoryDbPath: resolve2(root, ".massu/memory.db"),
|
|
750
|
+
knowledgeDbPath: resolve2(root, ".massu/knowledge.db"),
|
|
751
|
+
plansDir: resolve2(root, "docs/plans"),
|
|
752
|
+
docsDir: resolve2(root, "docs"),
|
|
753
|
+
claudeDir: resolve2(root, claudeDirName),
|
|
754
|
+
memoryDir: resolve2(homedir2(), claudeDirName, "projects", encodeMemoryDirName(root), "memory"),
|
|
755
|
+
sessionStatePath: resolve2(root, config.conventions?.sessionStatePath ?? `${claudeDirName}/session-state/CURRENT.md`),
|
|
756
|
+
sessionArchivePath: resolve2(root, config.conventions?.sessionArchivePath ?? `${claudeDirName}/session-state/archive`),
|
|
757
|
+
mcpJsonPath: resolve2(root, ".mcp.json"),
|
|
758
|
+
settingsLocalPath: resolve2(root, claudeDirName, "settings.local.json")
|
|
690
759
|
};
|
|
691
760
|
}
|
|
692
761
|
|
|
@@ -789,7 +858,7 @@ var KNOWLEDGE_PROTECTED_FILES = [
|
|
|
789
858
|
];
|
|
790
859
|
function getDataDb() {
|
|
791
860
|
const dbPath = getResolvedPaths().dataDbPath;
|
|
792
|
-
if (!
|
|
861
|
+
if (!existsSync3(dbPath)) return null;
|
|
793
862
|
try {
|
|
794
863
|
const db = new Database2(dbPath, { readonly: true });
|
|
795
864
|
db.pragma("journal_mode = WAL");
|
|
@@ -930,14 +999,14 @@ async function main2() {
|
|
|
930
999
|
process.exit(0);
|
|
931
1000
|
}
|
|
932
1001
|
function readStdin2() {
|
|
933
|
-
return new Promise((
|
|
1002
|
+
return new Promise((resolve3) => {
|
|
934
1003
|
let data = "";
|
|
935
1004
|
process.stdin.setEncoding("utf-8");
|
|
936
1005
|
process.stdin.on("data", (chunk) => {
|
|
937
1006
|
data += chunk;
|
|
938
1007
|
});
|
|
939
|
-
process.stdin.on("end", () =>
|
|
940
|
-
setTimeout(() =>
|
|
1008
|
+
process.stdin.on("end", () => resolve3(data));
|
|
1009
|
+
setTimeout(() => resolve3(data), 400);
|
|
941
1010
|
});
|
|
942
1011
|
}
|
|
943
1012
|
if (process.argv[1]?.endsWith("pre-delete-check.js") || process.argv[1]?.endsWith("pre-delete-check")) {
|
|
@@ -959,14 +1028,14 @@ async function main3() {
|
|
|
959
1028
|
process.exit(0);
|
|
960
1029
|
}
|
|
961
1030
|
function readStdin3() {
|
|
962
|
-
return new Promise((
|
|
1031
|
+
return new Promise((resolve3) => {
|
|
963
1032
|
let data = "";
|
|
964
1033
|
process.stdin.setEncoding("utf-8");
|
|
965
1034
|
process.stdin.on("data", (chunk) => {
|
|
966
1035
|
data += chunk;
|
|
967
1036
|
});
|
|
968
|
-
process.stdin.on("end", () =>
|
|
969
|
-
setTimeout(() =>
|
|
1037
|
+
process.stdin.on("end", () => resolve3(data));
|
|
1038
|
+
setTimeout(() => resolve3(data), 400);
|
|
970
1039
|
});
|
|
971
1040
|
}
|
|
972
1041
|
main3();
|