opencode-magi 0.0.0-dev-20260525025216 → 0.0.0-dev-20260525030452

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 CHANGED
@@ -78,7 +78,7 @@ Add the following content to the configuration file.
78
78
  }
79
79
  },
80
80
  "review": {
81
- "agents": [
81
+ "reviewers": [
82
82
  { "ref": "account-1" },
83
83
  { "ref": "account-2" },
84
84
  { "ref": "account-3" }
@@ -87,7 +87,7 @@ Add the following content to the configuration file.
87
87
  }
88
88
  ```
89
89
 
90
- After refs are expanded, `review.agents[].account` is the GitHub account used to post reviews and approvals. Must be authenticated with `gh auth token --user <account>` and must be unique.
90
+ After `refs` are expanded, `review.reviewers[].account` is the GitHub account used to post reviews and approvals. Must be authenticated with `gh auth token --user <account>` and must be unique.
91
91
 
92
92
  #### Set project config
93
93
 
@@ -133,7 +133,7 @@ Add the following content to the configuration file.
133
133
  }
134
134
  },
135
135
  "review": {
136
- "agents": [
136
+ "reviewers": [
137
137
  { "ref": "account-1" },
138
138
  { "ref": "account-2" },
139
139
  { "ref": "account-3" }
@@ -143,7 +143,7 @@ Add the following content to the configuration file.
143
143
  "editor": { "ref": "account-4" }
144
144
  },
145
145
  "triage": {
146
- "agents": [
146
+ "voters": [
147
147
  { "ref": "account-1" },
148
148
  { "ref": "account-2" },
149
149
  { "ref": "account-3" }
@@ -168,7 +168,7 @@ Entries with `ref` are expanded from `agents.refs`. Fields set alongside `ref` o
168
168
  }
169
169
  ```
170
170
 
171
- After refs are expanded, `review.agents[].account` is the GitHub account used to post reviews and approvals. Must be authenticated with `gh auth token --user <account>` and must be unique. `merge.editor.account` is used by `/magi:merge` to push fixes, close PRs, and merge PRs.
171
+ After `refs` are expanded, `review.reviewers[].account` is the GitHub account used to post reviews and approvals. Must be authenticated with `gh auth token --user <account>` and must be unique. `merge.editor.account` is used by `/magi:merge` to push fixes, close PRs, and merge PRs.
172
172
 
173
173
  #### Validate config
174
174
 
@@ -96,14 +96,14 @@ export function resolveAgents(config) {
96
96
  permission: resolveEditorPermission(agents, editor),
97
97
  }
98
98
  : undefined,
99
- reviewers: (config.review?.agents ?? []).map((reviewer, index) => ({
99
+ reviewers: (config.review?.reviewers ?? []).map((reviewer, index) => ({
100
100
  ...reviewer,
101
101
  key: reviewerKey(reviewer, index),
102
102
  index,
103
103
  model: normalizedModel(reviewer.model),
104
104
  permission: resolveReviewerPermission(agents, reviewer),
105
105
  })),
106
- triage: (config.triage?.agents ?? []).map((agent, index) => ({
106
+ triage: (config.triage?.voters ?? []).map((agent, index) => ({
107
107
  ...agent,
108
108
  key: triageAgentKey(agent, index),
109
109
  index,
@@ -54,13 +54,13 @@ const TRIAGE_CREATOR_KEYS = new Set([
54
54
  const AUTHOR_KEYS = new Set(["email", "name"]);
55
55
  const GITHUB_KEYS = new Set(["apiRetryAttempts", "host", "owner", "repo"]);
56
56
  const REVIEW_KEYS = new Set([
57
- "agents",
58
57
  "automation",
59
58
  "checks",
60
59
  "concurrency",
61
60
  "merge",
62
61
  "output",
63
62
  "prompts",
63
+ "reviewers",
64
64
  "safety",
65
65
  "worktree",
66
66
  ]);
@@ -72,7 +72,6 @@ const MERGE_KEYS = new Set([
72
72
  "prompts",
73
73
  ]);
74
74
  const TRIAGE_KEYS = new Set([
75
- "agents",
76
75
  "automation",
77
76
  "categories",
78
77
  "concurrency",
@@ -81,6 +80,7 @@ const TRIAGE_KEYS = new Set([
81
80
  "prompts",
82
81
  "reporter",
83
82
  "safety",
83
+ "voters",
84
84
  "worktree",
85
85
  ]);
86
86
  const REVIEW_MERGE_KEYS = new Set([
@@ -187,14 +187,14 @@ function expandAgentRefs(config, errors) {
187
187
  const refsValue = isPlainObject(agents) ? agents.refs : undefined;
188
188
  const refsInvalid = refsValue != null && !isPlainObject(refsValue);
189
189
  const refs = isPlainObject(refsValue) ? refsValue : undefined;
190
- if (Array.isArray(magiConfig.review?.agents)) {
191
- magiConfig.review.agents = magiConfig.review.agents.map((agent, index) => expandAgentRefUse(agent, `review.agents[${index}]`, refs, refsInvalid, errors));
190
+ if (Array.isArray(magiConfig.review?.reviewers)) {
191
+ magiConfig.review.reviewers = magiConfig.review.reviewers.map((agent, index) => expandAgentRefUse(agent, `review.reviewers[${index}]`, refs, refsInvalid, errors));
192
192
  }
193
193
  if (isPlainObject(magiConfig.merge?.editor)) {
194
194
  magiConfig.merge.editor = expandAgentRefUse(magiConfig.merge.editor, "merge.editor", refs, refsInvalid, errors);
195
195
  }
196
- if (Array.isArray(magiConfig.triage?.agents)) {
197
- magiConfig.triage.agents = magiConfig.triage.agents.map((agent, index) => expandAgentRefUse(agent, `triage.agents[${index}]`, refs, refsInvalid, errors));
196
+ if (Array.isArray(magiConfig.triage?.voters)) {
197
+ magiConfig.triage.voters = magiConfig.triage.voters.map((agent, index) => expandAgentRefUse(agent, `triage.voters[${index}]`, refs, refsInvalid, errors));
198
198
  }
199
199
  if (isPlainObject(magiConfig.triage?.creator)) {
200
200
  magiConfig.triage.creator = expandAgentRefUse(magiConfig.triage.creator, "triage.creator", refs, refsInvalid, errors);
@@ -387,18 +387,18 @@ function validateReviewerList(reviewers, path, errors, catalog) {
387
387
  }
388
388
  });
389
389
  }
390
- function validateTriageAgentList(agents, path, errors, catalog) {
391
- if (agents == null)
390
+ function validateTriageAgentList(voters, path, errors, catalog) {
391
+ if (voters == null)
392
392
  return;
393
- if (!Array.isArray(agents)) {
393
+ if (!Array.isArray(voters)) {
394
394
  errors.push(`${path} must be an array`);
395
395
  return;
396
396
  }
397
- if (agents.length < 3)
398
- errors.push(`${path} must contain at least 3 agents`);
399
- if (agents.length % 2 === 0)
400
- errors.push(`${path} must contain an odd number of agents`);
401
- agents.forEach((agent, index) => {
397
+ if (voters.length < 3)
398
+ errors.push(`${path} must contain at least 3 voters`);
399
+ if (voters.length % 2 === 0)
400
+ errors.push(`${path} must contain an odd number of voters`);
401
+ voters.forEach((agent, index) => {
402
402
  if (!agent || typeof agent !== "object") {
403
403
  errors.push(`${path}[${index}] must be an object`);
404
404
  return;
@@ -722,11 +722,11 @@ function validateTriage(config, errors, options) {
722
722
  const creator = triage.creator;
723
723
  const reporter = typeof triage.reporter === "string" ? triage.reporter : undefined;
724
724
  const safety = triage.safety;
725
- if (!triage.agents)
726
- errors.push("triage.agents is required");
727
- validateTriageAgentList(triage.agents, "triage.agents", errors, options.modelCatalog);
728
- if (Array.isArray(triage.agents)) {
729
- const resolvedTriageAgents = triage.agents.map((agent, index) => ({
725
+ if (!triage.voters)
726
+ errors.push("triage.voters is required");
727
+ validateTriageAgentList(triage.voters, "triage.voters", errors, options.modelCatalog);
728
+ if (Array.isArray(triage.voters)) {
729
+ const resolvedTriageAgents = triage.voters.map((agent, index) => ({
730
730
  account: agent && typeof agent === "object" && typeof agent.account === "string"
731
731
  ? agent.account
732
732
  : "",
@@ -735,7 +735,7 @@ function validateTriage(config, errors, options) {
735
735
  validateResolvedTriageAgents(resolvedTriageAgents, "triage.resolvedAgents", errors);
736
736
  if (reporter != null &&
737
737
  !resolvedTriageAgents.some((agent) => agent.key === reporter)) {
738
- errors.push(`triage.reporter must match a triage agent key: ${reporter}`);
738
+ errors.push(`triage.reporter must match a triage voter key: ${reporter}`);
739
739
  }
740
740
  }
741
741
  validateString(triage.reporter, "triage.reporter", errors);
@@ -926,11 +926,11 @@ export async function validateConfig(config, options = {}) {
926
926
  else {
927
927
  validateKnownKeys(config.review, "review", REVIEW_KEYS, errors);
928
928
  }
929
- if (!config.review.agents)
930
- errors.push("review.agents is required");
931
- validateReviewerList(config.review.agents, "review.agents", errors, options.modelCatalog);
932
- if (Array.isArray(config.review.agents)) {
933
- validateResolvedReviewers(config.review.agents.map((reviewer, index) => ({
929
+ if (!config.review.reviewers)
930
+ errors.push("review.reviewers is required");
931
+ validateReviewerList(config.review.reviewers, "review.reviewers", errors, options.modelCatalog);
932
+ if (Array.isArray(config.review.reviewers)) {
933
+ validateResolvedReviewers(config.review.reviewers.map((reviewer, index) => ({
934
934
  account: reviewer &&
935
935
  typeof reviewer === "object" &&
936
936
  typeof reviewer.account === "string"
@@ -939,7 +939,7 @@ export async function validateConfig(config, options = {}) {
939
939
  key: reviewer && typeof reviewer === "object"
940
940
  ? reviewerKey(reviewer, index)
941
941
  : "",
942
- })), "review.resolvedAgents", errors);
942
+ })), "review.resolvedReviewers", errors);
943
943
  }
944
944
  }
945
945
  if (options.requireTriage && !config.triage) {
package/dist/index.js CHANGED
@@ -381,7 +381,7 @@ export async function validateMagiConfigFiles(directory, options = {}) {
381
381
  ? withGitHubApiRetry(options.exec, mergedConfig.github?.apiRetryAttempts ?? 3)
382
382
  : undefined,
383
383
  modelCatalog: options.modelCatalog,
384
- requireGithub: hasProjectConfig && Boolean(mergedConfig.review?.agents),
384
+ requireGithub: hasProjectConfig && Boolean(mergedConfig.review?.reviewers),
385
385
  requireModelCatalog: true,
386
386
  requireWorktreeConfig: true,
387
387
  });
@@ -547,7 +547,7 @@ export const MagiPlugin = async ({ client, directory }) => {
547
547
  },
548
548
  }),
549
549
  magi_triage: tool({
550
- description: "Triage one or more GitHub issues with configured Magi triage agents.",
550
+ description: "Triage one or more GitHub issues with configured Magi triage voters.",
551
551
  args: {
552
552
  issues: tool.schema.string(),
553
553
  dryRun: tool.schema.boolean().optional(),
@@ -1616,16 +1616,16 @@ export class MagiRunManager {
1616
1616
  }));
1617
1617
  }
1618
1618
  if (progress.type === "triage_agent_started") {
1619
- await this.notify(state, `**Triage agent ${progress.voter}** started ${progress.phase} for ${issue}.`);
1619
+ await this.notify(state, `**Triage voter ${progress.voter}** started ${progress.phase} for ${issue}.`);
1620
1620
  }
1621
1621
  if (progress.type === "triage_agent_repair") {
1622
- await this.notify(state, `**Triage agent ${progress.voter}** started JSON regeneration for ${issue}.`);
1622
+ await this.notify(state, `**Triage voter ${progress.voter}** started JSON regeneration for ${issue}.`);
1623
1623
  }
1624
1624
  if (progress.type === "triage_agent_completed") {
1625
- await this.notify(state, `**Triage agent ${progress.voter}** completed ${progress.phase} for ${issue}: ${progress.vote}.`);
1625
+ await this.notify(state, `**Triage voter ${progress.voter}** completed ${progress.phase} for ${issue}: ${progress.vote}.`);
1626
1626
  }
1627
1627
  if (progress.type === "triage_agent_failed") {
1628
- await this.notify(state, `**Triage agent ${progress.voter}** failed ${progress.phase} for ${issue}: ${redactSecrets(progress.error)}`);
1628
+ await this.notify(state, `**Triage voter ${progress.voter}** failed ${progress.phase} for ${issue}: ${redactSecrets(progress.error)}`);
1629
1629
  }
1630
1630
  if (progress.type === "comment_posting") {
1631
1631
  await this.notify(state, `Posting triage comment for ${issue}.`);
@@ -217,7 +217,7 @@ export function chooseDuplicateOutput(input) {
217
217
  async function runDuplicateVote(input) {
218
218
  const agents = input.input.repository.agents.triage;
219
219
  if (!agents?.length)
220
- throw new Error("triage.agents is required");
220
+ throw new Error("triage.voters is required");
221
221
  await emitProgress(input.input, { phase: "duplicate", type: "phase" });
222
222
  const outputs = await Promise.all(agents.map((agent) => runVote({
223
223
  agent,
@@ -259,7 +259,7 @@ async function runDuplicateVote(input) {
259
259
  async function runPhaseVote(input) {
260
260
  const agents = input.input.repository.agents.triage;
261
261
  if (!agents?.length)
262
- throw new Error("triage.agents is required");
262
+ throw new Error("triage.voters is required");
263
263
  await emitProgress(input.input, { phase: input.phase, type: "phase" });
264
264
  const promptTexts = await Promise.all(agents.map((agent) => input.prompt({
265
265
  context: input.context,
@@ -525,7 +525,7 @@ async function runReconsiderationVote(input) {
525
525
  function triageReporter(repository, issue) {
526
526
  const agents = repository.agents.triage ?? [];
527
527
  if (!agents.length)
528
- throw new Error("triage.agents is required");
528
+ throw new Error("triage.voters is required");
529
529
  const configured = repository.triage?.reporter;
530
530
  const reporter = configured
531
531
  ? agents.find((agent) => agent.key === configured)
@@ -563,7 +563,7 @@ function decisionCommentFallback(input) {
563
563
  function agentForKey(repository, key) {
564
564
  const agent = repository.agents.triage?.find((item) => item.key === key);
565
565
  if (!agent)
566
- throw new Error(`Unknown triage agent: ${key}`);
566
+ throw new Error(`Unknown triage voter: ${key}`);
567
567
  return agent;
568
568
  }
569
569
  function askOutputs(outputs) {
@@ -905,7 +905,7 @@ export async function runTriage(input) {
905
905
  throw new Error("triage configuration is required");
906
906
  const agents = input.repository.agents.triage;
907
907
  if (!agents?.length)
908
- throw new Error("triage.agents is required");
908
+ throw new Error("triage.voters is required");
909
909
  const runId = input.runId ?? `run-${Date.now().toString(36)}`;
910
910
  const outputDir = issueRunOutputDir({
911
911
  config: input.config,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-magi",
3
- "version": "0.0.0-dev-20260525025216",
3
+ "version": "0.0.0-dev-20260525030452",
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
@@ -316,7 +316,7 @@
316
316
  "type": "object",
317
317
  "additionalProperties": false,
318
318
  "properties": {
319
- "agents": {
319
+ "reviewers": {
320
320
  "type": "array",
321
321
  "minItems": 3,
322
322
  "items": { "$ref": "#/$defs/reviewer" }
@@ -351,7 +351,7 @@
351
351
  "type": "object",
352
352
  "additionalProperties": false,
353
353
  "properties": {
354
- "agents": {
354
+ "voters": {
355
355
  "type": "array",
356
356
  "minItems": 3,
357
357
  "items": { "$ref": "#/$defs/triageAgent" }