@cleocode/adapters 2026.4.48 → 2026.4.49
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/cant-context.d.ts +132 -1
- package/dist/cant-context.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +204 -4
- package/dist/index.js.map +3 -3
- package/dist/providers/claude-code/hooks.d.ts.map +1 -1
- package/dist/providers/claude-code/spawn.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/cant-context.ts +397 -3
- package/src/index.ts +16 -2
- package/src/providers/claude-code/hooks.ts +7 -1
- package/src/providers/claude-code/spawn.ts +5 -1
package/dist/cant-context.d.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* 1. Compiled CANT bundle (team topology, agent personas, tool ACLs)
|
|
9
9
|
* 2. Memory bridge (recent decisions, handoff notes, key patterns)
|
|
10
10
|
* 3. Mental model injection (validate-on-load agent-specific observations)
|
|
11
|
+
* 4. NEXUS code intelligence context (callers, callees, impact data) [T625]
|
|
11
12
|
*
|
|
12
13
|
* All operations are best-effort: if any step fails (missing packages, empty
|
|
13
14
|
* directories, compilation errors), the base prompt is returned unchanged.
|
|
@@ -17,6 +18,7 @@
|
|
|
17
18
|
* (Pi-only; this module generalizes the same logic for all providers)
|
|
18
19
|
*
|
|
19
20
|
* @task T555
|
|
21
|
+
* @task T625
|
|
20
22
|
*/
|
|
21
23
|
/** Per-tier file counts for diagnostic reporting. */
|
|
22
24
|
export interface TierDiscoveryStats {
|
|
@@ -52,6 +54,70 @@ export interface BuildCantEnrichedPromptOptions {
|
|
|
52
54
|
* Use this to avoid double-compilation when the Pi bridge already compiled the bundle.
|
|
53
55
|
*/
|
|
54
56
|
compiledBundle?: string;
|
|
57
|
+
/**
|
|
58
|
+
* Task ID to inject NEXUS code intelligence context for.
|
|
59
|
+
* When provided, step 6b fetches callers/callees/impact for symbols
|
|
60
|
+
* mentioned in the task description and injects them into the prompt.
|
|
61
|
+
*
|
|
62
|
+
* @task T625
|
|
63
|
+
*/
|
|
64
|
+
taskId?: string;
|
|
65
|
+
}
|
|
66
|
+
/** A single symbol's NEXUS context entry (callers, callees, impact). */
|
|
67
|
+
export interface NexusSymbolContext {
|
|
68
|
+
/** Symbol name as resolved in the code index. */
|
|
69
|
+
name: string;
|
|
70
|
+
/** Symbol kind (function, method, class, etc.). */
|
|
71
|
+
kind: string;
|
|
72
|
+
/** File path (relative to project root) where the symbol is defined. */
|
|
73
|
+
filePath: string | null;
|
|
74
|
+
/** Symbols that call this one (direct callers). */
|
|
75
|
+
callers: Array<{
|
|
76
|
+
name: string;
|
|
77
|
+
kind: string;
|
|
78
|
+
filePath: string | null;
|
|
79
|
+
}>;
|
|
80
|
+
/** Symbols that this one calls (direct callees). */
|
|
81
|
+
callees: Array<{
|
|
82
|
+
name: string;
|
|
83
|
+
kind: string;
|
|
84
|
+
filePath: string | null;
|
|
85
|
+
}>;
|
|
86
|
+
/** Risk level from impact analysis. */
|
|
87
|
+
riskLevel: string;
|
|
88
|
+
/** Total number of transitively impacted nodes. */
|
|
89
|
+
totalImpacted: number;
|
|
90
|
+
}
|
|
91
|
+
/** Options for {@link buildNexusContext}. */
|
|
92
|
+
export interface BuildNexusContextOptions {
|
|
93
|
+
/** Symbols to query NEXUS for (extracted from task description). */
|
|
94
|
+
symbols: string[];
|
|
95
|
+
/** Project root directory (used to resolve project ID and run CLI commands). */
|
|
96
|
+
projectDir: string;
|
|
97
|
+
/** Maximum callers/callees to include per symbol (default: 10). */
|
|
98
|
+
limit?: number;
|
|
99
|
+
/**
|
|
100
|
+
* CLI timeout in milliseconds for each `cleo nexus context` call (default: 10000).
|
|
101
|
+
*/
|
|
102
|
+
timeoutMs?: number;
|
|
103
|
+
}
|
|
104
|
+
/** Result of a post-modification NEXUS check (T625). */
|
|
105
|
+
export interface NexusModificationCheckResult {
|
|
106
|
+
/**
|
|
107
|
+
* True if the incremental re-analysis completed successfully.
|
|
108
|
+
* False if the analysis failed (non-fatal — agents should still continue).
|
|
109
|
+
*/
|
|
110
|
+
success: boolean;
|
|
111
|
+
/** Files that were re-indexed. */
|
|
112
|
+
reindexedFiles: string[];
|
|
113
|
+
/** Relations that exist in the post-check index but not in the snapshot. */
|
|
114
|
+
newRelations: number;
|
|
115
|
+
/** Relations that existed in the snapshot but are missing after re-analysis. */
|
|
116
|
+
removedRelations: number;
|
|
117
|
+
/** Human-readable summary of what changed. */
|
|
118
|
+
summary: string;
|
|
119
|
+
/** Any regressions detected (broken call chains, missing symbols). */
|
|
120
|
+
regressions: string[];
|
|
55
121
|
}
|
|
56
122
|
/**
|
|
57
123
|
* Recursively discover `.cant` files in a directory.
|
|
@@ -140,6 +206,70 @@ export declare function readIdentityFile(projectDir: string): string | null;
|
|
|
140
206
|
* @returns The fully assembled identity block, or "" if unavailable.
|
|
141
207
|
*/
|
|
142
208
|
export declare function buildIdentityBootstrap(projectDir: string): Promise<string>;
|
|
209
|
+
/**
|
|
210
|
+
* Extract candidate symbol names from a task description or title.
|
|
211
|
+
*
|
|
212
|
+
* Uses a simple heuristic: camelCase, PascalCase, and snake_case tokens
|
|
213
|
+
* longer than 3 characters that look like code identifiers.
|
|
214
|
+
*
|
|
215
|
+
* Pure function — no I/O.
|
|
216
|
+
*
|
|
217
|
+
* @param text - Raw text to scan for symbol names (task title + description).
|
|
218
|
+
* @returns Deduplicated array of candidate symbol names, longest first.
|
|
219
|
+
*/
|
|
220
|
+
export declare function extractSymbolsFromText(text: string): string[];
|
|
221
|
+
/**
|
|
222
|
+
* Build a NEXUS code intelligence context block for a set of symbols.
|
|
223
|
+
*
|
|
224
|
+
* Queries `cleo nexus context <symbol> --json` for each symbol and
|
|
225
|
+
* returns a formatted prompt block with callers, callees, and impact data.
|
|
226
|
+
*
|
|
227
|
+
* All CLI calls are best-effort with a configurable timeout. Failures
|
|
228
|
+
* for individual symbols are silently skipped.
|
|
229
|
+
*
|
|
230
|
+
* @param options - Symbols, project dir, and optional limits.
|
|
231
|
+
* @returns Array of resolved NEXUS symbol contexts.
|
|
232
|
+
* @task T625
|
|
233
|
+
*/
|
|
234
|
+
export declare function buildNexusContext(options: BuildNexusContextOptions): Promise<NexusSymbolContext[]>;
|
|
235
|
+
/**
|
|
236
|
+
* Format a NEXUS context array into a system-prompt block.
|
|
237
|
+
*
|
|
238
|
+
* Pure function — no I/O, safe to call in tests without a real DB.
|
|
239
|
+
*
|
|
240
|
+
* @param contexts - Resolved NEXUS symbol contexts.
|
|
241
|
+
* @returns Formatted prompt block, or empty string when contexts is empty.
|
|
242
|
+
* @task T625
|
|
243
|
+
*/
|
|
244
|
+
export declare function buildNexusContextBlock(contexts: NexusSymbolContext[]): string;
|
|
245
|
+
/**
|
|
246
|
+
* Inject NEXUS context for a task into the agent prompt.
|
|
247
|
+
*
|
|
248
|
+
* Fetches the task details from CLEO, extracts symbol names from the
|
|
249
|
+
* task title and description, then queries NEXUS for each symbol.
|
|
250
|
+
* Returns a formatted prompt block or empty string on any failure.
|
|
251
|
+
*
|
|
252
|
+
* @param taskId - CLEO task ID (e.g. "T625").
|
|
253
|
+
* @param projectDir - Project root directory.
|
|
254
|
+
* @returns Formatted NEXUS context block, or "" if unavailable.
|
|
255
|
+
* @task T625
|
|
256
|
+
*/
|
|
257
|
+
export declare function buildNexusContextForTask(taskId: string, projectDir: string): Promise<string>;
|
|
258
|
+
/**
|
|
259
|
+
* Run a post-modification NEXUS check on a set of changed files.
|
|
260
|
+
*
|
|
261
|
+
* Performs an incremental re-analysis of the changed files and compares
|
|
262
|
+
* relation counts before/after. Regressions (net loss of relations after
|
|
263
|
+
* modification) are flagged and returned for BRAIN storage.
|
|
264
|
+
*
|
|
265
|
+
* All operations are best-effort — never throws.
|
|
266
|
+
*
|
|
267
|
+
* @param changedFiles - Absolute paths to files that were modified.
|
|
268
|
+
* @param projectDir - Project root directory.
|
|
269
|
+
* @returns Check result with regression data.
|
|
270
|
+
* @task T625
|
|
271
|
+
*/
|
|
272
|
+
export declare function runNexusPostModificationCheck(changedFiles: string[], projectDir: string): Promise<NexusModificationCheckResult>;
|
|
143
273
|
/**
|
|
144
274
|
* Build an enriched prompt with CANT context, memory bridge, and mental model.
|
|
145
275
|
*
|
|
@@ -152,7 +282,8 @@ export declare function buildIdentityBootstrap(projectDir: string): Promise<stri
|
|
|
152
282
|
* 3. Renders the compiled system prompt
|
|
153
283
|
* 4. Reads the memory bridge from `.cleo/memory-bridge.md`
|
|
154
284
|
* 5. Fetches mental model observations for the named agent
|
|
155
|
-
*
|
|
285
|
+
* 6b. Injects NEXUS code intelligence context for the task (T625)
|
|
286
|
+
* 7. Concatenates: basePrompt + CANT bundle + memory bridge + mental model + NEXUS
|
|
156
287
|
*
|
|
157
288
|
* All operations are best-effort. If any step fails, the base prompt is
|
|
158
289
|
* returned unchanged. CANT context is an enrichment, not a gate — agents
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cant-context.d.ts","sourceRoot":"","sources":["../src/cant-context.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"cant-context.d.ts","sourceRoot":"","sources":["../src/cant-context.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
* The {@link discoverProviders} function and {@link getProviderManifests}
|
|
13
13
|
* registry enable dynamic adapter loading by AdapterManager.
|
|
14
14
|
*/
|
|
15
|
-
export type { BuildCantEnrichedPromptOptions, TierDiscoveryStats } from './cant-context.js';
|
|
16
|
-
export { buildCantEnrichedPrompt } from './cant-context.js';
|
|
15
|
+
export type { BuildCantEnrichedPromptOptions, BuildNexusContextOptions, NexusModificationCheckResult, NexusSymbolContext, TierDiscoveryStats, } from './cant-context.js';
|
|
16
|
+
export { buildCantEnrichedPrompt, buildNexusContext, buildNexusContextBlock, buildNexusContextForTask, extractSymbolsFromText, runNexusPostModificationCheck, } from './cant-context.js';
|
|
17
17
|
export { ClaudeCodeAdapter, ClaudeCodeContextMonitorProvider, ClaudeCodeHookProvider, ClaudeCodeInstallProvider, ClaudeCodePathProvider, ClaudeCodeSpawnProvider, ClaudeCodeTransportProvider, checkStatuslineIntegration, createAdapter as createClaudeCodeAdapter, getSetupInstructions, getStatuslineConfig, } from './providers/claude-code/index.js';
|
|
18
18
|
export type { McpServerMap, McpStdioConfig, SessionEntry } from './providers/claude-sdk/index.js';
|
|
19
19
|
export { ClaudeSDKSpawnProvider, DEFAULT_TOOLS, getServers, resolveTools, SessionStore, } from './providers/claude-sdk/index.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,YAAY,EACV,8BAA8B,EAC9B,wBAAwB,EACxB,4BAA4B,EAC5B,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,uBAAuB,EAEvB,iBAAiB,EACjB,sBAAsB,EACtB,wBAAwB,EACxB,sBAAsB,EACtB,6BAA6B,GAC9B,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,iBAAiB,EACjB,gCAAgC,EAChC,sBAAsB,EACtB,yBAAyB,EACzB,sBAAsB,EACtB,uBAAuB,EACvB,2BAA2B,EAC3B,0BAA0B,EAC1B,aAAa,IAAI,uBAAuB,EACxC,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,kCAAkC,CAAC;AAC1C,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAClG,OAAO,EACL,sBAAsB,EACtB,aAAa,EACb,UAAU,EACV,YAAY,EACZ,YAAY,GACb,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,oBAAoB,EACpB,aAAa,IAAI,kBAAkB,GACpC,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,qBAAqB,EACrB,aAAa,IAAI,mBAAmB,GACrC,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,aAAa,IAAI,sBAAsB,EACvC,gBAAgB,EAChB,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,aAAa,IAAI,iBAAiB,EAClC,WAAW,EACX,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,aAAa,IAAI,qBAAqB,EACtC,eAAe,EACf,oBAAoB,EACpB,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AACvC,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -15,11 +15,16 @@ __export(cant_context_exports, {
|
|
|
15
15
|
buildIdentityBootstrap: () => buildIdentityBootstrap,
|
|
16
16
|
buildMemoryBridgeBlock: () => buildMemoryBridgeBlock,
|
|
17
17
|
buildMentalModelInjection: () => buildMentalModelInjection,
|
|
18
|
+
buildNexusContext: () => buildNexusContext,
|
|
19
|
+
buildNexusContextBlock: () => buildNexusContextBlock,
|
|
20
|
+
buildNexusContextForTask: () => buildNexusContextForTask,
|
|
18
21
|
discoverCantFiles: () => discoverCantFiles,
|
|
19
22
|
discoverCantFilesMultiTier: () => discoverCantFilesMultiTier,
|
|
23
|
+
extractSymbolsFromText: () => extractSymbolsFromText,
|
|
20
24
|
readIdentityFile: () => readIdentityFile,
|
|
21
25
|
readMemoryBridge: () => readMemoryBridge,
|
|
22
|
-
resolveThreeTierPaths: () => resolveThreeTierPaths
|
|
26
|
+
resolveThreeTierPaths: () => resolveThreeTierPaths,
|
|
27
|
+
runNexusPostModificationCheck: () => runNexusPostModificationCheck
|
|
23
28
|
});
|
|
24
29
|
import { execFile } from "node:child_process";
|
|
25
30
|
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
@@ -225,8 +230,179 @@ async function buildIdentityBootstrap(projectDir) {
|
|
|
225
230
|
sections.push("===== END IDENTITY BOOTSTRAP =====");
|
|
226
231
|
return sections.join("\n");
|
|
227
232
|
}
|
|
233
|
+
function extractSymbolsFromText(text) {
|
|
234
|
+
const identifierPattern = /\b([A-Z][a-zA-Z0-9]{3,}|[a-z][a-zA-Z0-9]{3,}[A-Z][a-zA-Z0-9]*|[a-z]{2,}_[a-z][a-zA-Z0-9_]*)\b/g;
|
|
235
|
+
const seen = /* @__PURE__ */ new Set();
|
|
236
|
+
const matches = [];
|
|
237
|
+
for (const matchResult of text.matchAll(identifierPattern)) {
|
|
238
|
+
const symbol = matchResult[1];
|
|
239
|
+
if (symbol && !seen.has(symbol)) {
|
|
240
|
+
seen.add(symbol);
|
|
241
|
+
matches.push(symbol);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return matches.sort((a3, b4) => b4.length - a3.length).slice(0, 8);
|
|
245
|
+
}
|
|
246
|
+
async function buildNexusContext(options) {
|
|
247
|
+
const { symbols, projectDir, limit = 10, timeoutMs = 1e4 } = options;
|
|
248
|
+
if (symbols.length === 0) return [];
|
|
249
|
+
const results = [];
|
|
250
|
+
for (const symbol of symbols) {
|
|
251
|
+
try {
|
|
252
|
+
const { stdout } = await execFileAsync(
|
|
253
|
+
"cleo",
|
|
254
|
+
["nexus", "context", symbol, "--json", "--limit", String(limit)],
|
|
255
|
+
{ timeout: timeoutMs, cwd: projectDir || void 0 }
|
|
256
|
+
);
|
|
257
|
+
const parsed = JSON.parse(stdout);
|
|
258
|
+
if (!parsed.success || !parsed.data?.results?.length) continue;
|
|
259
|
+
let riskLevel = "UNKNOWN";
|
|
260
|
+
let totalImpacted = 0;
|
|
261
|
+
try {
|
|
262
|
+
const { stdout: impactStdout } = await execFileAsync(
|
|
263
|
+
"cleo",
|
|
264
|
+
["nexus", "impact", symbol, "--json", "--depth", "2"],
|
|
265
|
+
{ timeout: timeoutMs, cwd: projectDir || void 0 }
|
|
266
|
+
);
|
|
267
|
+
const impactParsed = JSON.parse(impactStdout);
|
|
268
|
+
if (impactParsed.success && impactParsed.data) {
|
|
269
|
+
riskLevel = String(impactParsed.data.riskLevel ?? "UNKNOWN");
|
|
270
|
+
totalImpacted = Number(impactParsed.data.totalImpactedNodes ?? 0);
|
|
271
|
+
}
|
|
272
|
+
} catch {
|
|
273
|
+
}
|
|
274
|
+
const primary = parsed.data.results[0];
|
|
275
|
+
if (!primary) continue;
|
|
276
|
+
results.push({
|
|
277
|
+
name: String(primary.name ?? symbol),
|
|
278
|
+
kind: String(primary.kind ?? "unknown"),
|
|
279
|
+
filePath: primary.filePath ? String(primary.filePath) : null,
|
|
280
|
+
callers: (primary.callers ?? []).slice(0, limit).map((c3) => ({
|
|
281
|
+
name: String(c3.name ?? ""),
|
|
282
|
+
kind: String(c3.kind ?? "unknown"),
|
|
283
|
+
filePath: c3.filePath ? String(c3.filePath) : null
|
|
284
|
+
})),
|
|
285
|
+
callees: (primary.callees ?? []).slice(0, limit).map((c3) => ({
|
|
286
|
+
name: String(c3.name ?? ""),
|
|
287
|
+
kind: String(c3.kind ?? "unknown"),
|
|
288
|
+
filePath: c3.filePath ? String(c3.filePath) : null
|
|
289
|
+
})),
|
|
290
|
+
riskLevel,
|
|
291
|
+
totalImpacted
|
|
292
|
+
});
|
|
293
|
+
} catch {
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return results;
|
|
297
|
+
}
|
|
298
|
+
function buildNexusContextBlock(contexts) {
|
|
299
|
+
if (contexts.length === 0) return "";
|
|
300
|
+
const lines = [
|
|
301
|
+
"",
|
|
302
|
+
"===== NEXUS CODE INTELLIGENCE (pre-modification context) =====",
|
|
303
|
+
"Consult this before modifying any of these symbols.",
|
|
304
|
+
"High-risk symbols MUST be checked for callers before editing.",
|
|
305
|
+
""
|
|
306
|
+
];
|
|
307
|
+
for (const ctx of contexts) {
|
|
308
|
+
lines.push(`## ${ctx.name} [${ctx.kind}]${ctx.filePath ? ` ${ctx.filePath}` : ""}`);
|
|
309
|
+
lines.push(` Risk: ${ctx.riskLevel} | Impacted nodes: ${ctx.totalImpacted}`);
|
|
310
|
+
if (ctx.callers.length > 0) {
|
|
311
|
+
lines.push(
|
|
312
|
+
` Callers (${ctx.callers.length}): ${ctx.callers.map((c3) => c3.name).join(", ")}`
|
|
313
|
+
);
|
|
314
|
+
} else {
|
|
315
|
+
lines.push(" Callers: none");
|
|
316
|
+
}
|
|
317
|
+
if (ctx.callees.length > 0) {
|
|
318
|
+
lines.push(
|
|
319
|
+
` Callees (${ctx.callees.length}): ${ctx.callees.map((c3) => c3.name).join(", ")}`
|
|
320
|
+
);
|
|
321
|
+
} else {
|
|
322
|
+
lines.push(" Callees: none");
|
|
323
|
+
}
|
|
324
|
+
lines.push("");
|
|
325
|
+
}
|
|
326
|
+
lines.push("===== END NEXUS CONTEXT =====");
|
|
327
|
+
return lines.join("\n");
|
|
328
|
+
}
|
|
329
|
+
async function buildNexusContextForTask(taskId, projectDir) {
|
|
330
|
+
try {
|
|
331
|
+
const { stdout: taskStdout } = await execFileAsync("cleo", ["show", taskId, "--json"], {
|
|
332
|
+
timeout: 8e3,
|
|
333
|
+
cwd: projectDir || void 0
|
|
334
|
+
});
|
|
335
|
+
const taskData = JSON.parse(taskStdout);
|
|
336
|
+
const title = taskData?.data?.title ?? "";
|
|
337
|
+
const description = taskData?.data?.description ?? "";
|
|
338
|
+
const combinedText = `${title} ${description}`;
|
|
339
|
+
const symbols = extractSymbolsFromText(combinedText);
|
|
340
|
+
if (symbols.length === 0) return "";
|
|
341
|
+
const contexts = await buildNexusContext({ symbols, projectDir });
|
|
342
|
+
return buildNexusContextBlock(contexts);
|
|
343
|
+
} catch {
|
|
344
|
+
return "";
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
async function runNexusPostModificationCheck(changedFiles, projectDir) {
|
|
348
|
+
const empty = {
|
|
349
|
+
success: false,
|
|
350
|
+
reindexedFiles: [],
|
|
351
|
+
newRelations: 0,
|
|
352
|
+
removedRelations: 0,
|
|
353
|
+
summary: "NEXUS post-check unavailable",
|
|
354
|
+
regressions: []
|
|
355
|
+
};
|
|
356
|
+
if (changedFiles.length === 0) return empty;
|
|
357
|
+
try {
|
|
358
|
+
const { stdout: beforeStdout } = await execFileAsync("cleo", ["nexus", "status", "--json"], {
|
|
359
|
+
timeout: 8e3,
|
|
360
|
+
cwd: projectDir || void 0
|
|
361
|
+
});
|
|
362
|
+
let relationsBefore = 0;
|
|
363
|
+
try {
|
|
364
|
+
const beforeData = JSON.parse(beforeStdout);
|
|
365
|
+
relationsBefore = beforeData?.data?.relationCount ?? beforeData?.data?.relations ?? 0;
|
|
366
|
+
} catch {
|
|
367
|
+
}
|
|
368
|
+
await execFileAsync("cleo", ["nexus", "analyze", projectDir, "--incremental", "--json"], {
|
|
369
|
+
timeout: 6e4,
|
|
370
|
+
cwd: projectDir || void 0
|
|
371
|
+
});
|
|
372
|
+
const { stdout: afterStdout } = await execFileAsync("cleo", ["nexus", "status", "--json"], {
|
|
373
|
+
timeout: 8e3,
|
|
374
|
+
cwd: projectDir || void 0
|
|
375
|
+
});
|
|
376
|
+
let relationsAfter = 0;
|
|
377
|
+
try {
|
|
378
|
+
const afterData = JSON.parse(afterStdout);
|
|
379
|
+
relationsAfter = afterData?.data?.relationCount ?? afterData?.data?.relations ?? 0;
|
|
380
|
+
} catch {
|
|
381
|
+
}
|
|
382
|
+
const delta = relationsAfter - relationsBefore;
|
|
383
|
+
const newRelations = Math.max(0, delta);
|
|
384
|
+
const removedRelations = Math.max(0, -delta);
|
|
385
|
+
const regressions = [];
|
|
386
|
+
if (removedRelations > 5) {
|
|
387
|
+
regressions.push(
|
|
388
|
+
`Lost ${removedRelations} relations after modifying: ${changedFiles.map((f6) => f6.split("/").pop() ?? f6).join(", ")}`
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
const summary = delta === 0 ? `NEXUS stable \u2014 no relation changes after modifying ${changedFiles.length} file(s)` : delta > 0 ? `NEXUS: +${newRelations} new relations from ${changedFiles.length} file(s)` : `NEXUS: -${removedRelations} relations removed from ${changedFiles.length} file(s)${regressions.length > 0 ? " \u2014 REGRESSION DETECTED" : ""}`;
|
|
392
|
+
return {
|
|
393
|
+
success: true,
|
|
394
|
+
reindexedFiles: changedFiles,
|
|
395
|
+
newRelations,
|
|
396
|
+
removedRelations,
|
|
397
|
+
summary,
|
|
398
|
+
regressions
|
|
399
|
+
};
|
|
400
|
+
} catch {
|
|
401
|
+
return empty;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
228
404
|
async function buildCantEnrichedPrompt(options) {
|
|
229
|
-
const { projectDir, basePrompt, agentName, isMainAgent, compiledBundle } = options;
|
|
405
|
+
const { projectDir, basePrompt, agentName, isMainAgent, compiledBundle, taskId } = options;
|
|
230
406
|
let appendix = "";
|
|
231
407
|
if (isMainAgent) {
|
|
232
408
|
try {
|
|
@@ -282,6 +458,15 @@ ${mentalModel}`;
|
|
|
282
458
|
} catch {
|
|
283
459
|
}
|
|
284
460
|
}
|
|
461
|
+
if (taskId) {
|
|
462
|
+
try {
|
|
463
|
+
const nexusBlock = await buildNexusContextForTask(taskId, projectDir);
|
|
464
|
+
if (nexusBlock) {
|
|
465
|
+
appendix += nexusBlock;
|
|
466
|
+
}
|
|
467
|
+
} catch {
|
|
468
|
+
}
|
|
469
|
+
}
|
|
285
470
|
return appendix ? basePrompt + appendix : basePrompt;
|
|
286
471
|
}
|
|
287
472
|
var execFileAsync, VALIDATE_ON_LOAD_PREAMBLE;
|
|
@@ -19880,6 +20065,12 @@ var init_hooks = __esm({
|
|
|
19880
20065
|
{
|
|
19881
20066
|
type: "command",
|
|
19882
20067
|
command: `cleo observe "File modified via $TOOL_NAME" --title "tool-use" --quiet # cleo-hook`
|
|
20068
|
+
},
|
|
20069
|
+
{
|
|
20070
|
+
// NEXUS post-modification check: re-index changed files and flag regressions.
|
|
20071
|
+
// $TOOL_INPUT_file_path is populated by Claude Code for Write/Edit events.
|
|
20072
|
+
type: "command",
|
|
20073
|
+
command: `cleo nexus analyze --incremental --json > /dev/null 2>&1 && cleo observe "NEXUS re-indexed after $TOOL_NAME on $TOOL_INPUT_file_path" --title "nexus-post-check" --quiet # cleo-hook`
|
|
19883
20074
|
}
|
|
19884
20075
|
]
|
|
19885
20076
|
});
|
|
@@ -20296,7 +20487,11 @@ var init_spawn2 = __esm({
|
|
|
20296
20487
|
enrichedPrompt = await buildCantEnrichedPrompt2({
|
|
20297
20488
|
projectDir: context.workingDirectory ?? process.cwd(),
|
|
20298
20489
|
basePrompt: context.prompt,
|
|
20299
|
-
agentName: context.options?.agentName ?? void 0
|
|
20490
|
+
agentName: context.options?.agentName ?? void 0,
|
|
20491
|
+
// Inject NEXUS code intelligence context for the task scope (T625).
|
|
20492
|
+
// This injects callers/callees/impact data so the agent understands
|
|
20493
|
+
// blast radius before modifying any symbol.
|
|
20494
|
+
taskId: context.taskId ?? void 0
|
|
20300
20495
|
});
|
|
20301
20496
|
} catch {
|
|
20302
20497
|
}
|
|
@@ -23501,6 +23696,9 @@ export {
|
|
|
23501
23696
|
OpenCodeSpawnProvider,
|
|
23502
23697
|
SessionStore,
|
|
23503
23698
|
buildCantEnrichedPrompt,
|
|
23699
|
+
buildNexusContext,
|
|
23700
|
+
buildNexusContextBlock,
|
|
23701
|
+
buildNexusContextForTask,
|
|
23504
23702
|
checkStatuslineIntegration,
|
|
23505
23703
|
createAdapter as createClaudeCodeAdapter,
|
|
23506
23704
|
createAdapter2 as createCodexAdapter,
|
|
@@ -23509,10 +23707,12 @@ export {
|
|
|
23509
23707
|
createAdapter5 as createKimiAdapter,
|
|
23510
23708
|
createAdapter6 as createOpenCodeAdapter,
|
|
23511
23709
|
discoverProviders,
|
|
23710
|
+
extractSymbolsFromText,
|
|
23512
23711
|
getProviderManifests,
|
|
23513
23712
|
getServers,
|
|
23514
23713
|
getSetupInstructions,
|
|
23515
23714
|
getStatuslineConfig,
|
|
23516
|
-
resolveTools
|
|
23715
|
+
resolveTools,
|
|
23716
|
+
runNexusPostModificationCheck
|
|
23517
23717
|
};
|
|
23518
23718
|
//# sourceMappingURL=index.js.map
|