@cleocode/cleo 2026.3.29 → 2026.3.31
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 +591 -332
- package/dist/cli/index.js.map +4 -4
- package/dist/mcp/index.js +576 -341
- package/dist/mcp/index.js.map +4 -4
- package/package.json +1 -1
- package/server.json +1 -1
- package/templates/CLEO-INJECTION.md +11 -0
package/dist/cli/index.js
CHANGED
|
@@ -4439,6 +4439,118 @@ var init_sqlite = __esm({
|
|
|
4439
4439
|
}
|
|
4440
4440
|
});
|
|
4441
4441
|
|
|
4442
|
+
// src/core/metrics/provider-detection.ts
|
|
4443
|
+
var provider_detection_exports = {};
|
|
4444
|
+
__export(provider_detection_exports, {
|
|
4445
|
+
detectRuntimeProviderContext: () => detectRuntimeProviderContext,
|
|
4446
|
+
resetRuntimeProviderContextCache: () => resetRuntimeProviderContextCache,
|
|
4447
|
+
selectRuntimeProviderContext: () => selectRuntimeProviderContext
|
|
4448
|
+
});
|
|
4449
|
+
import { basename as basename3 } from "node:path";
|
|
4450
|
+
import {
|
|
4451
|
+
detectProjectProviders,
|
|
4452
|
+
getProvider,
|
|
4453
|
+
resolveAlias
|
|
4454
|
+
} from "@cleocode/caamp";
|
|
4455
|
+
function inferProviderFromVendor(vendor) {
|
|
4456
|
+
const value = (vendor ?? "").trim().toLowerCase();
|
|
4457
|
+
if (!value) return void 0;
|
|
4458
|
+
if (value.includes("anthropic") || value.includes("claude")) return "anthropic";
|
|
4459
|
+
if (value.includes("openai") || value.includes("codex") || value.includes("chatgpt"))
|
|
4460
|
+
return "openai";
|
|
4461
|
+
if (value.includes("google") || value.includes("gemini")) return "google";
|
|
4462
|
+
if (value.includes("xai") || value.includes("grok")) return "xai";
|
|
4463
|
+
return void 0;
|
|
4464
|
+
}
|
|
4465
|
+
function getRuntimeHints(snapshot) {
|
|
4466
|
+
const argv = snapshot.argv ?? process.argv;
|
|
4467
|
+
const env = snapshot.env ?? process.env;
|
|
4468
|
+
const hints = /* @__PURE__ */ new Set();
|
|
4469
|
+
const bin = basename3(argv[1] ?? argv[0] ?? "").replace(/\.[^.]+$/, "");
|
|
4470
|
+
if (bin) hints.add(bin);
|
|
4471
|
+
if (env["CLAUDE_CODE_ENABLE_TELEMETRY"] || env["CLAUDE_CODE_ENTRYPOINT"]) {
|
|
4472
|
+
hints.add("claude-code");
|
|
4473
|
+
hints.add("claude");
|
|
4474
|
+
}
|
|
4475
|
+
if (env["OPENCODE_AGENT"] || env["OPENCODE"]) {
|
|
4476
|
+
hints.add("opencode");
|
|
4477
|
+
}
|
|
4478
|
+
if (env["CURSOR_TRACE_ID"] || env["CURSOR_AGENT"]) {
|
|
4479
|
+
hints.add("cursor");
|
|
4480
|
+
}
|
|
4481
|
+
return Array.from(hints);
|
|
4482
|
+
}
|
|
4483
|
+
function pickDetectionByHint(detections, hints) {
|
|
4484
|
+
for (const hint of hints) {
|
|
4485
|
+
const resolved = resolveAlias(hint);
|
|
4486
|
+
const direct = detections.find(
|
|
4487
|
+
(entry) => entry.provider.id === resolved || entry.provider.id === hint
|
|
4488
|
+
);
|
|
4489
|
+
if (direct) return direct;
|
|
4490
|
+
const byAlias = detections.find(
|
|
4491
|
+
(entry) => entry.provider.aliases.includes(hint) || entry.provider.agentFlag === hint || entry.provider.toolName.toLowerCase() === hint.toLowerCase()
|
|
4492
|
+
);
|
|
4493
|
+
if (byAlias) return byAlias;
|
|
4494
|
+
const provider = getProvider(resolved);
|
|
4495
|
+
if (provider) {
|
|
4496
|
+
return {
|
|
4497
|
+
provider,
|
|
4498
|
+
installed: true,
|
|
4499
|
+
methods: [],
|
|
4500
|
+
projectDetected: false
|
|
4501
|
+
};
|
|
4502
|
+
}
|
|
4503
|
+
}
|
|
4504
|
+
return null;
|
|
4505
|
+
}
|
|
4506
|
+
function selectRuntimeProviderContext(detections, snapshot = {}) {
|
|
4507
|
+
const hints = getRuntimeHints(snapshot);
|
|
4508
|
+
const hinted = pickDetectionByHint(detections, hints);
|
|
4509
|
+
const projectMatches = detections.filter((entry) => entry.projectDetected);
|
|
4510
|
+
const installed = detections.filter((entry) => entry.installed);
|
|
4511
|
+
const selected = hinted ?? (projectMatches.length === 1 ? projectMatches[0] : null) ?? (installed.length === 1 ? installed[0] : null);
|
|
4512
|
+
if (!selected) {
|
|
4513
|
+
return {
|
|
4514
|
+
runtimeCandidates: installed.map((entry) => entry.provider.id)
|
|
4515
|
+
};
|
|
4516
|
+
}
|
|
4517
|
+
return {
|
|
4518
|
+
runtimeProviderId: selected.provider.id,
|
|
4519
|
+
runtimeToolName: selected.provider.toolName,
|
|
4520
|
+
runtimeVendor: selected.provider.vendor,
|
|
4521
|
+
runtimeInstructionFile: selected.provider.instructFile,
|
|
4522
|
+
runtimeProjectDetected: selected.projectDetected,
|
|
4523
|
+
runtimeDetectionMethods: selected.methods,
|
|
4524
|
+
runtimeCandidates: installed.map((entry) => entry.provider.id),
|
|
4525
|
+
inferredModelProvider: inferProviderFromVendor(selected.provider.vendor)
|
|
4526
|
+
};
|
|
4527
|
+
}
|
|
4528
|
+
function detectRuntimeProviderContext(snapshot = {}) {
|
|
4529
|
+
if (!snapshot.cwd && !snapshot.argv && !snapshot.env && cachedRuntimeProvider) {
|
|
4530
|
+
return cachedRuntimeProvider;
|
|
4531
|
+
}
|
|
4532
|
+
try {
|
|
4533
|
+
const detections = detectProjectProviders(snapshot.cwd ?? process.cwd());
|
|
4534
|
+
const context = selectRuntimeProviderContext(detections, snapshot);
|
|
4535
|
+
if (!snapshot.cwd && !snapshot.argv && !snapshot.env) {
|
|
4536
|
+
cachedRuntimeProvider = context;
|
|
4537
|
+
}
|
|
4538
|
+
return context;
|
|
4539
|
+
} catch {
|
|
4540
|
+
return {};
|
|
4541
|
+
}
|
|
4542
|
+
}
|
|
4543
|
+
function resetRuntimeProviderContextCache() {
|
|
4544
|
+
cachedRuntimeProvider = null;
|
|
4545
|
+
}
|
|
4546
|
+
var cachedRuntimeProvider;
|
|
4547
|
+
var init_provider_detection = __esm({
|
|
4548
|
+
"src/core/metrics/provider-detection.ts"() {
|
|
4549
|
+
"use strict";
|
|
4550
|
+
cachedRuntimeProvider = null;
|
|
4551
|
+
}
|
|
4552
|
+
});
|
|
4553
|
+
|
|
4442
4554
|
// src/store/parsers.ts
|
|
4443
4555
|
function safeParseJson(str) {
|
|
4444
4556
|
if (!str) return void 0;
|
|
@@ -8482,14 +8594,16 @@ async function writeMemoryBridge(projectRoot, config) {
|
|
|
8482
8594
|
}
|
|
8483
8595
|
writeFileSync4(bridgePath, content, "utf-8");
|
|
8484
8596
|
return { path: bridgePath, written: true };
|
|
8485
|
-
} catch {
|
|
8597
|
+
} catch (err) {
|
|
8598
|
+
console.error("[CLEO] Failed to write memory bridge:", err instanceof Error ? err.message : String(err));
|
|
8486
8599
|
return { path: bridgePath, written: false };
|
|
8487
8600
|
}
|
|
8488
8601
|
}
|
|
8489
8602
|
async function refreshMemoryBridge(projectRoot) {
|
|
8490
8603
|
try {
|
|
8491
8604
|
await writeMemoryBridge(projectRoot);
|
|
8492
|
-
} catch {
|
|
8605
|
+
} catch (err) {
|
|
8606
|
+
console.error("[CLEO] Memory bridge refresh failed:", err instanceof Error ? err.message : String(err));
|
|
8493
8607
|
}
|
|
8494
8608
|
}
|
|
8495
8609
|
async function getLastHandoffSafe(projectRoot) {
|
|
@@ -9885,28 +9999,25 @@ async function ensureInjection(projectRoot) {
|
|
|
9885
9999
|
}
|
|
9886
10000
|
const { getInstalledProviders: getInstalledProviders3, inject, injectAll: injectAll2, buildInjectionContent: buildInjectionContent2 } = caamp;
|
|
9887
10001
|
const providers = getInstalledProviders3();
|
|
9888
|
-
if (providers.length === 0) {
|
|
9889
|
-
return {
|
|
9890
|
-
action: "skipped",
|
|
9891
|
-
path: join28(projectRoot, "AGENTS.md"),
|
|
9892
|
-
details: "No AI agent providers detected, skipping injection"
|
|
9893
|
-
};
|
|
9894
|
-
}
|
|
9895
10002
|
const actions = [];
|
|
9896
|
-
|
|
9897
|
-
|
|
9898
|
-
|
|
9899
|
-
|
|
9900
|
-
|
|
9901
|
-
|
|
9902
|
-
|
|
9903
|
-
|
|
9904
|
-
|
|
9905
|
-
|
|
9906
|
-
|
|
9907
|
-
|
|
9908
|
-
const
|
|
9909
|
-
|
|
10003
|
+
if (providers.length === 0) {
|
|
10004
|
+
actions.push("No providers detected (AGENTS.md created without provider injection)");
|
|
10005
|
+
} else {
|
|
10006
|
+
for (const provider of providers) {
|
|
10007
|
+
const instructFile = join28(projectRoot, provider.pathProject, provider.instructFile);
|
|
10008
|
+
await stripCLEOBlocks(instructFile);
|
|
10009
|
+
}
|
|
10010
|
+
await stripCLEOBlocks(join28(projectRoot, "AGENTS.md"));
|
|
10011
|
+
const removedStale = await removeStaleAgentInjection(projectRoot);
|
|
10012
|
+
if (removedStale) {
|
|
10013
|
+
actions.push("removed deprecated AGENT-INJECTION.md");
|
|
10014
|
+
}
|
|
10015
|
+
const injectionContent = buildInjectionContent2({ references: ["@AGENTS.md"] });
|
|
10016
|
+
const results = await injectAll2(providers, projectRoot, "project", injectionContent);
|
|
10017
|
+
for (const [filePath, action] of results) {
|
|
10018
|
+
const fileName = basename4(filePath);
|
|
10019
|
+
actions.push(`${fileName} (${action})`);
|
|
10020
|
+
}
|
|
9910
10021
|
}
|
|
9911
10022
|
const agentsMdPath = join28(projectRoot, "AGENTS.md");
|
|
9912
10023
|
const agentsMdLines = ["@~/.cleo/templates/CLEO-INJECTION.md"];
|
|
@@ -9914,6 +10025,10 @@ async function ensureInjection(projectRoot) {
|
|
|
9914
10025
|
if (existsSync26(projectContextPath)) {
|
|
9915
10026
|
agentsMdLines.push("@.cleo/project-context.json");
|
|
9916
10027
|
}
|
|
10028
|
+
const memoryBridgePath = join28(projectRoot, ".cleo", "memory-bridge.md");
|
|
10029
|
+
if (existsSync26(memoryBridgePath)) {
|
|
10030
|
+
agentsMdLines.push("@.cleo/memory-bridge.md");
|
|
10031
|
+
}
|
|
9917
10032
|
const contributorBlock = buildContributorInjectionBlock(projectRoot);
|
|
9918
10033
|
if (contributorBlock) {
|
|
9919
10034
|
agentsMdLines.push(contributorBlock);
|
|
@@ -10114,6 +10229,7 @@ __export(scaffold_exports, {
|
|
|
10114
10229
|
CLEO_GITIGNORE_FALLBACK: () => CLEO_GITIGNORE_FALLBACK,
|
|
10115
10230
|
REQUIRED_CLEO_SUBDIRS: () => REQUIRED_CLEO_SUBDIRS,
|
|
10116
10231
|
REQUIRED_GLOBAL_SUBDIRS: () => REQUIRED_GLOBAL_SUBDIRS,
|
|
10232
|
+
checkBrainDb: () => checkBrainDb,
|
|
10117
10233
|
checkCleoGitRepo: () => checkCleoGitRepo,
|
|
10118
10234
|
checkCleoStructure: () => checkCleoStructure,
|
|
10119
10235
|
checkConfig: () => checkConfig,
|
|
@@ -10121,10 +10237,12 @@ __export(scaffold_exports, {
|
|
|
10121
10237
|
checkGlobalHome: () => checkGlobalHome,
|
|
10122
10238
|
checkGlobalTemplates: () => checkGlobalTemplates,
|
|
10123
10239
|
checkLogDir: () => checkLogDir,
|
|
10240
|
+
checkMemoryBridge: () => checkMemoryBridge,
|
|
10124
10241
|
checkProjectContext: () => checkProjectContext,
|
|
10125
10242
|
checkProjectInfo: () => checkProjectInfo,
|
|
10126
10243
|
checkSqliteDb: () => checkSqliteDb,
|
|
10127
10244
|
createDefaultConfig: () => createDefaultConfig,
|
|
10245
|
+
ensureBrainDb: () => ensureBrainDb,
|
|
10128
10246
|
ensureCleoGitRepo: () => ensureCleoGitRepo,
|
|
10129
10247
|
ensureCleoStructure: () => ensureCleoStructure,
|
|
10130
10248
|
ensureConfig: () => ensureConfig,
|
|
@@ -10739,6 +10857,79 @@ function checkSqliteDb(projectRoot) {
|
|
|
10739
10857
|
fix: null
|
|
10740
10858
|
};
|
|
10741
10859
|
}
|
|
10860
|
+
async function ensureBrainDb(projectRoot) {
|
|
10861
|
+
const cleoDir = getCleoDirAbsolute(projectRoot);
|
|
10862
|
+
const dbPath = join29(cleoDir, "brain.db");
|
|
10863
|
+
if (existsSync27(dbPath)) {
|
|
10864
|
+
return { action: "skipped", path: dbPath, details: "brain.db already exists" };
|
|
10865
|
+
}
|
|
10866
|
+
try {
|
|
10867
|
+
const { getBrainDb: getBrainDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
|
|
10868
|
+
await getBrainDb2(projectRoot);
|
|
10869
|
+
return { action: "created", path: dbPath, details: "Brain database initialized" };
|
|
10870
|
+
} catch (err) {
|
|
10871
|
+
return {
|
|
10872
|
+
action: "skipped",
|
|
10873
|
+
path: dbPath,
|
|
10874
|
+
details: `Failed to initialize brain.db: ${err instanceof Error ? err.message : String(err)}`
|
|
10875
|
+
};
|
|
10876
|
+
}
|
|
10877
|
+
}
|
|
10878
|
+
function checkBrainDb(projectRoot) {
|
|
10879
|
+
const cleoDir = getCleoDirAbsolute(projectRoot);
|
|
10880
|
+
const dbPath = join29(cleoDir, "brain.db");
|
|
10881
|
+
if (!existsSync27(dbPath)) {
|
|
10882
|
+
return {
|
|
10883
|
+
id: "brain_db",
|
|
10884
|
+
category: "scaffold",
|
|
10885
|
+
status: "failed",
|
|
10886
|
+
message: "brain.db not found",
|
|
10887
|
+
details: { path: dbPath, exists: false },
|
|
10888
|
+
fix: "cleo init"
|
|
10889
|
+
};
|
|
10890
|
+
}
|
|
10891
|
+
const stat5 = statSync4(dbPath);
|
|
10892
|
+
if (stat5.size === 0) {
|
|
10893
|
+
return {
|
|
10894
|
+
id: "brain_db",
|
|
10895
|
+
category: "scaffold",
|
|
10896
|
+
status: "warning",
|
|
10897
|
+
message: "brain.db exists but is empty (0 bytes)",
|
|
10898
|
+
details: { path: dbPath, exists: true, size: 0 },
|
|
10899
|
+
fix: "cleo upgrade"
|
|
10900
|
+
};
|
|
10901
|
+
}
|
|
10902
|
+
return {
|
|
10903
|
+
id: "brain_db",
|
|
10904
|
+
category: "scaffold",
|
|
10905
|
+
status: "passed",
|
|
10906
|
+
message: `brain.db exists (${stat5.size} bytes)`,
|
|
10907
|
+
details: { path: dbPath, exists: true, size: stat5.size },
|
|
10908
|
+
fix: null
|
|
10909
|
+
};
|
|
10910
|
+
}
|
|
10911
|
+
function checkMemoryBridge(projectRoot) {
|
|
10912
|
+
const cleoDir = getCleoDirAbsolute(projectRoot);
|
|
10913
|
+
const bridgePath = join29(cleoDir, "memory-bridge.md");
|
|
10914
|
+
if (!existsSync27(bridgePath)) {
|
|
10915
|
+
return {
|
|
10916
|
+
id: "memory_bridge",
|
|
10917
|
+
category: "scaffold",
|
|
10918
|
+
status: "warning",
|
|
10919
|
+
message: "memory-bridge.md not found",
|
|
10920
|
+
details: { path: bridgePath, exists: false },
|
|
10921
|
+
fix: "cleo init or cleo refresh-memory"
|
|
10922
|
+
};
|
|
10923
|
+
}
|
|
10924
|
+
return {
|
|
10925
|
+
id: "memory_bridge",
|
|
10926
|
+
category: "scaffold",
|
|
10927
|
+
status: "passed",
|
|
10928
|
+
message: "memory-bridge.md exists",
|
|
10929
|
+
details: { path: bridgePath, exists: true },
|
|
10930
|
+
fix: null
|
|
10931
|
+
};
|
|
10932
|
+
}
|
|
10742
10933
|
async function ensureGlobalHome() {
|
|
10743
10934
|
const cleoHome = getCleoHome();
|
|
10744
10935
|
const alreadyExists = existsSync27(cleoHome);
|
|
@@ -11924,6 +12115,28 @@ var init_registry2 = __esm({
|
|
|
11924
12115
|
}
|
|
11925
12116
|
});
|
|
11926
12117
|
|
|
12118
|
+
// src/core/adapters/adapter-registry.ts
|
|
12119
|
+
var ADAPTER_REGISTRY;
|
|
12120
|
+
var init_adapter_registry = __esm({
|
|
12121
|
+
"src/core/adapters/adapter-registry.ts"() {
|
|
12122
|
+
"use strict";
|
|
12123
|
+
ADAPTER_REGISTRY = {
|
|
12124
|
+
"claude-code": async () => {
|
|
12125
|
+
const { ClaudeCodeAdapter } = await import("@cleocode/adapter-claude-code");
|
|
12126
|
+
return new ClaudeCodeAdapter();
|
|
12127
|
+
},
|
|
12128
|
+
"opencode": async () => {
|
|
12129
|
+
const { OpenCodeAdapter } = await import("@cleocode/adapter-opencode");
|
|
12130
|
+
return new OpenCodeAdapter();
|
|
12131
|
+
},
|
|
12132
|
+
"cursor": async () => {
|
|
12133
|
+
const { CursorAdapter } = await import("@cleocode/adapter-cursor");
|
|
12134
|
+
return new CursorAdapter();
|
|
12135
|
+
}
|
|
12136
|
+
};
|
|
12137
|
+
}
|
|
12138
|
+
});
|
|
12139
|
+
|
|
11927
12140
|
// src/core/adapters/discovery.ts
|
|
11928
12141
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
11929
12142
|
import { existsSync as existsSync31, readdirSync as readdirSync13, readFileSync as readFileSync22 } from "node:fs";
|
|
@@ -11993,13 +12206,16 @@ var log4, AdapterManager;
|
|
|
11993
12206
|
var init_manager = __esm({
|
|
11994
12207
|
"src/core/adapters/manager.ts"() {
|
|
11995
12208
|
"use strict";
|
|
12209
|
+
init_registry();
|
|
11996
12210
|
init_logger();
|
|
12211
|
+
init_adapter_registry();
|
|
11997
12212
|
init_discovery();
|
|
11998
12213
|
log4 = getLogger("adapter-manager");
|
|
11999
12214
|
AdapterManager = class _AdapterManager {
|
|
12000
12215
|
static instance = null;
|
|
12001
12216
|
adapters = /* @__PURE__ */ new Map();
|
|
12002
12217
|
manifests = /* @__PURE__ */ new Map();
|
|
12218
|
+
hookCleanups = /* @__PURE__ */ new Map();
|
|
12003
12219
|
activeId = null;
|
|
12004
12220
|
projectRoot;
|
|
12005
12221
|
constructor(projectRoot) {
|
|
@@ -12043,7 +12259,7 @@ var init_manager = __esm({
|
|
|
12043
12259
|
}
|
|
12044
12260
|
/**
|
|
12045
12261
|
* Load and initialize an adapter by manifest ID.
|
|
12046
|
-
*
|
|
12262
|
+
* Uses the static adapter registry for reliable bundled operation.
|
|
12047
12263
|
*/
|
|
12048
12264
|
async activate(adapterId) {
|
|
12049
12265
|
const manifest = this.manifests.get(adapterId);
|
|
@@ -12055,20 +12271,18 @@ var init_manager = __esm({
|
|
|
12055
12271
|
this.activeId = adapterId;
|
|
12056
12272
|
return existing;
|
|
12057
12273
|
}
|
|
12058
|
-
const
|
|
12059
|
-
|
|
12060
|
-
|
|
12061
|
-
|
|
12062
|
-
"adapters",
|
|
12063
|
-
manifest.provider,
|
|
12064
|
-
manifest.entryPoint
|
|
12065
|
-
);
|
|
12274
|
+
const factory = ADAPTER_REGISTRY[adapterId];
|
|
12275
|
+
if (!factory) {
|
|
12276
|
+
throw new Error(`No adapter registered in static registry: ${adapterId}`);
|
|
12277
|
+
}
|
|
12066
12278
|
try {
|
|
12067
|
-
const
|
|
12068
|
-
const adapter = typeof mod.default === "function" ? new mod.default() : typeof mod.createAdapter === "function" ? await mod.createAdapter() : mod.default;
|
|
12279
|
+
const adapter = await factory();
|
|
12069
12280
|
await adapter.initialize(this.projectRoot);
|
|
12070
12281
|
this.adapters.set(adapterId, adapter);
|
|
12071
12282
|
this.activeId = adapterId;
|
|
12283
|
+
if (adapter.hooks) {
|
|
12284
|
+
await this.wireAdapterHooks(adapterId, adapter);
|
|
12285
|
+
}
|
|
12072
12286
|
log4.info({ adapterId, provider: manifest.provider }, "Adapter activated");
|
|
12073
12287
|
return adapter;
|
|
12074
12288
|
} catch (err) {
|
|
@@ -12150,6 +12364,7 @@ var init_manager = __esm({
|
|
|
12150
12364
|
async dispose() {
|
|
12151
12365
|
for (const [id, adapter] of this.adapters) {
|
|
12152
12366
|
try {
|
|
12367
|
+
await this.cleanupAdapterHooks(id, adapter);
|
|
12153
12368
|
await adapter.dispose();
|
|
12154
12369
|
log4.info({ adapterId: id }, "Adapter disposed");
|
|
12155
12370
|
} catch (err) {
|
|
@@ -12157,6 +12372,7 @@ var init_manager = __esm({
|
|
|
12157
12372
|
}
|
|
12158
12373
|
}
|
|
12159
12374
|
this.adapters.clear();
|
|
12375
|
+
this.hookCleanups.clear();
|
|
12160
12376
|
this.activeId = null;
|
|
12161
12377
|
}
|
|
12162
12378
|
/** Dispose a single adapter. */
|
|
@@ -12164,6 +12380,7 @@ var init_manager = __esm({
|
|
|
12164
12380
|
const adapter = this.adapters.get(adapterId);
|
|
12165
12381
|
if (!adapter) return;
|
|
12166
12382
|
try {
|
|
12383
|
+
await this.cleanupAdapterHooks(adapterId, adapter);
|
|
12167
12384
|
await adapter.dispose();
|
|
12168
12385
|
} catch (err) {
|
|
12169
12386
|
log4.error({ adapterId, err }, "Failed to dispose adapter");
|
|
@@ -12173,6 +12390,51 @@ var init_manager = __esm({
|
|
|
12173
12390
|
this.activeId = null;
|
|
12174
12391
|
}
|
|
12175
12392
|
}
|
|
12393
|
+
/**
|
|
12394
|
+
* Wire an adapter's hook event map into CLEO's HookRegistry.
|
|
12395
|
+
* Creates bridging handlers at priority 50 for each mapped event.
|
|
12396
|
+
*/
|
|
12397
|
+
async wireAdapterHooks(adapterId, adapter) {
|
|
12398
|
+
if (!adapter.hooks) return;
|
|
12399
|
+
try {
|
|
12400
|
+
await adapter.hooks.registerNativeHooks(this.projectRoot);
|
|
12401
|
+
} catch (err) {
|
|
12402
|
+
log4.error({ adapterId, err }, "Failed to register native hooks");
|
|
12403
|
+
}
|
|
12404
|
+
const eventMap = adapter.hooks.getEventMap?.();
|
|
12405
|
+
if (!eventMap) return;
|
|
12406
|
+
const cleanups = [];
|
|
12407
|
+
for (const [_providerEvent, caampEvent] of Object.entries(eventMap)) {
|
|
12408
|
+
const hookId = `adapter-${adapterId}-${caampEvent}`;
|
|
12409
|
+
const unregister = hooks.register({
|
|
12410
|
+
id: hookId,
|
|
12411
|
+
event: caampEvent,
|
|
12412
|
+
priority: 50,
|
|
12413
|
+
handler: async (_projectRoot, payload) => {
|
|
12414
|
+
log4.debug({ adapterId, event: caampEvent, payload }, "Adapter hook dispatched");
|
|
12415
|
+
}
|
|
12416
|
+
});
|
|
12417
|
+
cleanups.push(unregister);
|
|
12418
|
+
}
|
|
12419
|
+
this.hookCleanups.set(adapterId, cleanups);
|
|
12420
|
+
}
|
|
12421
|
+
/**
|
|
12422
|
+
* Clean up hook registrations for an adapter.
|
|
12423
|
+
*/
|
|
12424
|
+
async cleanupAdapterHooks(adapterId, adapter) {
|
|
12425
|
+
const cleanups = this.hookCleanups.get(adapterId);
|
|
12426
|
+
if (cleanups) {
|
|
12427
|
+
for (const fn of cleanups) {
|
|
12428
|
+
fn();
|
|
12429
|
+
}
|
|
12430
|
+
this.hookCleanups.delete(adapterId);
|
|
12431
|
+
}
|
|
12432
|
+
try {
|
|
12433
|
+
await adapter.hooks?.unregisterNativeHooks();
|
|
12434
|
+
} catch (err) {
|
|
12435
|
+
log4.error({ adapterId, err }, "Failed to unregister native hooks");
|
|
12436
|
+
}
|
|
12437
|
+
}
|
|
12176
12438
|
};
|
|
12177
12439
|
}
|
|
12178
12440
|
});
|
|
@@ -12180,6 +12442,7 @@ var init_manager = __esm({
|
|
|
12180
12442
|
// src/core/adapters/index.ts
|
|
12181
12443
|
var adapters_exports = {};
|
|
12182
12444
|
__export(adapters_exports, {
|
|
12445
|
+
ADAPTER_REGISTRY: () => ADAPTER_REGISTRY,
|
|
12183
12446
|
AdapterManager: () => AdapterManager,
|
|
12184
12447
|
detectProvider: () => detectProvider,
|
|
12185
12448
|
discoverAdapterManifests: () => discoverAdapterManifests
|
|
@@ -12187,6 +12450,7 @@ __export(adapters_exports, {
|
|
|
12187
12450
|
var init_adapters = __esm({
|
|
12188
12451
|
"src/core/adapters/index.ts"() {
|
|
12189
12452
|
"use strict";
|
|
12453
|
+
init_adapter_registry();
|
|
12190
12454
|
init_manager();
|
|
12191
12455
|
init_discovery();
|
|
12192
12456
|
}
|
|
@@ -12410,6 +12674,14 @@ async function initProject(opts = {}) {
|
|
|
12410
12674
|
} catch (err) {
|
|
12411
12675
|
created.push(`tasks.db (deferred: ${err instanceof Error ? err.message : String(err)})`);
|
|
12412
12676
|
}
|
|
12677
|
+
try {
|
|
12678
|
+
const brainResult = await ensureBrainDb(projRoot);
|
|
12679
|
+
if (brainResult.action === "created") {
|
|
12680
|
+
created.push("brain.db");
|
|
12681
|
+
}
|
|
12682
|
+
} catch (err) {
|
|
12683
|
+
created.push(`brain.db (deferred: ${err instanceof Error ? err.message : String(err)})`);
|
|
12684
|
+
}
|
|
12413
12685
|
if (force) {
|
|
12414
12686
|
const gitignoreResult = await ensureGitignore(projRoot);
|
|
12415
12687
|
if (gitignoreResult.action === "skipped") {
|
|
@@ -12499,6 +12771,14 @@ async function initProject(opts = {}) {
|
|
|
12499
12771
|
} catch (err) {
|
|
12500
12772
|
warnings.push(`Project detection failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
12501
12773
|
}
|
|
12774
|
+
try {
|
|
12775
|
+
const bridgeResult = await writeMemoryBridge(projRoot);
|
|
12776
|
+
if (bridgeResult.written) {
|
|
12777
|
+
created.push("memory-bridge.md");
|
|
12778
|
+
}
|
|
12779
|
+
} catch (err) {
|
|
12780
|
+
warnings.push(`Memory bridge: ${err instanceof Error ? err.message : String(err)}`);
|
|
12781
|
+
}
|
|
12502
12782
|
try {
|
|
12503
12783
|
const injectionResult = await ensureInjection(projRoot);
|
|
12504
12784
|
if (injectionResult.action !== "skipped") {
|
|
@@ -12532,6 +12812,21 @@ async function initProject(opts = {}) {
|
|
|
12532
12812
|
const detected = mgr.detectActive();
|
|
12533
12813
|
if (detected.length > 0) {
|
|
12534
12814
|
created.push(`adapters: active provider detected (${detected.join(", ")})`);
|
|
12815
|
+
for (const adapterId of detected) {
|
|
12816
|
+
try {
|
|
12817
|
+
const adapter = await mgr.activate(adapterId);
|
|
12818
|
+
const installResult = await adapter.install.install({
|
|
12819
|
+
projectDir: projRoot
|
|
12820
|
+
});
|
|
12821
|
+
if (installResult.success) {
|
|
12822
|
+
created.push(`adapter install (${adapterId}): installed`);
|
|
12823
|
+
} else {
|
|
12824
|
+
warnings.push(`adapter install (${adapterId}): failed`);
|
|
12825
|
+
}
|
|
12826
|
+
} catch (err) {
|
|
12827
|
+
warnings.push(`adapter activate/install (${adapterId}): ${err instanceof Error ? err.message : String(err)}`);
|
|
12828
|
+
}
|
|
12829
|
+
}
|
|
12535
12830
|
}
|
|
12536
12831
|
}
|
|
12537
12832
|
} catch (err) {
|
|
@@ -12598,6 +12893,7 @@ var init_init = __esm({
|
|
|
12598
12893
|
init_paths();
|
|
12599
12894
|
init_scaffold();
|
|
12600
12895
|
init_schema_management();
|
|
12896
|
+
init_memory_bridge();
|
|
12601
12897
|
}
|
|
12602
12898
|
});
|
|
12603
12899
|
|
|
@@ -14546,6 +14842,13 @@ async function startSession(options, cwd, accessor) {
|
|
|
14546
14842
|
);
|
|
14547
14843
|
}
|
|
14548
14844
|
}
|
|
14845
|
+
let detectedProviderId = null;
|
|
14846
|
+
try {
|
|
14847
|
+
const { detectRuntimeProviderContext: detectRuntimeProviderContext2 } = await Promise.resolve().then(() => (init_provider_detection(), provider_detection_exports));
|
|
14848
|
+
const ctx = detectRuntimeProviderContext2();
|
|
14849
|
+
detectedProviderId = ctx.runtimeProviderId ?? null;
|
|
14850
|
+
} catch {
|
|
14851
|
+
}
|
|
14549
14852
|
const session = {
|
|
14550
14853
|
id: generateSessionId(),
|
|
14551
14854
|
name: options.name,
|
|
@@ -14560,7 +14863,7 @@ async function startSession(options, cwd, accessor) {
|
|
|
14560
14863
|
notes: [],
|
|
14561
14864
|
tasksCompleted: [],
|
|
14562
14865
|
tasksCreated: [],
|
|
14563
|
-
providerId: options.providerId ?? null
|
|
14866
|
+
providerId: options.providerId ?? detectedProviderId ?? null
|
|
14564
14867
|
};
|
|
14565
14868
|
if (options.grade) {
|
|
14566
14869
|
session.notes = ["[grade-mode:enabled]", ...session.notes ?? []];
|
|
@@ -14570,13 +14873,22 @@ async function startSession(options, cwd, accessor) {
|
|
|
14570
14873
|
}
|
|
14571
14874
|
sessions2.push(session);
|
|
14572
14875
|
await saveSessions(sessions2, cwd, accessor);
|
|
14876
|
+
if (session.providerId) {
|
|
14877
|
+
Promise.resolve().then(() => (init_adapters(), adapters_exports)).then(({ AdapterManager: AdapterManager2 }) => {
|
|
14878
|
+
const mgr = AdapterManager2.getInstance(cwd ?? process.cwd());
|
|
14879
|
+
mgr.discover();
|
|
14880
|
+
return mgr.activate(session.providerId);
|
|
14881
|
+
}).catch(() => {
|
|
14882
|
+
});
|
|
14883
|
+
}
|
|
14573
14884
|
const { hooks: hooks2 } = await Promise.resolve().then(() => (init_registry(), registry_exports));
|
|
14574
14885
|
hooks2.dispatch("onSessionStart", cwd ?? process.cwd(), {
|
|
14575
14886
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14576
14887
|
sessionId: session.id,
|
|
14577
14888
|
name: options.name,
|
|
14578
14889
|
scope,
|
|
14579
|
-
agent: options.agent
|
|
14890
|
+
agent: options.agent,
|
|
14891
|
+
providerId: session.providerId ?? void 0
|
|
14580
14892
|
}).catch(() => {
|
|
14581
14893
|
});
|
|
14582
14894
|
return session;
|
|
@@ -14612,7 +14924,8 @@ async function endSession(options = {}, cwd, accessor) {
|
|
|
14612
14924
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14613
14925
|
sessionId: session.id,
|
|
14614
14926
|
duration,
|
|
14615
|
-
tasksCompleted: session.tasksCompleted || []
|
|
14927
|
+
tasksCompleted: session.tasksCompleted || [],
|
|
14928
|
+
providerId: session.providerId ?? void 0
|
|
14616
14929
|
}).catch(() => {
|
|
14617
14930
|
});
|
|
14618
14931
|
const { bridgeSessionToMemory: bridgeSessionToMemory2 } = await Promise.resolve().then(() => (init_session_memory_bridge(), session_memory_bridge_exports));
|
|
@@ -15130,7 +15443,7 @@ async function initializeDefaultAdapters() {
|
|
|
15130
15443
|
}
|
|
15131
15444
|
}
|
|
15132
15445
|
var SpawnAdapterRegistry, spawnRegistry;
|
|
15133
|
-
var
|
|
15446
|
+
var init_adapter_registry2 = __esm({
|
|
15134
15447
|
"src/core/spawn/adapter-registry.ts"() {
|
|
15135
15448
|
"use strict";
|
|
15136
15449
|
SpawnAdapterRegistry = class {
|
|
@@ -16359,6 +16672,18 @@ async function startupHealthCheck(projectRoot) {
|
|
|
16359
16672
|
} else {
|
|
16360
16673
|
checks.push({ check: "log_dir", status: "pass", message: "Log directory present" });
|
|
16361
16674
|
}
|
|
16675
|
+
const brainDbCheck = checkBrainDb(root);
|
|
16676
|
+
checks.push({
|
|
16677
|
+
check: "brain_db",
|
|
16678
|
+
status: brainDbCheck.status === "passed" ? "pass" : "warn",
|
|
16679
|
+
message: brainDbCheck.message
|
|
16680
|
+
});
|
|
16681
|
+
const memBridgeCheck = checkMemoryBridge(root);
|
|
16682
|
+
checks.push({
|
|
16683
|
+
check: "memory_bridge",
|
|
16684
|
+
status: memBridgeCheck.status === "passed" ? "pass" : "warn",
|
|
16685
|
+
message: memBridgeCheck.message
|
|
16686
|
+
});
|
|
16362
16687
|
const hasFailures = failures.length > 0;
|
|
16363
16688
|
const state = hasFailures && !projectHealthy ? "needs_upgrade" : "healthy";
|
|
16364
16689
|
return {
|
|
@@ -16567,7 +16892,7 @@ async function loadCompletionEnforcement(cwd) {
|
|
|
16567
16892
|
const lifecycleModeRaw = await getRawConfigValue("lifecycle.mode", cwd);
|
|
16568
16893
|
const acceptanceMode = modeRaw === "off" || modeRaw === "warn" || modeRaw === "block" ? modeRaw : "warn";
|
|
16569
16894
|
const acceptanceRequiredForPriorities = Array.isArray(prioritiesRaw) ? prioritiesRaw.filter((p) => typeof p === "string") : ["critical", "high"];
|
|
16570
|
-
const verificationEnabled = verificationEnabledRaw
|
|
16895
|
+
const verificationEnabled = verificationEnabledRaw === true;
|
|
16571
16896
|
const verificationRequiredGates = Array.isArray(verificationRequiredGatesRaw) ? verificationRequiredGatesRaw.filter((g) => typeof g === "string").filter(isVerificationGate) : DEFAULT_VERIFICATION_REQUIRED_GATES;
|
|
16572
16897
|
const verificationMaxRounds = typeof verificationMaxRoundsRaw === "number" && Number.isInteger(verificationMaxRoundsRaw) ? verificationMaxRoundsRaw : 5;
|
|
16573
16898
|
const lifecycleMode = lifecycleModeRaw === "strict" || lifecycleModeRaw === "warn" || lifecycleModeRaw === "advisory" || lifecycleModeRaw === "none" || lifecycleModeRaw === "off" ? lifecycleModeRaw : "off";
|
|
@@ -20625,104 +20950,8 @@ async function resolveProviderFromModelRegistry(model) {
|
|
|
20625
20950
|
return resolveProviderFromModelIndex(index5, model);
|
|
20626
20951
|
}
|
|
20627
20952
|
|
|
20628
|
-
// src/core/metrics/provider-detection.ts
|
|
20629
|
-
import { basename as basename3 } from "node:path";
|
|
20630
|
-
import {
|
|
20631
|
-
detectProjectProviders,
|
|
20632
|
-
getProvider,
|
|
20633
|
-
resolveAlias
|
|
20634
|
-
} from "@cleocode/caamp";
|
|
20635
|
-
function inferProviderFromVendor(vendor) {
|
|
20636
|
-
const value = (vendor ?? "").trim().toLowerCase();
|
|
20637
|
-
if (!value) return void 0;
|
|
20638
|
-
if (value.includes("anthropic") || value.includes("claude")) return "anthropic";
|
|
20639
|
-
if (value.includes("openai") || value.includes("codex") || value.includes("chatgpt"))
|
|
20640
|
-
return "openai";
|
|
20641
|
-
if (value.includes("google") || value.includes("gemini")) return "google";
|
|
20642
|
-
if (value.includes("xai") || value.includes("grok")) return "xai";
|
|
20643
|
-
return void 0;
|
|
20644
|
-
}
|
|
20645
|
-
function getRuntimeHints(snapshot) {
|
|
20646
|
-
const argv = snapshot.argv ?? process.argv;
|
|
20647
|
-
const env = snapshot.env ?? process.env;
|
|
20648
|
-
const hints = /* @__PURE__ */ new Set();
|
|
20649
|
-
const bin = basename3(argv[1] ?? argv[0] ?? "").replace(/\.[^.]+$/, "");
|
|
20650
|
-
if (bin) hints.add(bin);
|
|
20651
|
-
if (env["CLAUDE_CODE_ENABLE_TELEMETRY"] || env["CLAUDE_CODE_ENTRYPOINT"]) {
|
|
20652
|
-
hints.add("claude-code");
|
|
20653
|
-
hints.add("claude");
|
|
20654
|
-
}
|
|
20655
|
-
if (env["OPENCODE_AGENT"] || env["OPENCODE"]) {
|
|
20656
|
-
hints.add("opencode");
|
|
20657
|
-
}
|
|
20658
|
-
if (env["CURSOR_TRACE_ID"] || env["CURSOR_AGENT"]) {
|
|
20659
|
-
hints.add("cursor");
|
|
20660
|
-
}
|
|
20661
|
-
return Array.from(hints);
|
|
20662
|
-
}
|
|
20663
|
-
function pickDetectionByHint(detections, hints) {
|
|
20664
|
-
for (const hint of hints) {
|
|
20665
|
-
const resolved = resolveAlias(hint);
|
|
20666
|
-
const direct = detections.find(
|
|
20667
|
-
(entry) => entry.provider.id === resolved || entry.provider.id === hint
|
|
20668
|
-
);
|
|
20669
|
-
if (direct) return direct;
|
|
20670
|
-
const byAlias = detections.find(
|
|
20671
|
-
(entry) => entry.provider.aliases.includes(hint) || entry.provider.agentFlag === hint || entry.provider.toolName.toLowerCase() === hint.toLowerCase()
|
|
20672
|
-
);
|
|
20673
|
-
if (byAlias) return byAlias;
|
|
20674
|
-
const provider = getProvider(resolved);
|
|
20675
|
-
if (provider) {
|
|
20676
|
-
return {
|
|
20677
|
-
provider,
|
|
20678
|
-
installed: true,
|
|
20679
|
-
methods: [],
|
|
20680
|
-
projectDetected: false
|
|
20681
|
-
};
|
|
20682
|
-
}
|
|
20683
|
-
}
|
|
20684
|
-
return null;
|
|
20685
|
-
}
|
|
20686
|
-
function selectRuntimeProviderContext(detections, snapshot = {}) {
|
|
20687
|
-
const hints = getRuntimeHints(snapshot);
|
|
20688
|
-
const hinted = pickDetectionByHint(detections, hints);
|
|
20689
|
-
const projectMatches = detections.filter((entry) => entry.projectDetected);
|
|
20690
|
-
const installed = detections.filter((entry) => entry.installed);
|
|
20691
|
-
const selected = hinted ?? (projectMatches.length === 1 ? projectMatches[0] : null) ?? (installed.length === 1 ? installed[0] : null);
|
|
20692
|
-
if (!selected) {
|
|
20693
|
-
return {
|
|
20694
|
-
runtimeCandidates: installed.map((entry) => entry.provider.id)
|
|
20695
|
-
};
|
|
20696
|
-
}
|
|
20697
|
-
return {
|
|
20698
|
-
runtimeProviderId: selected.provider.id,
|
|
20699
|
-
runtimeToolName: selected.provider.toolName,
|
|
20700
|
-
runtimeVendor: selected.provider.vendor,
|
|
20701
|
-
runtimeInstructionFile: selected.provider.instructFile,
|
|
20702
|
-
runtimeProjectDetected: selected.projectDetected,
|
|
20703
|
-
runtimeDetectionMethods: selected.methods,
|
|
20704
|
-
runtimeCandidates: installed.map((entry) => entry.provider.id),
|
|
20705
|
-
inferredModelProvider: inferProviderFromVendor(selected.provider.vendor)
|
|
20706
|
-
};
|
|
20707
|
-
}
|
|
20708
|
-
var cachedRuntimeProvider = null;
|
|
20709
|
-
function detectRuntimeProviderContext(snapshot = {}) {
|
|
20710
|
-
if (!snapshot.cwd && !snapshot.argv && !snapshot.env && cachedRuntimeProvider) {
|
|
20711
|
-
return cachedRuntimeProvider;
|
|
20712
|
-
}
|
|
20713
|
-
try {
|
|
20714
|
-
const detections = detectProjectProviders(snapshot.cwd ?? process.cwd());
|
|
20715
|
-
const context = selectRuntimeProviderContext(detections, snapshot);
|
|
20716
|
-
if (!snapshot.cwd && !snapshot.argv && !snapshot.env) {
|
|
20717
|
-
cachedRuntimeProvider = context;
|
|
20718
|
-
}
|
|
20719
|
-
return context;
|
|
20720
|
-
} catch {
|
|
20721
|
-
return {};
|
|
20722
|
-
}
|
|
20723
|
-
}
|
|
20724
|
-
|
|
20725
20953
|
// src/core/metrics/token-service.ts
|
|
20954
|
+
init_provider_detection();
|
|
20726
20955
|
function normalizeProvider(provider, model, runtimeProvider) {
|
|
20727
20956
|
const value = (provider ?? "").trim().toLowerCase();
|
|
20728
20957
|
const modelValue = (model ?? "").trim().toLowerCase();
|
|
@@ -27745,6 +27974,7 @@ function injectContext(protocolType, params, projectRoot) {
|
|
|
27745
27974
|
// src/dispatch/engines/session-engine.ts
|
|
27746
27975
|
init_handoff();
|
|
27747
27976
|
init_sessions();
|
|
27977
|
+
init_sessions();
|
|
27748
27978
|
|
|
27749
27979
|
// src/core/sessions/session-id.ts
|
|
27750
27980
|
import { randomBytes as randomBytes7 } from "node:crypto";
|
|
@@ -27893,29 +28123,31 @@ async function sessionStart(projectRoot, params) {
|
|
|
27893
28123
|
try {
|
|
27894
28124
|
let accessor = await getAccessor(projectRoot);
|
|
27895
28125
|
let taskData = await accessor.loadTaskFile();
|
|
28126
|
+
let scope;
|
|
28127
|
+
try {
|
|
28128
|
+
scope = parseScope2(params.scope);
|
|
28129
|
+
} catch (err) {
|
|
28130
|
+
return engineError("E_INVALID_INPUT", err instanceof Error ? err.message : "Invalid scope");
|
|
28131
|
+
}
|
|
28132
|
+
if (scope.type !== "global") {
|
|
28133
|
+
const rootTask = taskData.tasks?.find((t) => t.id === scope.rootTaskId);
|
|
28134
|
+
if (!rootTask) {
|
|
28135
|
+
return engineError("E_NOT_FOUND", `Root task '${scope.rootTaskId}' not found`);
|
|
28136
|
+
}
|
|
28137
|
+
}
|
|
27896
28138
|
const activeSessionId = taskData._meta?.activeSession;
|
|
27897
28139
|
if (activeSessionId) {
|
|
27898
28140
|
await sessionEnd(projectRoot);
|
|
27899
28141
|
accessor = await getAccessor(projectRoot);
|
|
27900
28142
|
taskData = await accessor.loadTaskFile();
|
|
27901
28143
|
}
|
|
27902
|
-
const scopeParts = params.scope.split(":");
|
|
27903
|
-
const scopeType = scopeParts[0] || "task";
|
|
27904
|
-
const rootTaskId = scopeParts[1] || "";
|
|
27905
|
-
if (!rootTaskId) {
|
|
27906
|
-
return engineError("E_INVALID_INPUT", "Scope must include a task ID (e.g., epic:T001)");
|
|
27907
|
-
}
|
|
27908
|
-
const rootTask = taskData.tasks?.find((t) => t.id === rootTaskId);
|
|
27909
|
-
if (!rootTask) {
|
|
27910
|
-
return engineError("E_NOT_FOUND", `Root task '${rootTaskId}' not found`);
|
|
27911
|
-
}
|
|
27912
28144
|
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
27913
28145
|
const sessionId = generateSessionId2();
|
|
27914
28146
|
let previousSessionId = null;
|
|
27915
28147
|
{
|
|
27916
28148
|
const sessions2 = await accessor.loadSessions();
|
|
27917
28149
|
const sameScope = sessions2.filter(
|
|
27918
|
-
(s) => s.status === "ended" && s.endedAt && s.scope?.
|
|
28150
|
+
(s) => s.status === "ended" && s.endedAt && s.scope?.type === scope.type && (scope.type === "global" || s.scope?.rootTaskId === scope.rootTaskId)
|
|
27919
28151
|
).sort(
|
|
27920
28152
|
(a, b) => new Date(b.endedAt).getTime() - new Date(a.endedAt).getTime()
|
|
27921
28153
|
);
|
|
@@ -27924,16 +28156,13 @@ async function sessionStart(projectRoot, params) {
|
|
|
27924
28156
|
}
|
|
27925
28157
|
}
|
|
27926
28158
|
const agentIdentifier = params.agentIdentifier ?? process.env.CLEO_AGENT_ID ?? null;
|
|
27927
|
-
const
|
|
28159
|
+
const rootTaskId = scope.type !== "global" ? scope.rootTaskId : void 0;
|
|
28160
|
+
const startingTaskId = params.startTask || (params.autoStart && rootTaskId ? rootTaskId : null);
|
|
27928
28161
|
const newSession = {
|
|
27929
28162
|
id: sessionId,
|
|
27930
28163
|
status: "active",
|
|
27931
28164
|
name: params.name || `session-${sessionId}`,
|
|
27932
|
-
scope: {
|
|
27933
|
-
type: scopeType,
|
|
27934
|
-
rootTaskId,
|
|
27935
|
-
includeDescendants: true
|
|
27936
|
-
},
|
|
28165
|
+
scope: scope.type === "global" ? { type: "global" } : { type: scope.type, rootTaskId: scope.rootTaskId, includeDescendants: true },
|
|
27937
28166
|
taskWork: {
|
|
27938
28167
|
taskId: startingTaskId,
|
|
27939
28168
|
setAt: now2
|
|
@@ -27964,7 +28193,7 @@ async function sessionStart(projectRoot, params) {
|
|
|
27964
28193
|
const startingTask = params.startTask;
|
|
27965
28194
|
if (startingTask) {
|
|
27966
28195
|
taskData.focus.currentTask = startingTask;
|
|
27967
|
-
} else if (params.autoStart) {
|
|
28196
|
+
} else if (params.autoStart && rootTaskId) {
|
|
27968
28197
|
taskData.focus.currentTask = rootTaskId;
|
|
27969
28198
|
}
|
|
27970
28199
|
if (taskData._meta) {
|
|
@@ -28570,7 +28799,7 @@ async function orchestrateValidate(taskId, projectRoot) {
|
|
|
28570
28799
|
async function orchestrateSpawnExecute(taskId, adapterId, protocolType, projectRoot, _tier) {
|
|
28571
28800
|
const cwd = projectRoot ?? process.cwd();
|
|
28572
28801
|
try {
|
|
28573
|
-
const { initializeDefaultAdapters: initializeDefaultAdapters2, spawnRegistry: spawnRegistry2 } = await Promise.resolve().then(() => (
|
|
28802
|
+
const { initializeDefaultAdapters: initializeDefaultAdapters2, spawnRegistry: spawnRegistry2 } = await Promise.resolve().then(() => (init_adapter_registry2(), adapter_registry_exports));
|
|
28574
28803
|
await initializeDefaultAdapters2();
|
|
28575
28804
|
let adapter;
|
|
28576
28805
|
if (adapterId) {
|
|
@@ -29699,7 +29928,10 @@ async function checkEpicCompleteness(releaseTaskIds, cwd, accessor) {
|
|
|
29699
29928
|
if (!epic) continue;
|
|
29700
29929
|
const allChildren = data.tasks.filter((t) => t.parentId === epicId && t.id !== epicId);
|
|
29701
29930
|
const includedSet = new Set(includedTasks);
|
|
29702
|
-
const
|
|
29931
|
+
const parentIds = new Set(data.tasks.filter((t) => t.parentId).map((t) => t.parentId));
|
|
29932
|
+
const missingChildren = allChildren.filter(
|
|
29933
|
+
(t) => t.status === "done" && !parentIds.has(t.id) && !includedSet.has(t.id) && !releaseSet.has(t.id)
|
|
29934
|
+
).map((t) => ({ id: t.id, title: t.title, status: t.status }));
|
|
29703
29935
|
if (missingChildren.length > 0) hasIncomplete = true;
|
|
29704
29936
|
epics.push({
|
|
29705
29937
|
epicId,
|
|
@@ -29856,9 +30088,9 @@ init_tasks_schema();
|
|
|
29856
30088
|
init_pagination();
|
|
29857
30089
|
init_paths();
|
|
29858
30090
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
29859
|
-
import { existsSync as
|
|
30091
|
+
import { existsSync as existsSync43, renameSync as renameSync7 } from "node:fs";
|
|
29860
30092
|
import { readFile as readFile11 } from "node:fs/promises";
|
|
29861
|
-
import { join as
|
|
30093
|
+
import { join as join44 } from "node:path";
|
|
29862
30094
|
import { and as and6, count as count4, desc as desc5, eq as eq15 } from "drizzle-orm";
|
|
29863
30095
|
|
|
29864
30096
|
// src/core/release/changelog-writer.ts
|
|
@@ -29952,6 +30184,170 @@ function escapeRegex(str) {
|
|
|
29952
30184
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
29953
30185
|
}
|
|
29954
30186
|
|
|
30187
|
+
// src/core/release/version-bump.ts
|
|
30188
|
+
init_exit_codes();
|
|
30189
|
+
init_errors();
|
|
30190
|
+
init_paths();
|
|
30191
|
+
import { existsSync as existsSync42, readFileSync as readFileSync29, writeFileSync as writeFileSync7 } from "node:fs";
|
|
30192
|
+
import { join as join43 } from "node:path";
|
|
30193
|
+
function readConfigValueSync2(path, defaultValue, cwd) {
|
|
30194
|
+
try {
|
|
30195
|
+
const configPath = join43(getCleoDir(cwd), "config.json");
|
|
30196
|
+
if (!existsSync42(configPath)) return defaultValue;
|
|
30197
|
+
const config = JSON.parse(readFileSync29(configPath, "utf-8"));
|
|
30198
|
+
const keys = path.split(".");
|
|
30199
|
+
let value = config;
|
|
30200
|
+
for (const key of keys) {
|
|
30201
|
+
if (value == null || typeof value !== "object") return defaultValue;
|
|
30202
|
+
value = value[key];
|
|
30203
|
+
}
|
|
30204
|
+
return value ?? defaultValue;
|
|
30205
|
+
} catch {
|
|
30206
|
+
return defaultValue;
|
|
30207
|
+
}
|
|
30208
|
+
}
|
|
30209
|
+
var VERSION_WITH_PRERELEASE = /^\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?$/;
|
|
30210
|
+
function validateVersionFormat(version) {
|
|
30211
|
+
return VERSION_WITH_PRERELEASE.test(version);
|
|
30212
|
+
}
|
|
30213
|
+
function getVersionBumpConfig(cwd) {
|
|
30214
|
+
try {
|
|
30215
|
+
const raw = readConfigValueSync2("release.versionBump.files", [], cwd);
|
|
30216
|
+
return raw.map((entry) => ({
|
|
30217
|
+
file: entry.path ?? entry.file ?? "",
|
|
30218
|
+
strategy: entry.strategy,
|
|
30219
|
+
field: entry.jsonPath?.replace(/^\./, "") ?? entry.field,
|
|
30220
|
+
key: entry.key,
|
|
30221
|
+
section: entry.section,
|
|
30222
|
+
pattern: entry.sedPattern ?? entry.pattern
|
|
30223
|
+
})).filter((t) => t.file !== "");
|
|
30224
|
+
} catch {
|
|
30225
|
+
return [];
|
|
30226
|
+
}
|
|
30227
|
+
}
|
|
30228
|
+
function bumpFile(target, newVersion, projectRoot) {
|
|
30229
|
+
const filePath = join43(projectRoot, target.file);
|
|
30230
|
+
if (!existsSync42(filePath)) {
|
|
30231
|
+
return {
|
|
30232
|
+
file: target.file,
|
|
30233
|
+
strategy: target.strategy,
|
|
30234
|
+
success: false,
|
|
30235
|
+
error: `File not found: ${target.file}`
|
|
30236
|
+
};
|
|
30237
|
+
}
|
|
30238
|
+
try {
|
|
30239
|
+
const content = readFileSync29(filePath, "utf-8");
|
|
30240
|
+
let previousVersion;
|
|
30241
|
+
let newContent;
|
|
30242
|
+
switch (target.strategy) {
|
|
30243
|
+
case "plain": {
|
|
30244
|
+
previousVersion = content.trim();
|
|
30245
|
+
newContent = newVersion + "\n";
|
|
30246
|
+
break;
|
|
30247
|
+
}
|
|
30248
|
+
case "json": {
|
|
30249
|
+
const field = target.field ?? "version";
|
|
30250
|
+
const json = JSON.parse(content);
|
|
30251
|
+
previousVersion = getNestedField(json, field);
|
|
30252
|
+
setNestedField(json, field, newVersion);
|
|
30253
|
+
newContent = JSON.stringify(json, null, 2) + "\n";
|
|
30254
|
+
break;
|
|
30255
|
+
}
|
|
30256
|
+
case "toml": {
|
|
30257
|
+
const key = target.key ?? "version";
|
|
30258
|
+
const versionRegex = new RegExp(`^(${key}\\s*=\\s*")([^"]+)(")`, "m");
|
|
30259
|
+
const match = content.match(versionRegex);
|
|
30260
|
+
previousVersion = match?.[2];
|
|
30261
|
+
newContent = content.replace(versionRegex, `$1${newVersion}$3`);
|
|
30262
|
+
break;
|
|
30263
|
+
}
|
|
30264
|
+
case "sed": {
|
|
30265
|
+
const pattern = target.pattern ?? "";
|
|
30266
|
+
if (!pattern.includes("{{VERSION}}")) {
|
|
30267
|
+
return {
|
|
30268
|
+
file: target.file,
|
|
30269
|
+
strategy: target.strategy,
|
|
30270
|
+
success: false,
|
|
30271
|
+
error: "sed strategy requires {{VERSION}} placeholder in pattern"
|
|
30272
|
+
};
|
|
30273
|
+
}
|
|
30274
|
+
const regex = new RegExp(pattern.replace("{{VERSION}}", "([\\d.]+)"));
|
|
30275
|
+
const match = content.match(regex);
|
|
30276
|
+
previousVersion = match?.[1];
|
|
30277
|
+
newContent = content.replace(regex, pattern.replace("{{VERSION}}", newVersion));
|
|
30278
|
+
break;
|
|
30279
|
+
}
|
|
30280
|
+
default:
|
|
30281
|
+
return {
|
|
30282
|
+
file: target.file,
|
|
30283
|
+
strategy: target.strategy,
|
|
30284
|
+
success: false,
|
|
30285
|
+
error: `Unknown strategy: ${target.strategy}`
|
|
30286
|
+
};
|
|
30287
|
+
}
|
|
30288
|
+
writeFileSync7(filePath, newContent, "utf-8");
|
|
30289
|
+
return {
|
|
30290
|
+
file: target.file,
|
|
30291
|
+
strategy: target.strategy,
|
|
30292
|
+
success: true,
|
|
30293
|
+
previousVersion,
|
|
30294
|
+
newVersion
|
|
30295
|
+
};
|
|
30296
|
+
} catch (err) {
|
|
30297
|
+
return {
|
|
30298
|
+
file: target.file,
|
|
30299
|
+
strategy: target.strategy,
|
|
30300
|
+
success: false,
|
|
30301
|
+
error: String(err)
|
|
30302
|
+
};
|
|
30303
|
+
}
|
|
30304
|
+
}
|
|
30305
|
+
function bumpVersionFromConfig(newVersion, options = {}, cwd) {
|
|
30306
|
+
if (!validateVersionFormat(newVersion)) {
|
|
30307
|
+
throw new CleoError(
|
|
30308
|
+
6 /* VALIDATION_ERROR */,
|
|
30309
|
+
`Invalid version: '${newVersion}' (expected X.Y.Z or YYYY.M.patch)`
|
|
30310
|
+
);
|
|
30311
|
+
}
|
|
30312
|
+
const targets = getVersionBumpConfig(cwd);
|
|
30313
|
+
if (targets.length === 0) {
|
|
30314
|
+
throw new CleoError(
|
|
30315
|
+
1 /* GENERAL_ERROR */,
|
|
30316
|
+
"No version bump targets configured. Add release.versionBump.files to .cleo/config.json"
|
|
30317
|
+
);
|
|
30318
|
+
}
|
|
30319
|
+
const projectRoot = getProjectRoot(cwd);
|
|
30320
|
+
const results = [];
|
|
30321
|
+
if (options.dryRun) {
|
|
30322
|
+
for (const target of targets) {
|
|
30323
|
+
results.push({
|
|
30324
|
+
file: target.file,
|
|
30325
|
+
strategy: target.strategy,
|
|
30326
|
+
success: true,
|
|
30327
|
+
newVersion
|
|
30328
|
+
});
|
|
30329
|
+
}
|
|
30330
|
+
return { results, allSuccess: true };
|
|
30331
|
+
}
|
|
30332
|
+
for (const target of targets) {
|
|
30333
|
+
results.push(bumpFile(target, newVersion, projectRoot));
|
|
30334
|
+
}
|
|
30335
|
+
const allSuccess = results.every((r) => r.success);
|
|
30336
|
+
return { results, allSuccess };
|
|
30337
|
+
}
|
|
30338
|
+
function getNestedField(obj, path) {
|
|
30339
|
+
return path.split(".").reduce((acc, key) => acc?.[key], obj);
|
|
30340
|
+
}
|
|
30341
|
+
function setNestedField(obj, path, value) {
|
|
30342
|
+
const parts = path.split(".");
|
|
30343
|
+
let current = obj;
|
|
30344
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
30345
|
+
if (typeof current[parts[i]] !== "object") current[parts[i]] = {};
|
|
30346
|
+
current = current[parts[i]];
|
|
30347
|
+
}
|
|
30348
|
+
current[parts[parts.length - 1]] = value;
|
|
30349
|
+
}
|
|
30350
|
+
|
|
29955
30351
|
// src/core/release/release-manifest.ts
|
|
29956
30352
|
function normalizeLimit2(limit) {
|
|
29957
30353
|
return typeof limit === "number" && limit > 0 ? limit : void 0;
|
|
@@ -30177,7 +30573,7 @@ async function generateReleaseChangelog(version, loadTasksFn, cwd) {
|
|
|
30177
30573
|
}
|
|
30178
30574
|
const changelog = sections.join("\n");
|
|
30179
30575
|
await db.update(releaseManifests).set({ changelog }).where(eq15(releaseManifests.version, normalizedVersion)).run();
|
|
30180
|
-
const changelogPath =
|
|
30576
|
+
const changelogPath = join44(cwd ?? process.cwd(), "CHANGELOG.md");
|
|
30181
30577
|
let existingChangelogContent = "";
|
|
30182
30578
|
try {
|
|
30183
30579
|
existingChangelogContent = await readFile11(changelogPath, "utf8");
|
|
@@ -30291,13 +30687,13 @@ async function runReleaseGates(version, loadTasksFn, cwd, opts) {
|
|
|
30291
30687
|
message: incompleteTasks.length === 0 ? "All tasks completed" : `${incompleteTasks.length} tasks not completed: ${incompleteTasks.join(", ")}`
|
|
30292
30688
|
});
|
|
30293
30689
|
const projectRoot = cwd ?? getProjectRoot();
|
|
30294
|
-
const distPath =
|
|
30295
|
-
const isNodeProject =
|
|
30690
|
+
const distPath = join44(projectRoot, "dist", "cli", "index.js");
|
|
30691
|
+
const isNodeProject = existsSync43(join44(projectRoot, "package.json"));
|
|
30296
30692
|
if (isNodeProject) {
|
|
30297
30693
|
gates.push({
|
|
30298
30694
|
name: "build_artifact",
|
|
30299
|
-
status:
|
|
30300
|
-
message:
|
|
30695
|
+
status: existsSync43(distPath) ? "passed" : "failed",
|
|
30696
|
+
message: existsSync43(distPath) ? "dist/cli/index.js present" : "dist/ not built \u2014 run: npm run build"
|
|
30301
30697
|
});
|
|
30302
30698
|
}
|
|
30303
30699
|
if (opts?.dryRun) {
|
|
@@ -30307,6 +30703,8 @@ async function runReleaseGates(version, loadTasksFn, cwd, opts) {
|
|
|
30307
30703
|
message: "Skipped in dry-run mode"
|
|
30308
30704
|
});
|
|
30309
30705
|
} else {
|
|
30706
|
+
const bumpTargets = getVersionBumpConfig(cwd);
|
|
30707
|
+
const allowedDirty = /* @__PURE__ */ new Set(["CHANGELOG.md", ...bumpTargets.map((t) => t.file)]);
|
|
30310
30708
|
let workingTreeClean = true;
|
|
30311
30709
|
let dirtyFiles = [];
|
|
30312
30710
|
try {
|
|
@@ -30315,14 +30713,15 @@ async function runReleaseGates(version, loadTasksFn, cwd, opts) {
|
|
|
30315
30713
|
encoding: "utf-8",
|
|
30316
30714
|
stdio: "pipe"
|
|
30317
30715
|
});
|
|
30318
|
-
dirtyFiles = porcelain.split("\n").filter((l) => l.trim()).filter((l) => !l.startsWith("?? ")).map((l) => l.slice(3).trim()).filter((f) =>
|
|
30716
|
+
dirtyFiles = porcelain.split("\n").filter((l) => l.trim()).filter((l) => !l.startsWith("?? ")).map((l) => l.slice(3).trim()).filter((f) => !allowedDirty.has(f));
|
|
30319
30717
|
workingTreeClean = dirtyFiles.length === 0;
|
|
30320
30718
|
} catch {
|
|
30321
30719
|
}
|
|
30720
|
+
const excludeList = [...allowedDirty].join(", ");
|
|
30322
30721
|
gates.push({
|
|
30323
30722
|
name: "clean_working_tree",
|
|
30324
30723
|
status: workingTreeClean ? "passed" : "failed",
|
|
30325
|
-
message: workingTreeClean ?
|
|
30724
|
+
message: workingTreeClean ? `Working tree clean (excluding ${excludeList})` : `Uncommitted changes in: ${dirtyFiles.slice(0, 5).join(", ")}${dirtyFiles.length > 5 ? ` (+${dirtyFiles.length - 5} more)` : ""}`
|
|
30326
30725
|
});
|
|
30327
30726
|
}
|
|
30328
30727
|
const isPreRelease = normalizedVersion.includes("-");
|
|
@@ -30437,7 +30836,7 @@ async function rollbackRelease(version, reason, cwd) {
|
|
|
30437
30836
|
};
|
|
30438
30837
|
}
|
|
30439
30838
|
async function readPushPolicy(cwd) {
|
|
30440
|
-
const configPath =
|
|
30839
|
+
const configPath = join44(getCleoDirAbsolute(cwd), "config.json");
|
|
30441
30840
|
const config = await readJson(configPath);
|
|
30442
30841
|
if (!config) return void 0;
|
|
30443
30842
|
const release2 = config.release;
|
|
@@ -30535,170 +30934,6 @@ async function markReleasePushed(version, pushedAt, cwd, provenance) {
|
|
|
30535
30934
|
}).where(eq15(releaseManifests.version, normalizedVersion)).run();
|
|
30536
30935
|
}
|
|
30537
30936
|
|
|
30538
|
-
// src/core/release/version-bump.ts
|
|
30539
|
-
init_exit_codes();
|
|
30540
|
-
init_errors();
|
|
30541
|
-
init_paths();
|
|
30542
|
-
import { existsSync as existsSync43, readFileSync as readFileSync29, writeFileSync as writeFileSync7 } from "node:fs";
|
|
30543
|
-
import { join as join44 } from "node:path";
|
|
30544
|
-
function readConfigValueSync2(path, defaultValue, cwd) {
|
|
30545
|
-
try {
|
|
30546
|
-
const configPath = join44(getCleoDir(cwd), "config.json");
|
|
30547
|
-
if (!existsSync43(configPath)) return defaultValue;
|
|
30548
|
-
const config = JSON.parse(readFileSync29(configPath, "utf-8"));
|
|
30549
|
-
const keys = path.split(".");
|
|
30550
|
-
let value = config;
|
|
30551
|
-
for (const key of keys) {
|
|
30552
|
-
if (value == null || typeof value !== "object") return defaultValue;
|
|
30553
|
-
value = value[key];
|
|
30554
|
-
}
|
|
30555
|
-
return value ?? defaultValue;
|
|
30556
|
-
} catch {
|
|
30557
|
-
return defaultValue;
|
|
30558
|
-
}
|
|
30559
|
-
}
|
|
30560
|
-
var VERSION_WITH_PRERELEASE = /^\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?$/;
|
|
30561
|
-
function validateVersionFormat(version) {
|
|
30562
|
-
return VERSION_WITH_PRERELEASE.test(version);
|
|
30563
|
-
}
|
|
30564
|
-
function getVersionBumpConfig(cwd) {
|
|
30565
|
-
try {
|
|
30566
|
-
const raw = readConfigValueSync2("release.versionBump.files", [], cwd);
|
|
30567
|
-
return raw.map((entry) => ({
|
|
30568
|
-
file: entry.path ?? entry.file ?? "",
|
|
30569
|
-
strategy: entry.strategy,
|
|
30570
|
-
field: entry.jsonPath?.replace(/^\./, "") ?? entry.field,
|
|
30571
|
-
key: entry.key,
|
|
30572
|
-
section: entry.section,
|
|
30573
|
-
pattern: entry.sedPattern ?? entry.pattern
|
|
30574
|
-
})).filter((t) => t.file !== "");
|
|
30575
|
-
} catch {
|
|
30576
|
-
return [];
|
|
30577
|
-
}
|
|
30578
|
-
}
|
|
30579
|
-
function bumpFile(target, newVersion, projectRoot) {
|
|
30580
|
-
const filePath = join44(projectRoot, target.file);
|
|
30581
|
-
if (!existsSync43(filePath)) {
|
|
30582
|
-
return {
|
|
30583
|
-
file: target.file,
|
|
30584
|
-
strategy: target.strategy,
|
|
30585
|
-
success: false,
|
|
30586
|
-
error: `File not found: ${target.file}`
|
|
30587
|
-
};
|
|
30588
|
-
}
|
|
30589
|
-
try {
|
|
30590
|
-
const content = readFileSync29(filePath, "utf-8");
|
|
30591
|
-
let previousVersion;
|
|
30592
|
-
let newContent;
|
|
30593
|
-
switch (target.strategy) {
|
|
30594
|
-
case "plain": {
|
|
30595
|
-
previousVersion = content.trim();
|
|
30596
|
-
newContent = newVersion + "\n";
|
|
30597
|
-
break;
|
|
30598
|
-
}
|
|
30599
|
-
case "json": {
|
|
30600
|
-
const field = target.field ?? "version";
|
|
30601
|
-
const json = JSON.parse(content);
|
|
30602
|
-
previousVersion = getNestedField(json, field);
|
|
30603
|
-
setNestedField(json, field, newVersion);
|
|
30604
|
-
newContent = JSON.stringify(json, null, 2) + "\n";
|
|
30605
|
-
break;
|
|
30606
|
-
}
|
|
30607
|
-
case "toml": {
|
|
30608
|
-
const key = target.key ?? "version";
|
|
30609
|
-
const versionRegex = new RegExp(`^(${key}\\s*=\\s*")([^"]+)(")`, "m");
|
|
30610
|
-
const match = content.match(versionRegex);
|
|
30611
|
-
previousVersion = match?.[2];
|
|
30612
|
-
newContent = content.replace(versionRegex, `$1${newVersion}$3`);
|
|
30613
|
-
break;
|
|
30614
|
-
}
|
|
30615
|
-
case "sed": {
|
|
30616
|
-
const pattern = target.pattern ?? "";
|
|
30617
|
-
if (!pattern.includes("{{VERSION}}")) {
|
|
30618
|
-
return {
|
|
30619
|
-
file: target.file,
|
|
30620
|
-
strategy: target.strategy,
|
|
30621
|
-
success: false,
|
|
30622
|
-
error: "sed strategy requires {{VERSION}} placeholder in pattern"
|
|
30623
|
-
};
|
|
30624
|
-
}
|
|
30625
|
-
const regex = new RegExp(pattern.replace("{{VERSION}}", "([\\d.]+)"));
|
|
30626
|
-
const match = content.match(regex);
|
|
30627
|
-
previousVersion = match?.[1];
|
|
30628
|
-
newContent = content.replace(regex, pattern.replace("{{VERSION}}", newVersion));
|
|
30629
|
-
break;
|
|
30630
|
-
}
|
|
30631
|
-
default:
|
|
30632
|
-
return {
|
|
30633
|
-
file: target.file,
|
|
30634
|
-
strategy: target.strategy,
|
|
30635
|
-
success: false,
|
|
30636
|
-
error: `Unknown strategy: ${target.strategy}`
|
|
30637
|
-
};
|
|
30638
|
-
}
|
|
30639
|
-
writeFileSync7(filePath, newContent, "utf-8");
|
|
30640
|
-
return {
|
|
30641
|
-
file: target.file,
|
|
30642
|
-
strategy: target.strategy,
|
|
30643
|
-
success: true,
|
|
30644
|
-
previousVersion,
|
|
30645
|
-
newVersion
|
|
30646
|
-
};
|
|
30647
|
-
} catch (err) {
|
|
30648
|
-
return {
|
|
30649
|
-
file: target.file,
|
|
30650
|
-
strategy: target.strategy,
|
|
30651
|
-
success: false,
|
|
30652
|
-
error: String(err)
|
|
30653
|
-
};
|
|
30654
|
-
}
|
|
30655
|
-
}
|
|
30656
|
-
function bumpVersionFromConfig(newVersion, options = {}, cwd) {
|
|
30657
|
-
if (!validateVersionFormat(newVersion)) {
|
|
30658
|
-
throw new CleoError(
|
|
30659
|
-
6 /* VALIDATION_ERROR */,
|
|
30660
|
-
`Invalid version: '${newVersion}' (expected X.Y.Z or YYYY.M.patch)`
|
|
30661
|
-
);
|
|
30662
|
-
}
|
|
30663
|
-
const targets = getVersionBumpConfig(cwd);
|
|
30664
|
-
if (targets.length === 0) {
|
|
30665
|
-
throw new CleoError(
|
|
30666
|
-
1 /* GENERAL_ERROR */,
|
|
30667
|
-
"No version bump targets configured. Add release.versionBump.files to .cleo/config.json"
|
|
30668
|
-
);
|
|
30669
|
-
}
|
|
30670
|
-
const projectRoot = getProjectRoot(cwd);
|
|
30671
|
-
const results = [];
|
|
30672
|
-
if (options.dryRun) {
|
|
30673
|
-
for (const target of targets) {
|
|
30674
|
-
results.push({
|
|
30675
|
-
file: target.file,
|
|
30676
|
-
strategy: target.strategy,
|
|
30677
|
-
success: true,
|
|
30678
|
-
newVersion
|
|
30679
|
-
});
|
|
30680
|
-
}
|
|
30681
|
-
return { results, allSuccess: true };
|
|
30682
|
-
}
|
|
30683
|
-
for (const target of targets) {
|
|
30684
|
-
results.push(bumpFile(target, newVersion, projectRoot));
|
|
30685
|
-
}
|
|
30686
|
-
const allSuccess = results.every((r) => r.success);
|
|
30687
|
-
return { results, allSuccess };
|
|
30688
|
-
}
|
|
30689
|
-
function getNestedField(obj, path) {
|
|
30690
|
-
return path.split(".").reduce((acc, key) => acc?.[key], obj);
|
|
30691
|
-
}
|
|
30692
|
-
function setNestedField(obj, path, value) {
|
|
30693
|
-
const parts = path.split(".");
|
|
30694
|
-
let current = obj;
|
|
30695
|
-
for (let i = 0; i < parts.length - 1; i++) {
|
|
30696
|
-
if (typeof current[parts[i]] !== "object") current[parts[i]] = {};
|
|
30697
|
-
current = current[parts[i]];
|
|
30698
|
-
}
|
|
30699
|
-
current[parts[parts.length - 1]] = value;
|
|
30700
|
-
}
|
|
30701
|
-
|
|
30702
30937
|
// src/dispatch/engines/release-engine.ts
|
|
30703
30938
|
init_data_accessor();
|
|
30704
30939
|
init_error();
|
|
@@ -45215,7 +45450,7 @@ import { execFileSync as execFileSync13 } from "node:child_process";
|
|
|
45215
45450
|
// src/config/build-config.ts
|
|
45216
45451
|
var BUILD_CONFIG = {
|
|
45217
45452
|
"name": "@cleocode/cleo",
|
|
45218
|
-
"version": "2026.3.
|
|
45453
|
+
"version": "2026.3.31",
|
|
45219
45454
|
"description": "CLEO V2 - TypeScript task management CLI for AI coding agents",
|
|
45220
45455
|
"repository": {
|
|
45221
45456
|
"owner": "kryptobaseddev",
|
|
@@ -45224,7 +45459,7 @@ var BUILD_CONFIG = {
|
|
|
45224
45459
|
"url": "https://github.com/kryptobaseddev/cleo.git",
|
|
45225
45460
|
"issuesUrl": "https://github.com/kryptobaseddev/cleo/issues"
|
|
45226
45461
|
},
|
|
45227
|
-
"buildDate": "2026-03-
|
|
45462
|
+
"buildDate": "2026-03-16T23:36:19.886Z",
|
|
45228
45463
|
"templates": {
|
|
45229
45464
|
"issueTemplatesDir": "templates/issue-templates"
|
|
45230
45465
|
}
|
|
@@ -47933,6 +48168,30 @@ async function runUpgrade(options = {}) {
|
|
|
47933
48168
|
}
|
|
47934
48169
|
} catch {
|
|
47935
48170
|
}
|
|
48171
|
+
try {
|
|
48172
|
+
const { ensureBrainDb: ensureBrainDb2 } = await Promise.resolve().then(() => (init_scaffold(), scaffold_exports));
|
|
48173
|
+
const brainResult = await ensureBrainDb2(projectRootForMaint);
|
|
48174
|
+
if (brainResult.action !== "skipped") {
|
|
48175
|
+
actions.push({
|
|
48176
|
+
action: "ensure_brain_db",
|
|
48177
|
+
status: "applied",
|
|
48178
|
+
details: brainResult.details ?? "brain.db initialized"
|
|
48179
|
+
});
|
|
48180
|
+
}
|
|
48181
|
+
} catch {
|
|
48182
|
+
}
|
|
48183
|
+
try {
|
|
48184
|
+
const { writeMemoryBridge: writeMemoryBridge2 } = await Promise.resolve().then(() => (init_memory_bridge(), memory_bridge_exports));
|
|
48185
|
+
const bridgeResult = await writeMemoryBridge2(projectRootForMaint);
|
|
48186
|
+
if (bridgeResult.written) {
|
|
48187
|
+
actions.push({
|
|
48188
|
+
action: "memory_bridge",
|
|
48189
|
+
status: "applied",
|
|
48190
|
+
details: "memory-bridge.md regenerated"
|
|
48191
|
+
});
|
|
48192
|
+
}
|
|
48193
|
+
} catch {
|
|
48194
|
+
}
|
|
47936
48195
|
try {
|
|
47937
48196
|
const rootGitignoreResult = await removeCleoFromRootGitignore(projectRootForMaint);
|
|
47938
48197
|
if (rootGitignoreResult.removed) {
|