pipane 0.1.11 → 0.1.12
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 +11 -1
- package/dist/build-info.json +2 -2
- package/dist/client/assets/{backend-landing-page-CF2aHs0U.js → backend-landing-page-DnP0b68z.js} +1 -1
- package/dist/client/assets/device-invite-page-BXdui21Z.js +1 -0
- package/dist/client/assets/index-CG96lus1.js +2 -0
- package/dist/client/assets/{index-DtrSEX3O.css → index-VW8gJNOU.css} +1 -1
- package/dist/client/assets/{main-CtM4oO40.js → main-BOivrw8_.js} +487 -481
- package/dist/client/assets/{pairing-page-CiEb8c3R.js → pairing-page-BUVrsL9A.js} +1 -1
- package/dist/client/assets/{remote-backend-manager-BY79yja7.js → remote-backend-manager-vEOu2dhH.js} +1 -1
- package/dist/client/assets/rendezvous-trust-api-Bv6fZVJA.js +1 -0
- package/dist/client/assets/{ws-agent-adapter-P9Rtv9sl.js → ws-agent-adapter-BUykBiJL.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/server/rendezvous/server.js +18 -1
- package/dist/server/rendezvous/trust-store.js +93 -4
- package/dist/server/server/ws-handler.js +30 -5
- package/docs/protocol.md +5 -1
- package/package.json +4 -1
- package/dist/client/assets/index-Cc4cqaXn.js +0 -2
- package/dist/client/assets/rendezvous-trust-api-xLnrhe-v.js +0 -1
package/README.md
CHANGED
|
@@ -32,6 +32,8 @@ npm install -g @earendil-works/pi-coding-agent
|
|
|
32
32
|
|
|
33
33
|
Run `pipane` to start the backend. It registers with `https://pipane.dev` by default and uses the machine's short hostname as its backend name, so no remote-access environment variables are required. Set `PIPANE_BACKEND_NAME` to customize the name, `PIPANE_RENDEZVOUS_URL` to use another rendezvous service, or set `PIPANE_RENDEZVOUS_URL` to an empty value to disable remote registration.
|
|
34
34
|
|
|
35
|
+
Authorize the first browser by running `pipane pair` and opening its short-lived link or scanning its QR code. From an authorized pipane.dev workspace, open a host's `•••` menu and choose **Add another device** to create a one-use, ten-minute QR code and link. The new browser receives access to the same account backends without transferring the original browser's private key.
|
|
36
|
+
|
|
35
37
|
### Explicit local deployments
|
|
36
38
|
|
|
37
39
|
Deploy the current working tree to the separate dev instance with:
|
|
@@ -42,6 +44,14 @@ npm run deploy:dev
|
|
|
42
44
|
|
|
43
45
|
This builds a release, atomically advances the `pipane-dev` systemd service, and verifies it on port `8223`. It does not change production.
|
|
44
46
|
|
|
47
|
+
To try the same working-tree change through the public site without publishing npm, deploy a preview stack:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npm run deploy:preview
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
This starts a detached `pipane-preview-deploy` systemd unit, which first deploys the local `pipane-dev` backend and then atomically uploads its matching browser bundle to `pipane.dev`. Detaching lets the workflow survive the local backend restart; follow it with `journalctl -u pipane-preview-deploy -f`. It leaves the central rendezvous process, the npm registry, and the local production backend untouched. The public browser bundle is health-checked and rolled back automatically if activation fails. Override the deployment target with `PIPANE_PREVIEW_WEB_HOST`, `PIPANE_PREVIEW_WEB_ROOT`, or `PIPANE_PREVIEW_PUBLIC_URL` when needed.
|
|
54
|
+
|
|
45
55
|
Deploy the current committed working tree to local production with:
|
|
46
56
|
|
|
47
57
|
```bash
|
|
@@ -61,7 +71,7 @@ journalctl -u pipane -f
|
|
|
61
71
|
|
|
62
72
|
- Session list and clean UI for `pi`
|
|
63
73
|
- Real-time tool calls and streaming output, nicely crafted
|
|
64
|
-
- One
|
|
74
|
+
- One recency-sorted cross-host project picker on pipane.dev
|
|
65
75
|
- ChatGPT/Codex and Claude subscription usage in the input toolbar
|
|
66
76
|
- A large amount high quality "vibe-code".
|
|
67
77
|
|
package/dist/build-info.json
CHANGED
package/dist/client/assets/{backend-landing-page-CF2aHs0U.js → backend-landing-page-DnP0b68z.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{B as u}from"./backend-protocol-BvNAsFvb.js";import{a as x}from"./device-identity-C_w2NbSk.js";import{R as b}from"./rendezvous-trust-api-
|
|
1
|
+
import{B as u}from"./backend-protocol-BvNAsFvb.js";import{a as x}from"./device-identity-C_w2NbSk.js";import{R as b}from"./rendezvous-trust-api-Bv6fZVJA.js";const f={loadIdentity:()=>x(),createTrustApi:()=>new b(window.location.origin),confirm:e=>window.confirm(e)};async function w(e=f){const l=document.getElementById("app")??document.body;l.replaceChildren();const r=document.createElement("main");r.dataset.testid="backend-landing",r.style.cssText="min-height:100vh;padding:40px 24px;font-family:ui-sans-serif,system-ui;color:var(--foreground,#111827);background:var(--background,#fff)";const i=document.createElement("section");i.style.cssText="width:min(760px,100%);margin:0 auto";const t=document.createElement("h1");t.textContent="Your pipane backends",t.style.cssText="margin:0 0 8px;font-size:28px";const s=document.createElement("p");s.textContent="Connections are opened directly and only when you choose a backend.",s.style.cssText="margin:0 0 24px;opacity:.72";const n=document.createElement("div");n.dataset.testid="backend-list",n.style.cssText="display:grid;gap:12px";const d=document.createElement("p");d.style.cssText="margin-top:24px;padding-top:18px;border-top:1px solid var(--border,#d1d5db);opacity:.78;line-height:1.5",d.textContent="Add a backend or recover this browser by running `pipane pair` in an owned backend terminal and scanning its QR code.",i.append(t,s,n,d),r.append(i),l.append(r);const c=await e.loadIdentity();if(!c){n.append(m("No paired browser key was found.","Use `pipane pair` on a backend to begin without creating an account."));return}const o=e.createTrustApi();let a;try{a=await o.listAuthorizedBackends(c)}catch(p){n.append(m("Backend access could not be recovered from this device key.",p instanceof Error?p.message:"Pair this browser again from an owned backend terminal."));return}if(a.length===0){n.append(m("No backends are paired.","Run `pipane pair` in a backend terminal to add one."));return}for(const p of a)n.append(y(p,c,o,e))}function y(e,l,r,i){const t=document.createElement("article");t.dataset.backendId=e.backendId,t.style.cssText="display:flex;align-items:center;gap:14px;border:1px solid var(--border,#d1d5db);border-radius:10px;padding:16px";const s=document.createElement("div");s.style.cssText="min-width:0;flex:1";const n=document.createElement("strong");n.textContent=e.name||`${e.backendId.slice(0,18)}…`,n.style.cssText="display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis";const d=document.createElement("small"),c=e.protocolVersions.includes(u);d.textContent=e.online?c?`Online${e.softwareVersion?` · v${e.softwareVersion}`:""}`:"Online · update required":"Offline",d.style.cssText=`color:${e.online&&c?"#15803d":"#a16207"}`,s.append(n,d);const o=document.createElement("a");o.textContent="Open",o.href=`/backend/${encodeURIComponent(e.backendId)}`,o.dataset.testid="open-backend",o.style.cssText="border-radius:8px;padding:8px 12px;background:#2563eb;color:white;text-decoration:none",(!e.online||!c)&&(o.removeAttribute("href"),o.setAttribute("aria-disabled","true"),o.style.opacity=".45");const a=document.createElement("button");return a.type="button",a.textContent="Remove",a.style.cssText="border:0;background:transparent;color:#dc2626;cursor:pointer",a.addEventListener("click",()=>{i.confirm(`Remove ${e.name||e.backendId} from this account?`)&&(a.disabled=!0,r.revokeBackend(l,e.backendId).then(()=>t.remove()).catch(p=>{a.disabled=!1,d.textContent=p instanceof Error?p.message:"Removal failed",d.style.color="#dc2626"}))}),t.append(s,o,a),t}function m(e,l){const r=document.createElement("div");r.style.cssText="border:1px solid var(--border,#d1d5db);border-radius:10px;padding:18px;line-height:1.5";const i=document.createElement("strong");i.textContent=e;const t=document.createElement("p");return t.textContent=l,t.style.cssText="margin:6px 0 0;opacity:.72",r.append(i,t),r}export{w as initializeBackendLandingPage};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{l as g}from"./device-identity-C_w2NbSk.js";import{R as b,p as m}from"./rendezvous-trust-api-Bv6fZVJA.js";const y={loadIdentity:()=>g(),createTrustApi:()=>new b(window.location.origin)};async function h(d=y){const p=document.getElementById("app")??document.body;p.replaceChildren();const a=document.createElement("main");Object.assign(a.style,{minHeight:"100vh",display:"grid",placeItems:"center",padding:"24px",background:"var(--background, #fff)",color:"var(--foreground, #111827)",fontFamily:"ui-sans-serif, system-ui, sans-serif"});const o=document.createElement("section");Object.assign(o.style,{width:"min(460px, 100%)",border:"1px solid var(--border, #d1d5db)",borderRadius:"12px",padding:"28px",boxShadow:"0 18px 45px rgba(0, 0, 0, 0.10)",background:"var(--card, #fff)"});const r=document.createElement("h1");r.textContent="Join this Pipane workspace",Object.assign(r.style,{margin:"0 0 8px",fontSize:"24px"});const s=document.createElement("p");s.textContent="This one-time invite gives this browser access to the same backends as the inviting device.",Object.assign(s.style,{margin:"0 0 20px",lineHeight:"1.5",opacity:"0.75"});const e=document.createElement("p");e.dataset.testid="device-invite-status",e.setAttribute("role","status"),Object.assign(e.style,{margin:"0",lineHeight:"1.5",fontWeight:"600"});const t=document.createElement("button");t.type="button",t.textContent="Try again",t.hidden=!0,Object.assign(t.style,{marginTop:"18px",border:"1px solid var(--border, #9ca3af)",borderRadius:"8px",padding:"9px 14px",background:"transparent",color:"inherit",cursor:"pointer"});const n=document.createElement("a");n.textContent="Open workspace",n.dataset.testid="device-invite-continue",n.hidden=!0,Object.assign(n.style,{display:"inline-block",marginTop:"18px",borderRadius:"8px",padding:"9px 14px",background:"#2563eb",color:"#fff",textDecoration:"none"}),o.append(r,s,e,t,n),a.append(o),p.append(a);let c=!1;const l=async()=>{if(!c){c=!0,t.hidden=!0,n.hidden=!0,e.style.color="",e.textContent="Creating this browser's private device key…";try{const i=m(window.location.href),u=await d.loadIdentity();e.textContent="Accepting the workspace invite…",await d.createTrustApi().acceptDeviceInvite(u,i),window.history.replaceState(null,"","/"),e.textContent="Device added. This browser can now open every backend in the workspace.",e.style.color="#15803d",n.href="/",n.hidden=!1}catch(i){e.textContent=i instanceof Error?i.message:"Device invite failed",e.style.color="#b91c1c",t.hidden=!1}finally{c=!1}}};t.addEventListener("click",()=>{l()}),await l()}export{h as initializeDeviceInvitePage};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/device-invite-page-BXdui21Z.js","assets/device-identity-C_w2NbSk.js","assets/rendezvous-trust-api-Bv6fZVJA.js","assets/pairing-page-BUVrsL9A.js","assets/webrtc-frame-transport-Drpqhhdy.js","assets/__vite-browser-external-DGfF_P2w.js","assets/remote-backend-manager-vEOu2dhH.js","assets/backend-protocol-BvNAsFvb.js","assets/ws-agent-adapter-BUykBiJL.js","assets/workspace-backend-client-C2DwlCed.js","assets/main-BOivrw8_.js","assets/app-runtime-Rw-O-AwW.js","assets/backend-landing-page-DnP0b68z.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
(function(){const n=document.createElement("link").relList;if(n&&n.supports&&n.supports("modulepreload"))return;for(const t of document.querySelectorAll('link[rel="modulepreload"]'))a(t);new MutationObserver(t=>{for(const r of t)if(r.type==="childList")for(const i of r.addedNodes)i.tagName==="LINK"&&i.rel==="modulepreload"&&a(i)}).observe(document,{childList:!0,subtree:!0});function o(t){const r={};return t.integrity&&(r.integrity=t.integrity),t.referrerPolicy&&(r.referrerPolicy=t.referrerPolicy),t.crossOrigin==="use-credentials"?r.credentials="include":t.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function a(t){if(t.ep)return;t.ep=!0;const r=o(t);fetch(t.href,r)}})();const w="modulepreload",_=function(e){return"/"+e},m={},u=function(n,o,a){let t=Promise.resolve();if(o&&o.length>0){let f=function(s){return Promise.all(s.map(l=>Promise.resolve(l).then(p=>({status:"fulfilled",value:p}),p=>({status:"rejected",reason:p}))))};document.getElementsByTagName("link");const i=document.querySelector("meta[property=csp-nonce]"),c=i?.nonce||i?.getAttribute("nonce");t=f(o.map(s=>{if(s=_(s),s in m)return;m[s]=!0;const l=s.endsWith(".css"),p=l?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${s}"]${p}`))return;const d=document.createElement("link");if(d.rel=l?"stylesheet":w,l||(d.as="script"),d.crossOrigin="",d.href=s,c&&d.setAttribute("nonce",c),document.head.appendChild(d),l)return new Promise((g,v)=>{d.addEventListener("load",g),d.addEventListener("error",()=>v(new Error(`Unable to preload CSS for ${s}`)))})}))}function r(i){const c=new Event("vite:preloadError",{cancelable:!0});if(c.payload=i,window.dispatchEvent(c),!c.defaultPrevented)throw i}return t.then(i=>{for(const c of i||[])c.status==="rejected"&&r(c.reason);return n().catch(r)})};"serviceWorker"in navigator&&navigator.serviceWorker.getRegistrations().then(e=>{for(const n of e)n.unregister()});y();async function y(){if(b(window.location.pathname)){const{initializeDeviceInvitePage:o}=await u(async()=>{const{initializeDeviceInvitePage:a}=await import("./device-invite-page-BXdui21Z.js");return{initializeDeviceInvitePage:a}},__vite__mapDeps([0,1,2]));await o();return}if(k(window.location.pathname)){const{initializePairingPage:o}=await u(async()=>{const{initializePairingPage:a}=await import("./pairing-page-BUVrsL9A.js");return{initializePairingPage:a}},__vite__mapDeps([3,1,2,4,5]));await o();return}const e=L(window.location.pathname);if(e!==void 0||window.location.pathname==="/"&&await E())try{const[{configureAppRuntime:o},{RemoteBackendManager:a},{WorkspaceBackendClient:t},{loadBrowserDeviceIdentity:r}]=await Promise.all([u(()=>import("./app-runtime-Rw-O-AwW.js"),[]),u(()=>import("./remote-backend-manager-vEOu2dhH.js"),__vite__mapDeps([6,7,1,2,4,5,8])),u(()=>import("./workspace-backend-client-C2DwlCed.js"),__vite__mapDeps([9,7])),u(()=>import("./device-identity-C_w2NbSk.js").then(f=>f.d),[])]);if(!await r()){await h();return}const i=new a(window.location.origin),c=await i.initialize();if(c.length===0){await h();return}o({client:new t(c,i,e)})}catch(o){P(o);return}await u(()=>import("./main-BOivrw8_.js"),__vite__mapDeps([10,8,7,5,11,1,2]))}async function h(){const{initializeBackendLandingPage:e}=await u(async()=>{const{initializeBackendLandingPage:n}=await import("./backend-landing-page-DnP0b68z.js");return{initializeBackendLandingPage:n}},__vite__mapDeps([12,7,1,2]));await e()}async function E(){try{const e=await fetch("/health",{cache:"no-store"});if(!e.ok||!e.headers.get("content-type")?.includes("application/json"))return!1;const n=await e.json();return!!n&&typeof n=="object"&&n.ok===!0}catch{return!1}}function P(e){const n=document.getElementById("app")??document.body;n.replaceChildren();const o=document.createElement("main");o.style.cssText="min-height:100vh;display:grid;place-items:center;padding:24px;font-family:ui-sans-serif,system-ui;color:var(--foreground,#111827);background:var(--background,#fff)";const a=document.createElement("section");a.style.cssText="max-width:520px;border:1px solid var(--border,#d1d5db);border-radius:12px;padding:28px";const t=document.createElement("h1");t.textContent="Cannot open backend";const r=document.createElement("p");r.textContent=e instanceof Error?e.message:"This browser is not authorized for the backend.";const i=document.createElement("p");i.textContent="To restore access, run `pipane pair` in the backend terminal and scan the new QR code with this browser.",a.append(t,r,i),o.append(a),n.append(o)}function b(e){return/^\/invite\/[^/]+$/u.test(e)}function k(e){return/^\/pair\/[^/]+$/u.test(e)}function L(e){const n=/^\/backend\/([^/]+)$/u.exec(e);return n?.[1]?decodeURIComponent(n[1]):void 0}export{u as _};
|