opencode-magi 0.0.0-dev-20260522110001 → 0.0.0-dev-20260522141748
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/index.js +23 -13
- package/dist/orchestrator/model.js +20 -9
- package/dist/orchestrator/run-manager.js +22 -87
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -96,6 +96,7 @@ export function parseRunArguments(value, dryRun = false, command = "review") {
|
|
|
96
96
|
const configOverrides = {};
|
|
97
97
|
const prTokens = [];
|
|
98
98
|
let sync = false;
|
|
99
|
+
let timeoutMs;
|
|
99
100
|
for (let index = 0; index < tokens.length; index++) {
|
|
100
101
|
const token = tokens[index];
|
|
101
102
|
if (token === "--dry-run") {
|
|
@@ -110,6 +111,11 @@ export function parseRunArguments(value, dryRun = false, command = "review") {
|
|
|
110
111
|
case "--language":
|
|
111
112
|
setConfigOverride(configOverrides, ["language"], nextFlagValue(tokens, ++index, token));
|
|
112
113
|
break;
|
|
114
|
+
case "--timeout":
|
|
115
|
+
timeoutMs =
|
|
116
|
+
parseIntegerFlag(nextFlagValue(tokens, ++index, token), token, 0) *
|
|
117
|
+
1_000;
|
|
118
|
+
break;
|
|
113
119
|
case "--merge":
|
|
114
120
|
case "--no-merge":
|
|
115
121
|
setConfigOverride(configOverrides, [command, "automation", "merge"], token === "--merge");
|
|
@@ -151,13 +157,20 @@ export function parseRunArguments(value, dryRun = false, command = "review") {
|
|
|
151
157
|
prTokens.push(token);
|
|
152
158
|
}
|
|
153
159
|
}
|
|
154
|
-
return {
|
|
160
|
+
return {
|
|
161
|
+
configOverrides,
|
|
162
|
+
dryRun,
|
|
163
|
+
prs: parsePrs(prTokens.join(" ")),
|
|
164
|
+
sync,
|
|
165
|
+
timeoutMs,
|
|
166
|
+
};
|
|
155
167
|
}
|
|
156
168
|
export function parseIssueRunArguments(value, dryRun = false) {
|
|
157
169
|
const tokens = value.split(/[\s,]+/).filter(Boolean);
|
|
158
170
|
const configOverrides = {};
|
|
159
171
|
const issueTokens = [];
|
|
160
172
|
let sync = false;
|
|
173
|
+
let timeoutMs;
|
|
161
174
|
for (let index = 0; index < tokens.length; index++) {
|
|
162
175
|
const token = tokens[index];
|
|
163
176
|
if (token === "--dry-run") {
|
|
@@ -172,6 +185,11 @@ export function parseIssueRunArguments(value, dryRun = false) {
|
|
|
172
185
|
case "--language":
|
|
173
186
|
setConfigOverride(configOverrides, ["language"], nextFlagValue(tokens, ++index, token));
|
|
174
187
|
break;
|
|
188
|
+
case "--timeout":
|
|
189
|
+
timeoutMs =
|
|
190
|
+
parseIntegerFlag(nextFlagValue(tokens, ++index, token), token, 0) *
|
|
191
|
+
1_000;
|
|
192
|
+
break;
|
|
175
193
|
case "--close":
|
|
176
194
|
case "--no-close":
|
|
177
195
|
setConfigOverride(configOverrides, ["triage", "automation", "close"], token === "--close");
|
|
@@ -210,6 +228,7 @@ export function parseIssueRunArguments(value, dryRun = false) {
|
|
|
210
228
|
dryRun,
|
|
211
229
|
issues: parseIssues(issueTokens.join(" ")),
|
|
212
230
|
sync,
|
|
231
|
+
timeoutMs,
|
|
213
232
|
};
|
|
214
233
|
}
|
|
215
234
|
function nextFlagValue(tokens, index, flag) {
|
|
@@ -461,7 +480,6 @@ export const MagiPlugin = async ({ client, directory }) => {
|
|
|
461
480
|
prs: tool.schema.string(),
|
|
462
481
|
dryRun: tool.schema.boolean().optional(),
|
|
463
482
|
sync: tool.schema.boolean().optional(),
|
|
464
|
-
timeoutSeconds: tool.schema.number().optional(),
|
|
465
483
|
},
|
|
466
484
|
async execute(args, context) {
|
|
467
485
|
const parsed = parseRunArguments(args.prs, args.dryRun ?? false, "merge");
|
|
@@ -487,9 +505,7 @@ export const MagiPlugin = async ({ client, directory }) => {
|
|
|
487
505
|
parentSessionId: context.sessionID,
|
|
488
506
|
signal: context.abort,
|
|
489
507
|
sync,
|
|
490
|
-
timeoutMs:
|
|
491
|
-
? undefined
|
|
492
|
-
: args.timeoutSeconds * 1_000,
|
|
508
|
+
timeoutMs: parsed.timeoutMs,
|
|
493
509
|
}), { signal: context.abort });
|
|
494
510
|
if (sync)
|
|
495
511
|
return syncResult(runManager, states);
|
|
@@ -507,7 +523,6 @@ export const MagiPlugin = async ({ client, directory }) => {
|
|
|
507
523
|
prs: tool.schema.string(),
|
|
508
524
|
dryRun: tool.schema.boolean().optional(),
|
|
509
525
|
sync: tool.schema.boolean().optional(),
|
|
510
|
-
timeoutSeconds: tool.schema.number().optional(),
|
|
511
526
|
},
|
|
512
527
|
async execute(args, context) {
|
|
513
528
|
const parsed = parseRunArguments(args.prs, args.dryRun ?? false);
|
|
@@ -532,9 +547,7 @@ export const MagiPlugin = async ({ client, directory }) => {
|
|
|
532
547
|
parentSessionId: context.sessionID,
|
|
533
548
|
signal: context.abort,
|
|
534
549
|
sync,
|
|
535
|
-
timeoutMs:
|
|
536
|
-
? undefined
|
|
537
|
-
: args.timeoutSeconds * 1_000,
|
|
550
|
+
timeoutMs: parsed.timeoutMs,
|
|
538
551
|
}), { signal: context.abort });
|
|
539
552
|
if (sync)
|
|
540
553
|
return syncResult(runManager, states);
|
|
@@ -549,7 +562,6 @@ export const MagiPlugin = async ({ client, directory }) => {
|
|
|
549
562
|
issues: tool.schema.string(),
|
|
550
563
|
dryRun: tool.schema.boolean().optional(),
|
|
551
564
|
sync: tool.schema.boolean().optional(),
|
|
552
|
-
timeoutSeconds: tool.schema.number().optional(),
|
|
553
565
|
},
|
|
554
566
|
async execute(args, context) {
|
|
555
567
|
const parsed = parseIssueRunArguments(args.issues, args.dryRun ?? false);
|
|
@@ -580,9 +592,7 @@ export const MagiPlugin = async ({ client, directory }) => {
|
|
|
580
592
|
repository,
|
|
581
593
|
signal: context.abort,
|
|
582
594
|
sync,
|
|
583
|
-
timeoutMs:
|
|
584
|
-
? undefined
|
|
585
|
-
: args.timeoutSeconds * 1_000,
|
|
595
|
+
timeoutMs: parsed.timeoutMs,
|
|
586
596
|
}), { signal: context.abort });
|
|
587
597
|
if (sync)
|
|
588
598
|
return syncResult(runManager, states);
|
|
@@ -97,15 +97,26 @@ export async function createModelSession(input) {
|
|
|
97
97
|
}
|
|
98
98
|
export async function promptModelText(input) {
|
|
99
99
|
throwIfAborted(input.signal);
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
100
|
+
const abort = () => {
|
|
101
|
+
void input.client.session
|
|
102
|
+
.abort?.({ path: { id: input.sessionId } })
|
|
103
|
+
.catch(() => undefined);
|
|
104
|
+
};
|
|
105
|
+
input.signal?.addEventListener("abort", abort, { once: true });
|
|
106
|
+
try {
|
|
107
|
+
const result = await input.client.session.prompt({
|
|
108
|
+
body: {
|
|
109
|
+
model: modelBody(input.model),
|
|
110
|
+
parts: [{ type: "text", text: input.prompt }],
|
|
111
|
+
},
|
|
112
|
+
path: { id: input.sessionId },
|
|
113
|
+
});
|
|
114
|
+
throwIfAborted(input.signal);
|
|
115
|
+
return extractText(result, input.allowEmpty);
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
input.signal?.removeEventListener("abort", abort);
|
|
119
|
+
}
|
|
109
120
|
}
|
|
110
121
|
async function sendPrompt(client, sessionId, model, prompt, signal) {
|
|
111
122
|
return promptModelText({ client, model, prompt, sessionId, signal });
|
|
@@ -676,53 +676,7 @@ export class MagiRunManager {
|
|
|
676
676
|
state.status = "cancelled";
|
|
677
677
|
state.phase = "cancelled";
|
|
678
678
|
state.completedAt = now();
|
|
679
|
-
|
|
680
|
-
state.editor?.status === "running" ||
|
|
681
|
-
state.editor?.status === "repairing") {
|
|
682
|
-
state.editor.status = "cancelled";
|
|
683
|
-
}
|
|
684
|
-
if (state.editor?.sessionId) {
|
|
685
|
-
await this.input.client.session
|
|
686
|
-
.abort?.({ path: { id: state.editor.sessionId } })
|
|
687
|
-
.catch(() => undefined);
|
|
688
|
-
}
|
|
689
|
-
if (state.triageCreator?.status === "pending" ||
|
|
690
|
-
state.triageCreator?.status === "running" ||
|
|
691
|
-
state.triageCreator?.status === "repairing" ||
|
|
692
|
-
state.triageCreator?.status === "blocked") {
|
|
693
|
-
state.triageCreator.status = "cancelled";
|
|
694
|
-
}
|
|
695
|
-
if (state.triageCreator?.sessionId) {
|
|
696
|
-
await this.input.client.session
|
|
697
|
-
.abort?.({ path: { id: state.triageCreator.sessionId } })
|
|
698
|
-
.catch(() => undefined);
|
|
699
|
-
}
|
|
700
|
-
for (const reviewer of Object.values(state.reviewers)) {
|
|
701
|
-
if (reviewer.status === "pending" ||
|
|
702
|
-
reviewer.status === "running" ||
|
|
703
|
-
reviewer.status === "repairing" ||
|
|
704
|
-
reviewer.status === "blocked") {
|
|
705
|
-
reviewer.status = "cancelled";
|
|
706
|
-
}
|
|
707
|
-
if (reviewer.sessionId) {
|
|
708
|
-
await this.input.client.session
|
|
709
|
-
.abort?.({ path: { id: reviewer.sessionId } })
|
|
710
|
-
.catch(() => undefined);
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
for (const classifier of Object.values(state.ciClassifiers ?? {})) {
|
|
714
|
-
if (classifier.status === "pending" ||
|
|
715
|
-
classifier.status === "running" ||
|
|
716
|
-
classifier.status === "repairing" ||
|
|
717
|
-
classifier.status === "blocked") {
|
|
718
|
-
classifier.status = "cancelled";
|
|
719
|
-
}
|
|
720
|
-
if (classifier.sessionId) {
|
|
721
|
-
await this.input.client.session
|
|
722
|
-
.abort?.({ path: { id: classifier.sessionId } })
|
|
723
|
-
.catch(() => undefined);
|
|
724
|
-
}
|
|
725
|
-
}
|
|
679
|
+
await this.finishActiveAgents(state, "cancelled");
|
|
726
680
|
if (state.worktreePath) {
|
|
727
681
|
await removeWorktree(this.input.exec, state.worktreePath).catch(() => undefined);
|
|
728
682
|
}
|
|
@@ -1223,6 +1177,26 @@ export class MagiRunManager {
|
|
|
1223
1177
|
...Object.entries(state.reviewers),
|
|
1224
1178
|
];
|
|
1225
1179
|
}
|
|
1180
|
+
isActiveAgent(agent) {
|
|
1181
|
+
return (agent.status === "pending" ||
|
|
1182
|
+
agent.status === "running" ||
|
|
1183
|
+
agent.status === "repairing" ||
|
|
1184
|
+
agent.status === "blocked");
|
|
1185
|
+
}
|
|
1186
|
+
async finishActiveAgents(state, status, error) {
|
|
1187
|
+
for (const [, agent] of this.agentEntries(state)) {
|
|
1188
|
+
if (this.isActiveAgent(agent)) {
|
|
1189
|
+
agent.status = status;
|
|
1190
|
+
if (error != null)
|
|
1191
|
+
agent.error = error;
|
|
1192
|
+
}
|
|
1193
|
+
if (agent.sessionId) {
|
|
1194
|
+
await this.input.client.session
|
|
1195
|
+
.abort?.({ path: { id: agent.sessionId } })
|
|
1196
|
+
.catch(() => undefined);
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1226
1200
|
selectPendingAgent(state, kind, key, requestId) {
|
|
1227
1201
|
const entries = key
|
|
1228
1202
|
? this.agentState(state, key)
|
|
@@ -1966,46 +1940,7 @@ export class MagiRunManager {
|
|
|
1966
1940
|
state.phase = "failed";
|
|
1967
1941
|
state.completedAt = now();
|
|
1968
1942
|
state.error = errorMessage(error);
|
|
1969
|
-
|
|
1970
|
-
state.editor?.status === "running" ||
|
|
1971
|
-
state.editor?.status === "repairing" ||
|
|
1972
|
-
state.editor?.status === "blocked") {
|
|
1973
|
-
state.editor.status = "failed";
|
|
1974
|
-
state.editor.error = state.error;
|
|
1975
|
-
}
|
|
1976
|
-
if (state.editor?.sessionId) {
|
|
1977
|
-
await this.input.client.session
|
|
1978
|
-
.abort?.({ path: { id: state.editor.sessionId } })
|
|
1979
|
-
.catch(() => undefined);
|
|
1980
|
-
}
|
|
1981
|
-
for (const reviewer of Object.values(state.reviewers)) {
|
|
1982
|
-
if (reviewer.status === "pending" ||
|
|
1983
|
-
reviewer.status === "running" ||
|
|
1984
|
-
reviewer.status === "repairing" ||
|
|
1985
|
-
reviewer.status === "blocked") {
|
|
1986
|
-
reviewer.status = "failed";
|
|
1987
|
-
reviewer.error = state.error;
|
|
1988
|
-
}
|
|
1989
|
-
if (reviewer.sessionId) {
|
|
1990
|
-
await this.input.client.session
|
|
1991
|
-
.abort?.({ path: { id: reviewer.sessionId } })
|
|
1992
|
-
.catch(() => undefined);
|
|
1993
|
-
}
|
|
1994
|
-
}
|
|
1995
|
-
for (const classifier of Object.values(state.ciClassifiers ?? {})) {
|
|
1996
|
-
if (classifier.status === "pending" ||
|
|
1997
|
-
classifier.status === "running" ||
|
|
1998
|
-
classifier.status === "repairing" ||
|
|
1999
|
-
classifier.status === "blocked") {
|
|
2000
|
-
classifier.status = "failed";
|
|
2001
|
-
classifier.error = state.error;
|
|
2002
|
-
}
|
|
2003
|
-
if (classifier.sessionId) {
|
|
2004
|
-
await this.input.client.session
|
|
2005
|
-
.abort?.({ path: { id: classifier.sessionId } })
|
|
2006
|
-
.catch(() => undefined);
|
|
2007
|
-
}
|
|
2008
|
-
}
|
|
1943
|
+
await this.finishActiveAgents(state, "failed", state.error);
|
|
2009
1944
|
await this.persist(state);
|
|
2010
1945
|
await this.notify(state, `Magi ${state.command} failed for ${runLabel(state)}: ${state.error}`, { reply: true });
|
|
2011
1946
|
this.active.delete(runId);
|
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-20260522141748",
|
|
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>",
|