opencode-webui 1.0.3 → 1.0.5
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/dist/assets/{index-D2GMPF3o.js → index-DmEJZk-g.js} +13 -13
- package/dist/assets/{report-bjdxXk2S.js → report-mXoOsBOG.js} +1 -1
- package/dist/assets/{runtime-status-DGOzOYuv.js → runtime-status-CnqERypy.js} +1 -1
- package/dist/index.html +1 -1
- package/package.json +1 -1
- package/skills/webui/SKILL.md +36 -3
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e,c as t,i as n,n as r,r as i,s as a,t as o}from"./index-
|
|
1
|
+
import{a as e,c as t,i as n,n as r,r as i,s as a,t as o}from"./index-DmEJZk-g.js";var s=`report`,c=`AbdelftahZowail/opencode-webui`,l=10,u=window;function d(e){let t=u.__reportErrors??=[];t.push(e),t.length>l&&t.splice(0,t.length-l)}u.__reportErrorsInstalled||(u.__reportErrorsInstalled=!0,window.onerror=(e,t,n,r,i)=>{d({message:String(e).slice(0,500),source:t??``,line:n??0,stack:i instanceof Error?i.stack?.slice(0,500):void 0})},window.addEventListener(`unhandledrejection`,e=>{let t=e.reason;d({message:(t instanceof Error?t.message:String(t)).slice(0,500),source:`unhandledrejection`,line:0,stack:t instanceof Error?t.stack?.slice(0,500):void 0})}));async function f(e){try{let t=await fetch(e);return t.ok?await t.json():null}catch{return null}}async function p(e){let[n,r]=await Promise.all([f(`/api/webui/config`),f(`/api/webui/extensions`)]);return{url:location.href,userAgent:navigator.userAgent,language:navigator.language,viewport:`${window.innerWidth}x${window.innerHeight}`,version:n?.version??`unknown`,reportRepo:n?.reportRepo??c,builtins:[...t],runtimeExtensions:(r?.data??[]).map(e=>e.id??``).filter(Boolean),errors:u.__reportErrors??[],sessionID:e,timestamp:new Date().toISOString()}}function m(e,t){let n=`WebUI bug: ${e?e.slice(0,80):`user report`}`,r=[`### What happened`,e||``,``,`### Steps to reproduce`,`1. `,``,`### Expected`,``,`### Actual`,``,`<details><summary>Diagnostics</summary>`,``,"```json",JSON.stringify(t,null,2),"```",`</details>`].join(`
|
|
2
2
|
`);return{title:n,body:r,url:`https://github.com/${t.reportRepo}/issues/new?title=${encodeURIComponent(n)}&body=${encodeURIComponent(r)}`}}async function h(e){try{return await navigator.clipboard.writeText(e),!0}catch{return!1}}async function g(t,a){let s=t.trim(),c=s.startsWith(`--agent`),l=c?s.replace(/^--agent\b/,``).trim():s,u=await p(a.sessionID??r().currentSessionID??null),{title:d,body:f,url:g}=m(l,u);if(c){let t=`File a bug against ${u.reportRepo} using the gh CLI: create an issue with the title and body below, then reply with the issue URL. Do not include any private session content beyond the diagnostics JSON.\n\nTitle: ${d}\n\n${f}`,s=a.sessionID??r().currentSessionID??null;if(s&&i(s))try{s=await n(``)}catch{s=null}if(!s){let e=await h(t);o({title:e?`No active session — report prompt copied`:`No active session`,description:e?`Paste it into a session to have the agent file the issue.`:`Could not copy the report prompt either.`,variant:e?`default`:`destructive`});return}o({title:`Report handed to the agent`,description:`It will file the issue and reply with the URL.`}),await e(s,t);return}if(window.open(g,`_blank`))o({title:`Opening GitHub issue…`});else{let e=await h(g);o({title:e?`Report ready — link copied`:`Report link`,description:e?`Popup blocked; paste the link in a browser.`:`Popup blocked and the clipboard is unavailable.`,variant:e?`default`:`destructive`})}}a({kind:`slash`,id:`report`,name:`report`,aliases:[`bug`],description:`Report a webui bug on GitHub — diag bundle prefilled`,run:g});export{s as id};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{l as e,o as t,s as n,u as r}from"./index-
|
|
1
|
+
import{l as e,o as t,s as n,u as r}from"./index-DmEJZk-g.js";var i=r(e(),1),a=`runtime-status`;function o(){let e=t(e=>e.connected),n=t(e=>e.serviceOK),r=t(e=>e.activeIDs.length),a=e&&n;return(0,i.jsxs)(`footer`,{className:`flex min-h-7 items-center justify-end gap-3 border-t border-[var(--border-weak-base)] bg-[var(--background-base)] px-3 py-1 font-mono text-[10px] text-[var(--text-weaker)]`,children:[(0,i.jsx)(`span`,{className:`hidden sm:inline`,children:`webui extension`}),(0,i.jsxs)(`span`,{className:`inline-flex items-center gap-1.5`,title:a?`Connected to the OpenCode service`:`Waiting for the OpenCode service`,children:[(0,i.jsx)(`span`,{className:`size-1.5 rounded-full ${a?`bg-[var(--surface-success-strong)]`:`bg-[var(--surface-warning-strong)]`}`}),a?`connected`:`offline`]}),r>0&&(0,i.jsxs)(`span`,{children:[r,` active`]})]})}n({kind:`region`,id:`runtime-status`,region:`footer`,render:()=>(0,i.jsx)(o,{})});export{a as id};
|
package/dist/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<link rel="icon" type="image/svg+xml" href="/assets/opencode.svg" />
|
|
7
7
|
<title>OpenCode Web</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-DmEJZk-g.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/assets/index-BJLgA6bC.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Web UI for the OpenCode coding agent — chat, streaming, tool cards, and extensions over the OpenCode engine's HTTP API.",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
|
-
"version": "1.0.
|
|
6
|
+
"version": "1.0.5",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
package/skills/webui/SKILL.md
CHANGED
|
@@ -10,6 +10,27 @@ the `opencode` TUI, with a Bun proxy in front so the browser never holds
|
|
|
10
10
|
service credentials. One port for UI + `/api/*`: http://localhost:4097
|
|
11
11
|
(`WEBUI_PROXY_PORT`).
|
|
12
12
|
|
|
13
|
+
- **Repo**: https://github.com/AbdelftahZowail/opencode-webui
|
|
14
|
+
- **This skill's version**: 1.0.5 (matches the `v1.0.5` git tag —
|
|
15
|
+
the file links below are pinned to it, so they always describe the code
|
|
16
|
+
this skill was generated with)
|
|
17
|
+
- **A running instance exposes its version** at `GET /api/webui/config` →
|
|
18
|
+
`{ version, reportRepo }`, and on the page as `window.__opencodeUI.version`.
|
|
19
|
+
|
|
20
|
+
## Source catalog (fetch, don't read local checkouts)
|
|
21
|
+
|
|
22
|
+
Everything needed to author extensions is below; when a table isn't enough,
|
|
23
|
+
fetch the exact file at the pinned tag instead of reading a local clone:
|
|
24
|
+
|
|
25
|
+
| File | Purpose |
|
|
26
|
+
| --- | --- |
|
|
27
|
+
| https://raw.githubusercontent.com/AbdelftahZowail/opencode-webui/v1.0.5/ui-extensions/README.md | Full authoring guide — the source of truth for kinds/hooks/regions |
|
|
28
|
+
| https://raw.githubusercontent.com/AbdelftahZowail/opencode-webui/v1.0.5/src/extensions/registry.tsx | The slot registry — exact register() shapes per kind |
|
|
29
|
+
| https://raw.githubusercontent.com/AbdelftahZowail/opencode-webui/v1.0.5/src/components/Composer.tsx | Where slash entries / prompt hooks / composer regions live |
|
|
30
|
+
| https://raw.githubusercontent.com/AbdelftahZowail/opencode-webui/v1.0.5/src/components/MessageItem.tsx | Where message/message.decoration/message.part render |
|
|
31
|
+
| https://raw.githubusercontent.com/AbdelftahZowail/opencode-webui/v1.0.5/src/lib/composerHandoff.ts | Type-anywhere → composer behavior (if your extension competes for keys) |
|
|
32
|
+
| https://raw.githubusercontent.com/AbdelftahZowail/opencode-webui/v1.0.5/src/store.ts | The store — actions useStore exposes to extensions |
|
|
33
|
+
|
|
13
34
|
## Environment
|
|
14
35
|
|
|
15
36
|
| Variable | Default | Purpose |
|
|
@@ -32,14 +53,26 @@ service credentials. One port for UI + `/api/*`: http://localhost:4097
|
|
|
32
53
|
- **Author a user-dir extension** for the user — a folder, no build step, no
|
|
33
54
|
restart.
|
|
34
55
|
|
|
56
|
+
### Dev extensions vs user extensions (two homes, one contract)
|
|
57
|
+
|
|
58
|
+
| | Dev (app repo) | User (any machine) |
|
|
59
|
+
| --- | --- | --- |
|
|
60
|
+
| Where | `ui-extensions/<name>/` in the webui checkout | `~/.config/opencode/webui-extensions/<name>/main.tsx` (per-user) or `<project>/.opencode/webui-extensions/<name>/main.tsx` (per-project) |
|
|
61
|
+
| How it loads | Bundled into the app build, listed in `ui-extensions/index.ts` | The proxy bundles it on the fly; page picks it up within ~8s |
|
|
62
|
+
| On/off | `enabled` list in `ui-extensions/config.ts` | Settings › Extensions toggle |
|
|
63
|
+
| API surface | Full app internals (imports, `useStore`, `api`) | ONLY the `window.__opencodeUI` bridge (`register`, `react`, `useStore`, `api`, `notify`, `getHooks`, `version`) |
|
|
64
|
+
|
|
65
|
+
Authoring rules (kinds, hook events) are identical in both homes — the tables
|
|
66
|
+
below apply to each.
|
|
67
|
+
|
|
35
68
|
### Minimal user-dir extension
|
|
36
69
|
|
|
37
70
|
Drop a folder — `~/.config/opencode/webui-extensions/<name>/main.tsx`
|
|
38
71
|
(per-user) or `<project>/.opencode/webui-extensions/<name>/main.tsx`
|
|
39
72
|
(per-project). The proxy bundles it and the page loads it within a poll cycle
|
|
40
|
-
|
|
41
|
-
the app ONLY through the
|
|
42
|
-
`react`, `useStore`, `api`, `notify`, `getHooks`):
|
|
73
|
+
`~8s` — see the dev-vs-user split above). Runtime extensions reach
|
|
74
|
+
the app ONLY through the `window.__opencodeUI` bridge (`register`,
|
|
75
|
+
`react`, `useStore`, `api`, `notify`, `getHooks`, `version`):
|
|
43
76
|
|
|
44
77
|
```tsx
|
|
45
78
|
// ~/.config/opencode/webui-extensions/hello/main.tsx
|