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.
@@ -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-D2GMPF3o.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(`
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-D2GMPF3o.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};
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-D2GMPF3o.js"></script>
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.3",
6
+ "version": "1.0.5",
7
7
  "license": "MIT",
8
8
  "repository": {
9
9
  "type": "git",
@@ -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
- (~8s); toggle per extension in Settings › Extensions. Runtime extensions reach
41
- the app ONLY through the versioned `window.__opencodeUI` bridge (`register`,
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