overlord-cli 3.21.0 → 3.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/bin/_cli/cli-update.mjs +119 -0
- package/bin/_cli/index.mjs +22 -1
- package/bin/_cli/setup.mjs +5 -34
- package/bin/_cli/version.mjs +2 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,6 +13,7 @@ npm install -g overlord-cli
|
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Use Node.js 20 or newer for every CLI install or update.
|
|
16
|
+
Run `ovld update` any time you want to refresh the global npm install to the latest release.
|
|
16
17
|
|
|
17
18
|
## Usage
|
|
18
19
|
|
|
@@ -31,6 +32,7 @@ ovld auth login
|
|
|
31
32
|
ovld attach
|
|
32
33
|
ovld create "Investigate the failing build"
|
|
33
34
|
ovld prompt "Draft a fix for the onboarding flow"
|
|
35
|
+
ovld update
|
|
34
36
|
ovld setup codex
|
|
35
37
|
ovld setup cursor
|
|
36
38
|
ovld setup gemini
|
|
@@ -54,6 +56,7 @@ ovld doctor
|
|
|
54
56
|
- `protocol` - run ticket lifecycle commands
|
|
55
57
|
- `connect`, `restart`, `run`, `resume`, `context` - launch or resume an agent session
|
|
56
58
|
- `setup` - install the Overlord connector or plugin bundle for a supported agent
|
|
59
|
+
- `update` - install the latest CLI release from npm
|
|
57
60
|
- `doctor` - verify installed agent connectors and check whether a newer CLI version is available
|
|
58
61
|
|
|
59
62
|
## License
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawnSync } from 'node:child_process';
|
|
4
|
+
import { createRequire } from 'node:module';
|
|
5
|
+
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
const cliPackage = require('../../package.json');
|
|
8
|
+
|
|
9
|
+
const CURRENT_CLI_VERSION = typeof cliPackage.version === 'string' ? cliPackage.version : '0.0.0';
|
|
10
|
+
const CLI_PACKAGE_NAME =
|
|
11
|
+
typeof cliPackage.name === 'string' && cliPackage.name ? cliPackage.name : 'overlord-cli';
|
|
12
|
+
|
|
13
|
+
const ORANGE = '\x1b[38;5;208m';
|
|
14
|
+
const RESET = '\x1b[0m';
|
|
15
|
+
|
|
16
|
+
function colorizeOrange(text) {
|
|
17
|
+
return `${ORANGE}${text}${RESET}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function getCurrentCliVersion() {
|
|
21
|
+
return CURRENT_CLI_VERSION;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function getCliPackageName() {
|
|
25
|
+
return CLI_PACKAGE_NAME;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export async function fetchLatestCliVersion({
|
|
29
|
+
fetchImpl = fetch,
|
|
30
|
+
packageName = CLI_PACKAGE_NAME,
|
|
31
|
+
timeoutMs = 2500
|
|
32
|
+
} = {}) {
|
|
33
|
+
const controller = new AbortController();
|
|
34
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
const response = await fetchImpl(`https://registry.npmjs.org/${packageName}/latest`, {
|
|
38
|
+
signal: controller.signal,
|
|
39
|
+
headers: { Accept: 'application/json' }
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
if (!response.ok) return null;
|
|
43
|
+
|
|
44
|
+
const payload = await response.json();
|
|
45
|
+
return typeof payload?.version === 'string' ? payload.version : null;
|
|
46
|
+
} catch {
|
|
47
|
+
return null;
|
|
48
|
+
} finally {
|
|
49
|
+
clearTimeout(timeout);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export async function checkForCliUpdate(options = {}) {
|
|
54
|
+
const currentVersion = options.currentVersion ?? CURRENT_CLI_VERSION;
|
|
55
|
+
const latestVersion = await fetchLatestCliVersion(options);
|
|
56
|
+
if (!latestVersion || latestVersion === currentVersion) return null;
|
|
57
|
+
return latestVersion;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function formatCliUpdateNotice(latestVersion, { currentVersion = CURRENT_CLI_VERSION } = {}) {
|
|
61
|
+
return `New Overlord CLI version available: v${latestVersion} (installed v${currentVersion}). Run \`ovld update\` to update via npm.`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function printCliUpdateNotice(
|
|
65
|
+
latestVersion,
|
|
66
|
+
{ currentVersion = CURRENT_CLI_VERSION, stream = process.stderr } = {}
|
|
67
|
+
) {
|
|
68
|
+
if (!latestVersion) return false;
|
|
69
|
+
stream.write(`${colorizeOrange(formatCliUpdateNotice(latestVersion, { currentVersion }))}\n`);
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export async function runCliUpdateCommand({
|
|
74
|
+
currentVersion = CURRENT_CLI_VERSION,
|
|
75
|
+
fetchLatestVersionFn = fetchLatestCliVersion,
|
|
76
|
+
logger = console,
|
|
77
|
+
npmCommand = 'npm',
|
|
78
|
+
packageName = CLI_PACKAGE_NAME,
|
|
79
|
+
spawnSyncImpl = spawnSync
|
|
80
|
+
} = {}) {
|
|
81
|
+
const latestVersion = await fetchLatestVersionFn({ currentVersion, packageName });
|
|
82
|
+
|
|
83
|
+
if (latestVersion && latestVersion === currentVersion) {
|
|
84
|
+
logger.log(`Overlord CLI ${currentVersion} is already the latest version.`);
|
|
85
|
+
return { alreadyLatest: true, currentVersion, latestVersion };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const target = `${packageName}@latest`;
|
|
89
|
+
if (latestVersion) {
|
|
90
|
+
logger.log(`Updating Overlord CLI ${currentVersion} -> ${latestVersion} via npm...`);
|
|
91
|
+
} else {
|
|
92
|
+
logger.log(`Updating Overlord CLI via npm...`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const result = spawnSyncImpl(npmCommand, ['install', '-g', target], {
|
|
96
|
+
env: process.env,
|
|
97
|
+
stdio: 'inherit'
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
if (result.error) {
|
|
101
|
+
throw result.error;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (typeof result.status === 'number' && result.status !== 0) {
|
|
105
|
+
throw new Error(`\`${npmCommand} install -g ${target}\` exited with status ${result.status}.`);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (typeof result.signal === 'string') {
|
|
109
|
+
throw new Error(`\`${npmCommand} install -g ${target}\` was terminated by ${result.signal}.`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (latestVersion) {
|
|
113
|
+
logger.log(`Overlord CLI updated to v${latestVersion}.`);
|
|
114
|
+
} else {
|
|
115
|
+
logger.log('Overlord CLI update complete. Run `ovld version` to confirm the installed version.');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return { alreadyLatest: false, currentVersion, latestVersion, result };
|
|
119
|
+
}
|
package/bin/_cli/index.mjs
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { runAttachCommand } from './attach.mjs';
|
|
4
4
|
import { runAuthCommand } from './auth.mjs';
|
|
5
|
+
import { checkForCliUpdate, printCliUpdateNotice, runCliUpdateCommand } from './cli-update.mjs';
|
|
5
6
|
import { runLauncherCommand } from './launcher.mjs';
|
|
6
7
|
import { runProtocolCommand } from './protocol.mjs';
|
|
7
8
|
import { runDoctorCommand, runSetupCommand } from './setup.mjs';
|
|
@@ -38,6 +39,7 @@ Usage:
|
|
|
38
39
|
${primaryCommand} restart <agent> Resume an agent session
|
|
39
40
|
${primaryCommand} context Print ticket context (requires TICKET_ID)
|
|
40
41
|
${primaryCommand} setup <agent|all> Install Overlord agent connector
|
|
42
|
+
${primaryCommand} update Install the latest CLI version from npm
|
|
41
43
|
${primaryCommand} doctor Validate installed agent connectors and check for CLI updates
|
|
42
44
|
${primaryCommand} version Show the installed CLI version
|
|
43
45
|
${primaryCommand} help Show this help message
|
|
@@ -66,6 +68,15 @@ Run a subcommand with --help for more detail.
|
|
|
66
68
|
export async function runCli({ primaryCommand }) {
|
|
67
69
|
assertSupportedNodeVersion();
|
|
68
70
|
const [command, ...rest] = process.argv.slice(2);
|
|
71
|
+
const shouldCheckForUpdate =
|
|
72
|
+
Boolean(process.stdout.isTTY || process.stderr.isTTY) &&
|
|
73
|
+
command !== 'doctor' &&
|
|
74
|
+
command !== 'update';
|
|
75
|
+
const latestCliVersion = shouldCheckForUpdate ? await checkForCliUpdate() : null;
|
|
76
|
+
|
|
77
|
+
if (latestCliVersion && command !== 'doctor' && command !== 'update') {
|
|
78
|
+
printCliUpdateNotice(latestCliVersion);
|
|
79
|
+
}
|
|
69
80
|
|
|
70
81
|
if (!command || command === 'help' || command === '--help' || command === '-h') {
|
|
71
82
|
printHelp(primaryCommand);
|
|
@@ -119,8 +130,18 @@ export async function runCli({ primaryCommand }) {
|
|
|
119
130
|
return;
|
|
120
131
|
}
|
|
121
132
|
|
|
133
|
+
if (command === 'update') {
|
|
134
|
+
if (rest[0] === '--help' || rest[0] === '-h' || rest[0] === 'help') {
|
|
135
|
+
console.log(`Usage:
|
|
136
|
+
${primaryCommand} update Install the latest CLI version from npm`);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
await runCliUpdateCommand();
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
122
143
|
if (command === 'doctor') {
|
|
123
|
-
await runDoctorCommand();
|
|
144
|
+
await runDoctorCommand({ latestCliVersion });
|
|
124
145
|
return;
|
|
125
146
|
}
|
|
126
147
|
|
package/bin/_cli/setup.mjs
CHANGED
|
@@ -12,6 +12,7 @@ import fs from 'node:fs';
|
|
|
12
12
|
import os from 'node:os';
|
|
13
13
|
import path from 'node:path';
|
|
14
14
|
import { fileURLToPath } from 'node:url';
|
|
15
|
+
import { checkForCliUpdate, getCurrentCliVersion, printCliUpdateNotice } from './cli-update.mjs';
|
|
15
16
|
|
|
16
17
|
const BUNDLE_VERSION = '1.8.0';
|
|
17
18
|
const MD_MARKER_START = '<!-- overlord:managed:start -->';
|
|
@@ -280,11 +281,6 @@ function readJsonFileOrNull(filePath) {
|
|
|
280
281
|
}
|
|
281
282
|
}
|
|
282
283
|
|
|
283
|
-
function localCliVersion() {
|
|
284
|
-
const cliPackage = readJsonFileOrNull(path.resolve(__dirname, '..', '..', 'package.json'));
|
|
285
|
-
return typeof cliPackage?.version === 'string' ? cliPackage.version : null;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
284
|
function writeJsonFile(filePath, data) {
|
|
289
285
|
const dir = path.dirname(filePath);
|
|
290
286
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
@@ -483,28 +479,6 @@ function currentContentHashForAgent(agent) {
|
|
|
483
479
|
);
|
|
484
480
|
}
|
|
485
481
|
|
|
486
|
-
async function checkForCliUpdate() {
|
|
487
|
-
const currentVersion = localCliVersion();
|
|
488
|
-
if (!currentVersion) return null;
|
|
489
|
-
const controller = new AbortController();
|
|
490
|
-
const timeout = setTimeout(() => controller.abort(), 2500);
|
|
491
|
-
try {
|
|
492
|
-
const response = await fetch('https://registry.npmjs.org/overlord-cli/latest', {
|
|
493
|
-
signal: controller.signal,
|
|
494
|
-
headers: { Accept: 'application/json' }
|
|
495
|
-
});
|
|
496
|
-
if (!response.ok) return null;
|
|
497
|
-
const payload = await response.json();
|
|
498
|
-
const latestVersion = typeof payload?.version === 'string' ? payload.version : null;
|
|
499
|
-
if (!latestVersion) return null;
|
|
500
|
-
return latestVersion === currentVersion ? null : latestVersion;
|
|
501
|
-
} catch {
|
|
502
|
-
return null;
|
|
503
|
-
} finally {
|
|
504
|
-
clearTimeout(timeout);
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
|
|
508
482
|
function codexSourcePluginDir() {
|
|
509
483
|
if (fs.existsSync(PACKAGE_PLUGIN_DIR)) return PACKAGE_PLUGIN_DIR;
|
|
510
484
|
if (fs.existsSync(REPO_PLUGIN_DIR)) return REPO_PLUGIN_DIR;
|
|
@@ -1035,7 +1009,7 @@ export async function runSetupCommand(args) {
|
|
|
1035
1009
|
}
|
|
1036
1010
|
}
|
|
1037
1011
|
|
|
1038
|
-
export async function runDoctorCommand() {
|
|
1012
|
+
export async function runDoctorCommand({ latestCliVersion = null } = {}) {
|
|
1039
1013
|
console.log('Overlord agent bundle status:\n');
|
|
1040
1014
|
let allOk = true;
|
|
1041
1015
|
const nodeMajor = currentNodeMajor();
|
|
@@ -1051,18 +1025,15 @@ export async function runDoctorCommand() {
|
|
|
1051
1025
|
for (const agent of supportedAgents) {
|
|
1052
1026
|
if (!doctorAgent(agent)) allOk = false;
|
|
1053
1027
|
}
|
|
1054
|
-
const
|
|
1028
|
+
const updateVersion = latestCliVersion ?? (await checkForCliUpdate());
|
|
1055
1029
|
console.log();
|
|
1056
1030
|
if (allOk) {
|
|
1057
1031
|
console.log('All bundles are up to date.');
|
|
1058
1032
|
} else {
|
|
1059
1033
|
console.log('Run `ovld setup <agent>` or `ovld setup all` to install/repair.');
|
|
1060
1034
|
}
|
|
1061
|
-
if (
|
|
1035
|
+
if (updateVersion) {
|
|
1062
1036
|
console.log();
|
|
1063
|
-
|
|
1064
|
-
console.log(
|
|
1065
|
-
`Update with Node.js ${REQUIRED_NODE_MAJOR}+ and reinstall the installed CLI wrapper if needed.`
|
|
1066
|
-
);
|
|
1037
|
+
printCliUpdateNotice(updateVersion, { currentVersion: getCurrentCliVersion(), stream: process.stdout });
|
|
1067
1038
|
}
|
|
1068
1039
|
}
|
package/bin/_cli/version.mjs
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
const require = createRequire(import.meta.url);
|
|
6
|
-
const { version } = require('../../package.json');
|
|
3
|
+
import { getCurrentCliVersion } from './cli-update.mjs';
|
|
7
4
|
|
|
8
5
|
export function runVersionCommand() {
|
|
9
|
-
console.log(`Overlord CLI ${
|
|
6
|
+
console.log(`Overlord CLI ${getCurrentCliVersion()}`);
|
|
10
7
|
}
|