nexus-agents 2.113.0 → 2.114.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/{child-mcp-config-UMNWY25S.js → child-mcp-config-BTYHNG2N.js} +2 -2
- package/dist/{chunk-5NE37CDW.js → chunk-36G75SD2.js} +1243 -3339
- package/dist/chunk-36G75SD2.js.map +1 -0
- package/dist/{chunk-5OOFU3EY.js → chunk-3S4N6OCF.js} +2 -2
- package/dist/{chunk-7E2ZCYKA.js → chunk-4K4OVG4O.js} +2 -2
- package/dist/{chunk-5EH7WMME.js → chunk-5RDUP5K7.js} +2 -2
- package/dist/{chunk-3XGPHTO6.js → chunk-7AO4FKAD.js} +2 -2
- package/dist/{chunk-P2K5GCLL.js → chunk-7BZKZUVR.js} +4 -4
- package/dist/{chunk-5KBR7SYI.js → chunk-AREFHG4Q.js} +7 -7
- package/dist/chunk-ATI7W2FT.js +2474 -0
- package/dist/chunk-ATI7W2FT.js.map +1 -0
- package/dist/{chunk-OMZD4OZP.js → chunk-B32GCV25.js} +5 -5
- package/dist/{chunk-LUCPCWIZ.js → chunk-BXEOO2KK.js} +2 -2
- package/dist/{chunk-RPWYEJ66.js → chunk-CLL2GXNL.js} +4 -4
- package/dist/chunk-E2ER3LQF.js +149 -0
- package/dist/chunk-E2ER3LQF.js.map +1 -0
- package/dist/{chunk-TIOXPJIO.js → chunk-E4HZTSBP.js} +2 -2
- package/dist/{chunk-SXG2NPZP.js → chunk-F6NOHVYQ.js} +3 -3
- package/dist/{chunk-JPCEQZPE.js → chunk-FSZNZZO5.js} +7 -7
- package/dist/{chunk-NCWD4UOI.js → chunk-IBRRXLMJ.js} +7 -7
- package/dist/{chunk-FSODHLOV.js → chunk-KTPMJSLZ.js} +3 -3
- package/dist/{chunk-2JIV7Q6A.js → chunk-MD6TVSOI.js} +3 -3
- package/dist/{chunk-WDOJESN6.js → chunk-MYN7CMD5.js} +2 -2
- package/dist/{chunk-ZSJG7EB2.js → chunk-N7NCTB3O.js} +5 -144
- package/dist/chunk-N7NCTB3O.js.map +1 -0
- package/dist/{chunk-5VGGVVPG.js → chunk-OTRXF5NM.js} +3 -3
- package/dist/{chunk-3DB4DEFY.js → chunk-Q6HUW6EI.js} +2 -2
- package/dist/{chunk-VV47MWHN.js → chunk-R2G4GZID.js} +3 -3
- package/dist/{chunk-AWXWDGG5.js → chunk-S7RTQRQ3.js} +2 -2
- package/dist/{chunk-N2HYXBQ6.js → chunk-VNU7OT7O.js} +2 -2
- package/dist/{chunk-VQVKI4XO.js → chunk-WJSQ5FRV.js} +2 -2
- package/dist/{chunk-F2ULTSZ6.js → chunk-XMNGHZBR.js} +7 -7
- package/dist/{chunk-2QBR4RVO.js → chunk-YJSXYHSK.js} +2 -2
- package/dist/{chunk-TI2BJ2OB.js → chunk-YKNLQLFM.js} +6 -6
- package/dist/{chunk-LMMMFZ64.js → chunk-YQW7MHST.js} +2 -2
- package/dist/{chunk-JRBUSUYD.js → chunk-ZXF2XA4R.js} +3 -3
- package/dist/{cli-circuit-breaker-XB5FPZJ5.js → cli-circuit-breaker-OR2Z2ZXU.js} +4 -4
- package/dist/cli.js +66 -63
- package/dist/cli.js.map +1 -1
- package/dist/{composite-router-VWQ65U6B.js → composite-router-QC4OLIQ5.js} +2 -2
- package/dist/{consensus-vote-EW5HWO6Z.js → consensus-vote-JMIK4USL.js} +12 -12
- package/dist/context-retriever-CFINY4KH.js +24 -0
- package/dist/{doctor-deep-RFHTNO2P.js → doctor-deep-53KZ3IYQ.js} +3 -3
- package/dist/{expert-bridge-LDWFPVHK.js → expert-bridge-WWAGNKZY.js} +4 -4
- package/dist/factory-3FKPAH26.js +21 -0
- package/dist/{factory-IYL24RFV.js → factory-KIGMY2XP.js} +5 -5
- package/dist/{improvement-review-7R5Q4OD3.js → improvement-review-A4HQ7KIQ.js} +4 -4
- package/dist/index.d.ts +8 -8
- package/dist/index.js +31 -30
- package/dist/index.js.map +1 -1
- package/dist/{init-opencode-26HTJ5QO.js → init-opencode-IMP5HG2J.js} +5 -5
- package/dist/{issue-triage-MVLE3SRA.js → issue-triage-VPL3N2AG.js} +5 -5
- package/dist/{pr-reviewer-helpers-HXEJ437Q.js → pr-reviewer-helpers-6FGXGRYA.js} +4 -4
- package/dist/{registry-command-RQH4YGK5.js → registry-command-IGVBSZX6.js} +2 -2
- package/dist/{repo-security-plan-SIOA64KN.js → repo-security-plan-PWFK3LCK.js} +3 -3
- package/dist/{research-helpers-synthesize-K43DWQVG.js → research-helpers-synthesize-IXWXFRKC.js} +4 -3
- package/dist/{routing-memory-AEYB4NPO.js → routing-memory-RQUM4XHT.js} +2 -2
- package/dist/{session-memory-GZOSVFDD.js → session-memory-7TDKNMRE.js} +3 -3
- package/dist/{setup-command-UZTCNASI.js → setup-command-MWZ5M3UB.js} +11 -11
- package/dist/{setup-config-R7GWRUW2.js → setup-config-ICI5OIGW.js} +3 -3
- package/dist/{setup-custom-api-DXS3Y4XW.js → setup-custom-api-IVJLG6WI.js} +3 -3
- package/dist/{tool-memory-CXHXCI6Q.js → tool-memory-USBUCDTD.js} +5 -5
- package/dist/{weather-report-PYDBRULK.js → weather-report-ZLUBKEG3.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-5NE37CDW.js.map +0 -1
- package/dist/chunk-KWHJL7HX.js +0 -276
- package/dist/chunk-KWHJL7HX.js.map +0 -1
- package/dist/chunk-ZSJG7EB2.js.map +0 -1
- package/dist/context-retriever-5VFAIPHM.js +0 -19
- package/dist/factory-AIERXI3O.js +0 -21
- /package/dist/{child-mcp-config-UMNWY25S.js.map → child-mcp-config-BTYHNG2N.js.map} +0 -0
- /package/dist/{chunk-5OOFU3EY.js.map → chunk-3S4N6OCF.js.map} +0 -0
- /package/dist/{chunk-7E2ZCYKA.js.map → chunk-4K4OVG4O.js.map} +0 -0
- /package/dist/{chunk-5EH7WMME.js.map → chunk-5RDUP5K7.js.map} +0 -0
- /package/dist/{chunk-3XGPHTO6.js.map → chunk-7AO4FKAD.js.map} +0 -0
- /package/dist/{chunk-P2K5GCLL.js.map → chunk-7BZKZUVR.js.map} +0 -0
- /package/dist/{chunk-5KBR7SYI.js.map → chunk-AREFHG4Q.js.map} +0 -0
- /package/dist/{chunk-OMZD4OZP.js.map → chunk-B32GCV25.js.map} +0 -0
- /package/dist/{chunk-LUCPCWIZ.js.map → chunk-BXEOO2KK.js.map} +0 -0
- /package/dist/{chunk-RPWYEJ66.js.map → chunk-CLL2GXNL.js.map} +0 -0
- /package/dist/{chunk-TIOXPJIO.js.map → chunk-E4HZTSBP.js.map} +0 -0
- /package/dist/{chunk-SXG2NPZP.js.map → chunk-F6NOHVYQ.js.map} +0 -0
- /package/dist/{chunk-JPCEQZPE.js.map → chunk-FSZNZZO5.js.map} +0 -0
- /package/dist/{chunk-NCWD4UOI.js.map → chunk-IBRRXLMJ.js.map} +0 -0
- /package/dist/{chunk-FSODHLOV.js.map → chunk-KTPMJSLZ.js.map} +0 -0
- /package/dist/{chunk-2JIV7Q6A.js.map → chunk-MD6TVSOI.js.map} +0 -0
- /package/dist/{chunk-WDOJESN6.js.map → chunk-MYN7CMD5.js.map} +0 -0
- /package/dist/{chunk-5VGGVVPG.js.map → chunk-OTRXF5NM.js.map} +0 -0
- /package/dist/{chunk-3DB4DEFY.js.map → chunk-Q6HUW6EI.js.map} +0 -0
- /package/dist/{chunk-VV47MWHN.js.map → chunk-R2G4GZID.js.map} +0 -0
- /package/dist/{chunk-AWXWDGG5.js.map → chunk-S7RTQRQ3.js.map} +0 -0
- /package/dist/{chunk-N2HYXBQ6.js.map → chunk-VNU7OT7O.js.map} +0 -0
- /package/dist/{chunk-VQVKI4XO.js.map → chunk-WJSQ5FRV.js.map} +0 -0
- /package/dist/{chunk-F2ULTSZ6.js.map → chunk-XMNGHZBR.js.map} +0 -0
- /package/dist/{chunk-2QBR4RVO.js.map → chunk-YJSXYHSK.js.map} +0 -0
- /package/dist/{chunk-TI2BJ2OB.js.map → chunk-YKNLQLFM.js.map} +0 -0
- /package/dist/{chunk-LMMMFZ64.js.map → chunk-YQW7MHST.js.map} +0 -0
- /package/dist/{chunk-JRBUSUYD.js.map → chunk-ZXF2XA4R.js.map} +0 -0
- /package/dist/{cli-circuit-breaker-XB5FPZJ5.js.map → cli-circuit-breaker-OR2Z2ZXU.js.map} +0 -0
- /package/dist/{composite-router-VWQ65U6B.js.map → composite-router-QC4OLIQ5.js.map} +0 -0
- /package/dist/{consensus-vote-EW5HWO6Z.js.map → consensus-vote-JMIK4USL.js.map} +0 -0
- /package/dist/{context-retriever-5VFAIPHM.js.map → context-retriever-CFINY4KH.js.map} +0 -0
- /package/dist/{doctor-deep-RFHTNO2P.js.map → doctor-deep-53KZ3IYQ.js.map} +0 -0
- /package/dist/{expert-bridge-LDWFPVHK.js.map → expert-bridge-WWAGNKZY.js.map} +0 -0
- /package/dist/{factory-AIERXI3O.js.map → factory-3FKPAH26.js.map} +0 -0
- /package/dist/{factory-IYL24RFV.js.map → factory-KIGMY2XP.js.map} +0 -0
- /package/dist/{improvement-review-7R5Q4OD3.js.map → improvement-review-A4HQ7KIQ.js.map} +0 -0
- /package/dist/{init-opencode-26HTJ5QO.js.map → init-opencode-IMP5HG2J.js.map} +0 -0
- /package/dist/{issue-triage-MVLE3SRA.js.map → issue-triage-VPL3N2AG.js.map} +0 -0
- /package/dist/{pr-reviewer-helpers-HXEJ437Q.js.map → pr-reviewer-helpers-6FGXGRYA.js.map} +0 -0
- /package/dist/{registry-command-RQH4YGK5.js.map → registry-command-IGVBSZX6.js.map} +0 -0
- /package/dist/{repo-security-plan-SIOA64KN.js.map → repo-security-plan-PWFK3LCK.js.map} +0 -0
- /package/dist/{research-helpers-synthesize-K43DWQVG.js.map → research-helpers-synthesize-IXWXFRKC.js.map} +0 -0
- /package/dist/{routing-memory-AEYB4NPO.js.map → routing-memory-RQUM4XHT.js.map} +0 -0
- /package/dist/{session-memory-GZOSVFDD.js.map → session-memory-7TDKNMRE.js.map} +0 -0
- /package/dist/{setup-command-UZTCNASI.js.map → setup-command-MWZ5M3UB.js.map} +0 -0
- /package/dist/{setup-config-R7GWRUW2.js.map → setup-config-ICI5OIGW.js.map} +0 -0
- /package/dist/{setup-custom-api-DXS3Y4XW.js.map → setup-custom-api-IVJLG6WI.js.map} +0 -0
- /package/dist/{tool-memory-CXHXCI6Q.js.map → tool-memory-USBUCDTD.js.map} +0 -0
- /package/dist/{weather-report-PYDBRULK.js.map → weather-report-ZLUBKEG3.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
GitHubProvider,
|
|
3
3
|
ScmError
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-Q6HUW6EI.js";
|
|
5
5
|
import {
|
|
6
6
|
ROLE_DEFAULT_TRUST,
|
|
7
7
|
ReputationCache,
|
|
@@ -11,13 +11,13 @@ import {
|
|
|
11
11
|
gateWithReputation,
|
|
12
12
|
resolveReputationGatingMode,
|
|
13
13
|
sanitizeInput
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-S7RTQRQ3.js";
|
|
15
15
|
import {
|
|
16
16
|
createLogger,
|
|
17
17
|
err,
|
|
18
18
|
getTimeProvider,
|
|
19
19
|
ok
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-ZXF2XA4R.js";
|
|
21
21
|
|
|
22
22
|
// src/security/trust-classifier.ts
|
|
23
23
|
function mapAuthorAssociation(association) {
|
|
@@ -1390,4 +1390,4 @@ export {
|
|
|
1390
1390
|
IssueTriage,
|
|
1391
1391
|
createIssueTriage
|
|
1392
1392
|
};
|
|
1393
|
-
//# sourceMappingURL=chunk-
|
|
1393
|
+
//# sourceMappingURL=chunk-CLL2GXNL.js.map
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolveInsideRoot
|
|
3
|
+
} from "./chunk-NUBSJGQZ.js";
|
|
4
|
+
import {
|
|
5
|
+
ParseError,
|
|
6
|
+
SecurityError,
|
|
7
|
+
err,
|
|
8
|
+
getErrorMessage,
|
|
9
|
+
ok,
|
|
10
|
+
parseBoolEnv
|
|
11
|
+
} from "./chunk-ZXF2XA4R.js";
|
|
12
|
+
|
|
13
|
+
// src/cli/research-helpers-io.ts
|
|
14
|
+
import * as fs2 from "fs/promises";
|
|
15
|
+
import { join, resolve as resolve2 } from "path";
|
|
16
|
+
import { parse as parseYaml, stringify as stringifyYaml2 } from "yaml";
|
|
17
|
+
|
|
18
|
+
// src/cli/research-scaffold.ts
|
|
19
|
+
import * as fs from "fs/promises";
|
|
20
|
+
import { existsSync } from "fs";
|
|
21
|
+
import { dirname, resolve } from "path";
|
|
22
|
+
import { stringify as stringifyYaml } from "yaml";
|
|
23
|
+
var SCHEMA_VERSION = "1.0";
|
|
24
|
+
var ANNOUNCED = /* @__PURE__ */ new Set();
|
|
25
|
+
function announceOnce(path, kind) {
|
|
26
|
+
if (ANNOUNCED.has(path)) return;
|
|
27
|
+
ANNOUNCED.add(path);
|
|
28
|
+
process.stderr.write(
|
|
29
|
+
`[scaffold] Created empty ${kind} at ${path}; add entries via 'nexus-agents research add' or research_add MCP tool.
|
|
30
|
+
`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
function scaffoldDisabled() {
|
|
34
|
+
return parseBoolEnv("NEXUS_NO_SCAFFOLD", false);
|
|
35
|
+
}
|
|
36
|
+
function emptyPapersYaml() {
|
|
37
|
+
return stringifyYaml({ schema_version: SCHEMA_VERSION, papers: {} });
|
|
38
|
+
}
|
|
39
|
+
function emptyTechniquesYaml() {
|
|
40
|
+
return stringifyYaml({ schema_version: SCHEMA_VERSION, techniques: {} });
|
|
41
|
+
}
|
|
42
|
+
async function ensureRegistryFile(rootDir, filename) {
|
|
43
|
+
const filePath = resolve(rootDir, REGISTRY_PATH, filename);
|
|
44
|
+
if (existsSync(filePath)) return ok(filePath);
|
|
45
|
+
if (scaffoldDisabled()) {
|
|
46
|
+
return err(
|
|
47
|
+
new ParseError(
|
|
48
|
+
`Registry file missing: ${filePath}. Scaffolding disabled (NEXUS_NO_SCAFFOLD=1). Create the file manually or unset the env var.`
|
|
49
|
+
)
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
if (!existsSync(resolve(rootDir, "docs"))) {
|
|
53
|
+
return err(
|
|
54
|
+
new ParseError(
|
|
55
|
+
`Registry file missing: ${filePath}. ${rootDir}/docs/ does not exist; refusing to create a Nexus subtree in a non-documented root. Run 'nexus-agents init' first, or create ${rootDir}/docs/ manually.`
|
|
56
|
+
)
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
await fs.mkdir(dirname(filePath), { recursive: true });
|
|
61
|
+
const content = filename === PAPERS_FILE ? emptyPapersYaml() : emptyTechniquesYaml();
|
|
62
|
+
await fs.writeFile(filePath, content, "utf-8");
|
|
63
|
+
announceOnce(filePath, filename);
|
|
64
|
+
return ok(filePath);
|
|
65
|
+
} catch (e) {
|
|
66
|
+
return err(
|
|
67
|
+
new ParseError(
|
|
68
|
+
`Failed to scaffold ${filename} at ${filePath}: ${getErrorMessage(e)}. Set NEXUS_NO_SCAFFOLD=1 and create manually if scaffolding is unwanted.`
|
|
69
|
+
)
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// src/cli/research-helpers-io.ts
|
|
75
|
+
var REGISTRY_PATH = "docs/research/registry";
|
|
76
|
+
var TECHNIQUES_FILE = "techniques.yaml";
|
|
77
|
+
var PAPERS_FILE = "papers.yaml";
|
|
78
|
+
function getProjectRoot() {
|
|
79
|
+
return process.cwd();
|
|
80
|
+
}
|
|
81
|
+
function validatePath(constructedPath, allowedRoot) {
|
|
82
|
+
const resolved = resolveInsideRoot(constructedPath, allowedRoot);
|
|
83
|
+
if (resolved === null) {
|
|
84
|
+
return {
|
|
85
|
+
ok: false,
|
|
86
|
+
error: new SecurityError("Path traversal detected: path escapes allowed root directory", {
|
|
87
|
+
context: { constructedPath, allowedRoot: resolve2(allowedRoot) }
|
|
88
|
+
})
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
return { ok: true, value: resolved };
|
|
92
|
+
}
|
|
93
|
+
async function loadTechniquesRegistry(rootDir) {
|
|
94
|
+
const root = rootDir ?? process.cwd();
|
|
95
|
+
const filePath = join(root, REGISTRY_PATH, TECHNIQUES_FILE);
|
|
96
|
+
const pathValidation = validatePath(filePath, root);
|
|
97
|
+
if (!pathValidation.ok) {
|
|
98
|
+
return pathValidation;
|
|
99
|
+
}
|
|
100
|
+
await ensureRegistryFile(root, TECHNIQUES_FILE);
|
|
101
|
+
try {
|
|
102
|
+
const content = await fs2.readFile(pathValidation.value, "utf-8");
|
|
103
|
+
return { ok: true, value: parseYaml(content) };
|
|
104
|
+
} catch (error) {
|
|
105
|
+
const message = getErrorMessage(error);
|
|
106
|
+
return { ok: false, error: new ParseError(`Failed to load techniques registry: ${message}`) };
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
async function loadPapersRegistry(rootDir) {
|
|
110
|
+
const root = rootDir ?? process.cwd();
|
|
111
|
+
const filePath = join(root, REGISTRY_PATH, PAPERS_FILE);
|
|
112
|
+
const pathValidation = validatePath(filePath, root);
|
|
113
|
+
if (!pathValidation.ok) {
|
|
114
|
+
return pathValidation;
|
|
115
|
+
}
|
|
116
|
+
await ensureRegistryFile(root, PAPERS_FILE);
|
|
117
|
+
try {
|
|
118
|
+
const content = await fs2.readFile(pathValidation.value, "utf-8");
|
|
119
|
+
return { ok: true, value: parseYaml(content) };
|
|
120
|
+
} catch (error) {
|
|
121
|
+
const message = getErrorMessage(error);
|
|
122
|
+
return { ok: false, error: new ParseError(`Failed to load papers registry: ${message}`) };
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
async function savePapersRegistry(registry, rootDir) {
|
|
126
|
+
const root = rootDir ?? process.cwd();
|
|
127
|
+
const filePath = join(root, REGISTRY_PATH, PAPERS_FILE);
|
|
128
|
+
const pathValidation = validatePath(filePath, root);
|
|
129
|
+
if (!pathValidation.ok) {
|
|
130
|
+
return pathValidation;
|
|
131
|
+
}
|
|
132
|
+
try {
|
|
133
|
+
const content = stringifyYaml2(registry, { lineWidth: 100 });
|
|
134
|
+
await fs2.writeFile(pathValidation.value, content, "utf-8");
|
|
135
|
+
return { ok: true, value: void 0 };
|
|
136
|
+
} catch (error) {
|
|
137
|
+
const message = getErrorMessage(error);
|
|
138
|
+
return { ok: false, error: new ParseError(`Failed to save papers registry: ${message}`) };
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export {
|
|
143
|
+
REGISTRY_PATH,
|
|
144
|
+
getProjectRoot,
|
|
145
|
+
loadTechniquesRegistry,
|
|
146
|
+
loadPapersRegistry,
|
|
147
|
+
savePapersRegistry
|
|
148
|
+
};
|
|
149
|
+
//# sourceMappingURL=chunk-E2ER3LQF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/research-helpers-io.ts","../src/cli/research-scaffold.ts"],"sourcesContent":["/**\n * Research Registry I/O Operations\n *\n * File operations for loading and saving research registry YAML files.\n * Includes path traversal protection per Issue #353.\n *\n * @see docs/research/RESEARCH_INDEX.md\n * @see Issue #237 (Epic #225)\n * @see Issue #353 (Security - Path traversal fix)\n */\n\nimport * as fs from 'node:fs/promises';\nimport { join, resolve } from 'node:path';\nimport { resolveInsideRoot } from '../security/safe-path.js';\nimport { parse as parseYaml, stringify as stringifyYaml } from 'yaml';\nimport type { Result } from '../core/index.js';\nimport { SecurityError, getErrorMessage } from '../core/index.js';\nimport { ParseError } from '../core/types/workflow.js';\nimport type { TechniquesRegistry, PapersRegistry } from './research-types.js';\nimport { ensureRegistryFile } from './research-scaffold.js';\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\n\n/** Path to research registry directory relative to project root */\nexport const REGISTRY_PATH = 'docs/research/registry';\n\n/** Filename for techniques registry */\nexport const TECHNIQUES_FILE = 'techniques.yaml';\n\n/** Filename for papers registry */\nexport const PAPERS_FILE = 'papers.yaml';\n\n// =============================================================================\n// PROJECT ROOT\n// =============================================================================\n\n/**\n * Get the project root directory.\n * Note: Returns cwd since registry operations use explicit rootDir parameter\n */\nexport function getProjectRoot(): string {\n return process.cwd();\n}\n\n// =============================================================================\n// PATH VALIDATION\n// =============================================================================\n\n/**\n * Validates that a constructed path stays within the allowed root directory.\n * Prevents path traversal attacks (e.g., ../../../etc/passwd).\n *\n * @param constructedPath - The full path to validate\n * @param allowedRoot - The root directory that paths must be within\n * @returns Result with validated absolute path or SecurityError\n */\nfunction validatePath(constructedPath: string, allowedRoot: string): Result<string, SecurityError> {\n const resolved = resolveInsideRoot(constructedPath, allowedRoot);\n if (resolved === null) {\n return {\n ok: false,\n error: new SecurityError('Path traversal detected: path escapes allowed root directory', {\n context: { constructedPath, allowedRoot: resolve(allowedRoot) },\n }),\n };\n }\n return { ok: true, value: resolved };\n}\n\n// =============================================================================\n// LOAD OPERATIONS\n// =============================================================================\n\n/**\n * Load techniques registry from YAML file.\n * Validates path to prevent directory traversal attacks.\n *\n * @param rootDir - Project root directory (defaults to cwd)\n * @returns Result with TechniquesRegistry or SecurityError/ParseError\n */\nexport async function loadTechniquesRegistry(\n rootDir?: string\n): Promise<Result<TechniquesRegistry, SecurityError | ParseError>> {\n const root = rootDir ?? process.cwd();\n const filePath = join(root, REGISTRY_PATH, TECHNIQUES_FILE);\n\n const pathValidation = validatePath(filePath, root);\n if (!pathValidation.ok) {\n return pathValidation;\n }\n\n // #2470: try to scaffold an empty techniques.yaml on first run so research_*\n // workflows don't error on a fresh install. No-op when file exists.\n // When scaffold refuses (e.g. <rootDir>/docs/ doesn't exist, or\n // NEXUS_NO_SCAFFOLD=1), fall through and let readFile produce the original\n // ENOENT error — that's the existing contract.\n await ensureRegistryFile(root, TECHNIQUES_FILE);\n\n try {\n const content = await fs.readFile(pathValidation.value, 'utf-8');\n return { ok: true, value: parseYaml(content) as TechniquesRegistry };\n } catch (error) {\n const message = getErrorMessage(error);\n return { ok: false, error: new ParseError(`Failed to load techniques registry: ${message}`) };\n }\n}\n\n/**\n * Load papers registry from YAML file.\n * Validates path to prevent directory traversal attacks.\n *\n * @param rootDir - Project root directory (defaults to cwd)\n * @returns Result with PapersRegistry or SecurityError/ParseError\n */\nexport async function loadPapersRegistry(\n rootDir?: string\n): Promise<Result<PapersRegistry, SecurityError | ParseError>> {\n const root = rootDir ?? process.cwd();\n const filePath = join(root, REGISTRY_PATH, PAPERS_FILE);\n\n const pathValidation = validatePath(filePath, root);\n if (!pathValidation.ok) {\n return pathValidation;\n }\n\n // #2470: try to scaffold an empty papers.yaml on first run so research_*\n // workflows don't error on a fresh install. No-op when file exists; falls\n // through silently when scaffold refuses (no docs/ root, or NEXUS_NO_SCAFFOLD).\n await ensureRegistryFile(root, PAPERS_FILE);\n\n try {\n const content = await fs.readFile(pathValidation.value, 'utf-8');\n return { ok: true, value: parseYaml(content) as PapersRegistry };\n } catch (error) {\n const message = getErrorMessage(error);\n return { ok: false, error: new ParseError(`Failed to load papers registry: ${message}`) };\n }\n}\n\n// =============================================================================\n// SAVE OPERATIONS\n// =============================================================================\n\n/**\n * Save techniques registry to YAML file.\n * Validates path to prevent directory traversal attacks.\n *\n * @param registry - The techniques registry to save\n * @param rootDir - Project root directory (defaults to cwd)\n * @returns Result with void on success or SecurityError/ParseError on failure\n */\nexport async function saveTechniquesRegistry(\n registry: TechniquesRegistry,\n rootDir?: string\n): Promise<Result<void, SecurityError | ParseError>> {\n const root = rootDir ?? process.cwd();\n const filePath = join(root, REGISTRY_PATH, TECHNIQUES_FILE);\n\n const pathValidation = validatePath(filePath, root);\n if (!pathValidation.ok) {\n return pathValidation;\n }\n\n try {\n const content = stringifyYaml(registry, { lineWidth: 100 });\n await fs.writeFile(pathValidation.value, content, 'utf-8');\n return { ok: true, value: undefined };\n } catch (error) {\n const message = getErrorMessage(error);\n return { ok: false, error: new ParseError(`Failed to save techniques registry: ${message}`) };\n }\n}\n\n/**\n * Save papers registry to YAML file.\n * Validates path to prevent directory traversal attacks.\n *\n * @param registry - The papers registry to save\n * @param rootDir - Project root directory (defaults to cwd)\n * @returns Result with void on success or SecurityError/ParseError on failure\n */\nexport async function savePapersRegistry(\n registry: PapersRegistry,\n rootDir?: string\n): Promise<Result<void, SecurityError | ParseError>> {\n const root = rootDir ?? process.cwd();\n const filePath = join(root, REGISTRY_PATH, PAPERS_FILE);\n\n const pathValidation = validatePath(filePath, root);\n if (!pathValidation.ok) {\n return pathValidation;\n }\n\n try {\n const content = stringifyYaml(registry, { lineWidth: 100 });\n await fs.writeFile(pathValidation.value, content, 'utf-8');\n return { ok: true, value: undefined };\n } catch (error) {\n const message = getErrorMessage(error);\n return { ok: false, error: new ParseError(`Failed to save papers registry: ${message}`) };\n }\n}\n","/**\n * research-scaffold — auto-create empty research registry files when missing.\n *\n * On a fresh install or in a sandboxed environment where the project doesn't\n * have `docs/research/registry/`, the research workflows previously errored\n * with `Failed to load papers registry: ENOENT`. The user has no idea what\n * to do.\n *\n * This module provides `ensureResearchRegistry()`: idempotent scaffolding\n * that creates empty YAML registries on ENOENT, announces what it did to\n * stderr (so the operator knows), and returns the path that's now safe to\n * read.\n *\n * Source: Issue #2470 (epic #2467 child).\n */\n\nimport * as fs from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport { stringify as stringifyYaml } from 'yaml';\n\nimport type { Result } from '../core/index.js';\nimport { ok, err, getErrorMessage } from '../core/index.js';\nimport { ParseError } from '../core/types/workflow.js';\n\nimport { REGISTRY_PATH, PAPERS_FILE, TECHNIQUES_FILE } from './research-helpers-io.js';\nimport { parseBoolEnv } from '../config/defaults-env.js';\n\n/**\n * Names of the registry files this scaffolder knows how to create.\n * `sources.yaml` and `alignments.yaml` live alongside but are populated by\n * different code paths; this scaffolder only owns the two YAML registries\n * that block `research_query` / `research_synthesize` on a fresh install.\n */\ntype ScaffoldedFile = typeof PAPERS_FILE | typeof TECHNIQUES_FILE;\n\nconst SCHEMA_VERSION = '1.0';\n\nconst ANNOUNCED = new Set<string>();\n\nfunction announceOnce(path: string, kind: ScaffoldedFile): void {\n // De-dupe so that running multiple research commands in one session\n // produces one announcement per scaffolded file, not per call.\n if (ANNOUNCED.has(path)) return;\n ANNOUNCED.add(path);\n process.stderr.write(\n `[scaffold] Created empty ${kind} at ${path}; add entries via 'nexus-agents research add' or research_add MCP tool.\\n`\n );\n}\n\n/**\n * Operator opt-out. When set, scaffolding errors loudly with an actionable\n * message instead of silently writing files. Useful for CI and for\n * environments that want strict \"fail when state is wrong\" semantics.\n */\nfunction scaffoldDisabled(): boolean {\n return parseBoolEnv('NEXUS_NO_SCAFFOLD', false);\n}\n\nfunction emptyPapersYaml(): string {\n return stringifyYaml({ schema_version: SCHEMA_VERSION, papers: {} });\n}\n\nfunction emptyTechniquesYaml(): string {\n return stringifyYaml({ schema_version: SCHEMA_VERSION, techniques: {} });\n}\n\n/**\n * Create the registry directory + an empty YAML file if either is missing.\n * Idempotent: existing files are left untouched.\n *\n * Scaffolds only when `<rootDir>/docs/` already exists. That guard keeps\n * tests, vitest's package cwd, and random scratch directories from getting\n * a `docs/research/` subtree implicitly. Operators on a real project root\n * (which always has `docs/`, either from cloning the repo or running\n * `nexus-agents init`) still get the auto-create behavior the issue asks for.\n *\n * Returns the resolved file path on success, or a ParseError when scaffolding\n * is disabled / refused (so the caller can pass the error through unchanged\n * for backwards compat with existing call sites).\n */\nexport async function ensureRegistryFile(\n rootDir: string,\n filename: ScaffoldedFile\n): Promise<Result<string, ParseError>> {\n const filePath = resolve(rootDir, REGISTRY_PATH, filename);\n\n if (existsSync(filePath)) return ok(filePath);\n\n if (scaffoldDisabled()) {\n return err(\n new ParseError(\n `Registry file missing: ${filePath}. Scaffolding disabled (NEXUS_NO_SCAFFOLD=1). Create the file manually or unset the env var.`\n )\n );\n }\n\n // Refuse to create a docs/ subtree in directories that aren't already\n // documented project roots. The presence of `<rootDir>/docs/` is the\n // strong signal we use.\n if (!existsSync(resolve(rootDir, 'docs'))) {\n return err(\n new ParseError(\n `Registry file missing: ${filePath}. ${rootDir}/docs/ does not exist; ` +\n `refusing to create a Nexus subtree in a non-documented root. ` +\n `Run 'nexus-agents init' first, or create ${rootDir}/docs/ manually.`\n )\n );\n }\n\n try {\n await fs.mkdir(dirname(filePath), { recursive: true });\n const content = filename === PAPERS_FILE ? emptyPapersYaml() : emptyTechniquesYaml();\n await fs.writeFile(filePath, content, 'utf-8');\n announceOnce(filePath, filename);\n return ok(filePath);\n } catch (e: unknown) {\n return err(\n new ParseError(\n `Failed to scaffold ${filename} at ${filePath}: ${getErrorMessage(e)}. Set NEXUS_NO_SCAFFOLD=1 and create manually if scaffolding is unwanted.`\n )\n );\n }\n}\n\n/**\n * Convenience: scaffold both papers.yaml and techniques.yaml. Used by the\n * research workflow startup paths that need both registries available.\n */\nexport async function ensureResearchRegistry(rootDir?: string): Promise<Result<void, ParseError>> {\n const root = rootDir ?? process.cwd();\n const papers = await ensureRegistryFile(root, PAPERS_FILE);\n if (!papers.ok) return papers;\n const techniques = await ensureRegistryFile(root, TECHNIQUES_FILE);\n if (!techniques.ok) return techniques;\n return ok(undefined);\n}\n\n/**\n * Test-only reset of the announcement de-dupe set. Production code never\n * needs this; tests do because Vitest reuses process state across files.\n */\nexport function _resetAnnouncedForTests(): void {\n ANNOUNCED.clear();\n}\n"],"mappings":"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","names":["fs","resolve","stringifyYaml","resolve","stringifyYaml"]}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
MODEL_IDS,
|
|
4
4
|
getTimeProvider,
|
|
5
5
|
resolveModelIdentitySync
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-ZXF2XA4R.js";
|
|
7
7
|
|
|
8
8
|
// src/config/model-availability.ts
|
|
9
9
|
var DEFAULT_TTL_MS = 6e4;
|
|
@@ -150,4 +150,4 @@ export {
|
|
|
150
150
|
resetAvailabilityCache,
|
|
151
151
|
filterAvailableModels
|
|
152
152
|
};
|
|
153
|
-
//# sourceMappingURL=chunk-
|
|
153
|
+
//# sourceMappingURL=chunk-E4HZTSBP.js.map
|
|
@@ -2,14 +2,14 @@ import {
|
|
|
2
2
|
CircuitBreakerRegistry,
|
|
3
3
|
CircuitError,
|
|
4
4
|
mapCliErrorToCategory
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-5RDUP5K7.js";
|
|
6
6
|
import {
|
|
7
7
|
createLogger,
|
|
8
8
|
err,
|
|
9
9
|
getFallbackChainForCategory,
|
|
10
10
|
getTimeProvider,
|
|
11
11
|
ok
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-ZXF2XA4R.js";
|
|
13
13
|
|
|
14
14
|
// src/cli-adapters/cli-circuit-breaker.ts
|
|
15
15
|
var CATEGORY_TO_FALLBACK = {
|
|
@@ -152,4 +152,4 @@ export {
|
|
|
152
152
|
CliCircuitBreakerIntegration,
|
|
153
153
|
createCliCircuitBreakerIntegration
|
|
154
154
|
};
|
|
155
|
-
//# sourceMappingURL=chunk-
|
|
155
|
+
//# sourceMappingURL=chunk-F6NOHVYQ.js.map
|
|
@@ -7,10 +7,10 @@ import {
|
|
|
7
7
|
import {
|
|
8
8
|
createAllAdapters,
|
|
9
9
|
probeCli
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-XMNGHZBR.js";
|
|
11
11
|
import {
|
|
12
12
|
DEFAULTS
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-7AO4FKAD.js";
|
|
14
14
|
import {
|
|
15
15
|
CliNameSchema,
|
|
16
16
|
DEFAULT_CAPABILITIES,
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
ok,
|
|
27
27
|
symbols,
|
|
28
28
|
writeLine
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-ZXF2XA4R.js";
|
|
30
30
|
import {
|
|
31
31
|
detectSandbox,
|
|
32
32
|
getLearningDir,
|
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
} from "./chunk-CH7QIDHQ.js";
|
|
41
41
|
|
|
42
42
|
// src/version.ts
|
|
43
|
-
var VERSION = true ? "2.
|
|
43
|
+
var VERSION = true ? "2.114.0" : "dev";
|
|
44
44
|
|
|
45
45
|
// src/config/schemas-core.ts
|
|
46
46
|
import { z } from "zod";
|
|
@@ -2099,7 +2099,7 @@ async function runDoctorFix(result) {
|
|
|
2099
2099
|
writeLine2("\u2500".repeat(40));
|
|
2100
2100
|
let fixCount = 0;
|
|
2101
2101
|
if (!result.dataDirectory.rootExists || result.dataDirectory.subdirectories.some((d) => !d.exists || !d.writable)) {
|
|
2102
|
-
const { runSetup } = await import("./setup-command-
|
|
2102
|
+
const { runSetup } = await import("./setup-command-MWZ5M3UB.js");
|
|
2103
2103
|
const setupResult = runSetup({
|
|
2104
2104
|
skipMcp: true,
|
|
2105
2105
|
skipRules: true,
|
|
@@ -2113,7 +2113,7 @@ async function runDoctorFix(result) {
|
|
|
2113
2113
|
}
|
|
2114
2114
|
}
|
|
2115
2115
|
if (!result.configFile.found) {
|
|
2116
|
-
const { runConfigInitSync } = await import("./setup-config-
|
|
2116
|
+
const { runConfigInitSync } = await import("./setup-config-ICI5OIGW.js");
|
|
2117
2117
|
const configResult = runConfigInitSync(process.cwd(), false, false);
|
|
2118
2118
|
if (configResult.success && configResult.created) {
|
|
2119
2119
|
writeLine2(`\u2713 Generated config: ${configResult.path}`);
|
|
@@ -2211,4 +2211,4 @@ export {
|
|
|
2211
2211
|
startStdioServer,
|
|
2212
2212
|
closeServer
|
|
2213
2213
|
};
|
|
2214
|
-
//# sourceMappingURL=chunk-
|
|
2214
|
+
//# sourceMappingURL=chunk-FSZNZZO5.js.map
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveCliSlot
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-E4HZTSBP.js";
|
|
4
4
|
import {
|
|
5
5
|
createLogger,
|
|
6
6
|
getTimeProvider,
|
|
7
7
|
isRateLimitText
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-ZXF2XA4R.js";
|
|
9
9
|
|
|
10
10
|
// src/pipeline/expert-bridge.ts
|
|
11
11
|
function resolveCliFromModelString(model) {
|
|
@@ -21,7 +21,7 @@ async function getMcpConfigPath() {
|
|
|
21
21
|
if (cachedMcpConfigPath !== null) return cachedMcpConfigPath;
|
|
22
22
|
mcpConfigInitPromise ??= (async () => {
|
|
23
23
|
try {
|
|
24
|
-
const { generateMcpConfig } = await import("./child-mcp-config-
|
|
24
|
+
const { generateMcpConfig } = await import("./child-mcp-config-BTYHNG2N.js");
|
|
25
25
|
const config = await generateMcpConfig();
|
|
26
26
|
cachedMcpConfigPath = config.configPath;
|
|
27
27
|
cachedMcpConfigCleanup = config.cleanup;
|
|
@@ -93,8 +93,8 @@ var routerInitPromise = null;
|
|
|
93
93
|
async function getRouter() {
|
|
94
94
|
if (cachedRouter !== null) return cachedRouter;
|
|
95
95
|
routerInitPromise ??= (async () => {
|
|
96
|
-
const { createAllAdapters } = await import("./factory-
|
|
97
|
-
const { createCompositeRouter } = await import("./composite-router-
|
|
96
|
+
const { createAllAdapters } = await import("./factory-3FKPAH26.js");
|
|
97
|
+
const { createCompositeRouter } = await import("./composite-router-QC4OLIQ5.js");
|
|
98
98
|
const adapters = createAllAdapters();
|
|
99
99
|
if (adapters.size === 0) {
|
|
100
100
|
routerInitPromise = null;
|
|
@@ -102,7 +102,7 @@ async function getRouter() {
|
|
|
102
102
|
}
|
|
103
103
|
cachedRouter = adaptCompositeRouter(createCompositeRouter(adapters));
|
|
104
104
|
try {
|
|
105
|
-
const { createCliCircuitBreakerIntegration } = await import("./cli-circuit-breaker-
|
|
105
|
+
const { createCliCircuitBreakerIntegration } = await import("./cli-circuit-breaker-OR2Z2ZXU.js");
|
|
106
106
|
cachedCircuitBreaker = createCliCircuitBreakerIntegration([...adapters.values()]);
|
|
107
107
|
} catch (error) {
|
|
108
108
|
const msg = error instanceof Error ? error.message : String(error);
|
|
@@ -213,4 +213,4 @@ export {
|
|
|
213
213
|
tokenSplitFromUsage,
|
|
214
214
|
executeExpert
|
|
215
215
|
};
|
|
216
|
-
//# sourceMappingURL=chunk-
|
|
216
|
+
//# sourceMappingURL=chunk-IBRRXLMJ.js.map
|
|
@@ -3,14 +3,14 @@ import {
|
|
|
3
3
|
createStream,
|
|
4
4
|
requireApiKey,
|
|
5
5
|
validateApiKeyPresence
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-3S4N6OCF.js";
|
|
7
7
|
import {
|
|
8
8
|
ModelCapability,
|
|
9
9
|
err,
|
|
10
10
|
getCliModelName,
|
|
11
11
|
getTokenEstimator,
|
|
12
12
|
ok
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-ZXF2XA4R.js";
|
|
14
14
|
|
|
15
15
|
// src/adapters/openai-types.ts
|
|
16
16
|
var OPENAI_MODELS = {
|
|
@@ -553,4 +553,4 @@ export {
|
|
|
553
553
|
OpenAIAdapter,
|
|
554
554
|
createOpenAIAdapter
|
|
555
555
|
};
|
|
556
|
-
//# sourceMappingURL=chunk-
|
|
556
|
+
//# sourceMappingURL=chunk-KTPMJSLZ.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
OpenAIAdapter
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-KTPMJSLZ.js";
|
|
4
4
|
import {
|
|
5
5
|
ConfigError,
|
|
6
6
|
createLogger,
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
getTimeProvider,
|
|
10
10
|
lookupInTreeCapability,
|
|
11
11
|
ok
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-ZXF2XA4R.js";
|
|
13
13
|
import {
|
|
14
14
|
getNexusDataDir
|
|
15
15
|
} from "./chunk-CH7QIDHQ.js";
|
|
@@ -307,4 +307,4 @@ export {
|
|
|
307
307
|
discoverModels,
|
|
308
308
|
buildOpenAICompatAdapters
|
|
309
309
|
};
|
|
310
|
-
//# sourceMappingURL=chunk-
|
|
310
|
+
//# sourceMappingURL=chunk-MD6TVSOI.js.map
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
TASK_CATEGORIES,
|
|
3
3
|
getAdaptiveBonus,
|
|
4
4
|
getOutcomeStore
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-ZXF2XA4R.js";
|
|
6
6
|
|
|
7
7
|
// src/cli/doctor-deep.ts
|
|
8
8
|
var CLI_NAMES = ["claude", "gemini", "codex", "opencode"];
|
|
@@ -106,4 +106,4 @@ export {
|
|
|
106
106
|
runDeepDiagnostics,
|
|
107
107
|
formatDeepDiagnostics
|
|
108
108
|
};
|
|
109
|
-
//# sourceMappingURL=chunk-
|
|
109
|
+
//# sourceMappingURL=chunk-MYN7CMD5.js.map
|
|
@@ -1,147 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
} from "./chunk-
|
|
2
|
+
loadPapersRegistry
|
|
3
|
+
} from "./chunk-E2ER3LQF.js";
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
err,
|
|
8
|
-
getErrorMessage,
|
|
9
|
-
ok,
|
|
10
|
-
parseBoolEnv
|
|
11
|
-
} from "./chunk-JRBUSUYD.js";
|
|
5
|
+
getErrorMessage
|
|
6
|
+
} from "./chunk-ZXF2XA4R.js";
|
|
12
7
|
|
|
13
8
|
// src/cli/research-helpers-synthesize.ts
|
|
14
9
|
import { z } from "zod";
|
|
15
10
|
|
|
16
|
-
// src/cli/research-helpers-io.ts
|
|
17
|
-
import * as fs2 from "fs/promises";
|
|
18
|
-
import { join, resolve as resolve2 } from "path";
|
|
19
|
-
import { parse as parseYaml, stringify as stringifyYaml2 } from "yaml";
|
|
20
|
-
|
|
21
|
-
// src/cli/research-scaffold.ts
|
|
22
|
-
import * as fs from "fs/promises";
|
|
23
|
-
import { existsSync } from "fs";
|
|
24
|
-
import { dirname, resolve } from "path";
|
|
25
|
-
import { stringify as stringifyYaml } from "yaml";
|
|
26
|
-
var SCHEMA_VERSION = "1.0";
|
|
27
|
-
var ANNOUNCED = /* @__PURE__ */ new Set();
|
|
28
|
-
function announceOnce(path, kind) {
|
|
29
|
-
if (ANNOUNCED.has(path)) return;
|
|
30
|
-
ANNOUNCED.add(path);
|
|
31
|
-
process.stderr.write(
|
|
32
|
-
`[scaffold] Created empty ${kind} at ${path}; add entries via 'nexus-agents research add' or research_add MCP tool.
|
|
33
|
-
`
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
function scaffoldDisabled() {
|
|
37
|
-
return parseBoolEnv("NEXUS_NO_SCAFFOLD", false);
|
|
38
|
-
}
|
|
39
|
-
function emptyPapersYaml() {
|
|
40
|
-
return stringifyYaml({ schema_version: SCHEMA_VERSION, papers: {} });
|
|
41
|
-
}
|
|
42
|
-
function emptyTechniquesYaml() {
|
|
43
|
-
return stringifyYaml({ schema_version: SCHEMA_VERSION, techniques: {} });
|
|
44
|
-
}
|
|
45
|
-
async function ensureRegistryFile(rootDir, filename) {
|
|
46
|
-
const filePath = resolve(rootDir, REGISTRY_PATH, filename);
|
|
47
|
-
if (existsSync(filePath)) return ok(filePath);
|
|
48
|
-
if (scaffoldDisabled()) {
|
|
49
|
-
return err(
|
|
50
|
-
new ParseError(
|
|
51
|
-
`Registry file missing: ${filePath}. Scaffolding disabled (NEXUS_NO_SCAFFOLD=1). Create the file manually or unset the env var.`
|
|
52
|
-
)
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
if (!existsSync(resolve(rootDir, "docs"))) {
|
|
56
|
-
return err(
|
|
57
|
-
new ParseError(
|
|
58
|
-
`Registry file missing: ${filePath}. ${rootDir}/docs/ does not exist; refusing to create a Nexus subtree in a non-documented root. Run 'nexus-agents init' first, or create ${rootDir}/docs/ manually.`
|
|
59
|
-
)
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
try {
|
|
63
|
-
await fs.mkdir(dirname(filePath), { recursive: true });
|
|
64
|
-
const content = filename === PAPERS_FILE ? emptyPapersYaml() : emptyTechniquesYaml();
|
|
65
|
-
await fs.writeFile(filePath, content, "utf-8");
|
|
66
|
-
announceOnce(filePath, filename);
|
|
67
|
-
return ok(filePath);
|
|
68
|
-
} catch (e) {
|
|
69
|
-
return err(
|
|
70
|
-
new ParseError(
|
|
71
|
-
`Failed to scaffold ${filename} at ${filePath}: ${getErrorMessage(e)}. Set NEXUS_NO_SCAFFOLD=1 and create manually if scaffolding is unwanted.`
|
|
72
|
-
)
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// src/cli/research-helpers-io.ts
|
|
78
|
-
var REGISTRY_PATH = "docs/research/registry";
|
|
79
|
-
var TECHNIQUES_FILE = "techniques.yaml";
|
|
80
|
-
var PAPERS_FILE = "papers.yaml";
|
|
81
|
-
function getProjectRoot() {
|
|
82
|
-
return process.cwd();
|
|
83
|
-
}
|
|
84
|
-
function validatePath(constructedPath, allowedRoot) {
|
|
85
|
-
const resolved = resolveInsideRoot(constructedPath, allowedRoot);
|
|
86
|
-
if (resolved === null) {
|
|
87
|
-
return {
|
|
88
|
-
ok: false,
|
|
89
|
-
error: new SecurityError("Path traversal detected: path escapes allowed root directory", {
|
|
90
|
-
context: { constructedPath, allowedRoot: resolve2(allowedRoot) }
|
|
91
|
-
})
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
return { ok: true, value: resolved };
|
|
95
|
-
}
|
|
96
|
-
async function loadTechniquesRegistry(rootDir) {
|
|
97
|
-
const root = rootDir ?? process.cwd();
|
|
98
|
-
const filePath = join(root, REGISTRY_PATH, TECHNIQUES_FILE);
|
|
99
|
-
const pathValidation = validatePath(filePath, root);
|
|
100
|
-
if (!pathValidation.ok) {
|
|
101
|
-
return pathValidation;
|
|
102
|
-
}
|
|
103
|
-
await ensureRegistryFile(root, TECHNIQUES_FILE);
|
|
104
|
-
try {
|
|
105
|
-
const content = await fs2.readFile(pathValidation.value, "utf-8");
|
|
106
|
-
return { ok: true, value: parseYaml(content) };
|
|
107
|
-
} catch (error) {
|
|
108
|
-
const message = getErrorMessage(error);
|
|
109
|
-
return { ok: false, error: new ParseError(`Failed to load techniques registry: ${message}`) };
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
async function loadPapersRegistry(rootDir) {
|
|
113
|
-
const root = rootDir ?? process.cwd();
|
|
114
|
-
const filePath = join(root, REGISTRY_PATH, PAPERS_FILE);
|
|
115
|
-
const pathValidation = validatePath(filePath, root);
|
|
116
|
-
if (!pathValidation.ok) {
|
|
117
|
-
return pathValidation;
|
|
118
|
-
}
|
|
119
|
-
await ensureRegistryFile(root, PAPERS_FILE);
|
|
120
|
-
try {
|
|
121
|
-
const content = await fs2.readFile(pathValidation.value, "utf-8");
|
|
122
|
-
return { ok: true, value: parseYaml(content) };
|
|
123
|
-
} catch (error) {
|
|
124
|
-
const message = getErrorMessage(error);
|
|
125
|
-
return { ok: false, error: new ParseError(`Failed to load papers registry: ${message}`) };
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
async function savePapersRegistry(registry, rootDir) {
|
|
129
|
-
const root = rootDir ?? process.cwd();
|
|
130
|
-
const filePath = join(root, REGISTRY_PATH, PAPERS_FILE);
|
|
131
|
-
const pathValidation = validatePath(filePath, root);
|
|
132
|
-
if (!pathValidation.ok) {
|
|
133
|
-
return pathValidation;
|
|
134
|
-
}
|
|
135
|
-
try {
|
|
136
|
-
const content = stringifyYaml2(registry, { lineWidth: 100 });
|
|
137
|
-
await fs2.writeFile(pathValidation.value, content, "utf-8");
|
|
138
|
-
return { ok: true, value: void 0 };
|
|
139
|
-
} catch (error) {
|
|
140
|
-
const message = getErrorMessage(error);
|
|
141
|
-
return { ok: false, error: new ParseError(`Failed to save papers registry: ${message}`) };
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
11
|
// src/cli/research-alignment-map.ts
|
|
146
12
|
var TECHNIQUE_IMPLEMENTATION_MAP = /* @__PURE__ */ new Map([
|
|
147
13
|
// Routing techniques
|
|
@@ -1006,13 +872,8 @@ function attributeFindings(papers) {
|
|
|
1006
872
|
}
|
|
1007
873
|
|
|
1008
874
|
export {
|
|
1009
|
-
REGISTRY_PATH,
|
|
1010
|
-
getProjectRoot,
|
|
1011
|
-
loadTechniquesRegistry,
|
|
1012
|
-
loadPapersRegistry,
|
|
1013
|
-
savePapersRegistry,
|
|
1014
875
|
normalizeTopicToCanonical,
|
|
1015
876
|
AttributedInsightSchema,
|
|
1016
877
|
synthesizeResearch
|
|
1017
878
|
};
|
|
1018
|
-
//# sourceMappingURL=chunk-
|
|
879
|
+
//# sourceMappingURL=chunk-N7NCTB3O.js.map
|