overlord-cli 0.2605151717.0 → 0.2605161310.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/bin/_cli/cli-update.mjs
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import { spawnSync } from 'node:child_process';
|
|
4
4
|
import { createRequire } from 'node:module';
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import os from 'node:os';
|
|
7
|
+
import path from 'node:path';
|
|
5
8
|
|
|
6
9
|
const require = createRequire(import.meta.url);
|
|
7
10
|
const cliPackage = require('../../package.json');
|
|
@@ -50,6 +53,41 @@ export async function fetchLatestCliVersion({
|
|
|
50
53
|
}
|
|
51
54
|
}
|
|
52
55
|
|
|
56
|
+
function pruneOldCliVersions() {
|
|
57
|
+
const cliInstallRoot = path.join(os.homedir(), '.ovld', 'cli');
|
|
58
|
+
if (!fs.existsSync(cliInstallRoot)) return;
|
|
59
|
+
|
|
60
|
+
let entries;
|
|
61
|
+
try {
|
|
62
|
+
entries = fs.readdirSync(cliInstallRoot);
|
|
63
|
+
} catch {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const versionDirs = entries
|
|
68
|
+
.filter(name => name.startsWith('overlord-cli-'))
|
|
69
|
+
.flatMap(name => {
|
|
70
|
+
const dirPath = path.join(cliInstallRoot, name);
|
|
71
|
+
try {
|
|
72
|
+
const stat = fs.statSync(dirPath);
|
|
73
|
+
if (!stat.isDirectory()) return [];
|
|
74
|
+
return [{ dirPath, mtime: stat.mtimeMs }];
|
|
75
|
+
} catch {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Sort newest-first, keep current + 1 previous, delete the rest
|
|
81
|
+
versionDirs.sort((a, b) => b.mtime - a.mtime);
|
|
82
|
+
for (const { dirPath } of versionDirs.slice(2)) {
|
|
83
|
+
try {
|
|
84
|
+
fs.rmSync(dirPath, { recursive: true, force: true });
|
|
85
|
+
} catch {
|
|
86
|
+
// Best-effort cleanup
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
53
91
|
export async function checkForCliUpdate(options = {}) {
|
|
54
92
|
const currentVersion = options.currentVersion ?? CURRENT_CLI_VERSION;
|
|
55
93
|
const latestVersion = await fetchLatestCliVersion(options);
|
|
@@ -115,5 +153,7 @@ export async function runCliUpdateCommand({
|
|
|
115
153
|
logger.log('Overlord CLI update complete. Run `ovld version` to confirm the installed version.');
|
|
116
154
|
}
|
|
117
155
|
|
|
156
|
+
pruneOldCliVersions();
|
|
157
|
+
|
|
118
158
|
return { alreadyLatest: false, currentVersion, latestVersion, result };
|
|
119
159
|
}
|
package/bin/_cli/launcher.mjs
CHANGED
|
@@ -68,10 +68,11 @@ const agentIdentifierMap = {
|
|
|
68
68
|
codex: 'codex',
|
|
69
69
|
cursor: 'cursor',
|
|
70
70
|
gemini: 'gemini',
|
|
71
|
-
opencode: 'opencode'
|
|
71
|
+
opencode: 'opencode',
|
|
72
|
+
pi: 'pi'
|
|
72
73
|
};
|
|
73
74
|
|
|
74
|
-
const supportedAgents = ['claude', 'codex', 'cursor', 'gemini', 'opencode'];
|
|
75
|
+
const supportedAgents = ['claude', 'codex', 'cursor', 'gemini', 'opencode', 'pi'];
|
|
75
76
|
|
|
76
77
|
function shellQuote(value) {
|
|
77
78
|
return `'${String(value).replace(/'/g, `'\\''`)}'`;
|
|
@@ -98,6 +99,8 @@ function buildExtraArgs(agent, options = {}) {
|
|
|
98
99
|
args.push('-c', `model_reasoning_effort=${toTomlString(options.thinking)}`);
|
|
99
100
|
} else if (agent === 'gemini') {
|
|
100
101
|
args.push('--thinking-level', options.thinking);
|
|
102
|
+
} else if (agent === 'pi') {
|
|
103
|
+
args.push('--thinking', options.thinking);
|
|
101
104
|
}
|
|
102
105
|
}
|
|
103
106
|
|
|
@@ -378,6 +381,17 @@ async function runAgent(agent, mode = 'run', options = {}) {
|
|
|
378
381
|
env: childEnv
|
|
379
382
|
});
|
|
380
383
|
}
|
|
384
|
+
} else if (agent === 'pi') {
|
|
385
|
+
if (mode === 'resume') {
|
|
386
|
+
const piSessionId = process.env.PI_SESSION_ID?.trim();
|
|
387
|
+
const args = piSessionId
|
|
388
|
+
? ['--session', piSessionId, context]
|
|
389
|
+
: ['--continue', context];
|
|
390
|
+
args.unshift(...extraArgs);
|
|
391
|
+
execFileSync('pi', args, { stdio: 'inherit', env: childEnv });
|
|
392
|
+
} else {
|
|
393
|
+
execFileSync('pi', [...extraArgs, context], { stdio: 'inherit', env: childEnv });
|
|
394
|
+
}
|
|
381
395
|
} else if (agent === 'gemini') {
|
|
382
396
|
// Write context to a temp file. Passing inline content as a positional arg
|
|
383
397
|
// causes Gemini's @-reference parser to lstat(cwd + content) when it encounters
|
|
@@ -413,7 +427,9 @@ async function runAgent(agent, mode = 'run', options = {}) {
|
|
|
413
427
|
? `No prior Codex session was found. Start one with \`ovld launch codex --ticket-id <ticket_id>\` first.`
|
|
414
428
|
: agent === 'opencode'
|
|
415
429
|
? `No prior OpenCode session was found. Start one with \`ovld launch opencode --ticket-id <ticket_id>\` first.`
|
|
416
|
-
: ''
|
|
430
|
+
: agent === 'pi'
|
|
431
|
+
? `No prior Pi session was found. Start one with \`ovld launch pi --ticket-id <ticket_id>\` first.`
|
|
432
|
+
: '';
|
|
417
433
|
const message = error instanceof Error ? error.message : String(error);
|
|
418
434
|
|
|
419
435
|
if (isResume && noSessionHint) {
|
package/bin/_cli/protocol.mjs
CHANGED
|
@@ -1035,6 +1035,42 @@ async function protocolAsk(args) {
|
|
|
1035
1035
|
console.log(JSON.stringify(data, null, 2));
|
|
1036
1036
|
}
|
|
1037
1037
|
|
|
1038
|
+
// ---------------------------------------------------------------------------
|
|
1039
|
+
// request-approval-gate
|
|
1040
|
+
// ---------------------------------------------------------------------------
|
|
1041
|
+
|
|
1042
|
+
async function protocolRequestApprovalGate(args) {
|
|
1043
|
+
const flags = parseFlags(args);
|
|
1044
|
+
const { sessionKey, ticketId } = resolveSessionFlags(flags);
|
|
1045
|
+
if (!sessionKey) throw new Error('--session-key is required (or set SESSION_KEY)');
|
|
1046
|
+
if (!ticketId) throw new Error('--ticket-id is required (or set TICKET_ID)');
|
|
1047
|
+
const reason = flags['reason-file']
|
|
1048
|
+
? await readTextFileOrStdin(String(flags['reason-file']), '--reason-file')
|
|
1049
|
+
: requireFlag(flags, 'reason', undefined);
|
|
1050
|
+
|
|
1051
|
+
const { platformUrl, bearerToken, localSecret, organizationId } =
|
|
1052
|
+
await resolveProtocolAuthForFlags(flags, ticketId);
|
|
1053
|
+
const timeoutMs = resolveTimeout(flags);
|
|
1054
|
+
|
|
1055
|
+
const body = {
|
|
1056
|
+
sessionKey,
|
|
1057
|
+
ticketId,
|
|
1058
|
+
reason,
|
|
1059
|
+
...(flags['objective-id'] ? { objectiveId: String(flags['objective-id']) } : {})
|
|
1060
|
+
};
|
|
1061
|
+
|
|
1062
|
+
const data = await apiPost(
|
|
1063
|
+
platformUrl,
|
|
1064
|
+
bearerToken,
|
|
1065
|
+
localSecret,
|
|
1066
|
+
organizationId,
|
|
1067
|
+
'/api/protocol/request-approval-gate',
|
|
1068
|
+
body,
|
|
1069
|
+
timeoutMs
|
|
1070
|
+
);
|
|
1071
|
+
console.log(JSON.stringify(data, null, 2));
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1038
1074
|
// ---------------------------------------------------------------------------
|
|
1039
1075
|
// permission-request
|
|
1040
1076
|
// ---------------------------------------------------------------------------
|
|
@@ -2238,6 +2274,7 @@ Subcommands:
|
|
|
2238
2274
|
update Post progress, activity events, and optional change rationales
|
|
2239
2275
|
record-change-rationales Persist structured change rationales without a progress update
|
|
2240
2276
|
ask Post a blocking question and move the ticket to review
|
|
2277
|
+
request-approval-gate Flip auto_advance=false on the next queued future objective
|
|
2241
2278
|
permission-request Notify Overlord that the agent is requesting tool permission
|
|
2242
2279
|
hook-event Record a lifecycle hook event without a session key
|
|
2243
2280
|
read-context Read shared persistent context for this ticket
|
|
@@ -2779,6 +2816,10 @@ EOF
|
|
|
2779
2816
|
await protocolAsk(args);
|
|
2780
2817
|
return;
|
|
2781
2818
|
}
|
|
2819
|
+
if (subcommand === 'request-approval-gate') {
|
|
2820
|
+
await protocolRequestApprovalGate(args);
|
|
2821
|
+
return;
|
|
2822
|
+
}
|
|
2782
2823
|
if (subcommand === 'permission-request') {
|
|
2783
2824
|
await protocolPermissionRequest(args);
|
|
2784
2825
|
return;
|
package/package.json
CHANGED
|
@@ -292,6 +292,31 @@ const tools = [
|
|
|
292
292
|
}),
|
|
293
293
|
subcommand: 'ask'
|
|
294
294
|
},
|
|
295
|
+
{
|
|
296
|
+
name: 'request_approval_gate',
|
|
297
|
+
description:
|
|
298
|
+
'Flip auto_advance=false on the next queued future objective so a human must approve before it runs.',
|
|
299
|
+
inputSchema: {
|
|
300
|
+
type: 'object',
|
|
301
|
+
properties: {
|
|
302
|
+
session_key: { type: 'string' },
|
|
303
|
+
ticket_id: {
|
|
304
|
+
type: 'string',
|
|
305
|
+
description: 'Ticket identifier (e.g. 1:899). Also accepts UUID.'
|
|
306
|
+
},
|
|
307
|
+
reason: { type: 'string' },
|
|
308
|
+
objective_id: { type: 'string' }
|
|
309
|
+
},
|
|
310
|
+
required: ['session_key', 'ticket_id', 'reason']
|
|
311
|
+
},
|
|
312
|
+
toCliFlags: args => ({
|
|
313
|
+
'session-key': args.session_key,
|
|
314
|
+
'ticket-id': args.ticket_id,
|
|
315
|
+
reason: args.reason,
|
|
316
|
+
'objective-id': args.objective_id
|
|
317
|
+
}),
|
|
318
|
+
subcommand: 'request-approval-gate'
|
|
319
|
+
},
|
|
295
320
|
{
|
|
296
321
|
name: 'read_context',
|
|
297
322
|
description: 'Read persistent shared context entries for a ticket.',
|