@cleocode/cleo 2026.6.2 → 2026.6.4
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 +218 -55
- package/dist/cli/index.js.map +3 -3
- package/package.json +12 -12
package/dist/cli/index.js
CHANGED
|
@@ -12302,6 +12302,13 @@ var init_plugin_llm = __esm({
|
|
|
12302
12302
|
}
|
|
12303
12303
|
});
|
|
12304
12304
|
|
|
12305
|
+
// packages/contracts/src/llm/system-resolver.ts
|
|
12306
|
+
var init_system_resolver = __esm({
|
|
12307
|
+
"packages/contracts/src/llm/system-resolver.ts"() {
|
|
12308
|
+
"use strict";
|
|
12309
|
+
}
|
|
12310
|
+
});
|
|
12311
|
+
|
|
12305
12312
|
// packages/contracts/src/memory/observe.ts
|
|
12306
12313
|
var init_observe = __esm({
|
|
12307
12314
|
"packages/contracts/src/memory/observe.ts"() {
|
|
@@ -14224,6 +14231,7 @@ var init_src2 = __esm({
|
|
|
14224
14231
|
init_invariants();
|
|
14225
14232
|
init_lafs();
|
|
14226
14233
|
init_plugin_llm();
|
|
14234
|
+
init_system_resolver();
|
|
14227
14235
|
init_observe();
|
|
14228
14236
|
init_migration_parity();
|
|
14229
14237
|
init_mvi();
|
|
@@ -28898,12 +28906,12 @@ async function orchestrateClassify(request, context, projectRoot, taskId) {
|
|
|
28898
28906
|
}
|
|
28899
28907
|
try {
|
|
28900
28908
|
const { getCleoCantWorkflowsDir } = await import("@cleocode/core/internal");
|
|
28901
|
-
const { readFileSync: readFileSync22, readdirSync: readdirSync3, existsSync:
|
|
28909
|
+
const { readFileSync: readFileSync22, readdirSync: readdirSync3, existsSync: existsSync22 } = await import("node:fs");
|
|
28902
28910
|
const { join: join38 } = await import("node:path");
|
|
28903
28911
|
const workflowsDir = getCleoCantWorkflowsDir();
|
|
28904
28912
|
const combined = `${request} ${context ?? ""}`.toLowerCase();
|
|
28905
28913
|
const matches = [];
|
|
28906
|
-
if (
|
|
28914
|
+
if (existsSync22(workflowsDir)) {
|
|
28907
28915
|
const files = readdirSync3(workflowsDir).filter((f) => f.endsWith(".cant"));
|
|
28908
28916
|
for (const file of files) {
|
|
28909
28917
|
try {
|
|
@@ -28923,7 +28931,7 @@ async function orchestrateClassify(request, context, projectRoot, taskId) {
|
|
|
28923
28931
|
}
|
|
28924
28932
|
}
|
|
28925
28933
|
const localCantDir = join38(projectRoot, CLEO_DIR_NAME2, WORKFLOWS_SUBDIR);
|
|
28926
|
-
if (
|
|
28934
|
+
if (existsSync22(localCantDir)) {
|
|
28927
28935
|
const files = readdirSync3(localCantDir).filter((f) => f.endsWith(".cant"));
|
|
28928
28936
|
for (const file of files) {
|
|
28929
28937
|
try {
|
|
@@ -36988,12 +36996,12 @@ var init_agent = __esm({
|
|
|
36988
36996
|
transportConfig: {},
|
|
36989
36997
|
isActive: true
|
|
36990
36998
|
});
|
|
36991
|
-
const { existsSync:
|
|
36999
|
+
const { existsSync: existsSync22, mkdirSync: mkdirSync7, writeFileSync: writeFileSync7 } = await import("node:fs");
|
|
36992
37000
|
const { join: join38 } = await import("node:path");
|
|
36993
37001
|
const cantDir = join38(CLEO_DIR_NAME3, AGENTS_SUBDIR);
|
|
36994
37002
|
const cantPath = join38(cantDir, `${agentId}.cant`);
|
|
36995
37003
|
let cantScaffolded = false;
|
|
36996
|
-
if (!
|
|
37004
|
+
if (!existsSync22(cantPath)) {
|
|
36997
37005
|
mkdirSync7(cantDir, { recursive: true });
|
|
36998
37006
|
const role = classification ?? "specialist";
|
|
36999
37007
|
const cantContent = `---
|
|
@@ -37053,7 +37061,7 @@ agent ${agentId}:
|
|
|
37053
37061
|
data: {
|
|
37054
37062
|
agentId: credential.agentId,
|
|
37055
37063
|
displayName: credential.displayName,
|
|
37056
|
-
cantFile: cantScaffolded ? cantPath :
|
|
37064
|
+
cantFile: cantScaffolded ? cantPath : existsSync22(cantPath) ? cantPath : null,
|
|
37057
37065
|
cantScaffolded
|
|
37058
37066
|
}
|
|
37059
37067
|
},
|
|
@@ -37172,7 +37180,7 @@ agent ${agentId}:
|
|
|
37172
37180
|
try {
|
|
37173
37181
|
const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
|
|
37174
37182
|
const { createRuntime } = await import("@cleocode/runtime");
|
|
37175
|
-
const { existsSync:
|
|
37183
|
+
const { existsSync: existsSync22, readFileSync: readFileSync22 } = await import("node:fs");
|
|
37176
37184
|
const { join: join38 } = await import("node:path");
|
|
37177
37185
|
await openCleoDb("project");
|
|
37178
37186
|
const registry = new AgentRegistryAccessor(getProjectRoot24());
|
|
@@ -37194,7 +37202,7 @@ agent ${agentId}:
|
|
|
37194
37202
|
let profile = null;
|
|
37195
37203
|
let cantValidation = null;
|
|
37196
37204
|
const cantPath = args.cant ?? join38(CLEO_DIR_NAME3, AGENTS_SUBDIR, `${args.agentId}.cant`);
|
|
37197
|
-
if (
|
|
37205
|
+
if (existsSync22(cantPath)) {
|
|
37198
37206
|
profile = readFileSync22(cantPath, "utf-8");
|
|
37199
37207
|
try {
|
|
37200
37208
|
const cantModule = await import("@cleocode/cant");
|
|
@@ -37718,7 +37726,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
|
|
|
37718
37726
|
try {
|
|
37719
37727
|
const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
|
|
37720
37728
|
const { createRuntime } = await import("@cleocode/runtime");
|
|
37721
|
-
const { existsSync:
|
|
37729
|
+
const { existsSync: existsSync22 } = await import("node:fs");
|
|
37722
37730
|
const { join: join38 } = await import("node:path");
|
|
37723
37731
|
await openCleoDb("project");
|
|
37724
37732
|
const registry = new AgentRegistryAccessor(getProjectRoot24());
|
|
@@ -37737,7 +37745,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
|
|
|
37737
37745
|
await registry.update(args.agentId, { isActive: true });
|
|
37738
37746
|
await registry.markUsed(args.agentId);
|
|
37739
37747
|
const cantPath = join38(CLEO_DIR_NAME3, AGENTS_SUBDIR, `${args.agentId}.cant`);
|
|
37740
|
-
const hasProfile =
|
|
37748
|
+
const hasProfile = existsSync22(cantPath);
|
|
37741
37749
|
const runtime = await createRuntime(registry, {
|
|
37742
37750
|
agentId: args.agentId,
|
|
37743
37751
|
pollIntervalMs: 5e3,
|
|
@@ -38530,10 +38538,10 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
|
|
|
38530
38538
|
async run({ args }) {
|
|
38531
38539
|
let tempDir = null;
|
|
38532
38540
|
try {
|
|
38533
|
-
const { existsSync:
|
|
38541
|
+
const { existsSync: existsSync22 } = await import("node:fs");
|
|
38534
38542
|
const { basename, resolve: resolve11 } = await import("node:path");
|
|
38535
38543
|
const resolvedPath = resolve11(args.path);
|
|
38536
|
-
if (!
|
|
38544
|
+
if (!existsSync22(resolvedPath)) {
|
|
38537
38545
|
cliOutput(
|
|
38538
38546
|
{
|
|
38539
38547
|
success: false,
|
|
@@ -38658,11 +38666,11 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
|
|
|
38658
38666
|
},
|
|
38659
38667
|
async run({ args }) {
|
|
38660
38668
|
try {
|
|
38661
|
-
const { existsSync:
|
|
38669
|
+
const { existsSync: existsSync22, statSync: statSync2 } = await import("node:fs");
|
|
38662
38670
|
const { resolve: resolve11, basename, dirname: dirname12 } = await import("node:path");
|
|
38663
38671
|
const { execFileSync: execFileSync5 } = await import("node:child_process");
|
|
38664
38672
|
const resolvedDir = resolve11(args.dir);
|
|
38665
|
-
if (!
|
|
38673
|
+
if (!existsSync22(resolvedDir) || !statSync2(resolvedDir).isDirectory()) {
|
|
38666
38674
|
cliOutput(
|
|
38667
38675
|
{
|
|
38668
38676
|
success: false,
|
|
@@ -38678,7 +38686,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
|
|
|
38678
38686
|
}
|
|
38679
38687
|
const { join: join38 } = await import("node:path");
|
|
38680
38688
|
const personaPath = join38(resolvedDir, "persona.cant");
|
|
38681
|
-
if (!
|
|
38689
|
+
if (!existsSync22(personaPath)) {
|
|
38682
38690
|
cliOutput(
|
|
38683
38691
|
{
|
|
38684
38692
|
success: false,
|
|
@@ -38973,10 +38981,10 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
|
|
|
38973
38981
|
},
|
|
38974
38982
|
async run({ args }) {
|
|
38975
38983
|
try {
|
|
38976
|
-
const { existsSync:
|
|
38984
|
+
const { existsSync: existsSync22, readFileSync: readFileSync22, mkdirSync: mkdirSync7 } = await import("node:fs");
|
|
38977
38985
|
const { resolve: resolve11, join: join38 } = await import("node:path");
|
|
38978
38986
|
const specPath = resolve11(args.spec);
|
|
38979
|
-
if (!
|
|
38987
|
+
if (!existsSync22(specPath)) {
|
|
38980
38988
|
cliError(`spec file not found: ${specPath}`, 4, { name: "E_NOT_FOUND" });
|
|
38981
38989
|
process.exitCode = 4;
|
|
38982
38990
|
return;
|
|
@@ -41928,11 +41936,11 @@ var init_caamp = __esm({
|
|
|
41928
41936
|
}
|
|
41929
41937
|
if (args["dry-run"]) {
|
|
41930
41938
|
const { parseCaampBlocks } = await import("@cleocode/caamp");
|
|
41931
|
-
const { existsSync:
|
|
41939
|
+
const { existsSync: existsSync22 } = await import("node:fs");
|
|
41932
41940
|
const { readFile: readFile9 } = await import("node:fs/promises");
|
|
41933
41941
|
const dryResults = [];
|
|
41934
41942
|
for (const filePath of filePaths) {
|
|
41935
|
-
if (!
|
|
41943
|
+
if (!existsSync22(filePath)) {
|
|
41936
41944
|
dryResults.push({ filePath, exists: false, blockCount: 0, wouldRemove: 0 });
|
|
41937
41945
|
continue;
|
|
41938
41946
|
}
|
|
@@ -43026,7 +43034,7 @@ var init_check2 = __esm({
|
|
|
43026
43034
|
},
|
|
43027
43035
|
async run({ args }) {
|
|
43028
43036
|
const { spawnSync } = await import("node:child_process");
|
|
43029
|
-
const { existsSync:
|
|
43037
|
+
const { existsSync: existsSync22 } = await import("node:fs");
|
|
43030
43038
|
const { join: join38, resolve: resolve11 } = await import("node:path");
|
|
43031
43039
|
const strict = Boolean(args.strict);
|
|
43032
43040
|
const jsonOnly = Boolean(args.json);
|
|
@@ -43068,7 +43076,7 @@ var init_check2 = __esm({
|
|
|
43068
43076
|
let anyFailed = false;
|
|
43069
43077
|
for (const gate of gates) {
|
|
43070
43078
|
const scriptPath = join38(repoRoot, gate.script);
|
|
43071
|
-
if (!
|
|
43079
|
+
if (!existsSync22(scriptPath)) {
|
|
43072
43080
|
results.push({
|
|
43073
43081
|
id: gate.id,
|
|
43074
43082
|
task: gate.task,
|
|
@@ -50684,6 +50692,97 @@ ${this.prefix}: \u2717 ${message}
|
|
|
50684
50692
|
}
|
|
50685
50693
|
});
|
|
50686
50694
|
|
|
50695
|
+
// packages/cleo/src/cli/commands/doctor-exodus-residue.ts
|
|
50696
|
+
import {
|
|
50697
|
+
archiveStrandedResidue,
|
|
50698
|
+
buildExodusPlan,
|
|
50699
|
+
detectStrandedResidue
|
|
50700
|
+
} from "@cleocode/core/store/exodus/index.js";
|
|
50701
|
+
var doctorExodusResidueCommand;
|
|
50702
|
+
var init_doctor_exodus_residue = __esm({
|
|
50703
|
+
"packages/cleo/src/cli/commands/doctor-exodus-residue.ts"() {
|
|
50704
|
+
"use strict";
|
|
50705
|
+
init_define_cli_command();
|
|
50706
|
+
init_renderers();
|
|
50707
|
+
doctorExodusResidueCommand = defineCommand({
|
|
50708
|
+
meta: {
|
|
50709
|
+
name: "exodus-residue",
|
|
50710
|
+
description: "Detect legacy exodus source DBs still present after a cutover (stranded residue that re-arms the exodus-on-open corruption trigger). Use --fix to archive them into _archive/ (reversible move, never deletes)."
|
|
50711
|
+
},
|
|
50712
|
+
args: {
|
|
50713
|
+
fix: {
|
|
50714
|
+
type: "boolean",
|
|
50715
|
+
description: "Archive stranded legacy source DBs into _archive/ (move, never delete)",
|
|
50716
|
+
default: false
|
|
50717
|
+
}
|
|
50718
|
+
},
|
|
50719
|
+
run({ args }) {
|
|
50720
|
+
const fix = args.fix === true;
|
|
50721
|
+
const cwd = process.cwd();
|
|
50722
|
+
const plan = buildExodusPlan(cwd);
|
|
50723
|
+
const stranded = detectStrandedResidue(plan.sources, cwd);
|
|
50724
|
+
if (stranded.length === 0) {
|
|
50725
|
+
cliOutput(
|
|
50726
|
+
{
|
|
50727
|
+
kind: "generic",
|
|
50728
|
+
ok: true,
|
|
50729
|
+
strandedCount: 0,
|
|
50730
|
+
stranded: [],
|
|
50731
|
+
fixed: false
|
|
50732
|
+
},
|
|
50733
|
+
{
|
|
50734
|
+
command: "doctor exodus-residue",
|
|
50735
|
+
message: "No stranded legacy exodus source DBs (clean cutover or pre-migration install)."
|
|
50736
|
+
}
|
|
50737
|
+
);
|
|
50738
|
+
return;
|
|
50739
|
+
}
|
|
50740
|
+
for (const entry of stranded) {
|
|
50741
|
+
humanInfo(` STRANDED [${entry.scope}] ${entry.name} \u2192 ${entry.path}`);
|
|
50742
|
+
}
|
|
50743
|
+
if (!fix) {
|
|
50744
|
+
cliOutput(
|
|
50745
|
+
{
|
|
50746
|
+
kind: "generic",
|
|
50747
|
+
ok: false,
|
|
50748
|
+
strandedCount: stranded.length,
|
|
50749
|
+
stranded: stranded.map((s) => ({ name: s.name, path: s.path, scope: s.scope })),
|
|
50750
|
+
fixed: false
|
|
50751
|
+
},
|
|
50752
|
+
{
|
|
50753
|
+
command: "doctor exodus-residue",
|
|
50754
|
+
message: `${stranded.length} stranded legacy source DB(s) found. Run \`cleo doctor exodus-residue --fix\` to archive them.`
|
|
50755
|
+
}
|
|
50756
|
+
);
|
|
50757
|
+
process.exitCode = 1;
|
|
50758
|
+
return;
|
|
50759
|
+
}
|
|
50760
|
+
const archived = archiveStrandedResidue(stranded, plan.sources, cwd);
|
|
50761
|
+
const movedCount = archived.filter((a) => a.action === "archived").length;
|
|
50762
|
+
humanInfo(` Archived ${movedCount} stranded source DB(s) \u2192 _archive/.`);
|
|
50763
|
+
cliOutput(
|
|
50764
|
+
{
|
|
50765
|
+
kind: "generic",
|
|
50766
|
+
ok: true,
|
|
50767
|
+
strandedCount: stranded.length,
|
|
50768
|
+
stranded: stranded.map((s) => ({ name: s.name, path: s.path, scope: s.scope })),
|
|
50769
|
+
fixed: true,
|
|
50770
|
+
archived: archived.map((a) => ({
|
|
50771
|
+
name: a.name,
|
|
50772
|
+
action: a.action,
|
|
50773
|
+
archivedTo: a.archivedTo
|
|
50774
|
+
}))
|
|
50775
|
+
},
|
|
50776
|
+
{
|
|
50777
|
+
command: "doctor exodus-residue",
|
|
50778
|
+
message: `Archived ${movedCount} stranded legacy source DB(s) into _archive/.`
|
|
50779
|
+
}
|
|
50780
|
+
);
|
|
50781
|
+
}
|
|
50782
|
+
});
|
|
50783
|
+
}
|
|
50784
|
+
});
|
|
50785
|
+
|
|
50687
50786
|
// packages/cleo/src/cli/commands/migrate-agents-v2.ts
|
|
50688
50787
|
var migrate_agents_v2_exports = {};
|
|
50689
50788
|
__export(migrate_agents_v2_exports, {
|
|
@@ -51048,6 +51147,7 @@ var init_doctor = __esm({
|
|
|
51048
51147
|
init_progress();
|
|
51049
51148
|
init_renderers();
|
|
51050
51149
|
init_doctor_db_substrate();
|
|
51150
|
+
init_doctor_exodus_residue();
|
|
51051
51151
|
init_doctor_legacy_backups();
|
|
51052
51152
|
init_doctor_projects();
|
|
51053
51153
|
init_doctor_release_readiness();
|
|
@@ -51066,6 +51166,8 @@ var init_doctor = __esm({
|
|
|
51066
51166
|
"db-substrate": doctorDbSubstrateCommand,
|
|
51067
51167
|
// T10309 / Saga T10281 / Epic T10282 — Legacy-backup walker
|
|
51068
51168
|
"legacy-backups": doctorLegacyBackupsCommand,
|
|
51169
|
+
// T11777 / Saga T11242 / Epic T11249 — exodus stranded-residue check (+ --fix)
|
|
51170
|
+
"exodus-residue": doctorExodusResidueCommand,
|
|
51069
51171
|
// T10458 / Saga T10431 / Epic T10436 — Release-readiness preflight
|
|
51070
51172
|
"release-readiness": doctorReleaseReadinessCommand
|
|
51071
51173
|
},
|
|
@@ -51268,7 +51370,7 @@ var init_doctor = __esm({
|
|
|
51268
51370
|
if (args["check-worktree-config"]) {
|
|
51269
51371
|
const { execFileSync: execFile2 } = await import("node:child_process");
|
|
51270
51372
|
const { join: pathJoin } = await import("node:path");
|
|
51271
|
-
const { existsSync:
|
|
51373
|
+
const { existsSync: existsSync22 } = await import("node:fs");
|
|
51272
51374
|
const { detectAndHealCoreWorktreeLeak } = await import("@cleocode/worktree");
|
|
51273
51375
|
const projectRoot = getProjectRoot42();
|
|
51274
51376
|
let gitRoot = projectRoot;
|
|
@@ -51285,7 +51387,7 @@ var init_doctor = __esm({
|
|
|
51285
51387
|
if (isDryRun) {
|
|
51286
51388
|
const gitConfigPath = pathJoin(gitRoot, ".git", "config");
|
|
51287
51389
|
let leakedValue;
|
|
51288
|
-
if (
|
|
51390
|
+
if (existsSync22(gitConfigPath)) {
|
|
51289
51391
|
try {
|
|
51290
51392
|
leakedValue = execFile2("git", ["config", "--file", gitConfigPath, "--get", "core.worktree"], {
|
|
51291
51393
|
encoding: "utf-8",
|
|
@@ -52188,14 +52290,18 @@ var exodus_exports = {};
|
|
|
52188
52290
|
__export(exodus_exports, {
|
|
52189
52291
|
exodusCommand: () => exodusCommand
|
|
52190
52292
|
});
|
|
52293
|
+
import { existsSync as existsSync15 } from "node:fs";
|
|
52191
52294
|
import { resolveDualScopeDbPath } from "@cleocode/core/store/dual-scope-db.js";
|
|
52192
52295
|
import {
|
|
52193
|
-
|
|
52296
|
+
archiveMigratedSources,
|
|
52297
|
+
buildExodusPlan as buildExodusPlan2,
|
|
52194
52298
|
runExodusMigrate,
|
|
52195
52299
|
runExodusStatus,
|
|
52196
52300
|
runExodusVerify,
|
|
52197
|
-
sourcesPresent
|
|
52301
|
+
sourcesPresent,
|
|
52302
|
+
verifyMigration
|
|
52198
52303
|
} from "@cleocode/core/store/exodus/index.js";
|
|
52304
|
+
import { isDataContinuityOk } from "@cleocode/core/store/exodus/on-open.js";
|
|
52199
52305
|
function fmtBytes2(n) {
|
|
52200
52306
|
if (n < 1024) return `${n} B`;
|
|
52201
52307
|
if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
|
|
@@ -52249,7 +52355,7 @@ var init_exodus = __esm({
|
|
|
52249
52355
|
async run({ args }) {
|
|
52250
52356
|
const dryRun = args["dry-run"] === true;
|
|
52251
52357
|
const forceCrossVersion = args["force-cross-version"] === true;
|
|
52252
|
-
const plan =
|
|
52358
|
+
const plan = buildExodusPlan2(process.cwd());
|
|
52253
52359
|
humanInfo(`Exodus migration plan:`);
|
|
52254
52360
|
humanInfo(
|
|
52255
52361
|
` Source DBs (${plan.sources.length} total, ${fmtBytes2(plan.totalSourceBytes)} combined):`
|
|
@@ -52323,6 +52429,25 @@ var init_exodus = __esm({
|
|
|
52323
52429
|
}
|
|
52324
52430
|
const copied = result.tables.filter((t) => !t.skipped).reduce((n, t) => n + t.rowsCopied, 0);
|
|
52325
52431
|
const skipped = result.tables.filter((t) => t.skipped).length;
|
|
52432
|
+
const verifyResult = verifyMigration(
|
|
52433
|
+
plan.sources,
|
|
52434
|
+
plan.projectDbPath,
|
|
52435
|
+
plan.globalDbPath,
|
|
52436
|
+
(msg) => humanInfo(` verify: ${msg}`)
|
|
52437
|
+
);
|
|
52438
|
+
let archived = [];
|
|
52439
|
+
if (isDataContinuityOk(verifyResult)) {
|
|
52440
|
+
const consumed = plan.sources.filter((s) => existsSync15(s.path));
|
|
52441
|
+
const archiveResult = archiveMigratedSources(consumed, process.cwd());
|
|
52442
|
+
archived = archiveResult.sources.filter((s) => s.action === "archived").map((s) => s.name);
|
|
52443
|
+
humanInfo(
|
|
52444
|
+
` Archived ${archived.length} legacy source DB(s) \u2192 _archive/ and sealed completion marker(s): ${archiveResult.markersWritten.join(", ")}`
|
|
52445
|
+
);
|
|
52446
|
+
} else {
|
|
52447
|
+
humanInfo(
|
|
52448
|
+
" Parity validation did NOT pass \u2014 legacy sources LEFT IN PLACE (not archived). Run `cleo exodus verify` to inspect."
|
|
52449
|
+
);
|
|
52450
|
+
}
|
|
52326
52451
|
cliOutput(
|
|
52327
52452
|
{
|
|
52328
52453
|
kind: "generic",
|
|
@@ -52332,7 +52457,9 @@ var init_exodus = __esm({
|
|
|
52332
52457
|
rowsCopied: copied,
|
|
52333
52458
|
tablesSkipped: skipped,
|
|
52334
52459
|
stagingDir: result.stagingDir,
|
|
52335
|
-
backupCount: result.backupPaths.length
|
|
52460
|
+
backupCount: result.backupPaths.length,
|
|
52461
|
+
archivedSources: archived,
|
|
52462
|
+
archived: archived.length > 0
|
|
52336
52463
|
},
|
|
52337
52464
|
tables: result.tables
|
|
52338
52465
|
},
|
|
@@ -52357,7 +52484,7 @@ var init_exodus = __esm({
|
|
|
52357
52484
|
},
|
|
52358
52485
|
run({ args }) {
|
|
52359
52486
|
const showPassing = args["show-passing"] === true;
|
|
52360
|
-
const plan =
|
|
52487
|
+
const plan = buildExodusPlan2(process.cwd());
|
|
52361
52488
|
const projectDbPath = resolveDualScopeDbPath("project", process.cwd());
|
|
52362
52489
|
const globalDbPath = resolveDualScopeDbPath("global");
|
|
52363
52490
|
humanInfo("Running equivalence verification\u2026");
|
|
@@ -54571,7 +54698,7 @@ __export(init_exports, {
|
|
|
54571
54698
|
getWorkflowTemplatesDir: () => getWorkflowTemplatesDir2,
|
|
54572
54699
|
initCommand: () => initCommand2
|
|
54573
54700
|
});
|
|
54574
|
-
import { existsSync as
|
|
54701
|
+
import { existsSync as existsSync16, readFileSync as readFileSync14 } from "node:fs";
|
|
54575
54702
|
import { join as join27 } from "node:path";
|
|
54576
54703
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
54577
54704
|
import {
|
|
@@ -54588,8 +54715,8 @@ function getGitignoreTemplate() {
|
|
|
54588
54715
|
const packageRoot = join27(thisFile, "..", "..", "..", "..");
|
|
54589
54716
|
const localTemplatePath = join27(packageRoot, "templates", "cleo-gitignore");
|
|
54590
54717
|
const monorepoTemplatePath = join27(packageRoot, "..", "..", "templates", "cleo-gitignore");
|
|
54591
|
-
const templatePath =
|
|
54592
|
-
if (
|
|
54718
|
+
const templatePath = existsSync16(localTemplatePath) ? localTemplatePath : monorepoTemplatePath;
|
|
54719
|
+
if (existsSync16(templatePath)) {
|
|
54593
54720
|
return readFileSync14(templatePath, "utf-8");
|
|
54594
54721
|
}
|
|
54595
54722
|
} catch {
|
|
@@ -55892,7 +56019,7 @@ import {
|
|
|
55892
56019
|
refreshPkceToken
|
|
55893
56020
|
} from "@cleocode/core/llm/oauth/pkce.js";
|
|
55894
56021
|
import { getKimiCodeMshHeaders } from "@cleocode/core/llm/provider-registry/builtin/kimi-code.js";
|
|
55895
|
-
import { getProviderProfile } from "@cleocode/core/llm/provider-registry/index.js";
|
|
56022
|
+
import { getProviderProfile, listProviders } from "@cleocode/core/llm/provider-registry/index.js";
|
|
55896
56023
|
async function runLlmLogin(provider, opts) {
|
|
55897
56024
|
const meta = { operation: "llm.login", timestamp: (/* @__PURE__ */ new Date()).toISOString() };
|
|
55898
56025
|
const profile = await getProviderProfile(provider);
|
|
@@ -55901,34 +56028,48 @@ async function runLlmLogin(provider, opts) {
|
|
|
55901
56028
|
return _runKimiCodeLogin(opts, meta);
|
|
55902
56029
|
}
|
|
55903
56030
|
if (oauthMode === "pkce") {
|
|
55904
|
-
return _runPkceLogin(
|
|
56031
|
+
return _runPkceLogin(profile.name, profile.oauth, opts, meta);
|
|
55905
56032
|
}
|
|
55906
56033
|
return {
|
|
55907
56034
|
success: false,
|
|
55908
56035
|
error: {
|
|
55909
56036
|
code: "E_NOT_IMPLEMENTED",
|
|
55910
56037
|
codeName: "E_NOT_IMPLEMENTED",
|
|
55911
|
-
message: `OAuth login for '${provider}' is not yet wired.
|
|
56038
|
+
message: `OAuth login for '${provider}' is not yet wired. ${await _supportedOauthProvidersHint()} For any other provider, add an API key with 'cleo llm add <provider> --api-key-stdin'.`
|
|
55912
56039
|
},
|
|
55913
56040
|
meta
|
|
55914
56041
|
};
|
|
55915
56042
|
}
|
|
56043
|
+
async function _supportedOauthProvidersHint() {
|
|
56044
|
+
try {
|
|
56045
|
+
const profiles = await listProviders();
|
|
56046
|
+
const oauthable = profiles.flatMap((p) => p.oauth ? [`'${p.name}' (${p.oauth.mode})`] : []);
|
|
56047
|
+
return oauthable.length > 0 ? `Providers with OAuth login: ${oauthable.join(", ")}.` : "No providers currently expose OAuth login.";
|
|
56048
|
+
} catch {
|
|
56049
|
+
return "Providers with OAuth login: 'anthropic' (pkce), 'openai' (pkce), 'kimi-code' (device-code).";
|
|
56050
|
+
}
|
|
56051
|
+
}
|
|
55916
56052
|
async function _runPkceLogin(provider, oauthCfg, opts, meta) {
|
|
55917
56053
|
const { codeVerifier, codeChallenge } = await generatePkcePair();
|
|
55918
56054
|
const state = _generateState();
|
|
55919
56055
|
const isHeadless = opts.headless || process.env["CLEO_HEADLESS"] === "1";
|
|
55920
|
-
const
|
|
55921
|
-
const
|
|
56056
|
+
const fixedPort = isHeadless ? null : _parseFixedLoopbackPort(oauthCfg.redirectUri);
|
|
56057
|
+
const isNonLoopbackPasteBack = !isHeadless && fixedPort === null && !_isLoopbackUri(oauthCfg.redirectUri);
|
|
56058
|
+
const effectiveHeadless = isHeadless || isNonLoopbackPasteBack;
|
|
56059
|
+
const port = effectiveHeadless ? 0 : fixedPort ?? await _findFreePort();
|
|
56060
|
+
const randomRedirect = `http://localhost:${port}/callback`;
|
|
56061
|
+
const redirectUri = effectiveHeadless ? oauthCfg.redirectUri ?? "http://localhost" : fixedPort != null ? oauthCfg.redirectUri ?? randomRedirect : randomRedirect;
|
|
55922
56062
|
const authUrl = buildAuthorizationUrl({
|
|
55923
56063
|
authorizationEndpoint: oauthCfg.authorizationEndpoint ?? "",
|
|
55924
56064
|
clientId: oauthCfg.clientId,
|
|
55925
56065
|
redirectUri,
|
|
55926
56066
|
scope: oauthCfg.scope ?? "",
|
|
55927
56067
|
codeChallenge,
|
|
55928
|
-
state
|
|
56068
|
+
state,
|
|
56069
|
+
extraParams: oauthCfg.extraAuthParams
|
|
55929
56070
|
});
|
|
55930
56071
|
let code;
|
|
55931
|
-
if (
|
|
56072
|
+
if (effectiveHeadless) {
|
|
55932
56073
|
code = await _headlessPkceFlow(provider, authUrl);
|
|
55933
56074
|
} else {
|
|
55934
56075
|
const result = await _localCallbackPkceFlow(provider, authUrl, state, port);
|
|
@@ -55962,6 +56103,7 @@ async function _runPkceLogin(provider, oauthCfg, opts, meta) {
|
|
|
55962
56103
|
process.stderr.write("\r Authorization approved. \n\n");
|
|
55963
56104
|
const label = opts.label ?? "oauth-login";
|
|
55964
56105
|
const expiresAt = typeof tokens.expiresIn === "number" ? Date.now() + tokens.expiresIn * 1e3 : void 0;
|
|
56106
|
+
const oauthExtraHeaders = provider === "anthropic" ? { "anthropic-beta": "oauth-2025-04-20" } : void 0;
|
|
55965
56107
|
try {
|
|
55966
56108
|
await addCredential({
|
|
55967
56109
|
provider,
|
|
@@ -55972,7 +56114,7 @@ async function _runPkceLogin(provider, oauthCfg, opts, meta) {
|
|
|
55972
56114
|
expiresAt,
|
|
55973
56115
|
priority: 10,
|
|
55974
56116
|
source: "oauth-pkce",
|
|
55975
|
-
|
|
56117
|
+
...oauthExtraHeaders ? { extraHeaders: oauthExtraHeaders } : {}
|
|
55976
56118
|
});
|
|
55977
56119
|
} catch (err) {
|
|
55978
56120
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -55992,6 +56134,27 @@ async function _runPkceLogin(provider, oauthCfg, opts, meta) {
|
|
|
55992
56134
|
meta
|
|
55993
56135
|
};
|
|
55994
56136
|
}
|
|
56137
|
+
function _parseFixedLoopbackPort(redirectUri) {
|
|
56138
|
+
if (!redirectUri) return null;
|
|
56139
|
+
try {
|
|
56140
|
+
const u = new URL(redirectUri);
|
|
56141
|
+
const isLoopback = u.hostname === "localhost" || u.hostname === "127.0.0.1";
|
|
56142
|
+
if (!isLoopback || !u.port) return null;
|
|
56143
|
+
const port = Number(u.port);
|
|
56144
|
+
return Number.isInteger(port) && port > 0 ? port : null;
|
|
56145
|
+
} catch {
|
|
56146
|
+
return null;
|
|
56147
|
+
}
|
|
56148
|
+
}
|
|
56149
|
+
function _isLoopbackUri(redirectUri) {
|
|
56150
|
+
if (!redirectUri) return false;
|
|
56151
|
+
try {
|
|
56152
|
+
const u = new URL(redirectUri);
|
|
56153
|
+
return u.hostname === "localhost" || u.hostname === "127.0.0.1";
|
|
56154
|
+
} catch {
|
|
56155
|
+
return false;
|
|
56156
|
+
}
|
|
56157
|
+
}
|
|
55995
56158
|
async function _headlessPkceFlow(provider, authUrl) {
|
|
55996
56159
|
process.stderr.write("\n");
|
|
55997
56160
|
process.stderr.write(` Provider: ${provider}
|
|
@@ -56278,11 +56441,11 @@ __export(llm_exports, {
|
|
|
56278
56441
|
});
|
|
56279
56442
|
import { pushWarning as pushWarning7 } from "@cleocode/core";
|
|
56280
56443
|
async function getListProviders() {
|
|
56281
|
-
const { listProviders } = await import(
|
|
56444
|
+
const { listProviders: listProviders2 } = await import(
|
|
56282
56445
|
/* webpackIgnore: true */
|
|
56283
56446
|
"@cleocode/core/llm/provider-registry"
|
|
56284
56447
|
);
|
|
56285
|
-
return
|
|
56448
|
+
return listProviders2;
|
|
56286
56449
|
}
|
|
56287
56450
|
async function readApiKeyFromStdin() {
|
|
56288
56451
|
if (process.stdin.isTTY) return "";
|
|
@@ -56593,8 +56756,8 @@ var init_llm3 = __esm({
|
|
|
56593
56756
|
}
|
|
56594
56757
|
},
|
|
56595
56758
|
async run() {
|
|
56596
|
-
const
|
|
56597
|
-
const profiles = await
|
|
56759
|
+
const listProviders2 = await getListProviders();
|
|
56760
|
+
const profiles = await listProviders2();
|
|
56598
56761
|
const providers = profiles.map((p) => ({
|
|
56599
56762
|
name: p.name,
|
|
56600
56763
|
displayName: p.displayName,
|
|
@@ -56654,12 +56817,12 @@ var init_llm3 = __esm({
|
|
|
56654
56817
|
loginCommand = defineCommand({
|
|
56655
56818
|
meta: {
|
|
56656
56819
|
name: "login",
|
|
56657
|
-
description: "Authenticate
|
|
56820
|
+
description: "Authenticate an LLM provider via OAuth. PKCE (browser): anthropic, openai/codex. Device-code: kimi-code. Example: `cleo llm login openai`. For any other provider use `cleo llm add <provider> --api-key-stdin`. Prompts/URLs go to stderr; the result is a human line on a terminal or a JSON envelope when piped/--json."
|
|
56658
56821
|
},
|
|
56659
56822
|
args: {
|
|
56660
56823
|
provider: {
|
|
56661
56824
|
type: "positional",
|
|
56662
|
-
description: "Provider to authenticate
|
|
56825
|
+
description: "Provider to authenticate: anthropic | openai | codex | kimi-code",
|
|
56663
56826
|
required: true
|
|
56664
56827
|
},
|
|
56665
56828
|
label: {
|
|
@@ -63395,7 +63558,7 @@ var project_exports = {};
|
|
|
63395
63558
|
__export(project_exports, {
|
|
63396
63559
|
projectCommand: () => projectCommand
|
|
63397
63560
|
});
|
|
63398
|
-
import { existsSync as
|
|
63561
|
+
import { existsSync as existsSync17, statSync } from "node:fs";
|
|
63399
63562
|
import { resolve as resolve7 } from "node:path";
|
|
63400
63563
|
import { moveProject, projectLifecycle, renameProject } from "@cleocode/core";
|
|
63401
63564
|
function formatSuccessSection(header, icon, items) {
|
|
@@ -63438,7 +63601,7 @@ var init_project = __esm({
|
|
|
63438
63601
|
const newPathRaw = args["newPath"];
|
|
63439
63602
|
const dryRun = args["dry-run"] ?? false;
|
|
63440
63603
|
const newPath = resolve7(newPathRaw);
|
|
63441
|
-
if (!dryRun &&
|
|
63604
|
+
if (!dryRun && existsSync17(newPath) && statSync(newPath).isFile()) {
|
|
63442
63605
|
cliOutput(formatErrorSection("E_INVALID_PATH", `newPath is not a directory: ${newPath}`), {
|
|
63443
63606
|
command: "project",
|
|
63444
63607
|
operation: "project.move"
|
|
@@ -71524,7 +71687,7 @@ var init_lib = __esm({
|
|
|
71524
71687
|
});
|
|
71525
71688
|
|
|
71526
71689
|
// packages/cleo/src/cli/commands/templates/diff.ts
|
|
71527
|
-
import { existsSync as
|
|
71690
|
+
import { existsSync as existsSync18, readFileSync as readFileSync16 } from "node:fs";
|
|
71528
71691
|
import { join as join31 } from "node:path";
|
|
71529
71692
|
import { getTemplateById } from "@cleocode/core/templates/registry";
|
|
71530
71693
|
function unifiedDiff(a, b) {
|
|
@@ -71606,7 +71769,7 @@ var init_diff = __esm({
|
|
|
71606
71769
|
process.exit(1 /* GENERAL_ERROR */);
|
|
71607
71770
|
return;
|
|
71608
71771
|
}
|
|
71609
|
-
if (!
|
|
71772
|
+
if (!existsSync18(installPath)) {
|
|
71610
71773
|
const missingResult = {
|
|
71611
71774
|
id,
|
|
71612
71775
|
installPath,
|
|
@@ -71645,7 +71808,7 @@ ${unifiedDiff("", rendered)}`
|
|
|
71645
71808
|
});
|
|
71646
71809
|
|
|
71647
71810
|
// packages/cleo/src/cli/commands/templates/install.ts
|
|
71648
|
-
import { existsSync as
|
|
71811
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync5, readFileSync as readFileSync17, writeFileSync as writeFileSync5 } from "node:fs";
|
|
71649
71812
|
import { dirname as dirname9, join as join32 } from "node:path";
|
|
71650
71813
|
import { getTemplateById as getTemplateById2 } from "@cleocode/core/templates/registry";
|
|
71651
71814
|
var templatesInstallCommand;
|
|
@@ -71713,7 +71876,7 @@ var init_install = __esm({
|
|
|
71713
71876
|
process.exit(1 /* GENERAL_ERROR */);
|
|
71714
71877
|
return;
|
|
71715
71878
|
}
|
|
71716
|
-
if (
|
|
71879
|
+
if (existsSync19(installPath)) {
|
|
71717
71880
|
const current = readFileSync17(installPath, "utf8");
|
|
71718
71881
|
if (current === rendered) {
|
|
71719
71882
|
const noopResult = {
|
|
@@ -71862,7 +72025,7 @@ var init_show3 = __esm({
|
|
|
71862
72025
|
});
|
|
71863
72026
|
|
|
71864
72027
|
// packages/cleo/src/cli/commands/templates/upgrade.ts
|
|
71865
|
-
import { existsSync as
|
|
72028
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync6, readFileSync as readFileSync18, writeFileSync as writeFileSync6 } from "node:fs";
|
|
71866
72029
|
import { dirname as dirname10, join as join33 } from "node:path";
|
|
71867
72030
|
import { getTemplateById as getTemplateById4 } from "@cleocode/core/templates/registry";
|
|
71868
72031
|
var templatesUpgradeCommand;
|
|
@@ -71938,7 +72101,7 @@ var init_upgrade2 = __esm({
|
|
|
71938
72101
|
}
|
|
71939
72102
|
const previewOnly = args["diff"] === true;
|
|
71940
72103
|
const accept = args["accept"] === true;
|
|
71941
|
-
const current =
|
|
72104
|
+
const current = existsSync20(installPath) ? readFileSync18(installPath, "utf8") : null;
|
|
71942
72105
|
const diffBody = current === null ? "" : current === rendered ? "" : unifiedDiff(current, rendered);
|
|
71943
72106
|
let outcome;
|
|
71944
72107
|
let reason;
|
|
@@ -75735,14 +75898,14 @@ function lazyCommand(meta, loader2) {
|
|
|
75735
75898
|
init_did_you_mean();
|
|
75736
75899
|
|
|
75737
75900
|
// packages/cleo/src/cli/lib/first-run-detection.ts
|
|
75738
|
-
import { existsSync as
|
|
75901
|
+
import { existsSync as existsSync21 } from "node:fs";
|
|
75739
75902
|
import { join as join36 } from "node:path";
|
|
75740
75903
|
async function detectFirstRun() {
|
|
75741
75904
|
const envKey = process.env["ANTHROPIC_API_KEY"];
|
|
75742
75905
|
if (typeof envKey === "string" && envKey.length > 0) return false;
|
|
75743
75906
|
const { getCleoPlatformPaths } = await import("@cleocode/paths");
|
|
75744
75907
|
const configPath = join36(getCleoPlatformPaths().config, "config.json");
|
|
75745
|
-
if (
|
|
75908
|
+
if (existsSync21(configPath)) return false;
|
|
75746
75909
|
try {
|
|
75747
75910
|
const { getCredentialPool } = await import("@cleocode/core/llm/credential-pool.js");
|
|
75748
75911
|
const pool = getCredentialPool();
|