overlord-cli 0.2605101225.0 → 0.2605111118.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 +2 -0
- package/bin/_cli/credentials.mjs +14 -4
- package/bin/_cli/launcher.mjs +19 -8
- package/bin/_cli/protocol.mjs +118 -63
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -74,6 +74,8 @@ ovld setup all
|
|
|
74
74
|
ovld doctor
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
+
For ticket-scoped protocol and launch commands, `ticket_id` values such as `1:899` carry the organization id. The CLI uses that first, then `--organization-id` for UUID compatibility, then stored auth.
|
|
78
|
+
|
|
77
79
|
## Requirements
|
|
78
80
|
|
|
79
81
|
- Node.js 20 or newer
|
package/bin/_cli/credentials.mjs
CHANGED
|
@@ -520,11 +520,20 @@ function isLocalDevCli() {
|
|
|
520
520
|
return !sourcePath.split(path.sep).includes('node_modules');
|
|
521
521
|
}
|
|
522
522
|
|
|
523
|
+
function parseOrganizationIdHint(value) {
|
|
524
|
+
if (typeof value !== 'string' && typeof value !== 'number') return null;
|
|
525
|
+
const parsed = Number.parseInt(String(value), 10);
|
|
526
|
+
return Number.isInteger(parsed) && parsed > 0 ? parsed : null;
|
|
527
|
+
}
|
|
528
|
+
|
|
523
529
|
/**
|
|
524
530
|
* Resolve the Overlord auth session from env vars or shared credentials.
|
|
525
531
|
* Refreshes OAuth access tokens when possible.
|
|
532
|
+
*
|
|
533
|
+
* @param {{ organizationIdHint?: number | string | null }} [options]
|
|
526
534
|
*/
|
|
527
|
-
export async function resolveAuth() {
|
|
535
|
+
export async function resolveAuth(options = {}) {
|
|
536
|
+
const organizationIdHint = parseOrganizationIdHint(options.organizationIdHint);
|
|
528
537
|
const selectedCredentials = selectStoredCredentials();
|
|
529
538
|
const creds = selectedCredentials?.credentials ?? migrateLegacyCredentials();
|
|
530
539
|
const overlordUrlFromEnv = normalizePlatformUrl(process.env.OVERLORD_URL);
|
|
@@ -548,7 +557,8 @@ export async function resolveAuth() {
|
|
|
548
557
|
typeof process.env.OVERLORD_ORGANIZATION_ID === 'string'
|
|
549
558
|
? Number.parseInt(process.env.OVERLORD_ORGANIZATION_ID, 10)
|
|
550
559
|
: null;
|
|
551
|
-
|
|
560
|
+
const resolvedOrganizationId = organizationIdHint ?? envOrganizationId;
|
|
561
|
+
if (!Number.isFinite(resolvedOrganizationId)) {
|
|
552
562
|
throw new Error(
|
|
553
563
|
'OVERLORD_ACCESS_TOKEN requires OVERLORD_ORGANIZATION_ID so protocol requests stay scoped.'
|
|
554
564
|
);
|
|
@@ -559,7 +569,7 @@ export async function resolveAuth() {
|
|
|
559
569
|
platformUrl,
|
|
560
570
|
bearerToken: envAccessToken,
|
|
561
571
|
localSecret,
|
|
562
|
-
organizationId:
|
|
572
|
+
organizationId: resolvedOrganizationId,
|
|
563
573
|
authMode: 'oauth_env'
|
|
564
574
|
};
|
|
565
575
|
}
|
|
@@ -606,7 +616,7 @@ export async function resolveAuth() {
|
|
|
606
616
|
platformUrl,
|
|
607
617
|
bearerToken: nextCredentials.access_token,
|
|
608
618
|
localSecret,
|
|
609
|
-
organizationId: nextCredentials.organization_id,
|
|
619
|
+
organizationId: organizationIdHint ?? nextCredentials.organization_id,
|
|
610
620
|
authMode: 'oauth'
|
|
611
621
|
};
|
|
612
622
|
}
|
package/bin/_cli/launcher.mjs
CHANGED
|
@@ -72,7 +72,6 @@ const agentIdentifierMap = {
|
|
|
72
72
|
};
|
|
73
73
|
|
|
74
74
|
const supportedAgents = ['claude', 'codex', 'cursor', 'gemini', 'opencode'];
|
|
75
|
-
const TICKET_ID_REGEX = /^(\d+):\d+$/;
|
|
76
75
|
|
|
77
76
|
function shellQuote(value) {
|
|
78
77
|
return `'${String(value).replace(/'/g, `'\\''`)}'`;
|
|
@@ -112,14 +111,17 @@ function parseOrganizationId(value) {
|
|
|
112
111
|
}
|
|
113
112
|
|
|
114
113
|
function organizationIdFromTicketId(ticketId) {
|
|
115
|
-
const
|
|
116
|
-
|
|
114
|
+
const [organizationPart, _ticketSequencePart, ...rest] = String(ticketId ?? '')
|
|
115
|
+
.trim()
|
|
116
|
+
.split(':');
|
|
117
|
+
if (rest.length > 0) return null;
|
|
118
|
+
return parseOrganizationId(organizationPart);
|
|
117
119
|
}
|
|
118
120
|
|
|
119
121
|
function resolveLaunchOrganizationId(ticketId, optionsOrganizationId, authOrganizationId) {
|
|
120
122
|
return (
|
|
121
|
-
parseOrganizationId(optionsOrganizationId) ??
|
|
122
123
|
organizationIdFromTicketId(ticketId) ??
|
|
124
|
+
parseOrganizationId(optionsOrganizationId) ??
|
|
123
125
|
parseOrganizationId(authOrganizationId)
|
|
124
126
|
);
|
|
125
127
|
}
|
|
@@ -278,8 +280,15 @@ async function runAgent(agent, mode = 'run', options = {}) {
|
|
|
278
280
|
process.chdir(options.workingDirectory);
|
|
279
281
|
}
|
|
280
282
|
|
|
281
|
-
const { platformUrl, bearerToken, localSecret, organizationId } = await resolveAuth();
|
|
282
283
|
const launchOrganizationId = resolveLaunchOrganizationId(
|
|
284
|
+
ticketId,
|
|
285
|
+
options.organizationId,
|
|
286
|
+
null
|
|
287
|
+
);
|
|
288
|
+
const { platformUrl, bearerToken, localSecret, organizationId } = await resolveAuth({
|
|
289
|
+
organizationIdHint: launchOrganizationId
|
|
290
|
+
});
|
|
291
|
+
const resolvedLaunchOrganizationId = resolveLaunchOrganizationId(
|
|
283
292
|
ticketId,
|
|
284
293
|
options.organizationId,
|
|
285
294
|
organizationId
|
|
@@ -287,7 +296,7 @@ async function runAgent(agent, mode = 'run', options = {}) {
|
|
|
287
296
|
if (options.sshCommand?.trim()) {
|
|
288
297
|
const remoteCommand = buildRemoteLaunchCommand(agent, {
|
|
289
298
|
...options,
|
|
290
|
-
organizationId:
|
|
299
|
+
organizationId: resolvedLaunchOrganizationId
|
|
291
300
|
});
|
|
292
301
|
try {
|
|
293
302
|
execFileSync('sh', ['-lc', remoteCommand], { stdio: 'inherit', env: process.env });
|
|
@@ -303,7 +312,7 @@ async function runAgent(agent, mode = 'run', options = {}) {
|
|
|
303
312
|
platformUrl,
|
|
304
313
|
bearerToken,
|
|
305
314
|
localSecret,
|
|
306
|
-
|
|
315
|
+
resolvedLaunchOrganizationId,
|
|
307
316
|
ticketId,
|
|
308
317
|
agent
|
|
309
318
|
);
|
|
@@ -311,7 +320,9 @@ async function runAgent(agent, mode = 'run', options = {}) {
|
|
|
311
320
|
const childEnv = {
|
|
312
321
|
...process.env,
|
|
313
322
|
AGENT_IDENTIFIER: agentIdentifierMap[agent],
|
|
314
|
-
...(
|
|
323
|
+
...(resolvedLaunchOrganizationId
|
|
324
|
+
? { OVERLORD_ORGANIZATION_ID: String(resolvedLaunchOrganizationId) }
|
|
325
|
+
: {})
|
|
315
326
|
};
|
|
316
327
|
const extraArgs = buildExtraArgs(agent, options);
|
|
317
328
|
|
package/bin/_cli/protocol.mjs
CHANGED
|
@@ -7,6 +7,7 @@ import path from 'node:path';
|
|
|
7
7
|
|
|
8
8
|
import { buildAuthHeaders, getAuthStatus, resolveAuth } from './credentials.mjs';
|
|
9
9
|
|
|
10
|
+
|
|
10
11
|
/**
|
|
11
12
|
* Parse simple CLI flags: --key value or --key=value
|
|
12
13
|
* @param {string[]} args
|
|
@@ -69,7 +70,7 @@ export function resolveProtocolModelIdentifier(flags = {}) {
|
|
|
69
70
|
return envModel || null;
|
|
70
71
|
}
|
|
71
72
|
|
|
72
|
-
function resolveProtocolMetadata(flags = {}, base = {}) {
|
|
73
|
+
async function resolveProtocolMetadata(flags = {}, base = {}) {
|
|
73
74
|
const metadata = { ...base };
|
|
74
75
|
|
|
75
76
|
if (flags['metadata-json']) {
|
|
@@ -85,6 +86,11 @@ function resolveProtocolMetadata(flags = {}, base = {}) {
|
|
|
85
86
|
metadata.model = modelIdentifier;
|
|
86
87
|
}
|
|
87
88
|
|
|
89
|
+
const snapshot = await resolveSnapshotContext(flags);
|
|
90
|
+
if (snapshot) {
|
|
91
|
+
metadata.snapshot = snapshot;
|
|
92
|
+
}
|
|
93
|
+
|
|
88
94
|
return metadata;
|
|
89
95
|
}
|
|
90
96
|
|
|
@@ -233,6 +239,28 @@ function requireFlag(flags, name, envAlias) {
|
|
|
233
239
|
return String(value);
|
|
234
240
|
}
|
|
235
241
|
|
|
242
|
+
function parseOrganizationId(value) {
|
|
243
|
+
if (typeof value !== 'string' && typeof value !== 'number') return null;
|
|
244
|
+
const parsed = Number.parseInt(String(value), 10);
|
|
245
|
+
return Number.isInteger(parsed) && parsed > 0 ? parsed : null;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function organizationIdFromTicketId(ticketId) {
|
|
249
|
+
const [organizationPart, _ticketSequencePart, ...rest] = String(ticketId ?? '')
|
|
250
|
+
.trim()
|
|
251
|
+
.split(':');
|
|
252
|
+
if (rest.length > 0) return null;
|
|
253
|
+
return parseOrganizationId(organizationPart);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function resolveOrganizationIdHint(flags, ticketId) {
|
|
257
|
+
return organizationIdFromTicketId(ticketId) ?? parseOrganizationId(flags['organization-id']);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
async function resolveProtocolAuthForFlags(flags, ticketId = '') {
|
|
261
|
+
return resolveAuth({ organizationIdHint: resolveOrganizationIdHint(flags, ticketId) });
|
|
262
|
+
}
|
|
263
|
+
|
|
236
264
|
function parseJsonFlag(flagName, rawValue) {
|
|
237
265
|
try {
|
|
238
266
|
return JSON.parse(String(rawValue));
|
|
@@ -318,6 +346,19 @@ async function resolveChangeRationales(flags) {
|
|
|
318
346
|
return [];
|
|
319
347
|
}
|
|
320
348
|
|
|
349
|
+
async function resolveSnapshotContext(flags) {
|
|
350
|
+
if (flags['snapshot-file']) {
|
|
351
|
+
return await readJsonFileOrStdin(String(flags['snapshot-file']), '--snapshot-file');
|
|
352
|
+
}
|
|
353
|
+
if (flags['snapshot-json']) {
|
|
354
|
+
return parseJsonFlag('--snapshot-json', flags['snapshot-json']);
|
|
355
|
+
}
|
|
356
|
+
if (process.env.OVERLORD_SNAPSHOT_JSON?.trim()) {
|
|
357
|
+
return parseJsonFlag('--snapshot-json', process.env.OVERLORD_SNAPSHOT_JSON);
|
|
358
|
+
}
|
|
359
|
+
return null;
|
|
360
|
+
}
|
|
361
|
+
|
|
321
362
|
function normalizeRepoRelativeFilePath(filePath, repoRoot) {
|
|
322
363
|
if (typeof filePath !== 'string') return null;
|
|
323
364
|
|
|
@@ -493,7 +534,7 @@ function resolveExternalSessionId(flags) {
|
|
|
493
534
|
async function protocolAttach(args) {
|
|
494
535
|
const flags = parseFlags(args);
|
|
495
536
|
const ticketId = requireFlag(flags, 'ticket-id', 'TICKET_ID');
|
|
496
|
-
const { platformUrl, bearerToken, localSecret, organizationId } = await
|
|
537
|
+
const { platformUrl, bearerToken, localSecret, organizationId } = await resolveProtocolAuthForFlags(flags, ticketId);
|
|
497
538
|
const timeoutMs = resolveTimeout(flags);
|
|
498
539
|
|
|
499
540
|
const externalSessionId = resolveExternalSessionId(flags);
|
|
@@ -503,7 +544,7 @@ async function protocolAttach(args) {
|
|
|
503
544
|
agentIdentifier: resolveProtocolAgentIdentifier(flags),
|
|
504
545
|
connectionMethod: String(flags.method ?? 'cli'),
|
|
505
546
|
...(externalSessionId !== undefined ? { externalSessionId } : {}),
|
|
506
|
-
metadata: resolveProtocolMetadata(flags, { cwd: process.cwd() })
|
|
547
|
+
metadata: await resolveProtocolMetadata(flags, { cwd: process.cwd() })
|
|
507
548
|
};
|
|
508
549
|
|
|
509
550
|
const data = await apiPost(
|
|
@@ -539,10 +580,11 @@ async function protocolUpdate(args) {
|
|
|
539
580
|
? readTextFile(String(flags['summary-file']), '--summary-file')
|
|
540
581
|
: requireFlag(flags, 'summary', undefined);
|
|
541
582
|
|
|
542
|
-
const { platformUrl, bearerToken, localSecret, organizationId } = await
|
|
583
|
+
const { platformUrl, bearerToken, localSecret, organizationId } = await resolveProtocolAuthForFlags(flags, ticketId);
|
|
543
584
|
const timeoutMs = resolveTimeout(flags);
|
|
544
585
|
const changeRationales = await resolveChangeRationales(flags);
|
|
545
586
|
const externalSessionId = resolveExternalSessionId(flags);
|
|
587
|
+
const snapshot = await resolveSnapshotContext(flags);
|
|
546
588
|
|
|
547
589
|
const body = {
|
|
548
590
|
sessionKey,
|
|
@@ -562,6 +604,7 @@ async function protocolUpdate(args) {
|
|
|
562
604
|
...(flags['payload-json']
|
|
563
605
|
? { payload: parseJsonFlag('--payload-json', flags['payload-json']) }
|
|
564
606
|
: {}),
|
|
607
|
+
...(snapshot ? { snapshot } : {}),
|
|
565
608
|
...(changeRationales.length > 0 ? { changeRationales } : {})
|
|
566
609
|
};
|
|
567
610
|
|
|
@@ -594,8 +637,9 @@ async function protocolRecordChangeRationales(args) {
|
|
|
594
637
|
);
|
|
595
638
|
}
|
|
596
639
|
|
|
597
|
-
const { platformUrl, bearerToken, localSecret, organizationId } = await
|
|
640
|
+
const { platformUrl, bearerToken, localSecret, organizationId } = await resolveProtocolAuthForFlags(flags, ticketId);
|
|
598
641
|
const timeoutMs = resolveTimeout(flags);
|
|
642
|
+
const snapshot = await resolveSnapshotContext(flags);
|
|
599
643
|
|
|
600
644
|
const body = {
|
|
601
645
|
sessionKey,
|
|
@@ -606,7 +650,8 @@ async function protocolRecordChangeRationales(args) {
|
|
|
606
650
|
: flags.summary
|
|
607
651
|
? { summary: String(flags.summary) }
|
|
608
652
|
: {}),
|
|
609
|
-
...(flags.phase ? { phase: String(flags.phase) } : {})
|
|
653
|
+
...(flags.phase ? { phase: String(flags.phase) } : {}),
|
|
654
|
+
...(snapshot ? { snapshot } : {})
|
|
610
655
|
};
|
|
611
656
|
|
|
612
657
|
const data = await apiPost(
|
|
@@ -634,7 +679,7 @@ async function protocolAsk(args) {
|
|
|
634
679
|
? readTextFile(String(flags['question-file']), '--question-file')
|
|
635
680
|
: requireFlag(flags, 'question', undefined);
|
|
636
681
|
|
|
637
|
-
const { platformUrl, bearerToken, localSecret, organizationId } = await
|
|
682
|
+
const { platformUrl, bearerToken, localSecret, organizationId } = await resolveProtocolAuthForFlags(flags, ticketId);
|
|
638
683
|
const timeoutMs = resolveTimeout(flags);
|
|
639
684
|
|
|
640
685
|
const body = {
|
|
@@ -670,7 +715,7 @@ async function protocolPermissionRequest(args) {
|
|
|
670
715
|
? await readJsonFileOrStdin(String(flags['payload-file']), '--payload-file')
|
|
671
716
|
: {};
|
|
672
717
|
|
|
673
|
-
const { platformUrl, bearerToken, localSecret, organizationId } = await
|
|
718
|
+
const { platformUrl, bearerToken, localSecret, organizationId } = await resolveProtocolAuthForFlags(flags, ticketId);
|
|
674
719
|
const timeoutMs = resolveTimeout(flags);
|
|
675
720
|
|
|
676
721
|
const data = await apiPost(
|
|
@@ -695,7 +740,7 @@ async function protocolReadContext(args) {
|
|
|
695
740
|
if (!sessionKey) throw new Error('--session-key is required (or set SESSION_KEY)');
|
|
696
741
|
if (!ticketId) throw new Error('--ticket-id is required (or set TICKET_ID)');
|
|
697
742
|
|
|
698
|
-
const { platformUrl, bearerToken, localSecret, organizationId } = await
|
|
743
|
+
const { platformUrl, bearerToken, localSecret, organizationId } = await resolveProtocolAuthForFlags(flags, ticketId);
|
|
699
744
|
const timeoutMs = resolveTimeout(flags);
|
|
700
745
|
|
|
701
746
|
const body = {
|
|
@@ -739,7 +784,7 @@ async function protocolWriteContext(args) {
|
|
|
739
784
|
value = String(flags.value);
|
|
740
785
|
}
|
|
741
786
|
|
|
742
|
-
const { platformUrl, bearerToken, localSecret, organizationId } = await
|
|
787
|
+
const { platformUrl, bearerToken, localSecret, organizationId } = await resolveProtocolAuthForFlags(flags, ticketId);
|
|
743
788
|
const timeoutMs = resolveTimeout(flags);
|
|
744
789
|
|
|
745
790
|
const body = {
|
|
@@ -786,7 +831,7 @@ async function protocolDeliver(args) {
|
|
|
786
831
|
? readTextFile(String(flags['summary-file']), '--summary-file')
|
|
787
832
|
: requireFlag(flags, 'summary', undefined));
|
|
788
833
|
|
|
789
|
-
const { platformUrl, bearerToken, localSecret, organizationId } = await
|
|
834
|
+
const { platformUrl, bearerToken, localSecret, organizationId } = await resolveProtocolAuthForFlags(flags, ticketId);
|
|
790
835
|
const timeoutMs = resolveTimeout(flags);
|
|
791
836
|
|
|
792
837
|
let artifacts = deliverPayload?.artifacts ?? [];
|
|
@@ -808,6 +853,7 @@ async function protocolDeliver(args) {
|
|
|
808
853
|
|
|
809
854
|
const changeRationales =
|
|
810
855
|
deliverPayload?.changeRationales ?? (await resolveChangeRationales(flags));
|
|
856
|
+
const snapshot = (await resolveSnapshotContext(flags)) ?? deliverPayload?.snapshot ?? null;
|
|
811
857
|
validateDeliverFileChanges(flags, changeRationales);
|
|
812
858
|
|
|
813
859
|
const body = {
|
|
@@ -815,6 +861,7 @@ async function protocolDeliver(args) {
|
|
|
815
861
|
ticketId,
|
|
816
862
|
summary,
|
|
817
863
|
artifacts,
|
|
864
|
+
...(snapshot ? { snapshot } : {}),
|
|
818
865
|
...(changeRationales.length > 0 ? { changeRationales } : {})
|
|
819
866
|
};
|
|
820
867
|
|
|
@@ -840,7 +887,7 @@ async function protocolAttachmentList(args) {
|
|
|
840
887
|
if (!sessionKey) throw new Error('--session-key is required (or set SESSION_KEY)');
|
|
841
888
|
if (!ticketId) throw new Error('--ticket-id is required (or set TICKET_ID)');
|
|
842
889
|
|
|
843
|
-
const { platformUrl, bearerToken, localSecret, organizationId } = await
|
|
890
|
+
const { platformUrl, bearerToken, localSecret, organizationId } = await resolveProtocolAuthForFlags(flags, ticketId);
|
|
844
891
|
const timeoutMs = resolveTimeout(flags);
|
|
845
892
|
|
|
846
893
|
const body = {
|
|
@@ -869,7 +916,7 @@ async function protocolAttachmentPrepareUpload(args) {
|
|
|
869
916
|
const objectiveId = requireFlag(flags, 'objective-id', undefined);
|
|
870
917
|
const fileName = requireFlag(flags, 'file-name', undefined);
|
|
871
918
|
|
|
872
|
-
const { platformUrl, bearerToken, localSecret, organizationId } = await
|
|
919
|
+
const { platformUrl, bearerToken, localSecret, organizationId } = await resolveProtocolAuthForFlags(flags, ticketId);
|
|
873
920
|
const timeoutMs = resolveTimeout(flags);
|
|
874
921
|
|
|
875
922
|
const body = {
|
|
@@ -906,7 +953,7 @@ async function protocolAttachmentFinalizeUpload(args) {
|
|
|
906
953
|
const storagePath = requireFlag(flags, 'storage-path', undefined);
|
|
907
954
|
const label = requireFlag(flags, 'label', undefined);
|
|
908
955
|
|
|
909
|
-
const { platformUrl, bearerToken, localSecret, organizationId } = await
|
|
956
|
+
const { platformUrl, bearerToken, localSecret, organizationId } = await resolveProtocolAuthForFlags(flags, ticketId);
|
|
910
957
|
const timeoutMs = resolveTimeout(flags);
|
|
911
958
|
|
|
912
959
|
const body = {
|
|
@@ -946,7 +993,7 @@ async function protocolAttachmentGetDownloadUrl(args) {
|
|
|
946
993
|
throw new Error('--objective-id is required when using --storage-path');
|
|
947
994
|
}
|
|
948
995
|
|
|
949
|
-
const { platformUrl, bearerToken, localSecret, organizationId } = await
|
|
996
|
+
const { platformUrl, bearerToken, localSecret, organizationId } = await resolveProtocolAuthForFlags(flags, ticketId);
|
|
950
997
|
const timeoutMs = resolveTimeout(flags);
|
|
951
998
|
|
|
952
999
|
const body = {
|
|
@@ -987,7 +1034,7 @@ async function protocolAttachmentUploadFile(args) {
|
|
|
987
1034
|
const fileStats = await stat(filePath);
|
|
988
1035
|
const fileBytes = await readFile(filePath);
|
|
989
1036
|
|
|
990
|
-
const { platformUrl, bearerToken, localSecret, organizationId } = await
|
|
1037
|
+
const { platformUrl, bearerToken, localSecret, organizationId } = await resolveProtocolAuthForFlags(flags, ticketId);
|
|
991
1038
|
const timeoutMs = resolveTimeout(flags);
|
|
992
1039
|
|
|
993
1040
|
const metadata = flags['metadata-json']
|
|
@@ -1049,7 +1096,8 @@ async function protocolAttachmentUploadFile(args) {
|
|
|
1049
1096
|
|
|
1050
1097
|
async function protocolDiscoverProject(args) {
|
|
1051
1098
|
const flags = parseFlags(args);
|
|
1052
|
-
const { platformUrl, bearerToken, localSecret, organizationId } =
|
|
1099
|
+
const { platformUrl, bearerToken, localSecret, organizationId } =
|
|
1100
|
+
await resolveProtocolAuthForFlags(flags);
|
|
1053
1101
|
const timeoutMs = resolveTimeout(flags);
|
|
1054
1102
|
|
|
1055
1103
|
const workingDirectory = String(flags['working-directory'] ?? process.cwd());
|
|
@@ -1077,14 +1125,14 @@ async function protocolDiscoverProject(args) {
|
|
|
1077
1125
|
async function protocolConnect(args) {
|
|
1078
1126
|
const flags = parseFlags(args);
|
|
1079
1127
|
const ticketId = requireFlag(flags, 'ticket-id', 'TICKET_ID');
|
|
1080
|
-
const { platformUrl, bearerToken, localSecret, organizationId } = await
|
|
1128
|
+
const { platformUrl, bearerToken, localSecret, organizationId } = await resolveProtocolAuthForFlags(flags, ticketId);
|
|
1081
1129
|
const timeoutMs = resolveTimeout(flags);
|
|
1082
1130
|
|
|
1083
1131
|
const body = {
|
|
1084
1132
|
ticketId,
|
|
1085
1133
|
agentIdentifier: resolveProtocolAgentIdentifier(flags),
|
|
1086
1134
|
connectionMethod: String(flags.method ?? 'cli'),
|
|
1087
|
-
metadata: resolveProtocolMetadata(flags, { cwd: process.cwd() })
|
|
1135
|
+
metadata: await resolveProtocolMetadata(flags, { cwd: process.cwd() })
|
|
1088
1136
|
};
|
|
1089
1137
|
|
|
1090
1138
|
const data = await apiPost(
|
|
@@ -1112,7 +1160,7 @@ async function protocolConnect(args) {
|
|
|
1112
1160
|
async function protocolLoadContext(args) {
|
|
1113
1161
|
const flags = parseFlags(args);
|
|
1114
1162
|
const ticketId = requireFlag(flags, 'ticket-id', 'TICKET_ID');
|
|
1115
|
-
const { platformUrl, bearerToken, localSecret, organizationId } = await
|
|
1163
|
+
const { platformUrl, bearerToken, localSecret, organizationId } = await resolveProtocolAuthForFlags(flags, ticketId);
|
|
1116
1164
|
const timeoutMs = resolveTimeout(flags);
|
|
1117
1165
|
|
|
1118
1166
|
const body = { ticketId };
|
|
@@ -1136,7 +1184,12 @@ async function protocolLoadContext(args) {
|
|
|
1136
1184
|
async function protocolPrompt(args) {
|
|
1137
1185
|
const flags = parseFlags(args);
|
|
1138
1186
|
const objective = requireFlag(flags, 'objective', undefined);
|
|
1139
|
-
const
|
|
1187
|
+
const parentTicketId =
|
|
1188
|
+
flags['parent-ticket-id'] !== undefined
|
|
1189
|
+
? String(flags['parent-ticket-id'] ?? process.env.TICKET_ID ?? '')
|
|
1190
|
+
: '';
|
|
1191
|
+
const { platformUrl, bearerToken, localSecret, organizationId } =
|
|
1192
|
+
await resolveProtocolAuthForFlags(flags, parentTicketId);
|
|
1140
1193
|
const timeoutMs = resolveTimeout(flags);
|
|
1141
1194
|
const agentIdentifier = resolveProtocolAgentIdentifier(flags);
|
|
1142
1195
|
const modelIdentifier = resolveProtocolModelIdentifier(flags);
|
|
@@ -1152,7 +1205,7 @@ async function protocolPrompt(args) {
|
|
|
1152
1205
|
objective,
|
|
1153
1206
|
agentIdentifier,
|
|
1154
1207
|
connectionMethod: String(flags.method ?? 'cli'),
|
|
1155
|
-
metadata: resolveProtocolMetadata(flags, { cwd: process.cwd() }),
|
|
1208
|
+
metadata: await resolveProtocolMetadata(flags, { cwd: process.cwd() }),
|
|
1156
1209
|
...(flags.title ? { title: String(flags.title) } : {}),
|
|
1157
1210
|
...(flags.priority ? { priority: String(flags.priority) } : {}),
|
|
1158
1211
|
...(flags['project-id'] ? { projectId: String(flags['project-id']) } : {}),
|
|
@@ -1167,9 +1220,7 @@ async function protocolPrompt(args) {
|
|
|
1167
1220
|
...(flags['parent-session-key']
|
|
1168
1221
|
? { parentSessionKey: String(flags['parent-session-key']) }
|
|
1169
1222
|
: {}),
|
|
1170
|
-
...(
|
|
1171
|
-
? { parentTicketId: String(flags['parent-ticket-id'] ?? process.env.TICKET_ID ?? '') }
|
|
1172
|
-
: {})
|
|
1223
|
+
...(parentTicketId ? { parentTicketId } : {})
|
|
1173
1224
|
};
|
|
1174
1225
|
|
|
1175
1226
|
const data = await apiPost(
|
|
@@ -1202,7 +1253,7 @@ async function protocolCreateTicket(args) {
|
|
|
1202
1253
|
const flags = parseFlags(args);
|
|
1203
1254
|
const { sessionKey, ticketId } = resolveSessionFlags(flags);
|
|
1204
1255
|
const objective = requireFlag(flags, 'objective', undefined);
|
|
1205
|
-
const { platformUrl, bearerToken, localSecret, organizationId } = await
|
|
1256
|
+
const { platformUrl, bearerToken, localSecret, organizationId } = await resolveProtocolAuthForFlags(flags, ticketId);
|
|
1206
1257
|
const timeoutMs = resolveTimeout(flags);
|
|
1207
1258
|
const agentIdentifier = resolveProtocolAgentIdentifier(flags);
|
|
1208
1259
|
const modelIdentifier = resolveProtocolModelIdentifier(flags);
|
|
@@ -1283,7 +1334,8 @@ async function protocolCreateTicket(args) {
|
|
|
1283
1334
|
|
|
1284
1335
|
async function protocolSearchTickets(args) {
|
|
1285
1336
|
const flags = parseFlags(args);
|
|
1286
|
-
const { platformUrl, bearerToken, localSecret, organizationId } =
|
|
1337
|
+
const { platformUrl, bearerToken, localSecret, organizationId } =
|
|
1338
|
+
await resolveProtocolAuthForFlags(flags);
|
|
1287
1339
|
const timeoutMs = resolveTimeout(flags);
|
|
1288
1340
|
|
|
1289
1341
|
const statuses = flags.status
|
|
@@ -1407,10 +1459,13 @@ Environment fallback:
|
|
|
1407
1459
|
Common flags:
|
|
1408
1460
|
--timeout <ms> Request timeout in milliseconds (default: ${DEFAULT_TIMEOUT_MS})
|
|
1409
1461
|
--ticket-id <ticket_id> Ticket identifier (e.g. 1:899) when the subcommand operates on an existing ticket
|
|
1462
|
+
--organization-id <id> Legacy organization override for UUID ticket ids; inferred from ticket_id when possible
|
|
1410
1463
|
--session-key <key> Session key returned by attach/connect/prompt
|
|
1411
1464
|
--agent <identifier> Agent identifier sent to Overlord (default: AGENT_IDENTIFIER or claude-code)
|
|
1412
1465
|
--model <identifier> Model identifier to snapshot on executing objectives
|
|
1413
1466
|
--method <connectionMethod> Connection method sent to Overlord (default: cli)
|
|
1467
|
+
--snapshot-json <json> Snapshot metadata to attach to sessions/file changes
|
|
1468
|
+
--snapshot-file <path|-> Read snapshot metadata JSON from a file or stdin
|
|
1414
1469
|
|
|
1415
1470
|
auth-status:
|
|
1416
1471
|
Purpose:
|
|
@@ -1463,7 +1518,7 @@ load-context:
|
|
|
1463
1518
|
Purpose:
|
|
1464
1519
|
Read ticket details without creating a session
|
|
1465
1520
|
Required:
|
|
1466
|
-
--ticket-id <
|
|
1521
|
+
--ticket-id <ticket_id>
|
|
1467
1522
|
|
|
1468
1523
|
search-tickets:
|
|
1469
1524
|
Purpose:
|
|
@@ -1486,7 +1541,7 @@ update:
|
|
|
1486
1541
|
Post progress or activity events during execution
|
|
1487
1542
|
Required:
|
|
1488
1543
|
--session-key <key>
|
|
1489
|
-
--ticket-id <
|
|
1544
|
+
--ticket-id <ticket_id>
|
|
1490
1545
|
--summary <text> or --summary-file <path>
|
|
1491
1546
|
Optional:
|
|
1492
1547
|
--phase <status> draft | execute | review | deliver | complete | blocked | cancelled
|
|
@@ -1504,7 +1559,7 @@ record-change-rationales:
|
|
|
1504
1559
|
Persist structured file-change rationale records without also posting a normal update
|
|
1505
1560
|
Required:
|
|
1506
1561
|
--session-key <key>
|
|
1507
|
-
--ticket-id <
|
|
1562
|
+
--ticket-id <ticket_id>
|
|
1508
1563
|
--change-rationales-json <json> or --change-rationales-file <path>
|
|
1509
1564
|
Optional:
|
|
1510
1565
|
--summary <text> or --summary-file <path>
|
|
@@ -1515,7 +1570,7 @@ ask:
|
|
|
1515
1570
|
Raise a blocking question for a human reviewer/PM
|
|
1516
1571
|
Required:
|
|
1517
1572
|
--session-key <key>
|
|
1518
|
-
--ticket-id <
|
|
1573
|
+
--ticket-id <ticket_id>
|
|
1519
1574
|
--question <text> or --question-file <path>
|
|
1520
1575
|
Optional:
|
|
1521
1576
|
--phase <status>
|
|
@@ -1528,7 +1583,7 @@ permission-request:
|
|
|
1528
1583
|
Notify Overlord that the local agent runtime is requesting tool permission.
|
|
1529
1584
|
This is primarily used by installed permission hooks.
|
|
1530
1585
|
Required:
|
|
1531
|
-
--ticket-id <
|
|
1586
|
+
--ticket-id <ticket_id>
|
|
1532
1587
|
Optional:
|
|
1533
1588
|
--payload-file <path|-> Hook JSON payload, or stdin when "-"
|
|
1534
1589
|
|
|
@@ -1537,7 +1592,7 @@ read-context:
|
|
|
1537
1592
|
Read persistent shared context written by earlier sessions
|
|
1538
1593
|
Required:
|
|
1539
1594
|
--session-key <key>
|
|
1540
|
-
--ticket-id <
|
|
1595
|
+
--ticket-id <ticket_id>
|
|
1541
1596
|
Optional:
|
|
1542
1597
|
--query <text> Filter by key substring
|
|
1543
1598
|
--limit <n> Max entries to return
|
|
@@ -1547,7 +1602,7 @@ write-context:
|
|
|
1547
1602
|
Save shared facts for future sessions
|
|
1548
1603
|
Required:
|
|
1549
1604
|
--session-key <key>
|
|
1550
|
-
--ticket-id <
|
|
1605
|
+
--ticket-id <ticket_id>
|
|
1551
1606
|
--key <name>
|
|
1552
1607
|
--value <json-or-string> Parsed as JSON first; stored as a string if JSON parsing fails
|
|
1553
1608
|
Optional:
|
|
@@ -1558,7 +1613,7 @@ deliver:
|
|
|
1558
1613
|
Conclude the session and submit the final narrative plus artifacts/change rationales
|
|
1559
1614
|
Required:
|
|
1560
1615
|
--session-key <key>
|
|
1561
|
-
--ticket-id <
|
|
1616
|
+
--ticket-id <ticket_id>
|
|
1562
1617
|
--summary <text> or --summary-file <path>
|
|
1563
1618
|
or: --payload-file <path|-> containing { summary, artifacts, changeRationales }
|
|
1564
1619
|
Optional:
|
|
@@ -1590,7 +1645,7 @@ prompt:
|
|
|
1590
1645
|
--execution-target <t> agent | human
|
|
1591
1646
|
--delegate <model> Model or delegate identifier that created the ticket
|
|
1592
1647
|
--parent-session-key <key>
|
|
1593
|
-
--parent-ticket-id <
|
|
1648
|
+
--parent-ticket-id <ticket_id>
|
|
1594
1649
|
--agent <identifier>
|
|
1595
1650
|
--model <identifier>
|
|
1596
1651
|
--method <connectionMethod>
|
|
@@ -1607,7 +1662,7 @@ create:
|
|
|
1607
1662
|
--objective <text>
|
|
1608
1663
|
Optional:
|
|
1609
1664
|
--session-key <key>
|
|
1610
|
-
--ticket-id <
|
|
1665
|
+
--ticket-id <ticket_id>
|
|
1611
1666
|
--working-directory <path> Resolve project by your configured local working directory (default: cwd)
|
|
1612
1667
|
--project-id <id> Explicit project for standalone draft creation
|
|
1613
1668
|
--personal Create a private standalone draft without a project
|
|
@@ -1628,7 +1683,7 @@ create:
|
|
|
1628
1683
|
attachment-list:
|
|
1629
1684
|
Required:
|
|
1630
1685
|
--session-key <key>
|
|
1631
|
-
--ticket-id <
|
|
1686
|
+
--ticket-id <ticket_id>
|
|
1632
1687
|
Optional:
|
|
1633
1688
|
--objective-id <id> Filter to a single objective
|
|
1634
1689
|
Returns:
|
|
@@ -1637,7 +1692,7 @@ attachment-list:
|
|
|
1637
1692
|
attachment-prepare-upload:
|
|
1638
1693
|
Required:
|
|
1639
1694
|
--session-key <key>
|
|
1640
|
-
--ticket-id <
|
|
1695
|
+
--ticket-id <ticket_id>
|
|
1641
1696
|
--objective-id <id>
|
|
1642
1697
|
--file-name <name>
|
|
1643
1698
|
Optional:
|
|
@@ -1649,7 +1704,7 @@ attachment-prepare-upload:
|
|
|
1649
1704
|
attachment-finalize-upload:
|
|
1650
1705
|
Required:
|
|
1651
1706
|
--session-key <key>
|
|
1652
|
-
--ticket-id <
|
|
1707
|
+
--ticket-id <ticket_id>
|
|
1653
1708
|
--objective-id <id>
|
|
1654
1709
|
--storage-path <path>
|
|
1655
1710
|
--label <text>
|
|
@@ -1661,7 +1716,7 @@ attachment-finalize-upload:
|
|
|
1661
1716
|
attachment-download-url:
|
|
1662
1717
|
Required:
|
|
1663
1718
|
--session-key <key>
|
|
1664
|
-
--ticket-id <
|
|
1719
|
+
--ticket-id <ticket_id>
|
|
1665
1720
|
one of: --attachment-id <id> | --storage-path <path>
|
|
1666
1721
|
Optional:
|
|
1667
1722
|
--objective-id <id> Required when using --storage-path
|
|
@@ -1670,7 +1725,7 @@ attachment-download-url:
|
|
|
1670
1725
|
attachment-upload-file:
|
|
1671
1726
|
Required:
|
|
1672
1727
|
--session-key <key>
|
|
1673
|
-
--ticket-id <
|
|
1728
|
+
--ticket-id <ticket_id>
|
|
1674
1729
|
--objective-id <id>
|
|
1675
1730
|
--file <path>
|
|
1676
1731
|
Optional:
|
|
@@ -1684,30 +1739,30 @@ Examples:
|
|
|
1684
1739
|
ovld protocol discover-project
|
|
1685
1740
|
ovld protocol discover-project --working-directory /path/to/repo
|
|
1686
1741
|
ovld protocol prompt --agent codex --objective "Implement feature X" # auto-resolves project from cwd
|
|
1687
|
-
ovld protocol attach --ticket-id
|
|
1688
|
-
ovld protocol attach --ticket-id
|
|
1689
|
-
ovld protocol connect --ticket-id
|
|
1690
|
-
ovld protocol load-context --ticket-id
|
|
1742
|
+
ovld protocol attach --ticket-id 1:899
|
|
1743
|
+
ovld protocol attach --ticket-id 1:899 --external-session-id null
|
|
1744
|
+
ovld protocol connect --ticket-id 1:899
|
|
1745
|
+
ovld protocol load-context --ticket-id 1:899
|
|
1691
1746
|
ovld protocol search-tickets --query "auth refactor" --status next-up,execute --limit 10
|
|
1692
1747
|
ovld protocol create --agent codex --objective "Capture follow-up work from this repo"
|
|
1693
|
-
ovld protocol create --agent codex --session-key <key> --ticket-id <
|
|
1748
|
+
ovld protocol create --agent codex --session-key <key> --ticket-id <ticket_id> --objective "Capture follow-up work"
|
|
1694
1749
|
ovld protocol prompt --agent codex --objective "Implement user auth" --priority high
|
|
1695
|
-
ovld protocol update --session-key <key> --ticket-id <
|
|
1696
|
-
ovld protocol update --session-key <key> --ticket-id <
|
|
1697
|
-
ovld protocol record-change-rationales --session-key <key> --ticket-id <
|
|
1698
|
-
ovld protocol ask --session-key <key> --ticket-id <
|
|
1699
|
-
ovld protocol read-context --session-key <key> --ticket-id <
|
|
1700
|
-
ovld protocol write-context --session-key <key> --ticket-id <
|
|
1701
|
-
ovld protocol attachment-list --session-key <key> --ticket-id <
|
|
1702
|
-
ovld protocol attachment-prepare-upload --session-key <key> --ticket-id <
|
|
1703
|
-
ovld protocol attachment-upload-file --session-key <key> --ticket-id <
|
|
1704
|
-
ovld protocol attachment-download-url --session-key <key> --ticket-id <
|
|
1705
|
-
ovld protocol deliver --session-key <key> --ticket-id <
|
|
1706
|
-
ovld protocol deliver --session-key <key> --ticket-id <
|
|
1707
|
-
ovld protocol deliver --session-key <key> --ticket-id <
|
|
1708
|
-
ovld protocol deliver --session-key <key> --ticket-id <
|
|
1709
|
-
ovld protocol deliver --session-key <key> --ticket-id <
|
|
1710
|
-
ovld protocol deliver --session-key <key> --ticket-id <
|
|
1750
|
+
ovld protocol update --session-key <key> --ticket-id <ticket_id> --summary "Did X" --phase execute
|
|
1751
|
+
ovld protocol update --session-key <key> --ticket-id <ticket_id> --summary-file ./update.txt --event-type user_follow_up
|
|
1752
|
+
ovld protocol record-change-rationales --session-key <key> --ticket-id <ticket_id> --change-rationales-json '[{"label":"...","file_path":"...","summary":"...","why":"...","impact":"...","hunks":[{"header":"@@ ... @@"}]}]'
|
|
1753
|
+
ovld protocol ask --session-key <key> --ticket-id <ticket_id> --question-file ./question.txt
|
|
1754
|
+
ovld protocol read-context --session-key <key> --ticket-id <ticket_id> --query arch --limit 5
|
|
1755
|
+
ovld protocol write-context --session-key <key> --ticket-id <ticket_id> --key "arch" --value '"monorepo"' --tags repo,agent
|
|
1756
|
+
ovld protocol attachment-list --session-key <key> --ticket-id <ticket_id>
|
|
1757
|
+
ovld protocol attachment-prepare-upload --session-key <key> --ticket-id <ticket_id> --objective-id <objective-id> --file-name spec.pdf --content-type application/pdf
|
|
1758
|
+
ovld protocol attachment-upload-file --session-key <key> --ticket-id <ticket_id> --objective-id <objective-id> --file ./spec.pdf
|
|
1759
|
+
ovld protocol attachment-download-url --session-key <key> --ticket-id <ticket_id> --attachment-id <attachment-id>
|
|
1760
|
+
ovld protocol deliver --session-key <key> --ticket-id <ticket_id> --summary "Done"
|
|
1761
|
+
ovld protocol deliver --session-key <key> --ticket-id <ticket_id> --summary "Done" --artifacts-file ./artifacts.json
|
|
1762
|
+
ovld protocol deliver --session-key <key> --ticket-id <ticket_id> --payload-file ./deliver.json
|
|
1763
|
+
ovld protocol deliver --session-key <key> --ticket-id <ticket_id> --payload-file -
|
|
1764
|
+
ovld protocol deliver --session-key <key> --ticket-id <ticket_id> --summary "Done" --skip-file-change-check
|
|
1765
|
+
ovld protocol deliver --session-key <key> --ticket-id <ticket_id> --summary "Done" --timeout 60000
|
|
1711
1766
|
`);
|
|
1712
1767
|
return;
|
|
1713
1768
|
}
|