overlord-cli 5.11.0 → 5.12.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 +4 -4
- package/bin/_cli/protocol.mjs +185 -81
- package/bin/_cli/setup.mjs +24 -11
- package/package.json +1 -1
- package/plugins/claude/skills/overlord-ticket/SKILL.md +3 -3
- package/plugins/overlord/.codex-plugin/plugin.json +1 -1
- package/plugins/overlord/README.md +1 -1
- package/plugins/overlord/scripts/overlord-mcp.mjs +26 -24
- package/plugins/overlord/skills/overlord-ticket/SKILL.md +3 -3
package/README.md
CHANGED
|
@@ -118,10 +118,10 @@ Agents can find docs here: https://www.ovld.ai/docs/for-agents
|
|
|
118
118
|
- `read-context` - read shared persistent context for this ticket
|
|
119
119
|
- `write-context` - write shared persistent context for future sessions
|
|
120
120
|
- `deliver` - finish work, send artifacts, and move the ticket to review
|
|
121
|
-
- `
|
|
122
|
-
- `
|
|
123
|
-
- `
|
|
124
|
-
- `
|
|
121
|
+
- `attachment-prepare-upload` - get a signed upload URL for an objective attachment
|
|
122
|
+
- `attachment-finalize-upload` - finalize an uploaded objective attachment row after storage upload
|
|
123
|
+
- `attachment-download-url` - get a signed download URL for an existing objective attachment
|
|
124
|
+
- `attachment-upload-file` - prepare, upload, and finalize a local objective attachment in one command
|
|
125
125
|
|
|
126
126
|
## License
|
|
127
127
|
|
package/bin/_cli/protocol.mjs
CHANGED
|
@@ -43,7 +43,11 @@ export function resolveProtocolAgentIdentifier(flags = {}) {
|
|
|
43
43
|
return envAgent || 'claude-code';
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
export function resolveProtocolTicketDelegate(
|
|
46
|
+
export function resolveProtocolTicketDelegate(
|
|
47
|
+
flags = {},
|
|
48
|
+
modelIdentifier = '',
|
|
49
|
+
agentIdentifier = ''
|
|
50
|
+
) {
|
|
47
51
|
const explicitDelegate = typeof flags.delegate === 'string' ? flags.delegate.trim() : '';
|
|
48
52
|
if (explicitDelegate) return explicitDelegate;
|
|
49
53
|
|
|
@@ -120,19 +124,20 @@ async function apiPost(
|
|
|
120
124
|
if (error && (error.name === 'TimeoutError' || error.name === 'AbortError')) {
|
|
121
125
|
throw new Error(
|
|
122
126
|
`Request timed out after ${timeoutMs}ms calling ${requestUrl}.\n` +
|
|
123
|
-
|
|
124
|
-
|
|
127
|
+
`Tip: Ensure Overlord is running and reachable from this environment. ` +
|
|
128
|
+
`Increase the limit with --timeout <ms> or OVERLORD_TIMEOUT=<ms>.`
|
|
125
129
|
);
|
|
126
130
|
}
|
|
127
131
|
|
|
128
|
-
const causeCode =
|
|
132
|
+
const causeCode =
|
|
129
133
|
typeof error === 'object' &&
|
|
130
134
|
error !== null &&
|
|
131
135
|
'cause' in error &&
|
|
132
136
|
typeof error.cause === 'object' &&
|
|
133
137
|
error.cause !== null &&
|
|
134
138
|
'code' in error.cause
|
|
135
|
-
|
|
139
|
+
? String(error.cause.code)
|
|
140
|
+
: '';
|
|
136
141
|
|
|
137
142
|
let hint = 'Check your network and Overlord server settings.';
|
|
138
143
|
if (causeCode === 'ECONNREFUSED') {
|
|
@@ -162,10 +167,10 @@ async function apiPost(
|
|
|
162
167
|
if (res.status === 401) {
|
|
163
168
|
throw new Error(
|
|
164
169
|
`Authentication failed (401): ${data.error ?? 'Invalid or missing token.'}\n` +
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
170
|
+
`IMPORTANT: Stop all work immediately. Your Overlord auth session is invalid, expired, or missing required scope.\n` +
|
|
171
|
+
`First run \`ovld auth repair\` yourself.\n` +
|
|
172
|
+
`If repair does not fix it, ask the user to sign in again with Overlord Desktop or \`ovld auth login\` if needed.\n` +
|
|
173
|
+
`Then ask whether they would like to proceed without submitting updates to Overlord.`
|
|
169
174
|
);
|
|
170
175
|
}
|
|
171
176
|
|
|
@@ -376,10 +381,10 @@ function createFileChangeCheckError(message, changedFiles, rationalePaths = [])
|
|
|
376
381
|
|
|
377
382
|
return new Error(
|
|
378
383
|
`${message}\n` +
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
384
|
+
`Overlord persists file changes through \`changeRationales\`, not \`file_changes\` artifacts.\n` +
|
|
385
|
+
`Re-run with --change-rationales-json or --change-rationales-file, or pass --skip-file-change-check if this was intentional.` +
|
|
386
|
+
`${changedPreview ? `\nChanged files: ${changedPreview}${changedFiles.size > 10 ? ', ...' : ''}` : ''}` +
|
|
387
|
+
`${rationalePreview ? `\nProvided rationale paths: ${rationalePreview}${rationalePaths.length > 10 ? ', ...' : ''}` : ''}`
|
|
383
388
|
);
|
|
384
389
|
}
|
|
385
390
|
|
|
@@ -427,7 +432,8 @@ function detectClaudeSessionId() {
|
|
|
427
432
|
|
|
428
433
|
if (!fs.existsSync(sessionsDir)) return null;
|
|
429
434
|
|
|
430
|
-
const files = fs
|
|
435
|
+
const files = fs
|
|
436
|
+
.readdirSync(sessionsDir)
|
|
431
437
|
.filter(f => f.endsWith('.jsonl'))
|
|
432
438
|
.map(f => ({
|
|
433
439
|
name: f,
|
|
@@ -553,7 +559,9 @@ async function protocolUpdate(args) {
|
|
|
553
559
|
: {}),
|
|
554
560
|
...(flags.phase ? { phase: String(flags.phase) } : {}),
|
|
555
561
|
...(flags['event-type'] ? { eventType: String(flags['event-type']) } : {}),
|
|
556
|
-
...(flags['payload-json']
|
|
562
|
+
...(flags['payload-json']
|
|
563
|
+
? { payload: parseJsonFlag('--payload-json', flags['payload-json']) }
|
|
564
|
+
: {}),
|
|
557
565
|
...(changeRationales.length > 0 ? { changeRationales } : {})
|
|
558
566
|
};
|
|
559
567
|
|
|
@@ -634,7 +642,9 @@ async function protocolAsk(args) {
|
|
|
634
642
|
ticketId,
|
|
635
643
|
question,
|
|
636
644
|
...(flags.phase ? { phase: String(flags.phase) } : {}),
|
|
637
|
-
...(flags['payload-json']
|
|
645
|
+
...(flags['payload-json']
|
|
646
|
+
? { payload: parseJsonFlag('--payload-json', flags['payload-json']) }
|
|
647
|
+
: {})
|
|
638
648
|
};
|
|
639
649
|
|
|
640
650
|
const data = await apiPost(
|
|
@@ -737,7 +747,13 @@ async function protocolWriteContext(args) {
|
|
|
737
747
|
ticketId,
|
|
738
748
|
key,
|
|
739
749
|
value,
|
|
740
|
-
...(flags.tags
|
|
750
|
+
...(flags.tags
|
|
751
|
+
? {
|
|
752
|
+
tags: String(flags.tags)
|
|
753
|
+
.split(',')
|
|
754
|
+
.map(t => t.trim())
|
|
755
|
+
}
|
|
756
|
+
: {})
|
|
741
757
|
};
|
|
742
758
|
|
|
743
759
|
const data = await apiPost(
|
|
@@ -764,7 +780,8 @@ async function protocolDeliver(args) {
|
|
|
764
780
|
const deliverPayload = flags['payload-file']
|
|
765
781
|
? await readJsonFileOrStdin(String(flags['payload-file']), '--payload-file')
|
|
766
782
|
: null;
|
|
767
|
-
const summary =
|
|
783
|
+
const summary =
|
|
784
|
+
deliverPayload?.summary ??
|
|
768
785
|
(flags['summary-file']
|
|
769
786
|
? readTextFile(String(flags['summary-file']), '--summary-file')
|
|
770
787
|
: requireFlag(flags, 'summary', undefined));
|
|
@@ -789,7 +806,8 @@ async function protocolDeliver(args) {
|
|
|
789
806
|
throw new Error('Use either --payload-file or change-rationale flags, not both');
|
|
790
807
|
}
|
|
791
808
|
|
|
792
|
-
const changeRationales =
|
|
809
|
+
const changeRationales =
|
|
810
|
+
deliverPayload?.changeRationales ?? (await resolveChangeRationales(flags));
|
|
793
811
|
validateDeliverFileChanges(flags, changeRationales);
|
|
794
812
|
|
|
795
813
|
const body = {
|
|
@@ -813,14 +831,15 @@ async function protocolDeliver(args) {
|
|
|
813
831
|
}
|
|
814
832
|
|
|
815
833
|
// ---------------------------------------------------------------------------
|
|
816
|
-
//
|
|
834
|
+
// objective attachments
|
|
817
835
|
// ---------------------------------------------------------------------------
|
|
818
836
|
|
|
819
|
-
async function
|
|
837
|
+
async function protocolAttachmentPrepareUpload(args) {
|
|
820
838
|
const flags = parseFlags(args);
|
|
821
839
|
const { sessionKey, ticketId } = resolveSessionFlags(flags);
|
|
822
840
|
if (!sessionKey) throw new Error('--session-key is required (or set SESSION_KEY)');
|
|
823
841
|
if (!ticketId) throw new Error('--ticket-id is required (or set TICKET_ID)');
|
|
842
|
+
const objectiveId = requireFlag(flags, 'objective-id', undefined);
|
|
824
843
|
const fileName = requireFlag(flags, 'file-name', undefined);
|
|
825
844
|
|
|
826
845
|
const { platformUrl, bearerToken, localSecret, organizationId } = await resolveAuth();
|
|
@@ -829,12 +848,14 @@ async function protocolArtifactPrepareUpload(args) {
|
|
|
829
848
|
const body = {
|
|
830
849
|
sessionKey,
|
|
831
850
|
ticketId,
|
|
851
|
+
objectiveId,
|
|
832
852
|
fileName,
|
|
833
853
|
...(flags.label ? { label: String(flags.label) } : {}),
|
|
834
|
-
...(flags['artifact-type'] ? { artifactType: String(flags['artifact-type']) } : {}),
|
|
835
854
|
...(flags['content-type'] ? { contentType: String(flags['content-type']) } : {}),
|
|
836
855
|
...(flags['file-size'] ? { fileSize: parseInt(String(flags['file-size']), 10) } : {}),
|
|
837
|
-
...(flags['metadata-json']
|
|
856
|
+
...(flags['metadata-json']
|
|
857
|
+
? { metadata: parseJsonFlag('--metadata-json', flags['metadata-json']) }
|
|
858
|
+
: {})
|
|
838
859
|
};
|
|
839
860
|
|
|
840
861
|
const data = await apiPost(
|
|
@@ -842,18 +863,19 @@ async function protocolArtifactPrepareUpload(args) {
|
|
|
842
863
|
bearerToken,
|
|
843
864
|
localSecret,
|
|
844
865
|
organizationId,
|
|
845
|
-
'/api/protocol/
|
|
866
|
+
'/api/protocol/attachments/prepare-upload',
|
|
846
867
|
body,
|
|
847
868
|
timeoutMs
|
|
848
869
|
);
|
|
849
870
|
console.log(JSON.stringify(data, null, 2));
|
|
850
871
|
}
|
|
851
872
|
|
|
852
|
-
async function
|
|
873
|
+
async function protocolAttachmentFinalizeUpload(args) {
|
|
853
874
|
const flags = parseFlags(args);
|
|
854
875
|
const { sessionKey, ticketId } = resolveSessionFlags(flags);
|
|
855
876
|
if (!sessionKey) throw new Error('--session-key is required (or set SESSION_KEY)');
|
|
856
877
|
if (!ticketId) throw new Error('--ticket-id is required (or set TICKET_ID)');
|
|
878
|
+
const objectiveId = requireFlag(flags, 'objective-id', undefined);
|
|
857
879
|
const storagePath = requireFlag(flags, 'storage-path', undefined);
|
|
858
880
|
const label = requireFlag(flags, 'label', undefined);
|
|
859
881
|
|
|
@@ -863,12 +885,14 @@ async function protocolArtifactFinalizeUpload(args) {
|
|
|
863
885
|
const body = {
|
|
864
886
|
sessionKey,
|
|
865
887
|
ticketId,
|
|
888
|
+
objectiveId,
|
|
866
889
|
storagePath,
|
|
867
890
|
label,
|
|
868
|
-
...(flags['artifact-type'] ? { artifactType: String(flags['artifact-type']) } : {}),
|
|
869
891
|
...(flags['content-type'] ? { contentType: String(flags['content-type']) } : {}),
|
|
870
892
|
...(flags['file-size'] ? { fileSize: parseInt(String(flags['file-size']), 10) } : {}),
|
|
871
|
-
...(flags['metadata-json']
|
|
893
|
+
...(flags['metadata-json']
|
|
894
|
+
? { metadata: parseJsonFlag('--metadata-json', flags['metadata-json']) }
|
|
895
|
+
: {})
|
|
872
896
|
};
|
|
873
897
|
|
|
874
898
|
const data = await apiPost(
|
|
@@ -876,20 +900,23 @@ async function protocolArtifactFinalizeUpload(args) {
|
|
|
876
900
|
bearerToken,
|
|
877
901
|
localSecret,
|
|
878
902
|
organizationId,
|
|
879
|
-
'/api/protocol/
|
|
903
|
+
'/api/protocol/attachments/finalize-upload',
|
|
880
904
|
body,
|
|
881
905
|
timeoutMs
|
|
882
906
|
);
|
|
883
907
|
console.log(JSON.stringify(data, null, 2));
|
|
884
908
|
}
|
|
885
909
|
|
|
886
|
-
async function
|
|
910
|
+
async function protocolAttachmentGetDownloadUrl(args) {
|
|
887
911
|
const flags = parseFlags(args);
|
|
888
912
|
const { sessionKey, ticketId } = resolveSessionFlags(flags);
|
|
889
913
|
if (!sessionKey) throw new Error('--session-key is required (or set SESSION_KEY)');
|
|
890
914
|
if (!ticketId) throw new Error('--ticket-id is required (or set TICKET_ID)');
|
|
891
|
-
if (!flags['
|
|
892
|
-
throw new Error('--
|
|
915
|
+
if (!flags['attachment-id'] && !flags['storage-path']) {
|
|
916
|
+
throw new Error('--attachment-id or --storage-path is required');
|
|
917
|
+
}
|
|
918
|
+
if (flags['storage-path'] && !flags['objective-id']) {
|
|
919
|
+
throw new Error('--objective-id is required when using --storage-path');
|
|
893
920
|
}
|
|
894
921
|
|
|
895
922
|
const { platformUrl, bearerToken, localSecret, organizationId } = await resolveAuth();
|
|
@@ -898,7 +925,8 @@ async function protocolArtifactGetDownloadUrl(args) {
|
|
|
898
925
|
const body = {
|
|
899
926
|
sessionKey,
|
|
900
927
|
ticketId,
|
|
901
|
-
...(flags['
|
|
928
|
+
...(flags['objective-id'] ? { objectiveId: String(flags['objective-id']) } : {}),
|
|
929
|
+
...(flags['attachment-id'] ? { attachmentId: String(flags['attachment-id']) } : {}),
|
|
902
930
|
...(flags['storage-path'] ? { storagePath: String(flags['storage-path']) } : {}),
|
|
903
931
|
...(flags['expires-in'] ? { expiresIn: parseInt(String(flags['expires-in']), 10) } : {})
|
|
904
932
|
};
|
|
@@ -908,18 +936,19 @@ async function protocolArtifactGetDownloadUrl(args) {
|
|
|
908
936
|
bearerToken,
|
|
909
937
|
localSecret,
|
|
910
938
|
organizationId,
|
|
911
|
-
'/api/protocol/
|
|
939
|
+
'/api/protocol/attachments/get-download-url',
|
|
912
940
|
body,
|
|
913
941
|
timeoutMs
|
|
914
942
|
);
|
|
915
943
|
console.log(JSON.stringify(data, null, 2));
|
|
916
944
|
}
|
|
917
945
|
|
|
918
|
-
async function
|
|
946
|
+
async function protocolAttachmentUploadFile(args) {
|
|
919
947
|
const flags = parseFlags(args);
|
|
920
948
|
const { sessionKey, ticketId } = resolveSessionFlags(flags);
|
|
921
949
|
if (!sessionKey) throw new Error('--session-key is required (or set SESSION_KEY)');
|
|
922
950
|
if (!ticketId) throw new Error('--ticket-id is required (or set TICKET_ID)');
|
|
951
|
+
const objectiveId = requireFlag(flags, 'objective-id', undefined);
|
|
923
952
|
const filePath = requireFlag(flags, 'file', undefined);
|
|
924
953
|
|
|
925
954
|
const { readFile, stat } = await import('node:fs/promises');
|
|
@@ -934,21 +963,25 @@ async function protocolArtifactUploadFile(args) {
|
|
|
934
963
|
const { platformUrl, bearerToken, localSecret, organizationId } = await resolveAuth();
|
|
935
964
|
const timeoutMs = resolveTimeout(flags);
|
|
936
965
|
|
|
966
|
+
const metadata = flags['metadata-json']
|
|
967
|
+
? parseJsonFlag('--metadata-json', flags['metadata-json'])
|
|
968
|
+
: undefined;
|
|
969
|
+
|
|
937
970
|
const prepared = await apiPost(
|
|
938
971
|
platformUrl,
|
|
939
972
|
bearerToken,
|
|
940
973
|
localSecret,
|
|
941
974
|
organizationId,
|
|
942
|
-
'/api/protocol/
|
|
975
|
+
'/api/protocol/attachments/prepare-upload',
|
|
943
976
|
{
|
|
944
977
|
sessionKey,
|
|
945
978
|
ticketId,
|
|
979
|
+
objectiveId,
|
|
946
980
|
fileName,
|
|
947
981
|
label,
|
|
948
|
-
artifactType: String(flags['artifact-type'] ?? 'document'),
|
|
949
982
|
contentType,
|
|
950
983
|
fileSize: fileStats.size,
|
|
951
|
-
...(
|
|
984
|
+
...(metadata ? { metadata } : {})
|
|
952
985
|
},
|
|
953
986
|
timeoutMs
|
|
954
987
|
);
|
|
@@ -966,16 +999,16 @@ async function protocolArtifactUploadFile(args) {
|
|
|
966
999
|
bearerToken,
|
|
967
1000
|
localSecret,
|
|
968
1001
|
organizationId,
|
|
969
|
-
'/api/protocol/
|
|
1002
|
+
'/api/protocol/attachments/finalize-upload',
|
|
970
1003
|
{
|
|
971
1004
|
sessionKey,
|
|
972
1005
|
ticketId,
|
|
1006
|
+
objectiveId,
|
|
973
1007
|
storagePath,
|
|
974
1008
|
label,
|
|
975
|
-
artifactType: String(flags['artifact-type'] ?? 'document'),
|
|
976
1009
|
contentType,
|
|
977
1010
|
fileSize: fileStats.size,
|
|
978
|
-
...(
|
|
1011
|
+
...(metadata ? { metadata } : {})
|
|
979
1012
|
},
|
|
980
1013
|
timeoutMs
|
|
981
1014
|
);
|
|
@@ -1098,12 +1131,18 @@ async function protocolPrompt(args) {
|
|
|
1098
1131
|
...(flags['project-id'] ? { projectId: String(flags['project-id']) } : {}),
|
|
1099
1132
|
...(personal ? { personal: true } : {}),
|
|
1100
1133
|
...(workingDirectory ? { workingDirectory: String(workingDirectory) } : {}),
|
|
1101
|
-
...(flags['acceptance-criteria']
|
|
1134
|
+
...(flags['acceptance-criteria']
|
|
1135
|
+
? { acceptanceCriteria: String(flags['acceptance-criteria']) }
|
|
1136
|
+
: {}),
|
|
1102
1137
|
...(flags['available-tools'] ? { availableTools: String(flags['available-tools']) } : {}),
|
|
1103
1138
|
...(flags['execution-target'] ? { executionTarget: String(flags['execution-target']) } : {}),
|
|
1104
1139
|
delegate: resolveProtocolTicketDelegate(flags, modelIdentifier, agentIdentifier),
|
|
1105
|
-
...(flags['parent-session-key']
|
|
1106
|
-
|
|
1140
|
+
...(flags['parent-session-key']
|
|
1141
|
+
? { parentSessionKey: String(flags['parent-session-key']) }
|
|
1142
|
+
: {}),
|
|
1143
|
+
...(flags['parent-ticket-id']
|
|
1144
|
+
? { parentTicketId: String(flags['parent-ticket-id'] ?? process.env.TICKET_ID ?? '') }
|
|
1145
|
+
: {})
|
|
1107
1146
|
};
|
|
1108
1147
|
|
|
1109
1148
|
const data = await apiPost(
|
|
@@ -1151,7 +1190,9 @@ async function protocolCreateTicket(args) {
|
|
|
1151
1190
|
objective,
|
|
1152
1191
|
...(flags.title ? { title: String(flags.title) } : {}),
|
|
1153
1192
|
...(flags.priority ? { priority: String(flags.priority) } : {}),
|
|
1154
|
-
...(flags['acceptance-criteria']
|
|
1193
|
+
...(flags['acceptance-criteria']
|
|
1194
|
+
? { acceptanceCriteria: String(flags['acceptance-criteria']) }
|
|
1195
|
+
: {}),
|
|
1155
1196
|
...(flags['available-tools'] ? { availableTools: String(flags['available-tools']) } : {}),
|
|
1156
1197
|
...(flags['execution-target'] ? { executionTarget: String(flags['execution-target']) } : {}),
|
|
1157
1198
|
delegate: resolveProtocolTicketDelegate(flags, modelIdentifier, agentIdentifier)
|
|
@@ -1189,7 +1230,9 @@ async function protocolCreateTicket(args) {
|
|
|
1189
1230
|
...(standaloneWorkingDirectory ? { workingDirectory: standaloneWorkingDirectory } : {}),
|
|
1190
1231
|
...(flags.title ? { title: String(flags.title) } : {}),
|
|
1191
1232
|
...(flags.priority ? { priority: String(flags.priority) } : {}),
|
|
1192
|
-
...(flags['acceptance-criteria']
|
|
1233
|
+
...(flags['acceptance-criteria']
|
|
1234
|
+
? { acceptanceCriteria: String(flags['acceptance-criteria']) }
|
|
1235
|
+
: {}),
|
|
1193
1236
|
...(flags['available-tools'] ? { availableTools: String(flags['available-tools']) } : {}),
|
|
1194
1237
|
...(flags['execution-target'] ? { executionTarget: String(flags['execution-target']) } : {}),
|
|
1195
1238
|
delegate: resolveProtocolTicketDelegate(flags, modelIdentifier, agentIdentifier)
|
|
@@ -1227,7 +1270,10 @@ async function protocolSearchTickets(args) {
|
|
|
1227
1270
|
...(flags.query ? { query: String(flags.query) } : {}),
|
|
1228
1271
|
...(statuses?.length ? { statuses } : {}),
|
|
1229
1272
|
...(flags['include-completed'] !== undefined
|
|
1230
|
-
? {
|
|
1273
|
+
? {
|
|
1274
|
+
includeCompleted:
|
|
1275
|
+
flags['include-completed'] !== false && flags['include-completed'] !== 'false'
|
|
1276
|
+
}
|
|
1231
1277
|
: {}),
|
|
1232
1278
|
...(flags.limit ? { limit: parseInt(String(flags.limit), 10) } : {}),
|
|
1233
1279
|
...(flags['project-id'] ? { projectId: String(flags['project-id']) } : {}),
|
|
@@ -1318,11 +1364,11 @@ Subcommands:
|
|
|
1318
1364
|
permission-request Notify Overlord that the agent is requesting tool permission
|
|
1319
1365
|
read-context Read shared persistent context for this ticket
|
|
1320
1366
|
write-context Write shared persistent context for future sessions
|
|
1321
|
-
deliver
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1367
|
+
deliver Finish work, send artifacts, and move the ticket to review
|
|
1368
|
+
attachment-prepare-upload Get a signed upload URL for an objective attachment
|
|
1369
|
+
attachment-finalize-upload Finalize an uploaded attachment row after storage upload
|
|
1370
|
+
attachment-download-url Get a signed download URL for an existing attachment
|
|
1371
|
+
attachment-upload-file Prepare, upload, and finalize a local file in one command
|
|
1326
1372
|
|
|
1327
1373
|
Environment fallback:
|
|
1328
1374
|
--session-key <- SESSION_KEY
|
|
@@ -1551,47 +1597,48 @@ create:
|
|
|
1551
1597
|
Standalone create auto-discovers the project from the current working directory unless --personal is set.
|
|
1552
1598
|
Follow-up create requires both --session-key and --ticket-id.
|
|
1553
1599
|
|
|
1554
|
-
|
|
1600
|
+
attachment-prepare-upload:
|
|
1555
1601
|
Required:
|
|
1556
1602
|
--session-key <key>
|
|
1557
1603
|
--ticket-id <id>
|
|
1604
|
+
--objective-id <id>
|
|
1558
1605
|
--file-name <name>
|
|
1559
1606
|
Optional:
|
|
1560
1607
|
--label <text>
|
|
1561
|
-
--artifact-type <type>
|
|
1562
1608
|
--content-type <mime>
|
|
1563
1609
|
--file-size <bytes>
|
|
1564
1610
|
--metadata-json <json>
|
|
1565
1611
|
|
|
1566
|
-
|
|
1612
|
+
attachment-finalize-upload:
|
|
1567
1613
|
Required:
|
|
1568
1614
|
--session-key <key>
|
|
1569
1615
|
--ticket-id <id>
|
|
1616
|
+
--objective-id <id>
|
|
1570
1617
|
--storage-path <path>
|
|
1571
1618
|
--label <text>
|
|
1572
1619
|
Optional:
|
|
1573
|
-
--artifact-type <type>
|
|
1574
1620
|
--content-type <mime>
|
|
1575
1621
|
--file-size <bytes>
|
|
1576
1622
|
--metadata-json <json>
|
|
1577
1623
|
|
|
1578
|
-
|
|
1624
|
+
attachment-download-url:
|
|
1579
1625
|
Required:
|
|
1580
1626
|
--session-key <key>
|
|
1581
1627
|
--ticket-id <id>
|
|
1582
|
-
one of: --
|
|
1628
|
+
one of: --attachment-id <id> | --storage-path <path>
|
|
1583
1629
|
Optional:
|
|
1630
|
+
--objective-id <id> Required when using --storage-path
|
|
1584
1631
|
--expires-in <seconds>
|
|
1585
1632
|
|
|
1586
|
-
|
|
1633
|
+
attachment-upload-file:
|
|
1587
1634
|
Required:
|
|
1588
1635
|
--session-key <key>
|
|
1589
1636
|
--ticket-id <id>
|
|
1637
|
+
--objective-id <id>
|
|
1590
1638
|
--file <path>
|
|
1591
1639
|
Optional:
|
|
1592
1640
|
--file-name <name> Defaults to basename of --file
|
|
1593
1641
|
--label <text> Defaults to file name
|
|
1594
|
-
--artifact-type <type> Defaults to document
|
|
1595
1642
|
--content-type <mime> Defaults to application/octet-stream
|
|
1596
1643
|
--metadata-json <json>
|
|
1597
1644
|
|
|
@@ -1614,9 +1661,9 @@ Examples:
|
|
|
1614
1661
|
ovld protocol ask --session-key <key> --ticket-id <id> --question-file ./question.txt
|
|
1615
1662
|
ovld protocol read-context --session-key <key> --ticket-id <id> --query arch --limit 5
|
|
1616
1663
|
ovld protocol write-context --session-key <key> --ticket-id <id> --key "arch" --value '"monorepo"' --tags repo,agent
|
|
1617
|
-
ovld protocol
|
|
1618
|
-
ovld protocol
|
|
1619
|
-
ovld protocol
|
|
1664
|
+
ovld protocol attachment-prepare-upload --session-key <key> --ticket-id <id> --objective-id <objective-id> --file-name spec.pdf --content-type application/pdf
|
|
1665
|
+
ovld protocol attachment-upload-file --session-key <key> --ticket-id <id> --objective-id <objective-id> --file ./spec.pdf
|
|
1666
|
+
ovld protocol attachment-download-url --session-key <key> --ticket-id <id> --attachment-id <attachment-id>
|
|
1620
1667
|
ovld protocol deliver --session-key <key> --ticket-id <id> --summary "Done"
|
|
1621
1668
|
ovld protocol deliver --session-key <key> --ticket-id <id> --summary "Done" --artifacts-file ./artifacts.json
|
|
1622
1669
|
ovld protocol deliver --session-key <key> --ticket-id <id> --payload-file ./deliver.json
|
|
@@ -1627,25 +1674,82 @@ Examples:
|
|
|
1627
1674
|
return;
|
|
1628
1675
|
}
|
|
1629
1676
|
|
|
1630
|
-
if (subcommand === 'discover-project') {
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
if (subcommand === '
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
if (subcommand === '
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
if (subcommand === '
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
if (subcommand === '
|
|
1647
|
-
|
|
1648
|
-
|
|
1677
|
+
if (subcommand === 'discover-project') {
|
|
1678
|
+
await protocolDiscoverProject(args);
|
|
1679
|
+
return;
|
|
1680
|
+
}
|
|
1681
|
+
if (subcommand === 'auth-status') {
|
|
1682
|
+
await protocolAuthStatus();
|
|
1683
|
+
return;
|
|
1684
|
+
}
|
|
1685
|
+
if (subcommand === 'attach') {
|
|
1686
|
+
await protocolAttach(args);
|
|
1687
|
+
return;
|
|
1688
|
+
}
|
|
1689
|
+
if (subcommand === 'connect') {
|
|
1690
|
+
await protocolConnect(args);
|
|
1691
|
+
return;
|
|
1692
|
+
}
|
|
1693
|
+
if (subcommand === 'load-context') {
|
|
1694
|
+
await protocolLoadContext(args);
|
|
1695
|
+
return;
|
|
1696
|
+
}
|
|
1697
|
+
if (subcommand === 'search-tickets') {
|
|
1698
|
+
await protocolSearchTickets(args);
|
|
1699
|
+
return;
|
|
1700
|
+
}
|
|
1701
|
+
if (subcommand === 'create' || subcommand === 'create-ticket') {
|
|
1702
|
+
await protocolCreateTicket(args);
|
|
1703
|
+
return;
|
|
1704
|
+
}
|
|
1705
|
+
if (subcommand === 'prompt' || subcommand === 'spawn') {
|
|
1706
|
+
await protocolPrompt(args);
|
|
1707
|
+
return;
|
|
1708
|
+
}
|
|
1709
|
+
if (subcommand === 'attachment-prepare-upload') {
|
|
1710
|
+
await protocolAttachmentPrepareUpload(args);
|
|
1711
|
+
return;
|
|
1712
|
+
}
|
|
1713
|
+
if (subcommand === 'attachment-finalize-upload') {
|
|
1714
|
+
await protocolAttachmentFinalizeUpload(args);
|
|
1715
|
+
return;
|
|
1716
|
+
}
|
|
1717
|
+
if (subcommand === 'attachment-download-url') {
|
|
1718
|
+
await protocolAttachmentGetDownloadUrl(args);
|
|
1719
|
+
return;
|
|
1720
|
+
}
|
|
1721
|
+
if (subcommand === 'attachment-upload-file') {
|
|
1722
|
+
await protocolAttachmentUploadFile(args);
|
|
1723
|
+
return;
|
|
1724
|
+
}
|
|
1725
|
+
if (subcommand === 'update') {
|
|
1726
|
+
await protocolUpdate(args);
|
|
1727
|
+
return;
|
|
1728
|
+
}
|
|
1729
|
+
if (subcommand === 'record-change-rationales') {
|
|
1730
|
+
await protocolRecordChangeRationales(args);
|
|
1731
|
+
return;
|
|
1732
|
+
}
|
|
1733
|
+
if (subcommand === 'ask') {
|
|
1734
|
+
await protocolAsk(args);
|
|
1735
|
+
return;
|
|
1736
|
+
}
|
|
1737
|
+
if (subcommand === 'permission-request') {
|
|
1738
|
+
await protocolPermissionRequest(args);
|
|
1739
|
+
return;
|
|
1740
|
+
}
|
|
1741
|
+
if (subcommand === 'read-context') {
|
|
1742
|
+
await protocolReadContext(args);
|
|
1743
|
+
return;
|
|
1744
|
+
}
|
|
1745
|
+
if (subcommand === 'write-context') {
|
|
1746
|
+
await protocolWriteContext(args);
|
|
1747
|
+
return;
|
|
1748
|
+
}
|
|
1749
|
+
if (subcommand === 'deliver') {
|
|
1750
|
+
await protocolDeliver(args);
|
|
1751
|
+
return;
|
|
1752
|
+
}
|
|
1649
1753
|
|
|
1650
1754
|
console.error(`Unknown protocol subcommand: ${subcommand}\n`);
|
|
1651
1755
|
console.log('Run: ovld protocol help');
|
package/bin/_cli/setup.mjs
CHANGED
|
@@ -130,7 +130,7 @@ ovld protocol prompt --agent claude-code --objective "Implement feature X" --pri
|
|
|
130
130
|
\`\`\`bash
|
|
131
131
|
ovld protocol read-context --session-key <sessionKey> --ticket-id $TICKET_ID
|
|
132
132
|
ovld protocol write-context --session-key <sessionKey> --ticket-id $TICKET_ID --key "key" --value '"json-value"'
|
|
133
|
-
ovld protocol
|
|
133
|
+
ovld protocol attachment-upload-file --session-key <sessionKey> --ticket-id $TICKET_ID --objective-id <objective-id> --file ./spec.pdf --content-type application/pdf
|
|
134
134
|
\`\`\`
|
|
135
135
|
|
|
136
136
|
## Rules
|
|
@@ -209,7 +209,7 @@ ovld protocol prompt --agent opencode --objective "Implement feature X" --priori
|
|
|
209
209
|
\`\`\`bash
|
|
210
210
|
ovld protocol read-context --session-key <sessionKey> --ticket-id $TICKET_ID
|
|
211
211
|
ovld protocol write-context --session-key <sessionKey> --ticket-id $TICKET_ID --key "key" --value '"json-value"'
|
|
212
|
-
ovld protocol
|
|
212
|
+
ovld protocol attachment-upload-file --session-key <sessionKey> --ticket-id $TICKET_ID --objective-id <objective-id> --file ./spec.pdf --content-type application/pdf
|
|
213
213
|
\`\`\`
|
|
214
214
|
|
|
215
215
|
## Rules
|
|
@@ -540,7 +540,11 @@ function currentContentHashForAgent(agent) {
|
|
|
540
540
|
return contentHashForDirectory(cursorSourcePluginDir());
|
|
541
541
|
}
|
|
542
542
|
if (agent === 'gemini') {
|
|
543
|
-
return contentHash(
|
|
543
|
+
return contentHash(
|
|
544
|
+
slashCommandFiles('gemini')
|
|
545
|
+
.map(file => file.content)
|
|
546
|
+
.join('\n')
|
|
547
|
+
);
|
|
544
548
|
}
|
|
545
549
|
if (agent === 'codex') return codexContentHash();
|
|
546
550
|
return contentHash(
|
|
@@ -796,7 +800,14 @@ function cursorPaths() {
|
|
|
796
800
|
const base = path.join(os.homedir(), '.cursor');
|
|
797
801
|
return {
|
|
798
802
|
pluginDir: path.join(base, 'plugins', 'local', 'overlord'),
|
|
799
|
-
pluginManifest: path.join(
|
|
803
|
+
pluginManifest: path.join(
|
|
804
|
+
base,
|
|
805
|
+
'plugins',
|
|
806
|
+
'local',
|
|
807
|
+
'overlord',
|
|
808
|
+
'.cursor-plugin',
|
|
809
|
+
'plugin.json'
|
|
810
|
+
),
|
|
800
811
|
rulesFile: path.join(base, 'rules', 'overlord-local.mdc'),
|
|
801
812
|
settingsFile: path.join(base, 'settings.json')
|
|
802
813
|
};
|
|
@@ -956,10 +967,7 @@ function installCursor() {
|
|
|
956
967
|
? existingSettings.permissions
|
|
957
968
|
: {};
|
|
958
969
|
const mergedAllow = Array.from(
|
|
959
|
-
new Set([
|
|
960
|
-
...asStringArray(permissions.allow),
|
|
961
|
-
'Shell(ovld protocol:*)'
|
|
962
|
-
])
|
|
970
|
+
new Set([...asStringArray(permissions.allow), 'Shell(ovld protocol:*)'])
|
|
963
971
|
);
|
|
964
972
|
writeJsonFile(paths.settingsFile, {
|
|
965
973
|
...existingSettings,
|
|
@@ -1327,7 +1335,7 @@ function installClaudePermissions(platformUrl) {
|
|
|
1327
1335
|
const entries = ['Bash(ovld protocol:*)'];
|
|
1328
1336
|
|
|
1329
1337
|
const existing = new Set(settings.permissions.allow);
|
|
1330
|
-
const toAdd = entries.filter(
|
|
1338
|
+
const toAdd = entries.filter(e => !existing.has(e));
|
|
1331
1339
|
|
|
1332
1340
|
if (toAdd.length === 0) {
|
|
1333
1341
|
console.log(' All required permissions already present. Nothing to do.\n');
|
|
@@ -1466,7 +1474,9 @@ export async function runSetupCommand(args) {
|
|
|
1466
1474
|
const selectedAgents = selectedLabels.map(label => label.split('-')[0].trim());
|
|
1467
1475
|
|
|
1468
1476
|
// Step 2: Install selected agents
|
|
1469
|
-
console.log(
|
|
1477
|
+
console.log(
|
|
1478
|
+
`\nPreparing Overlord agent plugins/connectors for: ${selectedAgents.join(', ')}...\n`
|
|
1479
|
+
);
|
|
1470
1480
|
|
|
1471
1481
|
const installedAgents = [];
|
|
1472
1482
|
for (const a of selectedAgents) {
|
|
@@ -1616,6 +1626,9 @@ export async function runDoctorCommand({ latestCliVersion = null } = {}) {
|
|
|
1616
1626
|
}
|
|
1617
1627
|
if (updateVersion) {
|
|
1618
1628
|
console.log();
|
|
1619
|
-
printCliUpdateNotice(updateVersion, {
|
|
1629
|
+
printCliUpdateNotice(updateVersion, {
|
|
1630
|
+
currentVersion: getCurrentCliVersion(),
|
|
1631
|
+
stream: process.stdout
|
|
1632
|
+
});
|
|
1620
1633
|
}
|
|
1621
1634
|
}
|
package/package.json
CHANGED
|
@@ -141,8 +141,8 @@ When in doubt, ask yourself: *can this be done entirely inside a terminal or bro
|
|
|
141
141
|
```bash
|
|
142
142
|
ovld protocol read-context --session-key <sessionKey> --ticket-id $TICKET_ID
|
|
143
143
|
ovld protocol write-context --session-key <sessionKey> --ticket-id $TICKET_ID --key "key" --value '"json-value"'
|
|
144
|
-
ovld protocol
|
|
145
|
-
ovld protocol
|
|
144
|
+
ovld protocol attachment-upload-file --session-key <sessionKey> --ticket-id $TICKET_ID --objective-id <objective-id> --file ./spec.pdf --content-type application/pdf
|
|
145
|
+
ovld protocol attachment-download-url --session-key <sessionKey> --ticket-id $TICKET_ID --attachment-id <attachment-id>
|
|
146
146
|
```
|
|
147
147
|
|
|
148
148
|
## Rules
|
|
@@ -158,4 +158,4 @@ ovld protocol artifact-download-url --session-key <sessionKey> --ticket-id $TICK
|
|
|
158
158
|
- Do not add or commit changes unless the user explicitly asks you to commit.
|
|
159
159
|
- Delivery is the concluding step. After delivering, stop unless the user follows up or the ticket is reopened.
|
|
160
160
|
|
|
161
|
-
<!-- version: 0.2.
|
|
161
|
+
<!-- version: 0.2.6 -->
|
|
@@ -25,7 +25,7 @@ personal marketplace entry at `~/.agents/plugins/marketplace.json`.
|
|
|
25
25
|
- Ticket session flow: `attach_ticket`, `connect_ticket`, `load_ticket_context`, `spawn_ticket`
|
|
26
26
|
- Progress and review flow: `post_update`, `record_change_rationales`, `ask_blocking_question`, `deliver_ticket`
|
|
27
27
|
- Shared context: `read_shared_context`, `write_shared_context`
|
|
28
|
-
-
|
|
28
|
+
- Objective attachments: `prepare_attachment_upload`, `finalize_attachment_upload`, `get_attachment_download_url`, `upload_attachment_file`
|
|
29
29
|
|
|
30
30
|
The MCP server shells into the installed `ovld` binary so the plugin stays aligned with the shipped CLI behavior instead of depending on this repository checkout.
|
|
31
31
|
|
|
@@ -296,72 +296,73 @@ const tools = [
|
|
|
296
296
|
subcommand: 'deliver'
|
|
297
297
|
},
|
|
298
298
|
{
|
|
299
|
-
name: '
|
|
300
|
-
description: 'Prepare an
|
|
299
|
+
name: 'prepare_attachment_upload',
|
|
300
|
+
description: 'Prepare an objective attachment upload and return a signed upload URL.',
|
|
301
301
|
inputSchema: {
|
|
302
302
|
type: 'object',
|
|
303
303
|
properties: {
|
|
304
304
|
session_key: { type: 'string' },
|
|
305
305
|
ticket_id: { type: 'string' },
|
|
306
|
+
objective_id: { type: 'string' },
|
|
306
307
|
file_name: { type: 'string' },
|
|
307
308
|
label: { type: 'string' },
|
|
308
|
-
artifact_type: { type: 'string' },
|
|
309
309
|
content_type: { type: 'string' },
|
|
310
310
|
file_size: { type: 'number' },
|
|
311
311
|
metadata: { type: 'object' }
|
|
312
312
|
},
|
|
313
|
-
required: ['session_key', 'ticket_id', 'file_name']
|
|
313
|
+
required: ['session_key', 'ticket_id', 'objective_id', 'file_name']
|
|
314
314
|
},
|
|
315
315
|
toCliFlags: args => ({
|
|
316
316
|
'session-key': args.session_key,
|
|
317
317
|
'ticket-id': args.ticket_id,
|
|
318
|
+
'objective-id': args.objective_id,
|
|
318
319
|
'file-name': args.file_name,
|
|
319
320
|
label: args.label,
|
|
320
|
-
'artifact-type': args.artifact_type,
|
|
321
321
|
'content-type': args.content_type,
|
|
322
322
|
'file-size': args.file_size,
|
|
323
323
|
'metadata-json': args.metadata
|
|
324
324
|
}),
|
|
325
|
-
subcommand: '
|
|
325
|
+
subcommand: 'attachment-prepare-upload'
|
|
326
326
|
},
|
|
327
327
|
{
|
|
328
|
-
name: '
|
|
329
|
-
description: 'Finalize an
|
|
328
|
+
name: 'finalize_attachment_upload',
|
|
329
|
+
description: 'Finalize an objective attachment after uploading bytes to the signed storage URL.',
|
|
330
330
|
inputSchema: {
|
|
331
331
|
type: 'object',
|
|
332
332
|
properties: {
|
|
333
333
|
session_key: { type: 'string' },
|
|
334
334
|
ticket_id: { type: 'string' },
|
|
335
|
+
objective_id: { type: 'string' },
|
|
335
336
|
storage_path: { type: 'string' },
|
|
336
337
|
label: { type: 'string' },
|
|
337
|
-
artifact_type: { type: 'string' },
|
|
338
338
|
content_type: { type: 'string' },
|
|
339
339
|
file_size: { type: 'number' },
|
|
340
340
|
metadata: { type: 'object' }
|
|
341
341
|
},
|
|
342
|
-
required: ['session_key', 'ticket_id', 'storage_path', 'label']
|
|
342
|
+
required: ['session_key', 'ticket_id', 'objective_id', 'storage_path', 'label']
|
|
343
343
|
},
|
|
344
344
|
toCliFlags: args => ({
|
|
345
345
|
'session-key': args.session_key,
|
|
346
346
|
'ticket-id': args.ticket_id,
|
|
347
|
+
'objective-id': args.objective_id,
|
|
347
348
|
'storage-path': args.storage_path,
|
|
348
349
|
label: args.label,
|
|
349
|
-
'artifact-type': args.artifact_type,
|
|
350
350
|
'content-type': args.content_type,
|
|
351
351
|
'file-size': args.file_size,
|
|
352
352
|
'metadata-json': args.metadata
|
|
353
353
|
}),
|
|
354
|
-
subcommand: '
|
|
354
|
+
subcommand: 'attachment-finalize-upload'
|
|
355
355
|
},
|
|
356
356
|
{
|
|
357
|
-
name: '
|
|
358
|
-
description: 'Create a signed download URL for an uploaded
|
|
357
|
+
name: 'get_attachment_download_url',
|
|
358
|
+
description: 'Create a signed download URL for an uploaded objective attachment.',
|
|
359
359
|
inputSchema: {
|
|
360
360
|
type: 'object',
|
|
361
361
|
properties: {
|
|
362
362
|
session_key: { type: 'string' },
|
|
363
363
|
ticket_id: { type: 'string' },
|
|
364
|
-
|
|
364
|
+
objective_id: { type: 'string' },
|
|
365
|
+
attachment_id: { type: 'string' },
|
|
365
366
|
storage_path: { type: 'string' },
|
|
366
367
|
expires_in: { type: 'number' }
|
|
367
368
|
},
|
|
@@ -370,40 +371,41 @@ const tools = [
|
|
|
370
371
|
toCliFlags: args => ({
|
|
371
372
|
'session-key': args.session_key,
|
|
372
373
|
'ticket-id': args.ticket_id,
|
|
373
|
-
'
|
|
374
|
+
'objective-id': args.objective_id,
|
|
375
|
+
'attachment-id': args.attachment_id,
|
|
374
376
|
'storage-path': args.storage_path,
|
|
375
377
|
'expires-in': args.expires_in
|
|
376
378
|
}),
|
|
377
|
-
subcommand: '
|
|
379
|
+
subcommand: 'attachment-download-url'
|
|
378
380
|
},
|
|
379
381
|
{
|
|
380
|
-
name: '
|
|
381
|
-
description: 'Prepare, upload, and finalize a local file as an
|
|
382
|
+
name: 'upload_attachment_file',
|
|
383
|
+
description: 'Prepare, upload, and finalize a local file as an objective attachment in one step.',
|
|
382
384
|
inputSchema: {
|
|
383
385
|
type: 'object',
|
|
384
386
|
properties: {
|
|
385
387
|
session_key: { type: 'string' },
|
|
386
388
|
ticket_id: { type: 'string' },
|
|
389
|
+
objective_id: { type: 'string' },
|
|
387
390
|
file: { type: 'string' },
|
|
388
391
|
file_name: { type: 'string' },
|
|
389
392
|
label: { type: 'string' },
|
|
390
|
-
artifact_type: { type: 'string' },
|
|
391
393
|
content_type: { type: 'string' },
|
|
392
394
|
metadata: { type: 'object' }
|
|
393
395
|
},
|
|
394
|
-
required: ['session_key', 'ticket_id', 'file']
|
|
396
|
+
required: ['session_key', 'ticket_id', 'objective_id', 'file']
|
|
395
397
|
},
|
|
396
398
|
toCliFlags: args => ({
|
|
397
399
|
'session-key': args.session_key,
|
|
398
400
|
'ticket-id': args.ticket_id,
|
|
401
|
+
'objective-id': args.objective_id,
|
|
399
402
|
file: args.file,
|
|
400
403
|
'file-name': args.file_name,
|
|
401
404
|
label: args.label,
|
|
402
|
-
'artifact-type': args.artifact_type,
|
|
403
405
|
'content-type': args.content_type,
|
|
404
406
|
'metadata-json': args.metadata
|
|
405
407
|
}),
|
|
406
|
-
subcommand: '
|
|
408
|
+
subcommand: 'attachment-upload-file'
|
|
407
409
|
}
|
|
408
410
|
];
|
|
409
411
|
|
|
@@ -610,7 +612,7 @@ async function handleRequest(message) {
|
|
|
610
612
|
},
|
|
611
613
|
serverInfo: {
|
|
612
614
|
name: 'overlord',
|
|
613
|
-
version: '0.
|
|
615
|
+
version: '0.2.1'
|
|
614
616
|
},
|
|
615
617
|
instructions:
|
|
616
618
|
'Use these tools to drive Overlord ticket workflows through the installed ovld CLI. Most operations expect a session key from attach or connect. If the CLI reports that OVERLORD_URL is unreachable, request permission escalation or network access before retrying.'
|
|
@@ -102,8 +102,8 @@ Record only meaningful behavioral changes. Skip formatting-only noise. Prefer 1-
|
|
|
102
102
|
```bash
|
|
103
103
|
ovld protocol read-context --session-key <sessionKey> --ticket-id $TICKET_ID
|
|
104
104
|
ovld protocol write-context --session-key <sessionKey> --ticket-id $TICKET_ID --key "key" --value '"json-value"'
|
|
105
|
-
ovld protocol
|
|
106
|
-
ovld protocol
|
|
105
|
+
ovld protocol attachment-upload-file --session-key <sessionKey> --ticket-id $TICKET_ID --objective-id <objective-id> --file ./spec.pdf --content-type application/pdf
|
|
106
|
+
ovld protocol attachment-download-url --session-key <sessionKey> --ticket-id $TICKET_ID --attachment-id <attachment-id>
|
|
107
107
|
```
|
|
108
108
|
|
|
109
109
|
## Project Discovery And Ticket Creation
|
|
@@ -140,4 +140,4 @@ When in doubt, ask yourself: *can this be done entirely inside a terminal or bro
|
|
|
140
140
|
- When the ticket was launched by Overlord, the ticket prompt remains authoritative for the specific task objective and ticket-level constraints.
|
|
141
141
|
- If a protocol or MCP call fails with auth/session errors, run `ovld auth repair` yourself before asking the user to log in again or proceed without Overlord updates.
|
|
142
142
|
|
|
143
|
-
<!-- version: 0.2.
|
|
143
|
+
<!-- version: 0.2.5 -->
|