@xinleibird/bridge-opencode 0.2.7 → 0.2.8

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.
Files changed (2) hide show
  1. package/bridge.ts +64 -17
  2. package/package.json +4 -1
package/bridge.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { Plugin } from "@opencode-ai/plugin";
2
+ import type { FilePart, Part } from "@opencode-ai/sdk";
2
3
  import crypto from "node:crypto";
3
4
  import { access } from "node:fs/promises";
4
5
  import { basename, isAbsolute, join } from "node:path";
@@ -126,7 +127,7 @@ export const BridgePlugin: Plugin = async ({ directory }) => {
126
127
  }
127
128
  },
128
129
 
129
- "chat.message": async (input, output) => {
130
+ "experimental.chat.messages.transform": async (_, output) => {
130
131
  let selections: Awaited<ReturnType<typeof getVisualSelections>>;
131
132
  try {
132
133
  selections = await getVisualSelections();
@@ -138,8 +139,17 @@ export const BridgePlugin: Plugin = async ({ directory }) => {
138
139
  const filteredSelections = selections.filter((s) => !s.cwd || s.cwd === cwd);
139
140
  if (filteredSelections.length === 0) return;
140
141
 
142
+ const userMessages = output.messages.filter((m) => m.info.role === "user");
143
+ if (userMessages.length === 0) return;
144
+
145
+ const latestUserMessage = userMessages[userMessages.length - 1];
146
+ const msgInfo = latestUserMessage.info;
147
+ if (!msgInfo || msgInfo.role !== "user") return;
148
+ if (!latestUserMessage.parts) {
149
+ latestUserMessage.parts = [];
150
+ }
151
+
141
152
  const refs: string[] = [];
142
- let attached = 0;
143
153
  for (const s of filteredSelections) {
144
154
  try {
145
155
  await access(s.filePath);
@@ -148,13 +158,59 @@ export const BridgePlugin: Plugin = async ({ directory }) => {
148
158
  }
149
159
  if (!s.startLine) continue;
150
160
 
151
- const filePath = s.filePath.startsWith(cwd + "/")
152
- ? "./" + s.filePath.slice(cwd.length + 1)
153
- : s.filePath;
161
+ const fileRef = `${s.filePath}:${s.startLine}-${s.endLine}`;
162
+ refs.push(fileRef);
154
163
 
155
- const fileRef = `${filePath}:${s.startLine}-${s.endLine}`;
164
+ const fileName = basename(s.filePath);
156
165
 
157
- refs.push(fileRef);
166
+ const filePart: FilePart = {
167
+ id: crypto.randomUUID(),
168
+ sessionID: msgInfo.sessionID,
169
+ messageID: msgInfo.id,
170
+ type: "file",
171
+ mime: "text/plain",
172
+ filename: fileName,
173
+ url: `file://${s.filePath}?start=${s.startLine}&end=${s.endLine}`,
174
+ source: {
175
+ text: {
176
+ start: 0,
177
+ value: fileRef,
178
+ end: fileRef.length,
179
+ },
180
+ type: "file",
181
+ path: s.filePath,
182
+ },
183
+ };
184
+ latestUserMessage.parts.push(filePart);
185
+ }
186
+
187
+ if (refs.length === 0) return;
188
+
189
+ const textPart = latestUserMessage.parts.find((p) => p.type === "text") as Part | undefined;
190
+ if (textPart && textPart.type === "text" && typeof textPart.text === "string") {
191
+ textPart.text = `${refs.join("\n")}\n\n${textPart.text}`;
192
+ }
193
+ },
194
+
195
+ "chat.message": async (input, output) => {
196
+ let selections: Awaited<ReturnType<typeof getVisualSelections>>;
197
+ try {
198
+ selections = await getVisualSelections();
199
+ } catch {
200
+ return;
201
+ }
202
+ if (!selections || selections.length === 0) return;
203
+
204
+ const filteredSelections = selections.filter((s) => !s.cwd || s.cwd === cwd);
205
+ if (filteredSelections.length === 0) return;
206
+
207
+ for (const s of filteredSelections) {
208
+ try {
209
+ await access(s.filePath);
210
+ } catch {
211
+ continue;
212
+ }
213
+ if (!s.startLine) continue;
158
214
 
159
215
  const fileName = basename(s.filePath);
160
216
 
@@ -164,20 +220,11 @@ export const BridgePlugin: Plugin = async ({ directory }) => {
164
220
  sessionID: input.sessionID,
165
221
  messageID: input.messageID ?? "",
166
222
  mime: "text/plain",
167
- filename: fileName,
223
+ filename: `${fileName}:${s.startLine}-${s.endLine}`,
168
224
  url: `file://${s.filePath}?start=${s.startLine}&end=${s.endLine}`,
169
225
  });
170
- attached++;
171
- }
172
-
173
- if (attached === 0) return;
174
-
175
- const textPart = output.parts.find((p: any) => p.type === "text") as any;
176
- if (textPart && typeof textPart.text === "string") {
177
- textPart.text = `${refs.join("\n")}\n\n${textPart.text}`;
178
226
  }
179
227
  },
180
228
  };
181
229
  };
182
-
183
230
  export default BridgePlugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xinleibird/bridge-opencode",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -38,5 +38,8 @@
38
38
  "aarch64-unknown-linux-gnu"
39
39
  ]
40
40
  }
41
+ },
42
+ "dependencies": {
43
+ "@opencode-ai/sdk": "^1.15.12"
41
44
  }
42
45
  }