opencode-browser-annotation-plugin 0.6.1 → 0.7.0
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 +7 -2
- package/dist/plugin.js +24 -20
- package/extension/icons/icon-128.png +0 -0
- package/extension/icons/icon-16.png +0 -0
- package/extension/icons/icon-32.png +0 -0
- package/extension/icons/icon-48.png +0 -0
- package/extension/icons/icon-512.png +0 -0
- package/extension/icons/icon.svg +27 -0
- package/extension/manifest.json +14 -2
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -177,8 +177,13 @@ The plugin source is `src/plugin.ts`; the extension is plain MV3 in `extension/`
|
|
|
177
177
|
## Limits
|
|
178
178
|
|
|
179
179
|
- Text + element metadata only; no screenshot is sent or seen by the model.
|
|
180
|
-
- The
|
|
181
|
-
|
|
180
|
+
- The picker lists every recent session across all projects and all running
|
|
181
|
+
OpenCode processes (the store is shared), with sessions you've touched this
|
|
182
|
+
run floating to the top. Pick any of them by id; without a `sessionID` the
|
|
183
|
+
plugin targets the most recently active one.
|
|
184
|
+
- A single server owns the port (default `39517`); the first OpenCode process to
|
|
185
|
+
bind it serves the extension for every session. Send a message first so a
|
|
186
|
+
session is active if you rely on the no-`sessionID` fallback.
|
|
182
187
|
|
|
183
188
|
## License
|
|
184
189
|
|
package/dist/plugin.js
CHANGED
|
@@ -139,17 +139,19 @@ function sendJson(res, status, body) {
|
|
|
139
139
|
res.statusCode = status;
|
|
140
140
|
res.end(payload);
|
|
141
141
|
}
|
|
142
|
-
export const BrowserAnnotationPlugin = async ({ client
|
|
142
|
+
export const BrowserAnnotationPlugin = async ({ client }) => {
|
|
143
143
|
const host = envHost();
|
|
144
144
|
const port = envPort();
|
|
145
145
|
let activeSessionID = null;
|
|
146
146
|
let server = null;
|
|
147
|
-
// Sessions
|
|
148
|
-
//
|
|
149
|
-
//
|
|
147
|
+
// Sessions this run has touched (created / messaged / status / idle). Used
|
|
148
|
+
// only to bias the picker ordering — NOT to filter — so sessions from other
|
|
149
|
+
// OpenCode processes and other project directories still appear.
|
|
150
150
|
const activeIDs = new Set();
|
|
151
|
-
|
|
152
|
-
|
|
151
|
+
// The picker shows every recent session across all directories/processes so
|
|
152
|
+
// one server (whichever wins the port) can target any of them; the shared
|
|
153
|
+
// OpenCode store makes them all reachable over the single loopback port.
|
|
154
|
+
const RECENT_MAX = 25;
|
|
153
155
|
const log = (level, message, extra) => {
|
|
154
156
|
void client.app
|
|
155
157
|
.log({ body: { service: "browser-annotation", level, message, extra } })
|
|
@@ -157,7 +159,10 @@ export const BrowserAnnotationPlugin = async ({ client, directory }) => {
|
|
|
157
159
|
};
|
|
158
160
|
async function allSessions() {
|
|
159
161
|
try {
|
|
160
|
-
|
|
162
|
+
// No directory filter: list every session in the shared OpenCode store so
|
|
163
|
+
// the picker spans all projects and all running processes, not just this
|
|
164
|
+
// plugin instance's own directory.
|
|
165
|
+
const res = (await client.session.list({}));
|
|
161
166
|
const rows = Array.isArray(res) ? res : Array.isArray(res?.data) ? res.data : [];
|
|
162
167
|
return rows
|
|
163
168
|
.filter((s) => s && typeof s.id === "string" && !s.parentID)
|
|
@@ -169,31 +174,30 @@ export const BrowserAnnotationPlugin = async ({ client, directory }) => {
|
|
|
169
174
|
}
|
|
170
175
|
}
|
|
171
176
|
/**
|
|
172
|
-
* The picker list: sessions
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
177
|
+
* The picker list: all sessions, newest first. Sessions this run has actively
|
|
178
|
+
* touched sort ahead of the rest (recency within each group), so "what you're
|
|
179
|
+
* working on" floats to the top without hiding sessions owned by other
|
|
180
|
+
* OpenCode processes or directories.
|
|
176
181
|
*/
|
|
177
182
|
async function listSessions() {
|
|
178
183
|
const all = await allSessions();
|
|
179
|
-
|
|
180
|
-
// Prune ids that no longer exist.
|
|
184
|
+
// Prune tracked ids that no longer exist.
|
|
181
185
|
const existing = new Set(all.map((s) => s.id));
|
|
182
186
|
for (const id of activeIDs)
|
|
183
187
|
if (!existing.has(id))
|
|
184
188
|
activeIDs.delete(id);
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
const
|
|
189
|
-
const
|
|
190
|
-
return
|
|
189
|
+
const byRecent = [...all].sort((a, b) => b.updated - a.updated);
|
|
190
|
+
// Stable partition: touched-this-run first, everything else after; each
|
|
191
|
+
// group already in recency order.
|
|
192
|
+
const touched = byRecent.filter((s) => activeIDs.has(s.id));
|
|
193
|
+
const rest = byRecent.filter((s) => !activeIDs.has(s.id));
|
|
194
|
+
return [...touched, ...rest].slice(0, RECENT_MAX);
|
|
191
195
|
}
|
|
192
196
|
async function injectPrompt(sessionID, annotations) {
|
|
193
197
|
try {
|
|
198
|
+
// No directory scoping: target the session by id wherever it lives.
|
|
194
199
|
await client.session.promptAsync({
|
|
195
200
|
path: { id: sessionID },
|
|
196
|
-
query: { directory },
|
|
197
201
|
body: { parts: [{ type: "text", text: buildPrompt(annotations) }] },
|
|
198
202
|
});
|
|
199
203
|
return { ok: true };
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<svg width="128" height="128" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="128" gradientUnits="userSpaceOnUse">
|
|
4
|
+
<stop offset="0" stop-color="#22262e"/>
|
|
5
|
+
<stop offset="1" stop-color="#15171c"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
<linearGradient id="mint" x1="34" y1="30" x2="94" y2="98" gradientUnits="userSpaceOnUse">
|
|
8
|
+
<stop offset="0" stop-color="#7ef0c8"/>
|
|
9
|
+
<stop offset="1" stop-color="#39c79a"/>
|
|
10
|
+
</linearGradient>
|
|
11
|
+
</defs>
|
|
12
|
+
|
|
13
|
+
<!-- rounded dark badge -->
|
|
14
|
+
<rect x="4" y="4" width="120" height="120" rx="28" fill="url(#bg)"/>
|
|
15
|
+
<rect x="4.5" y="4.5" width="119" height="119" rx="27.5" fill="none" stroke="#3a3f49" stroke-width="1"/>
|
|
16
|
+
|
|
17
|
+
<!-- element-picker corner brackets (mint) -->
|
|
18
|
+
<g stroke="url(#mint)" stroke-width="7" stroke-linecap="round" stroke-linejoin="round" fill="none">
|
|
19
|
+
<path d="M34 50 V38 A4 4 0 0 1 38 34 H50"/>
|
|
20
|
+
<path d="M78 34 H90 A4 4 0 0 1 94 38 V50"/>
|
|
21
|
+
<path d="M34 78 V90 A4 4 0 0 1 38 94 H50"/>
|
|
22
|
+
</g>
|
|
23
|
+
|
|
24
|
+
<!-- cursor / pick arrow, lower-right, on top of brackets -->
|
|
25
|
+
<path d="M66 60 L98 74 L83 80 L91 98 L82 102 L74 84 L62 92 Z"
|
|
26
|
+
fill="#ffffff" stroke="#15171c" stroke-width="3" stroke-linejoin="round"/>
|
|
27
|
+
</svg>
|
package/extension/manifest.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest_version": 3,
|
|
3
3
|
"name": "OpenCode Browser Annotation",
|
|
4
|
-
"version": "0.6.
|
|
4
|
+
"version": "0.6.2",
|
|
5
5
|
"description": "Alt+A to annotate an element, Alt+Shift+A for the annotation list. Sends element metadata to your OpenCode agent.",
|
|
6
6
|
"permissions": [
|
|
7
7
|
"activeTab",
|
|
@@ -16,8 +16,20 @@
|
|
|
16
16
|
"service_worker": "background.js",
|
|
17
17
|
"type": "module"
|
|
18
18
|
},
|
|
19
|
+
"icons": {
|
|
20
|
+
"16": "icons/icon-16.png",
|
|
21
|
+
"32": "icons/icon-32.png",
|
|
22
|
+
"48": "icons/icon-48.png",
|
|
23
|
+
"128": "icons/icon-128.png"
|
|
24
|
+
},
|
|
19
25
|
"action": {
|
|
20
|
-
"default_title": "OpenCode Annotation — Alt+A to pick, Alt+Shift+A for list"
|
|
26
|
+
"default_title": "OpenCode Annotation — Alt+A to pick, Alt+Shift+A for list",
|
|
27
|
+
"default_icon": {
|
|
28
|
+
"16": "icons/icon-16.png",
|
|
29
|
+
"32": "icons/icon-32.png",
|
|
30
|
+
"48": "icons/icon-48.png",
|
|
31
|
+
"128": "icons/icon-128.png"
|
|
32
|
+
}
|
|
21
33
|
},
|
|
22
34
|
"options_page": "options.html",
|
|
23
35
|
"commands": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-browser-annotation-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Select an element in your browser, type an instruction, and send it to your OpenCode agent over a loopback + SSH tunnel. Text and element metadata only (no screenshots).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"opencode",
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"scripts": {
|
|
35
35
|
"build": "tsc -p tsconfig.json",
|
|
36
36
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
37
|
+
"pack:ext": "node scripts/pack-extension.mjs",
|
|
37
38
|
"prepublishOnly": "npm run build"
|
|
38
39
|
},
|
|
39
40
|
"peerDependencies": {
|