@cleocode/cleo 2026.4.51 → 2026.4.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +666 -127
- package/dist/cli/index.js.map +4 -4
- package/package.json +8 -8
package/dist/cli/index.js
CHANGED
|
@@ -9600,11 +9600,14 @@ var init_brain_schema = __esm({
|
|
|
9600
9600
|
source: text("source").notNull(),
|
|
9601
9601
|
/** Estimated tokens consumed by this retrieval. */
|
|
9602
9602
|
tokensUsed: integer("tokens_used"),
|
|
9603
|
+
/** Session ID (soft FK to tasks.db sessions). Enables grouping retrievals by session for STDP analysis. */
|
|
9604
|
+
sessionId: text("session_id"),
|
|
9603
9605
|
createdAt: text("created_at").notNull().default(sql2`(datetime('now'))`)
|
|
9604
9606
|
},
|
|
9605
9607
|
(table) => [
|
|
9606
9608
|
index("idx_retrieval_log_created").on(table.createdAt),
|
|
9607
|
-
index("idx_retrieval_log_source").on(table.source)
|
|
9609
|
+
index("idx_retrieval_log_source").on(table.source),
|
|
9610
|
+
index("idx_retrieval_log_session").on(table.sessionId)
|
|
9608
9611
|
]
|
|
9609
9612
|
);
|
|
9610
9613
|
brainPlasticityEvents = sqliteTable(
|
|
@@ -11139,44 +11142,6 @@ var init_platform_paths = __esm({
|
|
|
11139
11142
|
});
|
|
11140
11143
|
|
|
11141
11144
|
// packages/core/src/paths.ts
|
|
11142
|
-
var paths_exports = {};
|
|
11143
|
-
__export(paths_exports, {
|
|
11144
|
-
getAgentOutputsAbsolute: () => getAgentOutputsAbsolute,
|
|
11145
|
-
getAgentOutputsDir: () => getAgentOutputsDir,
|
|
11146
|
-
getAgentsHome: () => getAgentsHome,
|
|
11147
|
-
getArchivePath: () => getArchivePath,
|
|
11148
|
-
getBackupDir: () => getBackupDir,
|
|
11149
|
-
getClaudeAgentsDir: () => getClaudeAgentsDir,
|
|
11150
|
-
getClaudeMemDbPath: () => getClaudeMemDbPath,
|
|
11151
|
-
getCleoCacheDir: () => getCleoCacheDir,
|
|
11152
|
-
getCleoCantWorkflowsDir: () => getCleoCantWorkflowsDir,
|
|
11153
|
-
getCleoConfigDir: () => getCleoConfigDir,
|
|
11154
|
-
getCleoDir: () => getCleoDir,
|
|
11155
|
-
getCleoDirAbsolute: () => getCleoDirAbsolute,
|
|
11156
|
-
getCleoDocsDir: () => getCleoDocsDir,
|
|
11157
|
-
getCleoGlobalAgentsDir: () => getCleoGlobalAgentsDir,
|
|
11158
|
-
getCleoGlobalJustfilePath: () => getCleoGlobalJustfilePath,
|
|
11159
|
-
getCleoGlobalRecipesDir: () => getCleoGlobalRecipesDir,
|
|
11160
|
-
getCleoHome: () => getCleoHome,
|
|
11161
|
-
getCleoLogDir: () => getCleoLogDir,
|
|
11162
|
-
getCleoPiExtensionsDir: () => getCleoPiExtensionsDir,
|
|
11163
|
-
getCleoSchemasDir: () => getCleoSchemasDir,
|
|
11164
|
-
getCleoTempDir: () => getCleoTempDir,
|
|
11165
|
-
getCleoTemplatesDir: () => getCleoTemplatesDir,
|
|
11166
|
-
getCleoTemplatesTildePath: () => getCleoTemplatesTildePath,
|
|
11167
|
-
getConfigPath: () => getConfigPath,
|
|
11168
|
-
getGlobalConfigPath: () => getGlobalConfigPath,
|
|
11169
|
-
getLogPath: () => getLogPath,
|
|
11170
|
-
getManifestArchivePath: () => getManifestArchivePath,
|
|
11171
|
-
getManifestPath: () => getManifestPath,
|
|
11172
|
-
getProjectRoot: () => getProjectRoot,
|
|
11173
|
-
getSessionsPath: () => getSessionsPath,
|
|
11174
|
-
getTaskPath: () => getTaskPath,
|
|
11175
|
-
isAbsolutePath: () => isAbsolutePath,
|
|
11176
|
-
isProjectInitialized: () => isProjectInitialized,
|
|
11177
|
-
resolveProjectPath: () => resolveProjectPath,
|
|
11178
|
-
worktreeScope: () => worktreeScope
|
|
11179
|
-
});
|
|
11180
11145
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
11181
11146
|
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "node:fs";
|
|
11182
11147
|
import { homedir } from "node:os";
|
|
@@ -11195,9 +11160,6 @@ function getCleoTemplatesDir() {
|
|
|
11195
11160
|
function getCleoSchemasDir() {
|
|
11196
11161
|
return join4(getCleoHome(), "schemas");
|
|
11197
11162
|
}
|
|
11198
|
-
function getCleoDocsDir() {
|
|
11199
|
-
return join4(getCleoHome(), "docs");
|
|
11200
|
-
}
|
|
11201
11163
|
function getCleoDir(cwd) {
|
|
11202
11164
|
if (cwd) {
|
|
11203
11165
|
return getCleoDirAbsolute(cwd);
|
|
@@ -11269,15 +11231,6 @@ function getTaskPath(cwd) {
|
|
|
11269
11231
|
function getConfigPath(cwd) {
|
|
11270
11232
|
return join4(getCleoDirAbsolute(cwd), "config.json");
|
|
11271
11233
|
}
|
|
11272
|
-
function getSessionsPath(cwd) {
|
|
11273
|
-
return join4(getCleoDirAbsolute(cwd), "sessions.json");
|
|
11274
|
-
}
|
|
11275
|
-
function getArchivePath(cwd) {
|
|
11276
|
-
return join4(getCleoDirAbsolute(cwd), "tasks-archive.json");
|
|
11277
|
-
}
|
|
11278
|
-
function getLogPath(cwd) {
|
|
11279
|
-
return join4(getCleoDirAbsolute(cwd), "logs", "cleo.log");
|
|
11280
|
-
}
|
|
11281
11234
|
function getBackupDir(cwd) {
|
|
11282
11235
|
return join4(getCleoDirAbsolute(cwd), "backups", "operational");
|
|
11283
11236
|
}
|
|
@@ -14330,8 +14283,8 @@ async function cleanupMigrationArtifacts(backupPath) {
|
|
|
14330
14283
|
}
|
|
14331
14284
|
async function validateSqliteDatabase(dbPath) {
|
|
14332
14285
|
try {
|
|
14333
|
-
const { createRequire:
|
|
14334
|
-
const _req =
|
|
14286
|
+
const { createRequire: createRequire20 } = await import("node:module");
|
|
14287
|
+
const _req = createRequire20(import.meta.url);
|
|
14335
14288
|
const { DatabaseSync: DatabaseSync10 } = _req("node:sqlite");
|
|
14336
14289
|
const db = new DatabaseSync10(dbPath, { readOnly: true });
|
|
14337
14290
|
const integrityRow = db.prepare("PRAGMA integrity_check").get();
|
|
@@ -14952,7 +14905,7 @@ function clearEmbeddingProvider() {
|
|
|
14952
14905
|
currentProvider = null;
|
|
14953
14906
|
}
|
|
14954
14907
|
async function embedText(text3) {
|
|
14955
|
-
if (!currentProvider
|
|
14908
|
+
if (!currentProvider?.isAvailable()) return null;
|
|
14956
14909
|
return currentProvider.embed(text3);
|
|
14957
14910
|
}
|
|
14958
14911
|
function isEmbeddingAvailable() {
|
|
@@ -22823,7 +22776,7 @@ function parseIdPrefix(id) {
|
|
|
22823
22776
|
return null;
|
|
22824
22777
|
}
|
|
22825
22778
|
async function searchSimilar(query, projectRoot, limit) {
|
|
22826
|
-
if (!query
|
|
22779
|
+
if (!query?.trim()) return [];
|
|
22827
22780
|
if (!isEmbeddingAvailable()) return [];
|
|
22828
22781
|
const maxResults = limit ?? 10;
|
|
22829
22782
|
const queryVector = await embedText(query);
|
|
@@ -50370,7 +50323,7 @@ async function computeLastSession(projectRoot, scopeFilter) {
|
|
|
50370
50323
|
const accessor = await getAccessor(projectRoot);
|
|
50371
50324
|
const allSessions = await accessor.loadSessions();
|
|
50372
50325
|
const session = allSessions.find((s3) => s3.id === sessionId);
|
|
50373
|
-
if (!session
|
|
50326
|
+
if (!session?.endedAt) return null;
|
|
50374
50327
|
let duration3 = 0;
|
|
50375
50328
|
if (session.startedAt) {
|
|
50376
50329
|
duration3 = Math.round(
|
|
@@ -51557,10 +51510,17 @@ async function searchBrainCompact(projectRoot, params) {
|
|
|
51557
51510
|
setImmediate(() => {
|
|
51558
51511
|
incrementCitationCounts(projectRoot, returnedIds).catch(() => {
|
|
51559
51512
|
});
|
|
51560
|
-
|
|
51561
|
-
(
|
|
51562
|
-
|
|
51563
|
-
|
|
51513
|
+
getCurrentSessionId(projectRoot).then((sessionId) => {
|
|
51514
|
+
return logRetrieval(
|
|
51515
|
+
projectRoot,
|
|
51516
|
+
query,
|
|
51517
|
+
returnedIds,
|
|
51518
|
+
"find-rrf",
|
|
51519
|
+
results2.length * 50,
|
|
51520
|
+
sessionId
|
|
51521
|
+
);
|
|
51522
|
+
}).catch(() => {
|
|
51523
|
+
});
|
|
51564
51524
|
});
|
|
51565
51525
|
}
|
|
51566
51526
|
return { results: results2, total: results2.length, tokensEstimated: results2.length * 50 };
|
|
@@ -51623,7 +51583,16 @@ async function searchBrainCompact(projectRoot, params) {
|
|
|
51623
51583
|
setImmediate(() => {
|
|
51624
51584
|
incrementCitationCounts(projectRoot, returnedIds).catch(() => {
|
|
51625
51585
|
});
|
|
51626
|
-
|
|
51586
|
+
getCurrentSessionId(projectRoot).then((sessionId) => {
|
|
51587
|
+
return logRetrieval(
|
|
51588
|
+
projectRoot,
|
|
51589
|
+
query,
|
|
51590
|
+
returnedIds,
|
|
51591
|
+
"find",
|
|
51592
|
+
results.length * 50,
|
|
51593
|
+
sessionId
|
|
51594
|
+
);
|
|
51595
|
+
}).catch(() => {
|
|
51627
51596
|
});
|
|
51628
51597
|
});
|
|
51629
51598
|
}
|
|
@@ -51811,13 +51780,16 @@ async function fetchBrainEntries(projectRoot, params) {
|
|
|
51811
51780
|
setImmediate(() => {
|
|
51812
51781
|
incrementCitationCounts(projectRoot, fetchedIds).catch(() => {
|
|
51813
51782
|
});
|
|
51814
|
-
|
|
51815
|
-
|
|
51816
|
-
|
|
51817
|
-
|
|
51818
|
-
|
|
51819
|
-
|
|
51820
|
-
|
|
51783
|
+
getCurrentSessionId(projectRoot).then((sessionId) => {
|
|
51784
|
+
return logRetrieval(
|
|
51785
|
+
projectRoot,
|
|
51786
|
+
fetchedIds.join(","),
|
|
51787
|
+
fetchedIds,
|
|
51788
|
+
"fetch",
|
|
51789
|
+
results.length * 500,
|
|
51790
|
+
sessionId
|
|
51791
|
+
);
|
|
51792
|
+
}).catch(() => {
|
|
51821
51793
|
});
|
|
51822
51794
|
});
|
|
51823
51795
|
}
|
|
@@ -52235,6 +52207,15 @@ async function retrieveWithBudget(projectRoot, query, tokenBudget = 500, options
|
|
|
52235
52207
|
excluded
|
|
52236
52208
|
};
|
|
52237
52209
|
}
|
|
52210
|
+
async function getCurrentSessionId(projectRoot) {
|
|
52211
|
+
try {
|
|
52212
|
+
const { sessionStatus: sessionStatus3 } = await Promise.resolve().then(() => (init_sessions2(), sessions_exports2));
|
|
52213
|
+
const session = await sessionStatus3(projectRoot);
|
|
52214
|
+
return session?.id;
|
|
52215
|
+
} catch {
|
|
52216
|
+
return void 0;
|
|
52217
|
+
}
|
|
52218
|
+
}
|
|
52238
52219
|
async function incrementCitationCounts(projectRoot, ids) {
|
|
52239
52220
|
if (ids.length === 0) return;
|
|
52240
52221
|
const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
|
|
@@ -52261,13 +52242,13 @@ async function incrementCitationCounts(projectRoot, ids) {
|
|
|
52261
52242
|
}
|
|
52262
52243
|
}
|
|
52263
52244
|
}
|
|
52264
|
-
async function logRetrieval(projectRoot, query, entryIds, source, tokensUsed) {
|
|
52245
|
+
async function logRetrieval(projectRoot, query, entryIds, source, tokensUsed, sessionId) {
|
|
52265
52246
|
if (entryIds.length === 0) return;
|
|
52266
52247
|
const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
|
|
52267
52248
|
await getBrainDb2(projectRoot);
|
|
52268
52249
|
const nativeDb = getBrainNativeDb2();
|
|
52269
52250
|
if (!nativeDb) return;
|
|
52270
|
-
const createSql = "CREATE TABLE IF NOT EXISTS brain_retrieval_log (id INTEGER PRIMARY KEY AUTOINCREMENT,query TEXT NOT NULL,entry_ids TEXT NOT NULL,entry_count INTEGER NOT NULL,source TEXT NOT NULL,tokens_used INTEGER,created_at TEXT NOT NULL DEFAULT (datetime('now')))";
|
|
52251
|
+
const createSql = "CREATE TABLE IF NOT EXISTS brain_retrieval_log (id INTEGER PRIMARY KEY AUTOINCREMENT,query TEXT NOT NULL,entry_ids TEXT NOT NULL,entry_count INTEGER NOT NULL,source TEXT NOT NULL,tokens_used INTEGER,session_id TEXT,created_at TEXT NOT NULL DEFAULT (datetime('now')))";
|
|
52271
52252
|
try {
|
|
52272
52253
|
nativeDb.prepare(createSql).run();
|
|
52273
52254
|
} catch {
|
|
@@ -52275,8 +52256,15 @@ async function logRetrieval(projectRoot, query, entryIds, source, tokensUsed) {
|
|
|
52275
52256
|
}
|
|
52276
52257
|
try {
|
|
52277
52258
|
nativeDb.prepare(
|
|
52278
|
-
"INSERT INTO brain_retrieval_log (query, entry_ids, entry_count, source, tokens_used) VALUES (?, ?, ?, ?, ?)"
|
|
52279
|
-
).run(
|
|
52259
|
+
"INSERT INTO brain_retrieval_log (query, entry_ids, entry_count, source, tokens_used, session_id) VALUES (?, ?, ?, ?, ?, ?)"
|
|
52260
|
+
).run(
|
|
52261
|
+
query,
|
|
52262
|
+
entryIds.join(","),
|
|
52263
|
+
entryIds.length,
|
|
52264
|
+
source,
|
|
52265
|
+
tokensUsed ?? null,
|
|
52266
|
+
sessionId ?? null
|
|
52267
|
+
);
|
|
52280
52268
|
} catch {
|
|
52281
52269
|
}
|
|
52282
52270
|
}
|
|
@@ -56018,6 +56006,7 @@ __export(scaffold_exports, {
|
|
|
56018
56006
|
checkConfig: () => checkConfig,
|
|
56019
56007
|
checkGitignore: () => checkGitignore,
|
|
56020
56008
|
checkGlobalHome: () => checkGlobalHome,
|
|
56009
|
+
checkGlobalIdentity: () => checkGlobalIdentity,
|
|
56021
56010
|
checkGlobalTemplates: () => checkGlobalTemplates,
|
|
56022
56011
|
checkLogDir: () => checkLogDir,
|
|
56023
56012
|
checkMemoryBridge: () => checkMemoryBridge,
|
|
@@ -56034,6 +56023,7 @@ __export(scaffold_exports, {
|
|
|
56034
56023
|
ensureContributorMcp: () => ensureContributorMcp,
|
|
56035
56024
|
ensureGitignore: () => ensureGitignore,
|
|
56036
56025
|
ensureGlobalHome: () => ensureGlobalHome,
|
|
56026
|
+
ensureGlobalIdentity: () => ensureGlobalIdentity,
|
|
56037
56027
|
ensureGlobalScaffold: () => ensureGlobalScaffold,
|
|
56038
56028
|
ensureGlobalTemplates: () => ensureGlobalTemplates,
|
|
56039
56029
|
ensureProjectContext: () => ensureProjectContext,
|
|
@@ -56051,6 +56041,7 @@ import { execFile as execFile3 } from "node:child_process";
|
|
|
56051
56041
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
56052
56042
|
import { existsSync as existsSync40, constants as fsConstants3, readFileSync as readFileSync26, statSync as statSync8 } from "node:fs";
|
|
56053
56043
|
import { access as access3, copyFile as copyFile2, mkdir as mkdir6, readdir as readdir2, readFile as readFile7, rm as rm2, writeFile as writeFile6 } from "node:fs/promises";
|
|
56044
|
+
import { createRequire as createRequire9 } from "node:module";
|
|
56054
56045
|
import { homedir as getHomedir } from "node:os";
|
|
56055
56046
|
import { dirname as dirname10, join as join42, resolve as resolve5 } from "node:path";
|
|
56056
56047
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
@@ -56906,6 +56897,102 @@ async function ensureCleoOsHub() {
|
|
|
56906
56897
|
details: `pi-extensions: ${piResult.copied} created/${piResult.kept} kept, global-recipes: ${recipesResult.copied} created/${recipesResult.kept} kept`
|
|
56907
56898
|
};
|
|
56908
56899
|
}
|
|
56900
|
+
function resolveIdentitySourcePath() {
|
|
56901
|
+
const monorepoPath = join42(
|
|
56902
|
+
process.cwd(),
|
|
56903
|
+
"packages",
|
|
56904
|
+
"cleo-os",
|
|
56905
|
+
"starter-bundle",
|
|
56906
|
+
"CLEOOS-IDENTITY.md"
|
|
56907
|
+
);
|
|
56908
|
+
if (existsSync40(monorepoPath)) return monorepoPath;
|
|
56909
|
+
try {
|
|
56910
|
+
const require2 = createRequire9(import.meta.url);
|
|
56911
|
+
const pkgJson = require2.resolve("@cleocode/cleo-os/package.json");
|
|
56912
|
+
const pkgDir = pkgJson.replace(/\/package\.json$/, "");
|
|
56913
|
+
const installedPath = join42(pkgDir, "starter-bundle", "CLEOOS-IDENTITY.md");
|
|
56914
|
+
if (existsSync40(installedPath)) return installedPath;
|
|
56915
|
+
} catch {
|
|
56916
|
+
}
|
|
56917
|
+
return null;
|
|
56918
|
+
}
|
|
56919
|
+
async function ensureGlobalIdentity(forceRefresh = false) {
|
|
56920
|
+
const sourcePath = resolveIdentitySourcePath();
|
|
56921
|
+
if (!sourcePath) {
|
|
56922
|
+
return {
|
|
56923
|
+
action: "skipped",
|
|
56924
|
+
path: "",
|
|
56925
|
+
details: "CLEOOS-IDENTITY.md source not found in monorepo or installed package"
|
|
56926
|
+
};
|
|
56927
|
+
}
|
|
56928
|
+
const cleoHome = getCleoHome();
|
|
56929
|
+
const dst = join42(cleoHome, "CLEOOS-IDENTITY.md");
|
|
56930
|
+
try {
|
|
56931
|
+
await mkdir6(cleoHome, { recursive: true });
|
|
56932
|
+
} catch (err) {
|
|
56933
|
+
return {
|
|
56934
|
+
action: "skipped",
|
|
56935
|
+
path: dst,
|
|
56936
|
+
details: `Failed to create global cleo home: ${err instanceof Error ? err.message : String(err)}`
|
|
56937
|
+
};
|
|
56938
|
+
}
|
|
56939
|
+
if (existsSync40(dst) && !forceRefresh) {
|
|
56940
|
+
return { action: "skipped", path: dst, details: "identity already present" };
|
|
56941
|
+
}
|
|
56942
|
+
const existedBefore = existsSync40(dst);
|
|
56943
|
+
try {
|
|
56944
|
+
const content = readFileSync26(sourcePath, "utf-8");
|
|
56945
|
+
await writeFile6(dst, content);
|
|
56946
|
+
return {
|
|
56947
|
+
action: existedBefore ? "repaired" : "created",
|
|
56948
|
+
path: dst,
|
|
56949
|
+
details: `from ${sourcePath}`
|
|
56950
|
+
};
|
|
56951
|
+
} catch (err) {
|
|
56952
|
+
return {
|
|
56953
|
+
action: "skipped",
|
|
56954
|
+
path: dst,
|
|
56955
|
+
details: `Failed to write identity: ${err instanceof Error ? err.message : String(err)}`
|
|
56956
|
+
};
|
|
56957
|
+
}
|
|
56958
|
+
}
|
|
56959
|
+
function checkGlobalIdentity() {
|
|
56960
|
+
const cleoHome = getCleoHome();
|
|
56961
|
+
const identityPath = join42(cleoHome, "CLEOOS-IDENTITY.md");
|
|
56962
|
+
if (!existsSync40(identityPath)) {
|
|
56963
|
+
return {
|
|
56964
|
+
id: "global_identity",
|
|
56965
|
+
category: "global",
|
|
56966
|
+
status: "failed",
|
|
56967
|
+
message: "Global CLEOOS-IDENTITY.md not found \u2014 orchestrator persona missing",
|
|
56968
|
+
details: { path: identityPath, exists: false },
|
|
56969
|
+
fix: "cleo upgrade (auto-deploys identity)"
|
|
56970
|
+
};
|
|
56971
|
+
}
|
|
56972
|
+
let size = 0;
|
|
56973
|
+
try {
|
|
56974
|
+
size = statSync8(identityPath).size;
|
|
56975
|
+
} catch {
|
|
56976
|
+
}
|
|
56977
|
+
if (size === 0) {
|
|
56978
|
+
return {
|
|
56979
|
+
id: "global_identity",
|
|
56980
|
+
category: "global",
|
|
56981
|
+
status: "failed",
|
|
56982
|
+
message: "Global CLEOOS-IDENTITY.md exists but is empty",
|
|
56983
|
+
details: { path: identityPath, exists: true, size: 0 },
|
|
56984
|
+
fix: "cleo upgrade --refresh-identity"
|
|
56985
|
+
};
|
|
56986
|
+
}
|
|
56987
|
+
return {
|
|
56988
|
+
id: "global_identity",
|
|
56989
|
+
category: "global",
|
|
56990
|
+
status: "passed",
|
|
56991
|
+
message: "Global CLEOOS-IDENTITY.md present",
|
|
56992
|
+
details: { path: identityPath, exists: true, size },
|
|
56993
|
+
fix: ""
|
|
56994
|
+
};
|
|
56995
|
+
}
|
|
56909
56996
|
function checkGlobalHome() {
|
|
56910
56997
|
const cleoHome = getCleoHome();
|
|
56911
56998
|
if (!existsSync40(cleoHome)) {
|
|
@@ -58851,7 +58938,7 @@ function prepareSpawnMulti(skillNames, tokenValues, cwd) {
|
|
|
58851
58938
|
const skillName = skillNames[i];
|
|
58852
58939
|
const isPrimary = i === 0;
|
|
58853
58940
|
const skill = findSkill(skillName, cwd);
|
|
58854
|
-
if (!skill
|
|
58941
|
+
if (!skill?.content) {
|
|
58855
58942
|
continue;
|
|
58856
58943
|
}
|
|
58857
58944
|
let content = isPrimary ? skill.content : loadProgressive(skill.content);
|
|
@@ -63304,7 +63391,7 @@ var init_agent_outputs = __esm({
|
|
|
63304
63391
|
// packages/core/src/migration/checksum.ts
|
|
63305
63392
|
import { createHash as createHash8 } from "node:crypto";
|
|
63306
63393
|
import { readFileSync as readFileSync37 } from "node:fs";
|
|
63307
|
-
import { createRequire as
|
|
63394
|
+
import { createRequire as createRequire10 } from "node:module";
|
|
63308
63395
|
async function computeChecksum2(filePath) {
|
|
63309
63396
|
const content = readFileSync37(filePath);
|
|
63310
63397
|
return createHash8("sha256").update(content).digest("hex");
|
|
@@ -63350,7 +63437,7 @@ var _require9, DatabaseSync4;
|
|
|
63350
63437
|
var init_checksum = __esm({
|
|
63351
63438
|
"packages/core/src/migration/checksum.ts"() {
|
|
63352
63439
|
"use strict";
|
|
63353
|
-
_require9 =
|
|
63440
|
+
_require9 = createRequire10(import.meta.url);
|
|
63354
63441
|
({ DatabaseSync: DatabaseSync4 } = _require9("node:sqlite"));
|
|
63355
63442
|
}
|
|
63356
63443
|
});
|
|
@@ -74367,7 +74454,7 @@ async function injectProtocol(skillContent, taskId, tokenValues, cwd, tier) {
|
|
|
74367
74454
|
}
|
|
74368
74455
|
async function orchestratorSpawnSkill(taskId, skillName, tokenValues, cwd, tier) {
|
|
74369
74456
|
const skill = findSkill(skillName, cwd);
|
|
74370
|
-
if (!skill
|
|
74457
|
+
if (!skill?.content) {
|
|
74371
74458
|
throw new CleoError(4 /* NOT_FOUND */, `Skill not found: ${skillName}`, {
|
|
74372
74459
|
fix: `Check skills directory for ${skillName}/SKILL.md`
|
|
74373
74460
|
});
|
|
@@ -74937,7 +75024,7 @@ async function buildPrompt(taskId, templateName = "TASK-EXECUTOR", cwd, tier) {
|
|
|
74937
75024
|
throw new CleoError(4 /* NOT_FOUND */, `Task ${taskId} not found`);
|
|
74938
75025
|
}
|
|
74939
75026
|
const skill = findSkill(templateName, cwd);
|
|
74940
|
-
if (!skill
|
|
75027
|
+
if (!skill?.content) {
|
|
74941
75028
|
const { canonical } = mapSkillName(templateName);
|
|
74942
75029
|
throw new CleoError(4 /* NOT_FOUND */, `Skill template ${templateName} not found`, {
|
|
74943
75030
|
fix: `Expected at skills/${canonical}/SKILL.md`
|
|
@@ -77732,7 +77819,7 @@ async function analyzeArchive(opts, accessor) {
|
|
|
77732
77819
|
const acc = accessor ?? await getAccessor(opts.cwd);
|
|
77733
77820
|
const data = await acc.loadArchive();
|
|
77734
77821
|
const reportType = opts.report ?? "summary";
|
|
77735
|
-
if (!data
|
|
77822
|
+
if (!data?.archivedTasks?.length) {
|
|
77736
77823
|
return {
|
|
77737
77824
|
report: reportType,
|
|
77738
77825
|
filters: null,
|
|
@@ -79528,7 +79615,7 @@ __export(parser_exports, {
|
|
|
79528
79615
|
parseFile: () => parseFile2
|
|
79529
79616
|
});
|
|
79530
79617
|
import { readFileSync as readFileSync67 } from "node:fs";
|
|
79531
|
-
import { createRequire as
|
|
79618
|
+
import { createRequire as createRequire11 } from "node:module";
|
|
79532
79619
|
import { relative as relative11 } from "node:path";
|
|
79533
79620
|
function tryRequire2(id) {
|
|
79534
79621
|
try {
|
|
@@ -79729,7 +79816,7 @@ var init_parser4 = __esm({
|
|
|
79729
79816
|
"packages/core/src/code/parser.ts"() {
|
|
79730
79817
|
"use strict";
|
|
79731
79818
|
init_tree_sitter_languages2();
|
|
79732
|
-
_require10 =
|
|
79819
|
+
_require10 = createRequire11(import.meta.url);
|
|
79733
79820
|
_ParserClass2 = null;
|
|
79734
79821
|
_QueryClass2 = null;
|
|
79735
79822
|
_parserInstance2 = null;
|
|
@@ -79835,7 +79922,7 @@ __export(dependencies_exports, {
|
|
|
79835
79922
|
getDependencySpecs: () => getDependencySpecs
|
|
79836
79923
|
});
|
|
79837
79924
|
import { execFileSync as execFileSync10 } from "node:child_process";
|
|
79838
|
-
import { createRequire as
|
|
79925
|
+
import { createRequire as createRequire12 } from "node:module";
|
|
79839
79926
|
import { dirname as dirname19 } from "node:path";
|
|
79840
79927
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
79841
79928
|
function tryExec(cmd, args, timeoutMs = 3e3) {
|
|
@@ -80108,7 +80195,7 @@ var init_dependencies = __esm({
|
|
|
80108
80195
|
"packages/core/src/system/dependencies.ts"() {
|
|
80109
80196
|
"use strict";
|
|
80110
80197
|
init_platform();
|
|
80111
|
-
_require11 =
|
|
80198
|
+
_require11 = createRequire12(import.meta.url);
|
|
80112
80199
|
_dirname = dirname19(fileURLToPath5(import.meta.url));
|
|
80113
80200
|
DEPENDENCY_SPECS = [
|
|
80114
80201
|
// ── Required ────────────────────────────────────────────────────────────
|
|
@@ -80180,7 +80267,7 @@ var init_dependencies = __esm({
|
|
|
80180
80267
|
// packages/core/src/system/health.ts
|
|
80181
80268
|
import { execFileSync as execFileSync11 } from "node:child_process";
|
|
80182
80269
|
import { existsSync as existsSync92, readFileSync as readFileSync68, statSync as statSync19 } from "node:fs";
|
|
80183
|
-
import { createRequire as
|
|
80270
|
+
import { createRequire as createRequire13 } from "node:module";
|
|
80184
80271
|
import { join as join94 } from "node:path";
|
|
80185
80272
|
function resolveStructuredLogPath(cleoDir) {
|
|
80186
80273
|
const defaultPath = join94(cleoDir, "logs", "cleo.log");
|
|
@@ -80721,6 +80808,7 @@ async function coreDoctorReport(projectRoot) {
|
|
|
80721
80808
|
});
|
|
80722
80809
|
checks.push(mapCheckResult(checkGlobalHome()));
|
|
80723
80810
|
checks.push(mapCheckResult(checkGlobalTemplates()));
|
|
80811
|
+
checks.push(mapCheckResult(checkGlobalIdentity()));
|
|
80724
80812
|
checks.push(mapSchemaCheckResult(checkGlobalSchemas()));
|
|
80725
80813
|
checks.push(mapCheckResult(checkLogDir(projectRoot)));
|
|
80726
80814
|
const hookResults = await checkGitHooks(projectRoot);
|
|
@@ -81152,7 +81240,7 @@ var init_health = __esm({
|
|
|
81152
81240
|
init_checks3();
|
|
81153
81241
|
init_dependencies();
|
|
81154
81242
|
init_storage_preflight();
|
|
81155
|
-
_require12 =
|
|
81243
|
+
_require12 = createRequire13(import.meta.url);
|
|
81156
81244
|
databaseSyncCtor = (() => {
|
|
81157
81245
|
try {
|
|
81158
81246
|
return _require12("node:sqlite").DatabaseSync;
|
|
@@ -85793,16 +85881,12 @@ function allEpicChildrenVerified(epicId, tasks2) {
|
|
|
85793
85881
|
if (children.length === 0) return false;
|
|
85794
85882
|
const incomplete = children.filter((t) => t.status !== "done");
|
|
85795
85883
|
if (incomplete.length > 0) return false;
|
|
85796
|
-
const unverified = children.filter(
|
|
85797
|
-
(t) => t.status === "done" && (!t.verification || !t.verification.passed)
|
|
85798
|
-
);
|
|
85884
|
+
const unverified = children.filter((t) => t.status === "done" && !t.verification?.passed);
|
|
85799
85885
|
return unverified.length === 0;
|
|
85800
85886
|
}
|
|
85801
85887
|
function allSiblingsVerified(parentId, tasks2) {
|
|
85802
85888
|
const siblings = tasks2.filter((t) => t.parentId === parentId);
|
|
85803
|
-
const unverifiedDone = siblings.filter(
|
|
85804
|
-
(t) => t.status === "done" && (!t.verification || !t.verification.passed)
|
|
85805
|
-
);
|
|
85889
|
+
const unverifiedDone = siblings.filter((t) => t.status === "done" && !t.verification?.passed);
|
|
85806
85890
|
const incomplete = siblings.filter(
|
|
85807
85891
|
(t) => t.status === "pending" || t.status === "active" || t.status === "blocked"
|
|
85808
85892
|
);
|
|
@@ -86526,8 +86610,8 @@ import { platform as platform4 } from "node:os";
|
|
|
86526
86610
|
import { basename as basename17, dirname as dirname23, join as join108 } from "node:path";
|
|
86527
86611
|
async function resolveSeedAgentsDir() {
|
|
86528
86612
|
try {
|
|
86529
|
-
const { createRequire:
|
|
86530
|
-
const req =
|
|
86613
|
+
const { createRequire: createRequire20 } = await import("node:module");
|
|
86614
|
+
const req = createRequire20(import.meta.url);
|
|
86531
86615
|
const agentsPkgMain = req.resolve("@cleocode/agents/package.json");
|
|
86532
86616
|
const agentsPkgRoot = dirname23(agentsPkgMain);
|
|
86533
86617
|
const candidate = join108(agentsPkgRoot, "seed-agents");
|
|
@@ -86554,8 +86638,8 @@ async function resolveSeedAgentsDir() {
|
|
|
86554
86638
|
async function initAgentDefinition(created, warnings) {
|
|
86555
86639
|
let agentSourceDir = null;
|
|
86556
86640
|
try {
|
|
86557
|
-
const { createRequire:
|
|
86558
|
-
const req =
|
|
86641
|
+
const { createRequire: createRequire20 } = await import("node:module");
|
|
86642
|
+
const req = createRequire20(import.meta.url);
|
|
86559
86643
|
const agentsPkgMain = req.resolve("@cleocode/agents/package.json");
|
|
86560
86644
|
const agentsPkgRoot = dirname23(agentsPkgMain);
|
|
86561
86645
|
const candidate = join108(agentsPkgRoot, "cleo-subagent");
|
|
@@ -86621,8 +86705,8 @@ async function initCoreSkills(created, warnings) {
|
|
|
86621
86705
|
const packageRoot = getPackageRoot();
|
|
86622
86706
|
let ctSkillsRoot = null;
|
|
86623
86707
|
try {
|
|
86624
|
-
const { createRequire:
|
|
86625
|
-
const req =
|
|
86708
|
+
const { createRequire: createRequire20 } = await import("node:module");
|
|
86709
|
+
const req = createRequire20(import.meta.url);
|
|
86626
86710
|
const skillsPkgMain = req.resolve("@cleocode/skills/package.json");
|
|
86627
86711
|
const skillsPkgRoot = dirname23(skillsPkgMain);
|
|
86628
86712
|
if (existsSync108(join108(skillsPkgRoot, "skills.json"))) {
|
|
@@ -87130,8 +87214,8 @@ async function deployStarterBundle(cleoDir, created, warnings) {
|
|
|
87130
87214
|
if (hasCantFiles) return;
|
|
87131
87215
|
let starterBundleSrc = null;
|
|
87132
87216
|
try {
|
|
87133
|
-
const { createRequire:
|
|
87134
|
-
const req =
|
|
87217
|
+
const { createRequire: createRequire20 } = await import("node:module");
|
|
87218
|
+
const req = createRequire20(import.meta.url);
|
|
87135
87219
|
const cleoOsPkgMain = req.resolve("@cleocode/cleo-os/package.json");
|
|
87136
87220
|
const cleoOsPkgRoot = dirname23(cleoOsPkgMain);
|
|
87137
87221
|
const candidate = join108(cleoOsPkgRoot, "starter-bundle");
|
|
@@ -87171,20 +87255,20 @@ async function deployStarterBundle(cleoDir, created, warnings) {
|
|
|
87171
87255
|
}
|
|
87172
87256
|
}
|
|
87173
87257
|
}
|
|
87174
|
-
const identitySrc = join108(starterBundleSrc, "CLEOOS-IDENTITY.md");
|
|
87175
|
-
const identityDst = join108(cleoDir, "CLEOOS-IDENTITY.md");
|
|
87176
|
-
if (existsSync108(identitySrc) && !existsSync108(identityDst)) {
|
|
87177
|
-
await copyFile4(identitySrc, identityDst);
|
|
87178
|
-
}
|
|
87179
87258
|
try {
|
|
87180
|
-
const {
|
|
87181
|
-
const
|
|
87182
|
-
if (
|
|
87183
|
-
|
|
87259
|
+
const { ensureGlobalIdentity: ensureGlobalIdentity2 } = await Promise.resolve().then(() => (init_scaffold(), scaffold_exports));
|
|
87260
|
+
const identityResult = await ensureGlobalIdentity2();
|
|
87261
|
+
if (identityResult.action === "created") {
|
|
87262
|
+
created.push(`identity: ${identityResult.path}`);
|
|
87263
|
+
} else if (identityResult.action === "skipped" && identityResult.details) {
|
|
87264
|
+
warnings.push(`identity skipped: ${identityResult.details}`);
|
|
87184
87265
|
}
|
|
87185
|
-
} catch {
|
|
87266
|
+
} catch (err) {
|
|
87267
|
+
warnings.push(`identity deploy failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
87186
87268
|
}
|
|
87187
|
-
created.push(
|
|
87269
|
+
created.push(
|
|
87270
|
+
"starter-bundle: team + agent .cant files deployed to .cleo/ (identity at global XDG)"
|
|
87271
|
+
);
|
|
87188
87272
|
}
|
|
87189
87273
|
var DIR_SYMLINK_TYPE2;
|
|
87190
87274
|
var init_init = __esm({
|
|
@@ -87208,7 +87292,7 @@ var init_init = __esm({
|
|
|
87208
87292
|
// packages/core/src/sessions/context-alert.ts
|
|
87209
87293
|
import { existsSync as existsSync109, readFileSync as readFileSync80, writeFileSync as writeFileSync20 } from "node:fs";
|
|
87210
87294
|
import { join as join109 } from "node:path";
|
|
87211
|
-
function
|
|
87295
|
+
function getCurrentSessionId2(cwd) {
|
|
87212
87296
|
if (process.env.CLEO_SESSION) return process.env.CLEO_SESSION;
|
|
87213
87297
|
const sessionFile = join109(getCleoDir(cwd), ".current-session");
|
|
87214
87298
|
if (existsSync109(sessionFile)) {
|
|
@@ -87242,7 +87326,7 @@ function createCliMeta(operation, duration_ms = 0) {
|
|
|
87242
87326
|
duration_ms,
|
|
87243
87327
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
87244
87328
|
};
|
|
87245
|
-
const sessionId =
|
|
87329
|
+
const sessionId = getCurrentSessionId2();
|
|
87246
87330
|
if (sessionId) {
|
|
87247
87331
|
meta3["sessionId"] = sessionId;
|
|
87248
87332
|
}
|
|
@@ -90912,6 +90996,160 @@ var init_brain_backfill = __esm({
|
|
|
90912
90996
|
}
|
|
90913
90997
|
});
|
|
90914
90998
|
|
|
90999
|
+
// packages/core/src/memory/brain-export.ts
|
|
91000
|
+
async function exportBrainAsGexf(projectRoot) {
|
|
91001
|
+
const db = await getBrainDb(projectRoot);
|
|
91002
|
+
let nodes = [];
|
|
91003
|
+
let edges = [];
|
|
91004
|
+
try {
|
|
91005
|
+
nodes = await db.select({
|
|
91006
|
+
id: brainPageNodes.id,
|
|
91007
|
+
nodeType: brainPageNodes.nodeType,
|
|
91008
|
+
label: brainPageNodes.label,
|
|
91009
|
+
qualityScore: brainPageNodes.qualityScore,
|
|
91010
|
+
contentHash: brainPageNodes.contentHash,
|
|
91011
|
+
lastActivityAt: brainPageNodes.lastActivityAt,
|
|
91012
|
+
metadataJson: brainPageNodes.metadataJson,
|
|
91013
|
+
createdAt: brainPageNodes.createdAt,
|
|
91014
|
+
updatedAt: brainPageNodes.updatedAt
|
|
91015
|
+
}).from(brainPageNodes);
|
|
91016
|
+
} catch {
|
|
91017
|
+
nodes = [];
|
|
91018
|
+
}
|
|
91019
|
+
try {
|
|
91020
|
+
const rawEdges = await db.select({
|
|
91021
|
+
fromId: brainPageEdges.fromId,
|
|
91022
|
+
toId: brainPageEdges.toId,
|
|
91023
|
+
edgeType: brainPageEdges.edgeType,
|
|
91024
|
+
weight: brainPageEdges.weight,
|
|
91025
|
+
createdAt: brainPageEdges.createdAt
|
|
91026
|
+
}).from(brainPageEdges);
|
|
91027
|
+
edges = rawEdges.map((e) => ({ ...e, provenance: null }));
|
|
91028
|
+
} catch {
|
|
91029
|
+
edges = [];
|
|
91030
|
+
}
|
|
91031
|
+
const gexf = buildGexfDocument(nodes, edges);
|
|
91032
|
+
return {
|
|
91033
|
+
success: true,
|
|
91034
|
+
format: "gexf",
|
|
91035
|
+
nodeCount: nodes.length,
|
|
91036
|
+
edgeCount: edges.length,
|
|
91037
|
+
content: gexf,
|
|
91038
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
91039
|
+
};
|
|
91040
|
+
}
|
|
91041
|
+
async function exportBrainAsJson(projectRoot) {
|
|
91042
|
+
const db = await getBrainDb(projectRoot);
|
|
91043
|
+
let nodes = [];
|
|
91044
|
+
let edges = [];
|
|
91045
|
+
try {
|
|
91046
|
+
nodes = await db.select({
|
|
91047
|
+
id: brainPageNodes.id,
|
|
91048
|
+
nodeType: brainPageNodes.nodeType,
|
|
91049
|
+
label: brainPageNodes.label,
|
|
91050
|
+
qualityScore: brainPageNodes.qualityScore,
|
|
91051
|
+
contentHash: brainPageNodes.contentHash,
|
|
91052
|
+
lastActivityAt: brainPageNodes.lastActivityAt,
|
|
91053
|
+
metadataJson: brainPageNodes.metadataJson,
|
|
91054
|
+
createdAt: brainPageNodes.createdAt,
|
|
91055
|
+
updatedAt: brainPageNodes.updatedAt
|
|
91056
|
+
}).from(brainPageNodes);
|
|
91057
|
+
} catch {
|
|
91058
|
+
nodes = [];
|
|
91059
|
+
}
|
|
91060
|
+
try {
|
|
91061
|
+
const rawEdges = await db.select({
|
|
91062
|
+
fromId: brainPageEdges.fromId,
|
|
91063
|
+
toId: brainPageEdges.toId,
|
|
91064
|
+
edgeType: brainPageEdges.edgeType,
|
|
91065
|
+
weight: brainPageEdges.weight,
|
|
91066
|
+
createdAt: brainPageEdges.createdAt
|
|
91067
|
+
}).from(brainPageEdges);
|
|
91068
|
+
edges = rawEdges.map((e) => ({ ...e, provenance: null }));
|
|
91069
|
+
} catch {
|
|
91070
|
+
edges = [];
|
|
91071
|
+
}
|
|
91072
|
+
return {
|
|
91073
|
+
success: true,
|
|
91074
|
+
format: "json",
|
|
91075
|
+
nodeCount: nodes.length,
|
|
91076
|
+
edgeCount: edges.length,
|
|
91077
|
+
nodes,
|
|
91078
|
+
edges,
|
|
91079
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
91080
|
+
};
|
|
91081
|
+
}
|
|
91082
|
+
function buildGexfDocument(nodes, edges) {
|
|
91083
|
+
const lines = [
|
|
91084
|
+
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
91085
|
+
'<gexf xmlns="http://www.gexf.net/1.3draft" version="1.3">',
|
|
91086
|
+
' <meta lastmodifieddate="' + (/* @__PURE__ */ new Date()).toISOString() + '">',
|
|
91087
|
+
" <creator>CLEO Brain Export (T626-M6)</creator>",
|
|
91088
|
+
" <description>Living brain knowledge graph (brain_page_nodes + brain_page_edges)</description>",
|
|
91089
|
+
" </meta>",
|
|
91090
|
+
' <graph mode="static" defaultedgetype="directed">'
|
|
91091
|
+
];
|
|
91092
|
+
lines.push(' <attributes class="node">');
|
|
91093
|
+
lines.push(' <attribute id="node_type" title="Node Type" type="string"/>');
|
|
91094
|
+
lines.push(' <attribute id="quality_score" title="Quality Score" type="double"/>');
|
|
91095
|
+
lines.push(' <attribute id="content_hash" title="Content Hash" type="string"/>');
|
|
91096
|
+
lines.push(' <attribute id="last_activity_at" title="Last Activity" type="string"/>');
|
|
91097
|
+
lines.push(' <attribute id="created_at" title="Created At" type="string"/>');
|
|
91098
|
+
lines.push(" </attributes>");
|
|
91099
|
+
lines.push(' <attributes class="edge">');
|
|
91100
|
+
lines.push(' <attribute id="edge_type" title="Edge Type" type="string"/>');
|
|
91101
|
+
lines.push(' <attribute id="provenance" title="Provenance" type="string"/>');
|
|
91102
|
+
lines.push(' <attribute id="created_at" title="Created At" type="string"/>');
|
|
91103
|
+
lines.push(" </attributes>");
|
|
91104
|
+
lines.push(" <nodes>");
|
|
91105
|
+
for (const node of nodes) {
|
|
91106
|
+
lines.push(` <node id="${escapeXml(node.id)}" label="${escapeXml(node.label)}">`);
|
|
91107
|
+
lines.push(" <attvalues>");
|
|
91108
|
+
lines.push(` <attvalue for="node_type" value="${escapeXml(node.nodeType)}"/>`);
|
|
91109
|
+
lines.push(` <attvalue for="quality_score" value="${node.qualityScore ?? 0.5}"/>`);
|
|
91110
|
+
if (node.contentHash) {
|
|
91111
|
+
lines.push(` <attvalue for="content_hash" value="${escapeXml(node.contentHash)}"/>`);
|
|
91112
|
+
}
|
|
91113
|
+
lines.push(
|
|
91114
|
+
` <attvalue for="last_activity_at" value="${escapeXml(node.lastActivityAt)}"/>`
|
|
91115
|
+
);
|
|
91116
|
+
lines.push(` <attvalue for="created_at" value="${escapeXml(node.createdAt)}"/>`);
|
|
91117
|
+
lines.push(" </attvalues>");
|
|
91118
|
+
lines.push(" </node>");
|
|
91119
|
+
}
|
|
91120
|
+
lines.push(" </nodes>");
|
|
91121
|
+
lines.push(" <edges>");
|
|
91122
|
+
for (let i = 0; i < edges.length; i++) {
|
|
91123
|
+
const edge = edges[i];
|
|
91124
|
+
const weight = edge.weight ?? 1;
|
|
91125
|
+
lines.push(
|
|
91126
|
+
` <edge id="${i}" source="${escapeXml(edge.fromId)}" target="${escapeXml(edge.toId)}" weight="${weight}">`
|
|
91127
|
+
);
|
|
91128
|
+
lines.push(" <attvalues>");
|
|
91129
|
+
lines.push(` <attvalue for="edge_type" value="${escapeXml(edge.edgeType)}"/>`);
|
|
91130
|
+
if (edge.provenance) {
|
|
91131
|
+
lines.push(` <attvalue for="provenance" value="${escapeXml(edge.provenance)}"/>`);
|
|
91132
|
+
}
|
|
91133
|
+
lines.push(` <attvalue for="created_at" value="${escapeXml(edge.createdAt)}"/>`);
|
|
91134
|
+
lines.push(" </attvalues>");
|
|
91135
|
+
lines.push(" </edge>");
|
|
91136
|
+
}
|
|
91137
|
+
lines.push(" </edges>");
|
|
91138
|
+
lines.push(" </graph>");
|
|
91139
|
+
lines.push("</gexf>");
|
|
91140
|
+
return lines.join("\n");
|
|
91141
|
+
}
|
|
91142
|
+
function escapeXml(text3) {
|
|
91143
|
+
return text3.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
91144
|
+
}
|
|
91145
|
+
var init_brain_export = __esm({
|
|
91146
|
+
"packages/core/src/memory/brain-export.ts"() {
|
|
91147
|
+
"use strict";
|
|
91148
|
+
init_brain_schema();
|
|
91149
|
+
init_brain_sqlite();
|
|
91150
|
+
}
|
|
91151
|
+
});
|
|
91152
|
+
|
|
90915
91153
|
// packages/core/src/memory/brain-maintenance.ts
|
|
90916
91154
|
async function runBrainMaintenance(projectRoot, options) {
|
|
90917
91155
|
const {
|
|
@@ -91162,7 +91400,7 @@ var init_brain_purge = __esm({
|
|
|
91162
91400
|
|
|
91163
91401
|
// packages/core/src/memory/claude-mem-migration.ts
|
|
91164
91402
|
import { existsSync as existsSync111 } from "node:fs";
|
|
91165
|
-
import { createRequire as
|
|
91403
|
+
import { createRequire as createRequire14 } from "node:module";
|
|
91166
91404
|
function typedAll3(db, sql16) {
|
|
91167
91405
|
return db.prepare(sql16).all();
|
|
91168
91406
|
}
|
|
@@ -91321,7 +91559,7 @@ Use --source <path> to specify a custom location.`
|
|
|
91321
91559
|
}
|
|
91322
91560
|
try {
|
|
91323
91561
|
for (const row of batch) {
|
|
91324
|
-
if (!row.learned
|
|
91562
|
+
if (!row.learned?.trim()) {
|
|
91325
91563
|
continue;
|
|
91326
91564
|
}
|
|
91327
91565
|
const learnId = `CML-${row.id}`;
|
|
@@ -91392,7 +91630,7 @@ var init_claude_mem_migration = __esm({
|
|
|
91392
91630
|
init_paths();
|
|
91393
91631
|
init_brain_sqlite();
|
|
91394
91632
|
init_brain_search();
|
|
91395
|
-
_require13 =
|
|
91633
|
+
_require13 = createRequire14(import.meta.url);
|
|
91396
91634
|
({ DatabaseSync: DatabaseSync5 } = _require13("node:sqlite"));
|
|
91397
91635
|
VALID_OBSERVATION_TYPES = /* @__PURE__ */ new Set([
|
|
91398
91636
|
"discovery",
|
|
@@ -97146,7 +97384,7 @@ var init_t310_readiness = __esm({
|
|
|
97146
97384
|
// packages/core/src/store/backup-pack.ts
|
|
97147
97385
|
import crypto5 from "node:crypto";
|
|
97148
97386
|
import fs4 from "node:fs";
|
|
97149
|
-
import { createRequire as
|
|
97387
|
+
import { createRequire as createRequire15 } from "node:module";
|
|
97150
97388
|
import os2 from "node:os";
|
|
97151
97389
|
import path4 from "node:path";
|
|
97152
97390
|
function resolveContractsSchemasDir() {
|
|
@@ -97586,7 +97824,7 @@ var init_backup_pack = __esm({
|
|
|
97586
97824
|
init_nexus_sqlite();
|
|
97587
97825
|
init_signaldock_sqlite();
|
|
97588
97826
|
init_t310_readiness();
|
|
97589
|
-
_require14 =
|
|
97827
|
+
_require14 = createRequire15(import.meta.url);
|
|
97590
97828
|
({ DatabaseSync: DatabaseSync6 } = _require14("node:sqlite"));
|
|
97591
97829
|
}
|
|
97592
97830
|
});
|
|
@@ -97655,7 +97893,7 @@ var init_cleanup_legacy = __esm({
|
|
|
97655
97893
|
|
|
97656
97894
|
// packages/core/src/store/migrate-signaldock-to-conduit.ts
|
|
97657
97895
|
import { existsSync as existsSync117, mkdirSync as mkdirSync27, renameSync as renameSync9, unlinkSync as unlinkSync9 } from "node:fs";
|
|
97658
|
-
import { createRequire as
|
|
97896
|
+
import { createRequire as createRequire16 } from "node:module";
|
|
97659
97897
|
import { join as join115 } from "node:path";
|
|
97660
97898
|
function needsSignaldockToConduitMigration(projectRoot) {
|
|
97661
97899
|
const legacyPath = join115(projectRoot, ".cleo", "signaldock.db");
|
|
@@ -97995,7 +98233,7 @@ var init_migrate_signaldock_to_conduit = __esm({
|
|
|
97995
98233
|
init_conduit_sqlite();
|
|
97996
98234
|
init_global_salt();
|
|
97997
98235
|
init_signaldock_sqlite();
|
|
97998
|
-
_require15 =
|
|
98236
|
+
_require15 = createRequire16(import.meta.url);
|
|
97999
98237
|
({ DatabaseSync: DatabaseSync7 } = _require15("node:sqlite"));
|
|
98000
98238
|
PROJECT_TIER_TABLES = [
|
|
98001
98239
|
"messages",
|
|
@@ -98701,7 +98939,7 @@ function measureDependencyDepth(taskId, taskMap, visited = /* @__PURE__ */ new S
|
|
|
98701
98939
|
if (visited.has(taskId)) return 0;
|
|
98702
98940
|
visited.add(taskId);
|
|
98703
98941
|
const task = taskMap.get(taskId);
|
|
98704
|
-
if (!task
|
|
98942
|
+
if (!task?.depends || task.depends.length === 0) return 0;
|
|
98705
98943
|
let maxDepth = 0;
|
|
98706
98944
|
for (const depId of task.depends) {
|
|
98707
98945
|
const depth = 1 + measureDependencyDepth(depId, taskMap, visited);
|
|
@@ -99055,7 +99293,7 @@ async function coreTaskUnarchive(projectRoot, taskId, params) {
|
|
|
99055
99293
|
throw new Error(`Task '${taskId}' already exists in active tasks`);
|
|
99056
99294
|
}
|
|
99057
99295
|
const archive = await accessor.loadArchive();
|
|
99058
|
-
if (!archive
|
|
99296
|
+
if (!archive?.archivedTasks) {
|
|
99059
99297
|
throw new Error("No archive file found");
|
|
99060
99298
|
}
|
|
99061
99299
|
const taskIndex = archive.archivedTasks.findIndex((t) => t.id === taskId);
|
|
@@ -101118,6 +101356,16 @@ async function runUpgrade(options = {}) {
|
|
|
101118
101356
|
}
|
|
101119
101357
|
} catch {
|
|
101120
101358
|
}
|
|
101359
|
+
try {
|
|
101360
|
+
const { ensureGlobalIdentity: ensureGlobalIdentity2 } = await Promise.resolve().then(() => (init_scaffold(), scaffold_exports));
|
|
101361
|
+
const identityResult = await ensureGlobalIdentity2();
|
|
101362
|
+
actions.push({
|
|
101363
|
+
action: "global_identity",
|
|
101364
|
+
status: identityResult.action === "created" || identityResult.action === "repaired" ? "applied" : "skipped",
|
|
101365
|
+
details: `${identityResult.path} (${identityResult.details ?? identityResult.action})`
|
|
101366
|
+
});
|
|
101367
|
+
} catch {
|
|
101368
|
+
}
|
|
101121
101369
|
try {
|
|
101122
101370
|
const skillsCreated = [];
|
|
101123
101371
|
const skillsWarnings = [];
|
|
@@ -110919,7 +111167,7 @@ var require__ = __commonJS({
|
|
|
110919
111167
|
// packages/core/src/store/backup-unpack.ts
|
|
110920
111168
|
import crypto6 from "node:crypto";
|
|
110921
111169
|
import fs6 from "node:fs";
|
|
110922
|
-
import { createRequire as
|
|
111170
|
+
import { createRequire as createRequire17 } from "node:module";
|
|
110923
111171
|
import os3 from "node:os";
|
|
110924
111172
|
import path6 from "node:path";
|
|
110925
111173
|
import { default as addFormatsImport2 } from "ajv-formats";
|
|
@@ -111188,7 +111436,7 @@ var init_backup_unpack = __esm({
|
|
|
111188
111436
|
import__ = __toESM(require__(), 1);
|
|
111189
111437
|
init_index_min();
|
|
111190
111438
|
init_backup_crypto();
|
|
111191
|
-
_require16 =
|
|
111439
|
+
_require16 = createRequire17(import.meta.url);
|
|
111192
111440
|
({ DatabaseSync: DatabaseSync8 } = _require16("node:sqlite"));
|
|
111193
111441
|
ajv2020Mod = import__.default;
|
|
111194
111442
|
Ajv2020 = typeof ajv2020Mod.default === "function" ? ajv2020Mod.default : import__.default;
|
|
@@ -112512,7 +112760,7 @@ var init_api_key_kdf = __esm({
|
|
|
112512
112760
|
// packages/core/src/store/agent-registry-accessor.ts
|
|
112513
112761
|
import { randomBytes as randomBytes17 } from "node:crypto";
|
|
112514
112762
|
import { existsSync as existsSync127, mkdirSync as mkdirSync32, readFileSync as readFileSync96, statSync as statSync21, writeFileSync as writeFileSync23 } from "node:fs";
|
|
112515
|
-
import { createRequire as
|
|
112763
|
+
import { createRequire as createRequire18 } from "node:module";
|
|
112516
112764
|
import { join as join123 } from "node:path";
|
|
112517
112765
|
function readMachineKey() {
|
|
112518
112766
|
const keyPath = join123(getCleoHome(), "machine-key");
|
|
@@ -112807,7 +113055,7 @@ var init_agent_registry_accessor = __esm({
|
|
|
112807
113055
|
init_conduit_sqlite();
|
|
112808
113056
|
init_global_salt();
|
|
112809
113057
|
init_signaldock_sqlite();
|
|
112810
|
-
_require17 =
|
|
113058
|
+
_require17 = createRequire18(import.meta.url);
|
|
112811
113059
|
({ DatabaseSync: DatabaseSync9 } = _require17("node:sqlite"));
|
|
112812
113060
|
MACHINE_KEY_LENGTH = 32;
|
|
112813
113061
|
AgentRegistryAccessor = class {
|
|
@@ -113440,6 +113688,8 @@ __export(internal_exports, {
|
|
|
113440
113688
|
ensureSqliteDb: () => ensureSqliteDb,
|
|
113441
113689
|
estimateContext: () => estimateContext,
|
|
113442
113690
|
executeTransfer: () => executeTransfer,
|
|
113691
|
+
exportBrainAsGexf: () => exportBrainAsGexf,
|
|
113692
|
+
exportBrainAsJson: () => exportBrainAsJson,
|
|
113443
113693
|
exportSnapshot: () => exportSnapshot,
|
|
113444
113694
|
exportTasks: () => exportTasks,
|
|
113445
113695
|
exportTasksPackage: () => exportTasksPackage,
|
|
@@ -113509,7 +113759,7 @@ __export(internal_exports, {
|
|
|
113509
113759
|
getConfigValue: () => getConfigValue,
|
|
113510
113760
|
getContextDrift: () => getContextDrift,
|
|
113511
113761
|
getCriticalPath: () => getCriticalPath,
|
|
113512
|
-
getCurrentSessionId: () =>
|
|
113762
|
+
getCurrentSessionId: () => getCurrentSessionId2,
|
|
113513
113763
|
getDashboard: () => getDashboard,
|
|
113514
113764
|
getDb: () => getDb,
|
|
113515
113765
|
getDecisionLog: () => getDecisionLog,
|
|
@@ -114017,6 +114267,7 @@ var init_internal = __esm({
|
|
|
114017
114267
|
init_stages();
|
|
114018
114268
|
init_tessera_engine();
|
|
114019
114269
|
init_brain_backfill();
|
|
114270
|
+
init_brain_export();
|
|
114020
114271
|
init_brain_lifecycle();
|
|
114021
114272
|
init_brain_maintenance();
|
|
114022
114273
|
init_brain_purge();
|
|
@@ -131522,7 +131773,7 @@ __export(cli_exports, {
|
|
|
131522
131773
|
});
|
|
131523
131774
|
import { randomUUID as randomUUID14 } from "node:crypto";
|
|
131524
131775
|
import { existsSync as existsSync130 } from "node:fs";
|
|
131525
|
-
import { createRequire as
|
|
131776
|
+
import { createRequire as createRequire19 } from "node:module";
|
|
131526
131777
|
import { dirname as dirname27, join as join127 } from "node:path";
|
|
131527
131778
|
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
131528
131779
|
import { catalog as catalog4, registerSkillLibraryFromPath } from "@cleocode/caamp";
|
|
@@ -131531,7 +131782,7 @@ function ensureCaampLibrary() {
|
|
|
131531
131782
|
try {
|
|
131532
131783
|
let skillsRoot = null;
|
|
131533
131784
|
try {
|
|
131534
|
-
const req =
|
|
131785
|
+
const req = createRequire19(import.meta.url);
|
|
131535
131786
|
const skillsPkgJson = req.resolve("@cleocode/skills/package.json");
|
|
131536
131787
|
const candidate = dirname27(skillsPkgJson);
|
|
131537
131788
|
if (existsSync130(join127(candidate, "skills.json"))) {
|
|
@@ -136332,6 +136583,47 @@ Recent Events (newest first, limit=${limit})`);
|
|
|
136332
136583
|
process.exit(1);
|
|
136333
136584
|
}
|
|
136334
136585
|
});
|
|
136586
|
+
brain.command("export").description("Export brain graph as GEXF (Gephi) or JSON format").option(
|
|
136587
|
+
"--format <format>",
|
|
136588
|
+
"Export format: gexf (Gephi standard) or json (flat arrays)",
|
|
136589
|
+
"gexf"
|
|
136590
|
+
).option("--output <file>", "Write to file instead of stdout (optional)").action(async (opts) => {
|
|
136591
|
+
const root = getProjectRoot();
|
|
136592
|
+
const format = opts.format ?? "gexf";
|
|
136593
|
+
if (format !== "gexf" && format !== "json") {
|
|
136594
|
+
console.error(`Invalid format: ${format}. Use 'gexf' or 'json'.`);
|
|
136595
|
+
process.exit(1);
|
|
136596
|
+
}
|
|
136597
|
+
try {
|
|
136598
|
+
let content;
|
|
136599
|
+
let nodeCount;
|
|
136600
|
+
let edgeCount;
|
|
136601
|
+
if (format === "gexf") {
|
|
136602
|
+
const result = await exportBrainAsGexf(root);
|
|
136603
|
+
content = result.content;
|
|
136604
|
+
nodeCount = result.nodeCount;
|
|
136605
|
+
edgeCount = result.edgeCount;
|
|
136606
|
+
} else {
|
|
136607
|
+
const result = await exportBrainAsJson(root);
|
|
136608
|
+
content = JSON.stringify(result, null, 2);
|
|
136609
|
+
nodeCount = result.nodeCount;
|
|
136610
|
+
edgeCount = result.edgeCount;
|
|
136611
|
+
}
|
|
136612
|
+
if (opts.output) {
|
|
136613
|
+
const fs11 = await import("node:fs");
|
|
136614
|
+
fs11.writeFileSync(opts.output, content, "utf-8");
|
|
136615
|
+
console.log(
|
|
136616
|
+
`Exported to ${opts.output}: ${nodeCount} nodes, ${edgeCount} edges (${format.toUpperCase()})`
|
|
136617
|
+
);
|
|
136618
|
+
} else {
|
|
136619
|
+
console.log(content);
|
|
136620
|
+
}
|
|
136621
|
+
} catch (err) {
|
|
136622
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
136623
|
+
console.error(`Brain export failed: ${message}`);
|
|
136624
|
+
process.exit(1);
|
|
136625
|
+
}
|
|
136626
|
+
});
|
|
136335
136627
|
}
|
|
136336
136628
|
|
|
136337
136629
|
// packages/cleo/src/cli/commands/briefing.ts
|
|
@@ -139643,6 +139935,175 @@ var NODE_KIND_PRIORITY = {
|
|
|
139643
139935
|
file: 40,
|
|
139644
139936
|
folder: 41
|
|
139645
139937
|
};
|
|
139938
|
+
function generateGexf(nodes, relations) {
|
|
139939
|
+
const nodeById = /* @__PURE__ */ new Map();
|
|
139940
|
+
for (const n of nodes) {
|
|
139941
|
+
nodeById.set(String(n["id"]), n);
|
|
139942
|
+
}
|
|
139943
|
+
const kindColors = {
|
|
139944
|
+
function: "#3498db",
|
|
139945
|
+
// blue
|
|
139946
|
+
method: "#2980b9",
|
|
139947
|
+
// darker blue
|
|
139948
|
+
class: "#e74c3c",
|
|
139949
|
+
// red
|
|
139950
|
+
interface: "#e67e22",
|
|
139951
|
+
// orange
|
|
139952
|
+
file: "#95a5a6",
|
|
139953
|
+
// gray
|
|
139954
|
+
folder: "#34495e",
|
|
139955
|
+
// dark gray
|
|
139956
|
+
community: "#9b59b6",
|
|
139957
|
+
// purple
|
|
139958
|
+
process: "#1abc9c",
|
|
139959
|
+
// teal
|
|
139960
|
+
import: "#f39c12",
|
|
139961
|
+
// amber
|
|
139962
|
+
default: "#7f8c8d"
|
|
139963
|
+
// medium gray
|
|
139964
|
+
};
|
|
139965
|
+
const getNodeColor = (kind) => {
|
|
139966
|
+
return kindColors[kind] ?? kindColors["default"];
|
|
139967
|
+
};
|
|
139968
|
+
let gexf = '<?xml version="1.0" encoding="UTF-8"?>\n';
|
|
139969
|
+
gexf += '<gexf xmlns="http://www.gexf.net/1.2draft" xmlns:viz="http://www.gexf.net/1.2draft/viz" version="1.2">\n';
|
|
139970
|
+
gexf += ' <meta lastmodifieddate="' + (/* @__PURE__ */ new Date()).toISOString().split("T")[0] + '">\n';
|
|
139971
|
+
gexf += " <creator>CLEO nexus export</creator>\n";
|
|
139972
|
+
gexf += " <description>Code intelligence graph from CLEO nexus</description>\n";
|
|
139973
|
+
gexf += " </meta>\n";
|
|
139974
|
+
gexf += ' <graph mode="static" defaultedgetype="directed">\n';
|
|
139975
|
+
gexf += ' <attributes class="node">\n';
|
|
139976
|
+
gexf += ' <attribute id="kind" title="Node Kind" type="string" />\n';
|
|
139977
|
+
gexf += ' <attribute id="filePath" title="File Path" type="string" />\n';
|
|
139978
|
+
gexf += ' <attribute id="language" title="Language" type="string" />\n';
|
|
139979
|
+
gexf += ' <attribute id="startLine" title="Start Line" type="integer" />\n';
|
|
139980
|
+
gexf += ' <attribute id="endLine" title="End Line" type="integer" />\n';
|
|
139981
|
+
gexf += ' <attribute id="isExported" title="Is Exported" type="boolean" />\n';
|
|
139982
|
+
gexf += ' <attribute id="projectId" title="Project ID" type="string" />\n';
|
|
139983
|
+
gexf += " </attributes>\n";
|
|
139984
|
+
gexf += ' <attributes class="edge">\n';
|
|
139985
|
+
gexf += ' <attribute id="relationType" title="Relation Type" type="string" />\n';
|
|
139986
|
+
gexf += ' <attribute id="confidence" title="Confidence" type="double" />\n';
|
|
139987
|
+
gexf += ' <attribute id="reason" title="Reason" type="string" />\n';
|
|
139988
|
+
gexf += " </attributes>\n";
|
|
139989
|
+
gexf += " <nodes>\n";
|
|
139990
|
+
for (const node of nodes) {
|
|
139991
|
+
const nodeId = String(node["id"]).replace(/[<>"'&]/g, (c) => {
|
|
139992
|
+
const map2 = {
|
|
139993
|
+
"<": "<",
|
|
139994
|
+
">": ">",
|
|
139995
|
+
'"': """,
|
|
139996
|
+
"'": "'",
|
|
139997
|
+
"&": "&"
|
|
139998
|
+
};
|
|
139999
|
+
return map2[c];
|
|
140000
|
+
});
|
|
140001
|
+
const label = String(node["label"] ?? node["id"]);
|
|
140002
|
+
const kind = String(node["kind"] ?? "unknown");
|
|
140003
|
+
const color = getNodeColor(kind);
|
|
140004
|
+
gexf += ` <node id="${nodeId}" label="${escapeXml2(label)}">
|
|
140005
|
+
`;
|
|
140006
|
+
gexf += ` <viz:color r="${hexToRgb(color).r}" g="${hexToRgb(color).g}" b="${hexToRgb(color).b}" />
|
|
140007
|
+
`;
|
|
140008
|
+
gexf += " <attvalues>\n";
|
|
140009
|
+
gexf += ` <attvalue id="kind" value="${escapeXml2(kind)}" />
|
|
140010
|
+
`;
|
|
140011
|
+
if (node["filePath"]) {
|
|
140012
|
+
gexf += ` <attvalue id="filePath" value="${escapeXml2(String(node["filePath"]))}" />
|
|
140013
|
+
`;
|
|
140014
|
+
}
|
|
140015
|
+
if (node["language"]) {
|
|
140016
|
+
gexf += ` <attvalue id="language" value="${escapeXml2(String(node["language"]))}" />
|
|
140017
|
+
`;
|
|
140018
|
+
}
|
|
140019
|
+
if (node["startLine"] != null) {
|
|
140020
|
+
gexf += ` <attvalue id="startLine" value="${node["startLine"]}" />
|
|
140021
|
+
`;
|
|
140022
|
+
}
|
|
140023
|
+
if (node["endLine"] != null) {
|
|
140024
|
+
gexf += ` <attvalue id="endLine" value="${node["endLine"]}" />
|
|
140025
|
+
`;
|
|
140026
|
+
}
|
|
140027
|
+
if (node["isExported"] != null) {
|
|
140028
|
+
gexf += ` <attvalue id="isExported" value="${node["isExported"] ? "true" : "false"}" />
|
|
140029
|
+
`;
|
|
140030
|
+
}
|
|
140031
|
+
if (node["projectId"]) {
|
|
140032
|
+
gexf += ` <attvalue id="projectId" value="${escapeXml2(String(node["projectId"]))}" />
|
|
140033
|
+
`;
|
|
140034
|
+
}
|
|
140035
|
+
gexf += " </attvalues>\n";
|
|
140036
|
+
gexf += " </node>\n";
|
|
140037
|
+
}
|
|
140038
|
+
gexf += " </nodes>\n";
|
|
140039
|
+
gexf += " <edges>\n";
|
|
140040
|
+
for (let i = 0; i < relations.length; i++) {
|
|
140041
|
+
const rel = relations[i];
|
|
140042
|
+
const sourceId = String(rel["sourceId"]).replace(/[<>"'&]/g, (c) => {
|
|
140043
|
+
const map2 = {
|
|
140044
|
+
"<": "<",
|
|
140045
|
+
">": ">",
|
|
140046
|
+
'"': """,
|
|
140047
|
+
"'": "'",
|
|
140048
|
+
"&": "&"
|
|
140049
|
+
};
|
|
140050
|
+
return map2[c];
|
|
140051
|
+
});
|
|
140052
|
+
const targetId = String(rel["targetId"]).replace(/[<>"'&]/g, (c) => {
|
|
140053
|
+
const map2 = {
|
|
140054
|
+
"<": "<",
|
|
140055
|
+
">": ">",
|
|
140056
|
+
'"': """,
|
|
140057
|
+
"'": "'",
|
|
140058
|
+
"&": "&"
|
|
140059
|
+
};
|
|
140060
|
+
return map2[c];
|
|
140061
|
+
});
|
|
140062
|
+
if (!nodeById.has(String(rel["sourceId"])) || !nodeById.has(String(rel["targetId"]))) {
|
|
140063
|
+
continue;
|
|
140064
|
+
}
|
|
140065
|
+
const confidence = typeof rel["confidence"] === "number" ? rel["confidence"] : 1;
|
|
140066
|
+
const relationType = String(rel["type"] ?? "unknown");
|
|
140067
|
+
const reason = rel["reason"] ? String(rel["reason"]) : "";
|
|
140068
|
+
gexf += ` <edge id="e${i}" source="${sourceId}" target="${targetId}" weight="${confidence}">
|
|
140069
|
+
`;
|
|
140070
|
+
gexf += " <attvalues>\n";
|
|
140071
|
+
gexf += ` <attvalue id="relationType" value="${escapeXml2(relationType)}" />
|
|
140072
|
+
`;
|
|
140073
|
+
gexf += ` <attvalue id="confidence" value="${confidence}" />
|
|
140074
|
+
`;
|
|
140075
|
+
if (reason) {
|
|
140076
|
+
gexf += ` <attvalue id="reason" value="${escapeXml2(reason)}" />
|
|
140077
|
+
`;
|
|
140078
|
+
}
|
|
140079
|
+
gexf += " </attvalues>\n";
|
|
140080
|
+
gexf += " </edge>\n";
|
|
140081
|
+
}
|
|
140082
|
+
gexf += " </edges>\n";
|
|
140083
|
+
gexf += " </graph>\n";
|
|
140084
|
+
gexf += "</gexf>\n";
|
|
140085
|
+
return gexf;
|
|
140086
|
+
}
|
|
140087
|
+
function escapeXml2(str) {
|
|
140088
|
+
return String(str).replace(/[<>"'&]/g, (c) => {
|
|
140089
|
+
const map2 = {
|
|
140090
|
+
"<": "<",
|
|
140091
|
+
">": ">",
|
|
140092
|
+
'"': """,
|
|
140093
|
+
"'": "'",
|
|
140094
|
+
"&": "&"
|
|
140095
|
+
};
|
|
140096
|
+
return map2[c];
|
|
140097
|
+
});
|
|
140098
|
+
}
|
|
140099
|
+
function hexToRgb(hex3) {
|
|
140100
|
+
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex3);
|
|
140101
|
+
return result ? {
|
|
140102
|
+
r: parseInt(result[1], 16),
|
|
140103
|
+
g: parseInt(result[2], 16),
|
|
140104
|
+
b: parseInt(result[3], 16)
|
|
140105
|
+
} : { r: 127, g: 140, b: 141 };
|
|
140106
|
+
}
|
|
139646
140107
|
function sortMatchingNodes(nodes, symbolName) {
|
|
139647
140108
|
const lowerSymbol = symbolName.toLowerCase();
|
|
139648
140109
|
return [...nodes].sort((a, b2) => {
|
|
@@ -140877,6 +141338,84 @@ function registerNexusCommand(program) {
|
|
|
140877
141338
|
process.exitCode = 1;
|
|
140878
141339
|
}
|
|
140879
141340
|
});
|
|
141341
|
+
nexus.command("export").description("Export nexus graph to GEXF (Gephi) or JSON format").option("--format <format>", "Output format: gexf, json", "gexf").option("--output <file>", "Output file path (stdout if omitted)").option("--project <id>", "Filter by project ID (exports all projects if omitted)").action(async (opts) => {
|
|
141342
|
+
const startTime = Date.now();
|
|
141343
|
+
const format = opts["format"] ?? "gexf";
|
|
141344
|
+
const outputFile = opts["output"];
|
|
141345
|
+
const projectFilter = opts["project"];
|
|
141346
|
+
try {
|
|
141347
|
+
const { getNexusDb: getNexusDb2, nexusSchema } = await import("@cleocode/core/store/nexus-sqlite");
|
|
141348
|
+
const db = await getNexusDb2();
|
|
141349
|
+
let allNodes = [];
|
|
141350
|
+
let allRelations = [];
|
|
141351
|
+
try {
|
|
141352
|
+
allNodes = db.select().from(nexusSchema.nexusNodes).all();
|
|
141353
|
+
allRelations = db.select().from(nexusSchema.nexusRelations).all();
|
|
141354
|
+
} catch {
|
|
141355
|
+
}
|
|
141356
|
+
const nodes = projectFilter ? allNodes.filter((n) => n["projectId"] === projectFilter) : allNodes;
|
|
141357
|
+
const relations = projectFilter ? allRelations.filter((r) => r["projectId"] === projectFilter) : allRelations;
|
|
141358
|
+
let output = "";
|
|
141359
|
+
if (format === "json") {
|
|
141360
|
+
output = JSON.stringify(
|
|
141361
|
+
{
|
|
141362
|
+
nodes: nodes.map((n) => ({
|
|
141363
|
+
id: n["id"],
|
|
141364
|
+
kind: n["kind"],
|
|
141365
|
+
label: n["label"],
|
|
141366
|
+
name: n["name"],
|
|
141367
|
+
filePath: n["filePath"],
|
|
141368
|
+
language: n["language"],
|
|
141369
|
+
isExported: n["isExported"],
|
|
141370
|
+
startLine: n["startLine"],
|
|
141371
|
+
endLine: n["endLine"],
|
|
141372
|
+
projectId: n["projectId"]
|
|
141373
|
+
})),
|
|
141374
|
+
edges: relations.map((r) => ({
|
|
141375
|
+
id: r["id"],
|
|
141376
|
+
source: r["sourceId"],
|
|
141377
|
+
target: r["targetId"],
|
|
141378
|
+
type: r["type"],
|
|
141379
|
+
confidence: r["confidence"],
|
|
141380
|
+
reason: r["reason"]
|
|
141381
|
+
}))
|
|
141382
|
+
},
|
|
141383
|
+
null,
|
|
141384
|
+
2
|
|
141385
|
+
);
|
|
141386
|
+
} else if (format === "gexf") {
|
|
141387
|
+
output = generateGexf(nodes, relations);
|
|
141388
|
+
} else {
|
|
141389
|
+
process.stderr.write(
|
|
141390
|
+
`[nexus] Error: Unknown format '${format}'. Supported: gexf, json
|
|
141391
|
+
`
|
|
141392
|
+
);
|
|
141393
|
+
process.exitCode = 1;
|
|
141394
|
+
return;
|
|
141395
|
+
}
|
|
141396
|
+
if (outputFile) {
|
|
141397
|
+
const { writeFileSync: writeFileSync26 } = await import("node:fs");
|
|
141398
|
+
writeFileSync26(outputFile, output, "utf-8");
|
|
141399
|
+
process.stdout.write(
|
|
141400
|
+
`[nexus] Exported to ${outputFile} (${nodes.length} nodes, ${relations.length} edges)
|
|
141401
|
+
`
|
|
141402
|
+
);
|
|
141403
|
+
} else {
|
|
141404
|
+
process.stdout.write(output);
|
|
141405
|
+
if (!output.endsWith("\n")) process.stdout.write("\n");
|
|
141406
|
+
}
|
|
141407
|
+
const durationMs = Date.now() - startTime;
|
|
141408
|
+
if (outputFile) {
|
|
141409
|
+
process.stderr.write(`[nexus] Export completed in ${durationMs}ms
|
|
141410
|
+
`);
|
|
141411
|
+
}
|
|
141412
|
+
} catch (err) {
|
|
141413
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
141414
|
+
process.stderr.write(`[nexus] Error: ${msg}
|
|
141415
|
+
`);
|
|
141416
|
+
process.exitCode = 1;
|
|
141417
|
+
}
|
|
141418
|
+
});
|
|
140880
141419
|
nexus.command("diff").description(
|
|
140881
141420
|
"Compare NEXUS index state between two git commits \u2014 shows new/removed relations and broken call chains"
|
|
140882
141421
|
).option("--before <sha>", 'Git SHA or ref for the "before" snapshot (default: HEAD~1)').option("--after <sha>", 'Git SHA or ref for the "after" snapshot (default: HEAD)', "HEAD").option("--path <dir>", "Repository directory to analyze (default: cwd)").option("--json", "Output result as JSON (LAFS envelope format)").option("--project-id <id>", "Override the project ID (default: auto-detected from path)").action(async (opts) => {
|