opencode-magi 0.0.0-dev-20260521012947 → 0.0.0-dev-20260521013053

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.
@@ -157,6 +157,56 @@ function ghHostOption(config) {
157
157
  function isPlainObject(value) {
158
158
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
159
159
  }
160
+ function expandAgentRefUse(value, path, refs, refsInvalid, errors) {
161
+ if (!isPlainObject(value) || !Object.hasOwn(value, "ref"))
162
+ return value;
163
+ const use = { ...value };
164
+ const ref = use.ref;
165
+ delete use.ref;
166
+ if (typeof ref !== "string") {
167
+ errors.push(`${path}.ref must be a string`);
168
+ return use;
169
+ }
170
+ if (refsInvalid) {
171
+ errors.push(`agents.refs must be an object to resolve ${path}.ref`);
172
+ return use;
173
+ }
174
+ const preset = refs?.[ref];
175
+ if (preset == null) {
176
+ errors.push(`${path}.ref references unknown agents.refs preset: ${ref}`);
177
+ return use;
178
+ }
179
+ if (!isPlainObject(preset)) {
180
+ errors.push(`agents.refs.${ref} must be an object when referenced by ${path}.ref`);
181
+ return use;
182
+ }
183
+ const presetFields = { ...preset };
184
+ delete presetFields.ref;
185
+ return { ...presetFields, ...use };
186
+ }
187
+ function expandAgentRefs(config, errors) {
188
+ if (!config || typeof config !== "object")
189
+ return;
190
+ const magiConfig = config;
191
+ const agents = magiConfig.agents;
192
+ const refsValue = isPlainObject(agents) ? agents.refs : undefined;
193
+ const refsInvalid = refsValue != null && !isPlainObject(refsValue);
194
+ const refs = isPlainObject(refsValue) ? refsValue : undefined;
195
+ if (Array.isArray(magiConfig.review?.agents)) {
196
+ magiConfig.review.agents = magiConfig.review.agents.map((agent, index) => expandAgentRefUse(agent, `review.agents[${index}]`, refs, refsInvalid, errors));
197
+ }
198
+ if (isPlainObject(magiConfig.merge?.editor)) {
199
+ magiConfig.merge.editor = expandAgentRefUse(magiConfig.merge.editor, "merge.editor", refs, refsInvalid, errors);
200
+ }
201
+ if (Array.isArray(magiConfig.triage?.agents)) {
202
+ magiConfig.triage.agents = magiConfig.triage.agents.map((agent, index) => expandAgentRefUse(agent, `triage.agents[${index}]`, refs, refsInvalid, errors));
203
+ }
204
+ if (isPlainObject(magiConfig.triage?.creator)) {
205
+ magiConfig.triage.creator = expandAgentRefUse(magiConfig.triage.creator, "triage.creator", refs, refsInvalid, errors);
206
+ }
207
+ if (isPlainObject(magiConfig.agents))
208
+ delete magiConfig.agents.refs;
209
+ }
160
210
  function validateKnownKeys(value, path, keys, errors) {
161
211
  if (!isPlainObject(value))
162
212
  return;
@@ -792,6 +842,7 @@ export async function validateConfig(config, options = {}) {
792
842
  const warnings = [];
793
843
  if (!config || typeof config !== "object")
794
844
  errors.push("config must be an object");
845
+ expandAgentRefs(config, errors);
795
846
  if (config && typeof config === "object")
796
847
  validateJsonSchema(config, errors);
797
848
  validateKnownKeys(config, "config", CONFIG_KEYS, errors);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-magi",
3
- "version": "0.0.0-dev-20260521012947",
3
+ "version": "0.0.0-dev-20260521013053",
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
@@ -9,7 +9,11 @@
9
9
  "type": "object",
10
10
  "additionalProperties": false,
11
11
  "properties": {
12
- "permissions": { "$ref": "#/$defs/permissions" }
12
+ "permissions": { "$ref": "#/$defs/permissions" },
13
+ "refs": {
14
+ "type": "object",
15
+ "additionalProperties": { "$ref": "#/$defs/agentRef" }
16
+ }
13
17
  }
14
18
  },
15
19
  "clear": {
@@ -51,11 +55,33 @@
51
55
  "triage": { "$ref": "#/$defs/triage" }
52
56
  },
53
57
  "$defs": {
58
+ "agentRef": {
59
+ "type": "object",
60
+ "additionalProperties": false,
61
+ "properties": {
62
+ "id": { "type": "string", "pattern": "^[A-Za-z0-9_-]+$" },
63
+ "model": { "type": "string", "minLength": 1 },
64
+ "options": { "type": "object", "additionalProperties": true },
65
+ "account": { "type": "string", "minLength": 1 },
66
+ "author": {
67
+ "type": "object",
68
+ "additionalProperties": false,
69
+ "properties": {
70
+ "name": { "type": "string", "minLength": 1 },
71
+ "email": { "type": "string", "minLength": 1 }
72
+ }
73
+ },
74
+ "permissions": { "$ref": "#/$defs/permissions" },
75
+ "persona": { "type": "string" }
76
+ }
77
+ },
54
78
  "reviewer": {
55
79
  "type": "object",
56
- "required": ["model", "account"],
80
+ "if": { "not": { "required": ["ref"] } },
81
+ "then": { "required": ["model", "account"] },
57
82
  "additionalProperties": false,
58
83
  "properties": {
84
+ "ref": { "type": "string", "minLength": 1 },
59
85
  "id": { "type": "string", "pattern": "^[A-Za-z0-9_-]+$" },
60
86
  "model": { "type": "string", "minLength": 1 },
61
87
  "options": { "type": "object", "additionalProperties": true },
@@ -66,9 +92,11 @@
66
92
  },
67
93
  "editor": {
68
94
  "type": "object",
69
- "required": ["model", "account", "author"],
95
+ "if": { "not": { "required": ["ref"] } },
96
+ "then": { "required": ["model", "account", "author"] },
70
97
  "additionalProperties": false,
71
98
  "properties": {
99
+ "ref": { "type": "string", "minLength": 1 },
72
100
  "model": { "type": "string", "minLength": 1 },
73
101
  "options": { "type": "object", "additionalProperties": true },
74
102
  "account": { "type": "string", "minLength": 1 },
@@ -87,9 +115,11 @@
87
115
  },
88
116
  "triageAgent": {
89
117
  "type": "object",
90
- "required": ["model"],
118
+ "if": { "not": { "required": ["ref"] } },
119
+ "then": { "required": ["model"] },
91
120
  "additionalProperties": false,
92
121
  "properties": {
122
+ "ref": { "type": "string", "minLength": 1 },
93
123
  "id": { "type": "string", "pattern": "^[A-Za-z0-9_-]+$" },
94
124
  "model": { "type": "string", "minLength": 1 },
95
125
  "options": { "type": "object", "additionalProperties": true },
@@ -99,9 +129,11 @@
99
129
  },
100
130
  "triageCreator": {
101
131
  "type": "object",
102
- "required": ["model", "author"],
132
+ "if": { "not": { "required": ["ref"] } },
133
+ "then": { "required": ["model", "author"] },
103
134
  "additionalProperties": false,
104
135
  "properties": {
136
+ "ref": { "type": "string", "minLength": 1 },
105
137
  "account": { "type": "string", "minLength": 1 },
106
138
  "model": { "type": "string", "minLength": 1 },
107
139
  "options": { "type": "object", "additionalProperties": true },