opencode-magi 0.0.0-dev-20260521143913 → 0.0.0-dev-20260521221144

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.
@@ -37,6 +37,23 @@ function quoteEvidence(value) {
37
37
  const compact = value.replaceAll(/\s+/g, " ").trim();
38
38
  return compact.length > 120 ? `${compact.slice(0, 117)}...` : compact;
39
39
  }
40
+ function errorText(error) {
41
+ if (!error || typeof error !== "object")
42
+ return String(error);
43
+ const value = error;
44
+ return [value.message, value.stderr, value.stdout]
45
+ .filter((item) => typeof item === "string")
46
+ .join("\n");
47
+ }
48
+ function isIssueLookupFailure(error) {
49
+ const text = errorText(error);
50
+ return (/could not resolve to an issue/i.test(text) ||
51
+ /could not fetch issue #\d+/i.test(text) ||
52
+ /not an issue/i.test(text));
53
+ }
54
+ function isIssueUrl(url) {
55
+ return /\/issues\/\d+(?:$|[/?#])/i.test(url);
56
+ }
40
57
  function issueReferencePattern(repository) {
41
58
  const host = escapeRegExp(repository.github.host || "github.com");
42
59
  const owner = escapeRegExp(repository.github.owner);
@@ -120,6 +137,9 @@ export function collectIssueRelationships(input) {
120
137
  async function contextIssue(input) {
121
138
  const issue = input.issue ??
122
139
  (await fetchIssue(input.exec, input.repository, input.relationship.number));
140
+ if (!isIssueUrl(issue.url)) {
141
+ throw new Error(`Reference #${issue.number} resolved to ${issue.url}, not an Issue`);
142
+ }
123
143
  const commentPage = await fetchIssueCommentPage(input.exec, input.repository, issue.number, input.limit);
124
144
  return {
125
145
  author: issue.author,
@@ -138,6 +158,19 @@ async function contextIssue(input) {
138
158
  url: issue.url,
139
159
  };
140
160
  }
161
+ async function contextIssueIfIssue(input) {
162
+ try {
163
+ return await contextIssue(input);
164
+ }
165
+ catch (error) {
166
+ if (isIssueLookupFailure(error))
167
+ return undefined;
168
+ throw error;
169
+ }
170
+ }
171
+ function presentIssue(issue) {
172
+ return Boolean(issue);
173
+ }
141
174
  function orderReviewThreads(threads) {
142
175
  return [...threads]
143
176
  .sort((a, b) => {
@@ -183,13 +216,13 @@ export async function buildReviewContextSnapshot(input) {
183
216
  const closingRelationships = relationships.filter((relationship) => relationship.relationship === "closing");
184
217
  const referencedRelationships = relationships.filter((relationship) => relationship.relationship === "referenced");
185
218
  return {
186
- closingIssues: await Promise.all(closingRelationships.map((relationship) => contextIssue({
219
+ closingIssues: (await Promise.all(closingRelationships.map((relationship) => contextIssueIfIssue({
187
220
  exec: input.exec,
188
221
  issue: closingIssueMap.get(relationship.number),
189
222
  limit: LIMITS.closingIssueComments,
190
223
  relationship,
191
224
  repository: input.repository,
192
- }))),
225
+ })))).filter(presentIssue),
193
226
  pullRequest: {
194
227
  author: input.pr.author?.login ?? safetyMeta.author,
195
228
  baseRef: input.pr.baseRefName,
@@ -207,12 +240,12 @@ export async function buildReviewContextSnapshot(input) {
207
240
  title: input.pr.title,
208
241
  url: input.pr.url,
209
242
  },
210
- referencedIssues: await Promise.all(referencedRelationships.map((relationship) => contextIssue({
243
+ referencedIssues: (await Promise.all(referencedRelationships.map((relationship) => contextIssueIfIssue({
211
244
  exec: input.exec,
212
245
  limit: LIMITS.referencedIssueComments,
213
246
  relationship,
214
247
  repository: input.repository,
215
- }))),
248
+ })))).filter(presentIssue),
216
249
  reviewDiscussion: {
217
250
  prComments: boundedComments(prComments, LIMITS.prComments),
218
251
  prCommentsOmitted,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-magi",
3
- "version": "0.0.0-dev-20260521143913",
3
+ "version": "0.0.0-dev-20260521221144",
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>",