opencode-magi 0.0.0-dev-20260519144738 → 0.0.0-dev-20260520030110
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/dist/commands.js +4 -0
- package/dist/config/output.js +11 -2
- package/dist/config/resolve.js +59 -0
- package/dist/config/validate.js +226 -2
- package/dist/config/worktree.js +8 -2
- package/dist/github/commands.js +93 -0
- package/dist/index.js +67 -0
- package/dist/orchestrator/majority.js +14 -0
- package/dist/orchestrator/triage.js +420 -0
- package/dist/prompts/compose.js +82 -1
- package/dist/prompts/contracts.js +48 -0
- package/dist/prompts/output.js +68 -0
- package/dist/prompts/templates/triage/action.md +5 -0
- package/dist/prompts/templates/triage/bug.md +7 -0
- package/dist/prompts/templates/triage/comment-classification.md +7 -0
- package/dist/prompts/templates/triage/comment.md +5 -0
- package/dist/prompts/templates/triage/create-pr.md +7 -0
- package/dist/prompts/templates/triage/duplicate.md +7 -0
- package/dist/prompts/templates/triage/existing-pr.md +7 -0
- package/dist/prompts/templates/triage/feature.md +7 -0
- package/dist/prompts/templates/triage/kind.md +7 -0
- package/dist/prompts/templates/triage/question.md +5 -0
- package/dist/prompts/templates/triage/reconsider.md +5 -0
- package/package.json +1 -1
- package/schema.json +122 -1
|
@@ -171,6 +171,48 @@ Rules:
|
|
|
171
171
|
- SCOPE_OUT means the failure is likely flaky, external, or infrastructure-related and may be rerun.
|
|
172
172
|
- If uncertain, choose SCOPE_IN.
|
|
173
173
|
</output_contract>`.trim();
|
|
174
|
+
export function triageVoteOutputContract(votes) {
|
|
175
|
+
return `
|
|
176
|
+
<output_contract>
|
|
177
|
+
Return exactly one JSON object and nothing else. Do not wrap it in markdown.
|
|
178
|
+
|
|
179
|
+
The object must match this shape:
|
|
180
|
+
{
|
|
181
|
+
"vote": ${votes},
|
|
182
|
+
"reason": "Short rationale."
|
|
183
|
+
}
|
|
184
|
+
</output_contract>`.trim();
|
|
185
|
+
}
|
|
186
|
+
export const triageDuplicateOutputContract = `
|
|
187
|
+
<output_contract>
|
|
188
|
+
Return exactly one JSON object and nothing else. Do not wrap it in markdown.
|
|
189
|
+
|
|
190
|
+
The object must match this shape:
|
|
191
|
+
{
|
|
192
|
+
"vote": "DUPLICATE" | "NOT_DUPLICATE",
|
|
193
|
+
"duplicateOf": 123,
|
|
194
|
+
"reason": "Short rationale."
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
Rules:
|
|
198
|
+
- duplicateOf is required only when vote is DUPLICATE.
|
|
199
|
+
- duplicateOf must be one of the provided duplicate candidate issue numbers.
|
|
200
|
+
</output_contract>`.trim();
|
|
201
|
+
export const triageCommentClassificationOutputContract = `
|
|
202
|
+
<output_contract>
|
|
203
|
+
Return exactly one JSON object and nothing else. Do not wrap it in markdown.
|
|
204
|
+
|
|
205
|
+
The object must match this shape:
|
|
206
|
+
{
|
|
207
|
+
"comments": [
|
|
208
|
+
{
|
|
209
|
+
"commentId": 123,
|
|
210
|
+
"classification": "OBJECTION" | "NEW_EVIDENCE" | "CLARIFICATION" | "ACKNOWLEDGEMENT" | "UNRELATED",
|
|
211
|
+
"reason": "Short rationale."
|
|
212
|
+
}
|
|
213
|
+
]
|
|
214
|
+
}
|
|
215
|
+
</output_contract>`.trim();
|
|
174
216
|
const outputContractsBySchemaName = {
|
|
175
217
|
"CI classification": ciClassificationOutputContract,
|
|
176
218
|
"close reconsideration": closeReconsiderationOutputContract,
|
|
@@ -179,6 +221,12 @@ const outputContractsBySchemaName = {
|
|
|
179
221
|
rereview: rereviewOutputContract,
|
|
180
222
|
"rereview close reconsideration": rereviewCloseReconsiderationOutputContract,
|
|
181
223
|
review: reviewOutputContract,
|
|
224
|
+
"triage bug": triageVoteOutputContract('"YES" | "NO" | "ASK"'),
|
|
225
|
+
"triage comment classification": triageCommentClassificationOutputContract,
|
|
226
|
+
"triage duplicate": triageDuplicateOutputContract,
|
|
227
|
+
"triage existing PR": triageVoteOutputContract('"RELATED_PR_HANDLES_ISSUE" | "RELATED_PR_DOES_NOT_HANDLE_ISSUE"'),
|
|
228
|
+
"triage feature": triageVoteOutputContract('"YES" | "NO" | "ASK"'),
|
|
229
|
+
"triage kind": triageVoteOutputContract('"BUG" | "FEATURE" | "ASK"'),
|
|
182
230
|
};
|
|
183
231
|
export function repairPrompt(schemaName) {
|
|
184
232
|
const outputContract = outputContractsBySchemaName[schemaName];
|
package/dist/prompts/output.js
CHANGED
|
@@ -71,6 +71,74 @@ function requireNumber(value, path) {
|
|
|
71
71
|
throw new Error(`${path} must be an integer`);
|
|
72
72
|
return value;
|
|
73
73
|
}
|
|
74
|
+
function requireOneOf(value, path, values) {
|
|
75
|
+
const text = requireString(value, path);
|
|
76
|
+
if (!values.includes(text)) {
|
|
77
|
+
throw new Error(`${path} must be ${values.join(", ")}`);
|
|
78
|
+
}
|
|
79
|
+
return text;
|
|
80
|
+
}
|
|
81
|
+
function parseTriageVote(text, votes) {
|
|
82
|
+
const data = extractJson(text);
|
|
83
|
+
if (!data || typeof data !== "object")
|
|
84
|
+
throw new Error("triage vote output must be an object");
|
|
85
|
+
return {
|
|
86
|
+
reason: requireString(data.reason, "reason"),
|
|
87
|
+
vote: requireOneOf(data.vote, "vote", votes),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
export function parseTriageExistingPrOutput(text) {
|
|
91
|
+
return parseTriageVote(text, [
|
|
92
|
+
"RELATED_PR_DOES_NOT_HANDLE_ISSUE",
|
|
93
|
+
"RELATED_PR_HANDLES_ISSUE",
|
|
94
|
+
]);
|
|
95
|
+
}
|
|
96
|
+
export function parseTriageKindOutput(text) {
|
|
97
|
+
return parseTriageVote(text, ["ASK", "BUG", "FEATURE"]);
|
|
98
|
+
}
|
|
99
|
+
export function parseTriageBinaryOutput(text) {
|
|
100
|
+
return parseTriageVote(text, ["ASK", "NO", "YES"]);
|
|
101
|
+
}
|
|
102
|
+
export function parseTriageDuplicateOutput(text) {
|
|
103
|
+
const data = extractJson(text);
|
|
104
|
+
if (!data || typeof data !== "object")
|
|
105
|
+
throw new Error("triage duplicate output must be an object");
|
|
106
|
+
const vote = requireOneOf(data.vote, "vote", [
|
|
107
|
+
"DUPLICATE",
|
|
108
|
+
"NOT_DUPLICATE",
|
|
109
|
+
]);
|
|
110
|
+
const duplicateOf = data.duplicateOf == null
|
|
111
|
+
? undefined
|
|
112
|
+
: requireNumber(data.duplicateOf, "duplicateOf");
|
|
113
|
+
if (vote === "DUPLICATE" && duplicateOf == null)
|
|
114
|
+
throw new Error("DUPLICATE requires duplicateOf");
|
|
115
|
+
return {
|
|
116
|
+
duplicateOf,
|
|
117
|
+
reason: requireString(data.reason, "reason"),
|
|
118
|
+
vote,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
export function parseTriageCommentClassificationOutput(text) {
|
|
122
|
+
const data = extractJson(text);
|
|
123
|
+
if (!data || typeof data !== "object")
|
|
124
|
+
throw new Error("triage comment classification output must be an object");
|
|
125
|
+
return {
|
|
126
|
+
comments: requireArray(data.comments, "comments").map((item, index) => {
|
|
127
|
+
const value = item;
|
|
128
|
+
return {
|
|
129
|
+
classification: requireOneOf(value.classification, `comments[${index}].classification`, [
|
|
130
|
+
"ACKNOWLEDGEMENT",
|
|
131
|
+
"CLARIFICATION",
|
|
132
|
+
"NEW_EVIDENCE",
|
|
133
|
+
"OBJECTION",
|
|
134
|
+
"UNRELATED",
|
|
135
|
+
]),
|
|
136
|
+
commentId: requireNumber(value.commentId, `comments[${index}].commentId`),
|
|
137
|
+
reason: requireString(value.reason, `comments[${index}].reason`),
|
|
138
|
+
};
|
|
139
|
+
}),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
74
142
|
export function parseReviewOutput(text) {
|
|
75
143
|
const data = extractJson(text);
|
|
76
144
|
if (!data || typeof data !== "object")
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Evaluate bug issue #{issue} in {owner}/{repo}.
|
|
2
|
+
|
|
3
|
+
Choose YES when the bug is reproduced or otherwise valid based on strong evidence. Choose NO when it is not reproduced, invalid, a misunderstanding, or not actionable as a bug. Choose ASK when specific missing information is required.
|
|
4
|
+
|
|
5
|
+
<context>
|
|
6
|
+
{context}
|
|
7
|
+
</context>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Classify allowed mention replies for issue #{issue} in {owner}/{repo}.
|
|
2
|
+
|
|
3
|
+
Use OBJECTION for disagreement or reconsideration requests. Use NEW_EVIDENCE for new logs, reproduction steps, screenshots, links, or use cases. Use CLARIFICATION for answers to questions or ambiguity reduction. Use ACKNOWLEDGEMENT for acceptance or thanks. Use UNRELATED for unrelated content.
|
|
4
|
+
|
|
5
|
+
<context>
|
|
6
|
+
{context}
|
|
7
|
+
</context>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Decide whether issue #{issue} in {owner}/{repo} duplicates one of the provided duplicate candidates.
|
|
2
|
+
|
|
3
|
+
Use only the provided context. Return DUPLICATE only when the target issue is clearly the same underlying report or request.
|
|
4
|
+
|
|
5
|
+
<context>
|
|
6
|
+
{context}
|
|
7
|
+
</context>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-magi",
|
|
3
|
-
"version": "0.0.0-dev-
|
|
3
|
+
"version": "0.0.0-dev-20260520030110",
|
|
4
4
|
"description": "Multi-agent PR review and merge orchestration plugin for OpenCode.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Hirotomo Yamada <hirotomo.yamada@avap.co.jp>",
|
package/schema.json
CHANGED
|
@@ -47,7 +47,8 @@
|
|
|
47
47
|
"repairAttempts": { "type": "integer", "minimum": 0, "default": 3 }
|
|
48
48
|
}
|
|
49
49
|
},
|
|
50
|
-
"review": { "$ref": "#/$defs/review" }
|
|
50
|
+
"review": { "$ref": "#/$defs/review" },
|
|
51
|
+
"triage": { "$ref": "#/$defs/triage" }
|
|
51
52
|
},
|
|
52
53
|
"$defs": {
|
|
53
54
|
"reviewer": {
|
|
@@ -84,6 +85,39 @@
|
|
|
84
85
|
"persona": { "type": "string" }
|
|
85
86
|
}
|
|
86
87
|
},
|
|
88
|
+
"triageAgent": {
|
|
89
|
+
"type": "object",
|
|
90
|
+
"required": ["model"],
|
|
91
|
+
"additionalProperties": false,
|
|
92
|
+
"properties": {
|
|
93
|
+
"id": { "type": "string", "pattern": "^[A-Za-z0-9_-]+$" },
|
|
94
|
+
"model": { "type": "string", "minLength": 1 },
|
|
95
|
+
"options": { "type": "object", "additionalProperties": true },
|
|
96
|
+
"permissions": { "$ref": "#/$defs/permissions" },
|
|
97
|
+
"persona": { "type": "string" }
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
"triageCreator": {
|
|
101
|
+
"type": "object",
|
|
102
|
+
"required": ["model", "author"],
|
|
103
|
+
"additionalProperties": false,
|
|
104
|
+
"properties": {
|
|
105
|
+
"account": { "type": "string", "minLength": 1 },
|
|
106
|
+
"model": { "type": "string", "minLength": 1 },
|
|
107
|
+
"options": { "type": "object", "additionalProperties": true },
|
|
108
|
+
"author": {
|
|
109
|
+
"type": "object",
|
|
110
|
+
"required": ["name", "email"],
|
|
111
|
+
"additionalProperties": false,
|
|
112
|
+
"properties": {
|
|
113
|
+
"name": { "type": "string", "minLength": 1 },
|
|
114
|
+
"email": { "type": "string", "minLength": 1 }
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
"permissions": { "$ref": "#/$defs/permissions" },
|
|
118
|
+
"persona": { "type": "string" }
|
|
119
|
+
}
|
|
120
|
+
},
|
|
87
121
|
"automation": {
|
|
88
122
|
"type": "object",
|
|
89
123
|
"additionalProperties": false,
|
|
@@ -116,6 +150,13 @@
|
|
|
116
150
|
"reviewers": { "type": "integer", "minimum": 1, "default": 3 }
|
|
117
151
|
}
|
|
118
152
|
},
|
|
153
|
+
"triageConcurrency": {
|
|
154
|
+
"type": "object",
|
|
155
|
+
"additionalProperties": false,
|
|
156
|
+
"properties": {
|
|
157
|
+
"runs": { "type": "integer", "minimum": 1, "default": 3 }
|
|
158
|
+
}
|
|
159
|
+
},
|
|
119
160
|
"safety": {
|
|
120
161
|
"type": "object",
|
|
121
162
|
"additionalProperties": false,
|
|
@@ -147,6 +188,66 @@
|
|
|
147
188
|
"ciClassification": { "type": "string" }
|
|
148
189
|
}
|
|
149
190
|
},
|
|
191
|
+
"triagePrompts": {
|
|
192
|
+
"type": "object",
|
|
193
|
+
"additionalProperties": false,
|
|
194
|
+
"properties": {
|
|
195
|
+
"existingPr": { "type": "string" },
|
|
196
|
+
"duplicate": { "type": "string" },
|
|
197
|
+
"kind": { "type": "string" },
|
|
198
|
+
"bug": { "type": "string" },
|
|
199
|
+
"feature": { "type": "string" },
|
|
200
|
+
"action": { "type": "string" },
|
|
201
|
+
"question": { "type": "string" },
|
|
202
|
+
"comment": { "type": "string" },
|
|
203
|
+
"commentClassification": { "type": "string" },
|
|
204
|
+
"reconsider": { "type": "string" },
|
|
205
|
+
"createPr": { "type": "string" }
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
"triageKindRule": {
|
|
209
|
+
"type": "object",
|
|
210
|
+
"additionalProperties": false,
|
|
211
|
+
"properties": {
|
|
212
|
+
"label": { "type": "array", "items": { "type": "string" } },
|
|
213
|
+
"type": { "type": "array", "items": { "type": "string" } }
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
"triageKind": {
|
|
217
|
+
"type": "object",
|
|
218
|
+
"additionalProperties": false,
|
|
219
|
+
"properties": {
|
|
220
|
+
"bug": { "$ref": "#/$defs/triageKindRule" },
|
|
221
|
+
"feature": { "$ref": "#/$defs/triageKindRule" }
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
"triageAutomation": {
|
|
225
|
+
"type": "object",
|
|
226
|
+
"additionalProperties": false,
|
|
227
|
+
"properties": {
|
|
228
|
+
"close": { "type": "boolean", "default": false },
|
|
229
|
+
"pr": { "type": "boolean", "default": false },
|
|
230
|
+
"clear": {
|
|
231
|
+
"type": "array",
|
|
232
|
+
"items": { "type": "string" },
|
|
233
|
+
"default": ["triage"]
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
"triageSafety": {
|
|
238
|
+
"type": "object",
|
|
239
|
+
"additionalProperties": false,
|
|
240
|
+
"properties": {
|
|
241
|
+
"requiredLabels": { "type": "array", "items": { "type": "string" } },
|
|
242
|
+
"blockedLabels": { "type": "array", "items": { "type": "string" } },
|
|
243
|
+
"allowAuthors": { "type": "array", "items": { "type": "string" } },
|
|
244
|
+
"allowMentionActors": {
|
|
245
|
+
"type": "array",
|
|
246
|
+
"items": { "type": "string" }
|
|
247
|
+
},
|
|
248
|
+
"allowMentionRoles": { "type": "array", "items": { "type": "string" } }
|
|
249
|
+
}
|
|
250
|
+
},
|
|
150
251
|
"reviewMerge": {
|
|
151
252
|
"type": "object",
|
|
152
253
|
"additionalProperties": false,
|
|
@@ -196,6 +297,26 @@
|
|
|
196
297
|
}
|
|
197
298
|
}
|
|
198
299
|
},
|
|
300
|
+
"triage": {
|
|
301
|
+
"type": "object",
|
|
302
|
+
"additionalProperties": false,
|
|
303
|
+
"properties": {
|
|
304
|
+
"account": { "type": "string", "minLength": 1 },
|
|
305
|
+
"agents": {
|
|
306
|
+
"type": "array",
|
|
307
|
+
"minItems": 3,
|
|
308
|
+
"items": { "$ref": "#/$defs/triageAgent" }
|
|
309
|
+
},
|
|
310
|
+
"creator": { "$ref": "#/$defs/triageCreator" },
|
|
311
|
+
"kind": { "$ref": "#/$defs/triageKind" },
|
|
312
|
+
"automation": { "$ref": "#/$defs/triageAutomation" },
|
|
313
|
+
"safety": { "$ref": "#/$defs/triageSafety" },
|
|
314
|
+
"concurrency": { "$ref": "#/$defs/triageConcurrency" },
|
|
315
|
+
"prompts": { "$ref": "#/$defs/triagePrompts" },
|
|
316
|
+
"output": { "type": "string" },
|
|
317
|
+
"worktree": { "type": "string" }
|
|
318
|
+
}
|
|
319
|
+
},
|
|
199
320
|
"permissionAction": { "enum": ["allow", "ask", "deny"] },
|
|
200
321
|
"permissionRule": {
|
|
201
322
|
"oneOf": [
|