opencode-magi 0.0.0-dev-20260721055255 → 0.0.0-dev-20260722060754
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/dist/magi.js +61 -19
- package/dist/tools/merge/editor.js +10 -2
- package/dist/tools/review/action.js +5 -1
- package/dist/tools/review/check.js +5 -1
- package/dist/tools/review/reviewer.js +15 -3
- package/package.json +1 -1
package/dist/magi.js
CHANGED
|
@@ -217,27 +217,69 @@ export class Magi {
|
|
|
217
217
|
}
|
|
218
218
|
}
|
|
219
219
|
async promptSession(sessionID, text, signal) {
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
220
|
+
const controller = new AbortController();
|
|
221
|
+
const events = await this.input.client.event.subscribe(undefined, {
|
|
222
|
+
signal: controller.signal,
|
|
223
|
+
});
|
|
224
|
+
try {
|
|
225
|
+
const result = await Promise.race([
|
|
226
|
+
this.input.client.session.prompt({
|
|
227
|
+
parts: [{ text, type: "text" }],
|
|
228
|
+
sessionID,
|
|
229
|
+
}, { signal }),
|
|
230
|
+
this.monitorSession(sessionID, events.stream),
|
|
231
|
+
]);
|
|
232
|
+
if (result.error) {
|
|
233
|
+
if (!isUndefined(result.response) && result.response.statusText)
|
|
234
|
+
throw new Error(result.response.statusText);
|
|
235
|
+
else if (result.error instanceof Error)
|
|
236
|
+
throw new Error(result.error.message);
|
|
237
|
+
else
|
|
238
|
+
throw new Error(JSON.stringify(result.error));
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
const output = result.data.parts
|
|
242
|
+
.filter((part) => part.type === "text")
|
|
243
|
+
.map((part) => part.text)
|
|
244
|
+
.join("\n");
|
|
245
|
+
if (!output)
|
|
246
|
+
throw new Error("OpenCode session.prompt did not return text output.");
|
|
247
|
+
return output;
|
|
248
|
+
}
|
|
231
249
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
.
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
250
|
+
catch (e) {
|
|
251
|
+
if (e instanceof MagiError)
|
|
252
|
+
await this.input.client.session.abort({ sessionID });
|
|
253
|
+
throw e;
|
|
254
|
+
}
|
|
255
|
+
finally {
|
|
256
|
+
controller.abort();
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
async monitorSession(sessionID, events) {
|
|
260
|
+
for await (const ev of events) {
|
|
261
|
+
if (ev.type === "permission.asked" &&
|
|
262
|
+
ev.properties.sessionID === sessionID) {
|
|
263
|
+
const { id, patterns, permission } = ev.properties;
|
|
264
|
+
const result = await this.input.client.permission.reply({
|
|
265
|
+
reply: "reject",
|
|
266
|
+
requestID: id,
|
|
267
|
+
});
|
|
268
|
+
if (result.error)
|
|
269
|
+
throw new MagiError("blocked", "Could not reject permission request.");
|
|
270
|
+
throw new MagiError("blocked", `OpenCode session requested ${permission} permission for ${patterns.join(", ")}.`);
|
|
271
|
+
}
|
|
272
|
+
if (ev.type === "question.asked" &&
|
|
273
|
+
ev.properties.sessionID === sessionID) {
|
|
274
|
+
const result = await this.input.client.question.reject({
|
|
275
|
+
requestID: ev.properties.id,
|
|
276
|
+
});
|
|
277
|
+
if (result.error)
|
|
278
|
+
throw new MagiError("blocked", "Could not reject user question.");
|
|
279
|
+
throw new MagiError("blocked", "OpenCode session requested user input.");
|
|
280
|
+
}
|
|
240
281
|
}
|
|
282
|
+
return new Promise(() => { });
|
|
241
283
|
}
|
|
242
284
|
async deleteSessions(state) {
|
|
243
285
|
const sessionIds = this.getSessionIds(state);
|
|
@@ -43,7 +43,11 @@ export async function edit() {
|
|
|
43
43
|
}
|
|
44
44
|
return output;
|
|
45
45
|
}, {
|
|
46
|
-
error: (
|
|
46
|
+
error: async (e, count) => {
|
|
47
|
+
if (e instanceof MagiError)
|
|
48
|
+
throw e;
|
|
49
|
+
await this.updateEvent(`Attempt ${count} failed to edit. Retrying...`);
|
|
50
|
+
},
|
|
47
51
|
retries: this.config.output.repairAttempts,
|
|
48
52
|
signal: this.context.abort,
|
|
49
53
|
});
|
|
@@ -134,7 +138,11 @@ export async function resolveConflict() {
|
|
|
134
138
|
responses: [],
|
|
135
139
|
};
|
|
136
140
|
}, {
|
|
137
|
-
error: (
|
|
141
|
+
error: async (e, count) => {
|
|
142
|
+
if (e instanceof MagiError)
|
|
143
|
+
throw e;
|
|
144
|
+
await this.updateEvent(`Attempt ${count} failed to resolve conflicts. Retrying...`);
|
|
145
|
+
},
|
|
138
146
|
retries: this.config.output.repairAttempts,
|
|
139
147
|
signal: this.context.abort,
|
|
140
148
|
});
|
|
@@ -86,7 +86,11 @@ export async function postReviews() {
|
|
|
86
86
|
throw new Error("Invalid output for operator.");
|
|
87
87
|
return parsed.comment;
|
|
88
88
|
}, {
|
|
89
|
-
error: (
|
|
89
|
+
error: async (e, count) => {
|
|
90
|
+
if (e instanceof MagiError)
|
|
91
|
+
throw e;
|
|
92
|
+
await this.updateEvent(`Attempt ${count} failed to post comment by operator. Retrying...`);
|
|
93
|
+
},
|
|
90
94
|
retries: this.config.output.repairAttempts,
|
|
91
95
|
signal: this.context.abort,
|
|
92
96
|
});
|
|
@@ -113,7 +113,11 @@ export async function classifyChecks() {
|
|
|
113
113
|
throw new Error(`Invalid output for reviewer ${id}.`);
|
|
114
114
|
return parsed;
|
|
115
115
|
}, {
|
|
116
|
-
error: (
|
|
116
|
+
error: async (e, count) => {
|
|
117
|
+
if (e instanceof MagiError)
|
|
118
|
+
throw e;
|
|
119
|
+
await this.updateEvent(`Attempt ${count} failed to classify CI checks with reviewer ${id}. Retrying...`);
|
|
120
|
+
},
|
|
117
121
|
retries: this.config.output.repairAttempts,
|
|
118
122
|
signal: this.context.abort,
|
|
119
123
|
});
|
|
@@ -125,7 +125,11 @@ export async function review() {
|
|
|
125
125
|
]).join("\n\n"));
|
|
126
126
|
return parsed;
|
|
127
127
|
}, {
|
|
128
|
-
error: (
|
|
128
|
+
error: async (e, count) => {
|
|
129
|
+
if (e instanceof MagiError)
|
|
130
|
+
throw e;
|
|
131
|
+
await this.updateEvent(`Attempt ${count} failed to ${label} with reviewer ${id}. Retrying...`);
|
|
132
|
+
},
|
|
129
133
|
retries: this.config.output.repairAttempts,
|
|
130
134
|
signal: this.context.abort,
|
|
131
135
|
});
|
|
@@ -208,7 +212,11 @@ export async function reconsiderClose() {
|
|
|
208
212
|
validateInlineCommentTargets("initial", parsed, inlineCommentTargets);
|
|
209
213
|
return parsed;
|
|
210
214
|
}, {
|
|
211
|
-
error: (
|
|
215
|
+
error: async (e, count) => {
|
|
216
|
+
if (e instanceof MagiError)
|
|
217
|
+
throw e;
|
|
218
|
+
await this.updateEvent(`Attempt ${count} failed to reconsider close verdict with reviewer ${id}. Retrying...`);
|
|
219
|
+
},
|
|
212
220
|
retries: this.config.output.repairAttempts,
|
|
213
221
|
signal: this.context.abort,
|
|
214
222
|
});
|
|
@@ -287,7 +295,11 @@ async function collectAcceptedFindings(findings) {
|
|
|
287
295
|
throw new Error(`Missing finding vote: ${key}.`);
|
|
288
296
|
return parsed;
|
|
289
297
|
}, {
|
|
290
|
-
error: (
|
|
298
|
+
error: async (e, count) => {
|
|
299
|
+
if (e instanceof MagiError)
|
|
300
|
+
throw e;
|
|
301
|
+
await this.updateEvent(`Attempt ${count} failed to validate review findings with reviewer ${id}. Retrying...`);
|
|
302
|
+
},
|
|
291
303
|
retries: this.config.output.repairAttempts,
|
|
292
304
|
signal: this.context.abort,
|
|
293
305
|
});
|
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-20260722060754",
|
|
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>",
|