@opencode/console 0.0.0-stage → 0.1.1

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.
@@ -0,0 +1 @@
1
+ import{gt,en,tn,nn,rn,Ys,Qo}from"./chunk-frqdgjbd.js";import"./chunk-p59r4b0j.js";import"./chunk-2y9vn023.js";import"./chunk-6rpbc10h.js";import"./chunk-zdf3mvav.js";export{Qo as Library,tn as fetchChanged,gt as library,en as servers,Ys as skillMarkdown,nn as write,rn as writeInstructions};
@@ -0,0 +1,2 @@
1
+ import{k,c,i,a,Es,P,u,O,St,$e,Lt,Re,r,o,q,Co,Jn,Ao,ot}from"./chunk-bkr0zk6g.js";var pi={};k(pi,{BrandError:()=>b,all:()=>M,check:()=>R,make:()=>D,nominal:()=>Ss});var fi={};k(fi,{Path:()=>Ft,TypeId:()=>C,layer:()=>Y,make:()=>Un});class b{constructor(e){this.issue=e}_tag="BrandError";name="BrandError";issue;get message(){return Co(this.issue)}toString(){return`BrandError(${this.message})`}}function Ss(){return Object.assign((e)=>e,{option:(e)=>a(e),result:(e)=>u(e),is:(e)=>!0})}function D(e){return R(Jn(e))}function R(...e){let t=(s)=>St(Ao(e,s),(f)=>new b(f));return Object.assign((s)=>$e(t(s)),{option:(s)=>Es(t(s)),result:t,is:(s)=>O(t(s)),checks:e})}function M(...e){let t=e.flatMap((s)=>s.checks??[]);return Lt(t)?R(...t):Ss()}var C="~effect/Path",Ft=P("effect/Path"),Un=(e)=>Ft.of({...e,[C]:C,resolveWithin(t,s){if(e.parse(s).root!=="")return i();let f=e.resolve(t),l=e.resolve(f,s),n=e.relative(f,l);return n===".."||n.startsWith(`..${e.sep}`)||e.isAbsolute(n)?i():a(l)}});function E(e,t){let s="",f=0,l=-1,n=0,x;for(let m=0;m<=e.length;++m){if(m<e.length)x=e.charCodeAt(m);else if(x===47)break;else x=47;if(x===47){if(l===m-1||n===1);else if(l!==m-1&&n===2){if(s.length<2||f!==2||s.charCodeAt(s.length-1)!==46||s.charCodeAt(s.length-2)!==46){if(s.length>2){let d=s.lastIndexOf("/");if(d!==s.length-1){if(d===-1)s="",f=0;else s=s.slice(0,d),f=s.length-1-s.lastIndexOf("/");l=m,n=0;continue}}else if(s.length===2||s.length===1){s="",f=0,l=m,n=0;continue}}if(t){if(s.length>0)s+="/..";else s="..";f=2}}else{if(s.length>0)s+="/"+e.slice(l+1,m);else s=e.slice(l+1,m);f=m-l-1}l=m,n=0}else if(x===46&&n!==-1)++n;else n=-1}return s}function N(e){if(!e)return"";return e.startsWith(".")?e:`.${e}`}function z(e,t){let s=t.dir||t.root,f=t.base||(t.name||"")+N(t.ext);if(!s)return f;if(s===t.root)return s+f;return s+e+f}function _(e){if(e.protocol!=="file:")return o(new ot({module:"Path",method:"fromFileUrl",description:"URL must be of scheme file"}));else if(e.hostname!=="")return o(new ot({module:"Path",method:"fromFileUrl",description:"Invalid file URL host"}));let t=e.pathname;for(let s=0;s<t.length;s++)if(t[s]==="%"){let f=t.codePointAt(s+2)|32;if(t[s+1]==="2"&&f===102)return o(new ot({module:"Path",method:"fromFileUrl",description:"must not include encoded / characters"}))}return q({try:()=>decodeURIComponent(t),catch:(s)=>new ot({module:"Path",method:"fromFileUrl",cause:s})})}var T=function(){let t="",s=!1,f=void 0;for(let l=arguments.length-1;l>=-1&&!s;l--){let n;if(l>=0)n=arguments[l];else{let x=globalThis.process;if(f===void 0&&"process"in globalThis&&typeof x==="object"&&x!==null&&typeof x.cwd==="function")f=x.cwd();n=f}if(n.length===0)continue;t=n+"/"+t,s=n.charCodeAt(0)===47}if(t=E(t,!s),s)if(t.length>0)return"/"+t;else return"/";else if(t.length>0)return t;else return"."},W=47;function G(e){let t=new URL("file://"),s=T(e);if(e.charCodeAt(e.length-1)===W&&s[s.length-1]!=="/")s+="/";return t.pathname=X(s),r(t)}var J=/%/g,Q=/\\/g,V=/\n/g,K=/\r/g,j=/\t/g;function X(e){if(e.includes("%"))e=e.replace(J,"%25");if(e.includes("\\"))e=e.replace(Q,"%5C");if(e.includes(`
2
+ `))e=e.replace(V,"%0A");if(e.includes("\r"))e=e.replace(K,"%0D");if(e.includes("\t"))e=e.replace(j,"%09");return e}var S=Un({resolve:T,normalize(e){if(e.length===0)return".";let t=e.charCodeAt(0)===47,s=e.charCodeAt(e.length-1)===47;if(e=E(e,!t),e.length===0&&!t)e=".";if(e.length>0&&s)e+="/";if(t)return"/"+e;return e},isAbsolute(e){return e.length>0&&e.charCodeAt(0)===47},join(){if(arguments.length===0)return".";let e;for(let t=0;t<arguments.length;++t){let s=arguments[t];if(s.length>0)if(e===void 0)e=s;else e+="/"+s}if(e===void 0)return".";return S.normalize(e)},relative(e,t){if(e===t)return"";if(e=S.resolve(e),t=S.resolve(t),e===t)return"";let s=1;for(;s<e.length;++s)if(e.charCodeAt(s)!==47)break;let f=e.length,l=f-s,n=1;for(;n<t.length;++n)if(t.charCodeAt(n)!==47)break;let m=t.length-n,d=l<m?l:m,h=-1,p=0;for(;p<=d;++p){if(p===d){if(m>d){if(t.charCodeAt(n+p)===47)return t.slice(n+p+1);else if(p===0)return t.slice(n+p)}else if(l>d){if(e.charCodeAt(s+p)===47)h=p;else if(p===0)h=0}break}let A=e.charCodeAt(s+p),L=t.charCodeAt(n+p);if(A!==L)break;else if(A===47)h=p}let g="";for(p=s+h+1;p<=f;++p)if(p===f||e.charCodeAt(p)===47)if(g.length===0)g+="..";else g+="/..";if(g.length>0)return g+t.slice(n+h);else{if(n+=h,t.charCodeAt(n)===47)++n;return t.slice(n)}},dirname(e){if(e.length===0)return".";let t=e.charCodeAt(0),s=t===47,f=-1,l=!0;for(let n=e.length-1;n>=1;--n)if(t=e.charCodeAt(n),t===47){if(!l){f=n;break}}else l=!1;if(f===-1)return s?"/":".";if(s&&f===1)return"//";return e.slice(0,f)},basename(e,t){let s=0,f=-1,l=!0,n;if(t!==void 0&&t.length>0&&t.length<=e.length){if(t.length===e.length&&t===e)return"";let x=t.length-1,m=-1;for(n=e.length-1;n>=0;--n){let d=e.charCodeAt(n);if(d===47){if(!l){s=n+1;break}}else{if(m===-1)l=!1,m=n+1;if(x>=0)if(d===t.charCodeAt(x)){if(--x===-1)f=n}else x=-1,f=m}}if(s===f)f=m;else if(f===-1)f=e.length;return e.slice(s,f)}else{for(n=e.length-1;n>=0;--n)if(e.charCodeAt(n)===47){if(!l){s=n+1;break}}else if(f===-1)l=!1,f=n+1;if(f===-1)return"";return e.slice(s,f)}},extname(e){let t=-1,s=0,f=-1,l=!0,n=0;for(let x=e.length-1;x>=0;--x){let m=e.charCodeAt(x);if(m===47){if(!l){s=x+1;break}continue}if(f===-1)l=!1,f=x+1;if(m===46){if(t===-1)t=x;else if(n!==1)n=1}else if(t!==-1)n=-1}if(t===-1||f===-1||n===0||n===1&&t===f-1&&t===s+1)return"";return e.slice(t,f)},format:function(t){if(t===null||typeof t!=="object")throw TypeError('The "pathObject" argument must be of type Object. Received type '+typeof t);return z("/",t)},parse(e){let t={root:"",dir:"",base:"",ext:"",name:""};if(e.length===0)return t;let s=e.charCodeAt(0),f=s===47,l;if(f)t.root="/",l=1;else l=0;let n=-1,x=0,m=-1,d=!0,h=e.length-1,p=0;for(;h>=l;--h){if(s=e.charCodeAt(h),s===47){if(!d){x=h+1;break}continue}if(m===-1)d=!1,m=h+1;if(s===46){if(n===-1)n=h;else if(p!==1)p=1}else if(n!==-1)p=-1}if(n===-1||m===-1||p===0||p===1&&n===m-1&&n===x+1){if(m!==-1)if(x===0&&f)t.base=t.name=e.slice(1,m);else t.base=t.name=e.slice(x,m)}else{if(x===0&&f)t.name=e.slice(1,n),t.base=e.slice(1,m);else t.name=e.slice(x,n),t.base=e.slice(x,m);t.ext=e.slice(n,m)}if(x>0)t.dir=e.slice(0,x-1);else if(f)t.dir="/";return t},sep:"/",fromFileUrl:_,toFileUrl:G,toNamespacedPath:c}),Y=Re(Ft)(S);export{Ss,pi,Ft,Un,fi};
package/index.js ADDED
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+ import{Me}from"./chunk-jh21wbwd.js";import{spawn as F}from"node:child_process";import N from"node:path";import{parseArgs as q}from"node:util";var S=q({allowPositionals:!0,strict:!1,options:{harness:{type:"string"},server:{type:"string"},json:{type:"boolean"},quiet:{type:"boolean"},remove:{type:"boolean"}}}),y=S.positionals[0],g=S.values,k=R("harness")??process.env.OPENCODE_CONSOLE_HARNESS,_="Not signed in. Run `npx @opencode/console login` or set OPENCODE_API_KEY.",j=["claude-code","pi","codex"],H=["claude-code","codex"],J={check:B,hook:V,login:Z,logout:se,"mcp-headers":ne,setup:Q,status:re,sync:ie,token:ae},x,K=y?J[y]:void 0;if(!K)process.stdout.write(pe()),process.exit(y&&!["help","--help","-h"].includes(y)?1:0);process.exitCode=await K().catch(async(o)=>{if(y==="hook")return b(`opencode-console couldn't check this: ${h(o)}`);if(process.stderr.write(`${h(o)}
3
+ `),y!=="check")return 1;return T(`opencode-console couldn't check this call: ${h(o)}`)});async function B(){let{Option:o,Schema:e}=await import("./chunk-p7wsm5k0.js"),t=e.decodeUnknownOption(e.fromJsonString(e.Struct({action:e.NonEmptyString,resources:e.NonEmptyArray(e.String),directory:e.optional(e.String),path:e.optional(e.String),shell:e.optional(e.String)})))(await L());if(o.isNone(t))return process.stderr.write(`Expected JSON on stdin: {"action": "...", "resources": ["...", ...]}
4
+ `),T("opencode-console couldn't read this tool call, so it was blocked");let[s]=await M([t.value]);return process.stdout.write(`${JSON.stringify(s)}
5
+ `),s?.effect==="deny"?2:0}async function V(){let o=S.positionals[1];if(!o||!H.includes(o))return process.stderr.write(`Usage: opencode-console hook <${H.join("|")}>
6
+ `),2;let{Option:e}=await import("./chunk-p7wsm5k0.js"),{ClaudeCodeHook:t}=await import("./chunk-kdkxhbxc.js"),s=await L();x=t.eventName(s);let r=o==="codex"?await G(s):c(t.decode(s));if(r===void 0)return b("opencode-console couldn't read this hook's input, so it was blocked");if(x==="SessionStart")return X();if(r.length===0)return 0;let a=(await M(r)).find((n)=>n.effect==="deny");return a?.effect==="deny"?b(a.message):0;function c(n){return e.isNone(n)?void 0:t.checks(n.value)}}async function G(o){let{Option:e}=await import("./chunk-p7wsm5k0.js"),{CodexHook:t}=await import("./chunk-c16zjbe1.js"),{Library:s}=await import("./chunk-xeq3evq0.js"),{WorkspaceSnapshot:r}=await import("./chunk-c9kvdzct.js"),{ConsoleStore:a}=await import("./chunk-mpmqsnkz.js"),c=t.decode(o);if(e.isNone(c))return;let n=r.read(a.make())?.config??{};return t.checks(c.value,{directory:process.cwd(),platform:process.platform,servers:Object.keys(s.servers(n))})}async function X(){let{ConsoleStore:o}=await import("./chunk-mpmqsnkz.js"),{ConsoleCredentials:e}=await import("./chunk-kvqewrn5.js"),{WorkspaceSync:t}=await import("./chunk-hpy9mszv.js"),s=o.make(),r=e.read(s);if(!r)return 0;await A({always:!0,force:!0});let a=t.current(s,e.owner(r))?.status;if(a)process.stdout.write(`${JSON.stringify({systemMessage:`${a.message}${a.url?`: ${a.url}`:""}`})}
7
+ `);return 0}async function M(o){let{Effect:e}=await import("./chunk-p7wsm5k0.js"),{ConsoleStore:t}=await import("./chunk-mpmqsnkz.js"),{ConsoleCredentials:s}=await import("./chunk-kvqewrn5.js"),{WorkspaceSnapshot:r}=await import("./chunk-c9kvdzct.js"),{PolicyEvaluator:a}=await import("./chunk-mzpdnb17.js"),c=t.make(),n=s.read(c),i=n&&s.owner(n),l=n?r.read(c):void 0,d=i&&l?.owner!==i?await(async()=>(await A({always:!0}),ce(()=>{let u=r.read(c);return u?.owner===i?u:void 0},3000)))():l&&r.stale(l,Date.now())?(await A(),l):l,p=r.workspace(n,d);return e.runPromise(e.forEach(o,(u)=>a.check(p,u)))}async function Z(){if(!await W())return 1;if(process.env.OPENCODE_API_KEY)process.stderr.write(`OPENCODE_API_KEY is set, so opencode-console keeps using that key until it's unset
8
+ `);return 0}async function W(){let{Effect:o}=await import("./chunk-p7wsm5k0.js"),{openUrl:e}=await import("./chunk-aesb1szb.js"),{ConsoleClient:t}=await import("./chunk-vqmbpbbm.js"),{ConsoleStore:s}=await import("./chunk-mpmqsnkz.js"),{ConsoleCredentials:r}=await import("./chunk-kvqewrn5.js"),{WorkspaceSync:a}=await import("./chunk-hpy9mszv.js"),c=R("server")??process.env.OPENCODE_CONSOLE_SERVER??t.defaultServer,n=t.normalizeServer(c);if(!n){process.stderr.write(`Not a Console URL: ${c}
9
+ `);return}let i=s.make(),l=await f(r.login(i,{server:n,prompt:(p)=>o.promise(async()=>{if(process.stderr.write(`Open ${p.url} and confirm the code ${p.code}
10
+ `),process.stdout.isTTY)await e(p.url).catch(()=>{return})})})),d=await f(a.sync(i,{force:!0}));if(process.stdout.write(`Signed in to ${l.orgName??"OpenCode Console"}${l.email?` as ${l.email}`:""}
11
+ `),d.error)process.stderr.write(`Couldn't fetch the workspace config: ${h(d.error)}. Run the command again to retry.
12
+ `);return l}async function Q(){let o=S.positionals[1];if(!o||!j.includes(o))return process.stderr.write(`Usage: opencode-console setup <${j.join("|")}> [--remove]
13
+ `),1;let e=o==="pi",t=o==="codex",s=e?"Pi":t?"Codex":"Claude Code",{ConsoleStore:r}=await import("./chunk-mpmqsnkz.js"),{ConsoleCredentials:a}=await import("./chunk-kvqewrn5.js"),{CliInstall:c}=await import("./chunk-5w6hy202.js"),{WorkspaceSync:n}=await import("./chunk-hpy9mszv.js"),i=r.make();if(g.remove===!0){let{Effect:v}=await import("./chunk-p7wsm5k0.js"),{ClaudeCode:O}=await import("./chunk-2ktsq2gj.js"),{Codex:P}=await import("./chunk-nvh2a5rc.js"),{Pi:C}=await import("./chunk-eyf3z07t.js"),Y=await v.runPromise(r.locked(i,v.sync(()=>{let U=e?C.remove(i):t?P.remove(i):O.remove(i);if(![O.manifestFile(i),C.manifestFile(i),P.manifestFile(i)].some((z)=>r.read(z)!==void 0))c.uninstall(i);return U})));return process.stdout.write(Y?`Removed OpenCode Console from ${s} and restored its settings. You're still signed in; \`npx @opencode/console logout\` signs out.
14
+ `:`${s} wasn't set up with OpenCode Console
15
+ `),0}let{ConsoleClient:l}=await import("./chunk-vqmbpbbm.js"),d=await de(e?"pi":t?"codex":"claude");if(d)k=e?`pi/${d}`:t?`codex_cli_rs/${d}`:`claude-cli/${d}`;let p=a.read(i),u=R("server");if(!p||u!==void 0&&p.server!==l.normalizeServer(u)){if(!await W())return 1}if(process.env.OPENCODE_API_KEY)process.stderr.write(`OPENCODE_API_KEY is set, so setup used that key, and ${s} will use it instead of your sign-in wherever it's set.
16
+ `);let w=await f(n.sync(i,{force:!0}));if(!w.snapshot?.config)return process.stderr.write(`Couldn't fetch the workspace config${w.error?`: ${h(w.error)}`:""}. Run setup again.
17
+ `),1;if(e&&D())return process.stderr.write("Set up Pi with the npm package: `npx @opencode/console setup pi`\n"),1;let E=c.install(i,{execPath:process.execPath,entry:D()?void 0:process.argv[1],path:process.env.PATH});if(t)return te(i,E,w.snapshot,d);return e?oe(i,E,w.snapshot,d):ee(i,E,w.snapshot,d)}async function ee(o,e,t,s){let{ClaudeCode:r}=await import("./chunk-2ktsq2gj.js"),{WorkspaceSnapshot:a}=await import("./chunk-c9kvdzct.js"),c=a.policies(t),n=await f(r.refresh(o,{paths:r.paths(),command:e,harness:s?`claude-cli/${s}`:void 0}));if(!n)return process.stderr.write(`Couldn't read the workspace config. Run setup again.
18
+ `),1;let l=[`Claude Code now uses ${t.organization??"your workspace"} through OpenCode Console.`,"",...n.models?[` Models ${m(n.models.options.length,"model","models")} in /model; opus is ${n.models.tiers.opus}, sonnet ${n.models.tiers.sonnet}, haiku ${n.models.tiers.haiku}`]:[" Models none from the workspace, so Claude Code keeps its own sign-in"],` Policies ${m(c?.length??0,"rule","rules")}, checked before every tool call`,...n.servers.length>0?[` MCP ${n.servers.join(", ")}`]:[],...I(n.instructions,n.skills.map((p)=>`/${p}`))];if(process.stdout.write(`${l.join(`
19
+ `)}
20
+ `),n.skipped.length>0)process.stderr.write(`
21
+ Kept your own ${n.skipped.join(", ")}, so the workspace's of the same name weren't added.
22
+ `);if(!s)process.stderr.write(`
23
+ Claude Code isn't on your PATH yet; these settings apply once it's installed.
24
+ `);let d=["ANTHROPIC_AUTH_TOKEN","ANTHROPIC_API_KEY"].filter((p)=>process.env[p]);if(n.models&&d.length>0)process.stderr.write(`
25
+ ${d.join(" and ")} ${d.length===1?"is":"are"} set in your shell and Claude Code would use ${d.length===1?"it":"them"} instead of the workspace. Unset ${d.length===1?"it":"them"} before running claude.
26
+ `);return process.stdout.write(`
27
+ Run claude to start.
28
+ `),0}async function oe(o,e,t,s){let{Pi:r}=await import("./chunk-eyf3z07t.js"),{Library:a}=await import("./chunk-xeq3evq0.js"),{WorkspaceSnapshot:c}=await import("./chunk-c9kvdzct.js"),n=e.at(-1),i=N.join(N.dirname(n),`pi-extension${N.extname(n)}`),l=r.session({store:o,...k?{harness:k}:{}}),d=await r.models(l),p=d&&r.defaultModel(d);await r.skills(l).catch((C)=>{process.stderr.write(`Couldn't download the Library's skills yet (${h(C)}); Pi tries again when it starts.
29
+ `);return});let u=t.config??{},{Effect:w}=await import("./chunk-p7wsm5k0.js"),{ConsoleStore:E}=await import("./chunk-mpmqsnkz.js");await w.runPromise(E.locked(o,w.sync(()=>r.setup(o,{paths:r.paths(),extension:i,...p?{model:p}:{}}))));let v=d?r.providers(d,()=>{return}).flatMap((C)=>C.models):[],O=Object.keys(a.servers(u)),P=[`Pi now uses ${t.organization??"your workspace"} through OpenCode Console.`,"",p?` Models ${m(v.length,"model","models")} in /model; new sessions start on ${p.provider}/${p.id}`:" Models none from the workspace, so Pi keeps its own providers",` Policies ${m(c.policies(t)?.length??0,"rule","rules")}, checked before every tool call and !command`,...O.length>0?[` MCP ${O.join(", ")}`]:[],...I(a.library(u).instructions.length,a.library(u).skills.map((C)=>`/skill:${C.slug}`))];if(process.stdout.write(`${P.join(`
30
+ `)}
31
+ `),!s)process.stderr.write(`
32
+ Pi isn't on your PATH yet; this applies once it's installed.
33
+ `);return process.stdout.write(`
34
+ Run pi to start.
35
+ `),0}async function te(o,e,t,s){let{Codex:r}=await import("./chunk-nvh2a5rc.js"),{WorkspaceSnapshot:a}=await import("./chunk-c9kvdzct.js"),c=Object.fromEntries(["XDG_DATA_HOME","XDG_CACHE_HOME","OPENCODE_CONSOLE_SERVER"].flatMap((u)=>process.env[u]?[[u,process.env[u]]]:[])),n=await f(r.refresh(o,{paths:r.paths(),command:e,harness:s?`codex_cli_rs/${s}`:void 0,environment:c}));if(!n)return process.stderr.write(`Couldn't read the workspace config. Run setup again.
36
+ `),1;let i=a.policies(t)?.length??0,l=[`Codex now uses ${t.organization??"your workspace"} through OpenCode Console.`,"",n.models?` Models ${m(n.models.count,"model","models")} in /model; new sessions start on ${n.models.model}`:" Models none from the workspace, so Codex keeps its own sign-in",` Policies ${m(i,"rule","rules")}, checked before every tool call${n.rules>0?`; Codex also enforces ${m(n.rules,"shell rule","shell rules")} itself`:""}`,...n.searchOff?[" Search Codex's web search is off, since the workspace's policy limits it"]:[],...n.servers.length>0?[` MCP ${n.servers.join(", ")}`]:[],...I(n.instructions,n.skills.map((u)=>`$${u}`))];if(process.stdout.write(`${l.join(`
37
+ `)}
38
+ `),n.skipped.length>0)process.stderr.write(`
39
+ Kept your own ${n.skipped.join(", ")}, so the workspace's of the same name weren't added.
40
+ `);let{Library:d}=await import("./chunk-xeq3evq0.js"),p=Object.entries(d.servers(t.config??{})).filter(([u,w])=>w.headers!==void 0&&n.servers.includes(u)).map(([u])=>u);if(process.env.OPENCODE_API_KEY&&p.length>0)process.stderr.write(`
41
+ Codex connects to ${p.join(", ")} without your shell's environment, so ${p.length===1?"it":"they"} can't use OPENCODE_API_KEY. Run \`npx @opencode/console login\` to connect ${p.length===1?"it":"them"}.
42
+ `);if(!s)process.stderr.write(`
43
+ Codex isn't on your PATH yet; these settings apply once it's installed.
44
+ `);return process.stdout.write(`
45
+ Run codex to start.
46
+ `),0}function I(o,e){if(o+e.length===0)return[];return[` Library ${[...o>0?[m(o,"instruction","instructions")]:[],...e.length>0?[e.join(", ")]:[]].join(", ")}`]}async function ne(){let o=S.positionals[1];if(!o)return process.stderr.write(`Usage: opencode-console mcp-headers <server>
47
+ `),1;let{Option:e,Schema:t}=await import("./chunk-p7wsm5k0.js"),{ConsoleStore:s}=await import("./chunk-mpmqsnkz.js"),{WorkspaceSync:r}=await import("./chunk-hpy9mszv.js"),{snapshot:a}=await f(r.sync(s.make()));if(!a)return process.stderr.write(`${_}
48
+ `),1;let c=t.decodeUnknownOption(t.Struct({servers:t.Record(t.String,t.Struct({headers:t.optional(t.Record(t.String,t.String))}))}))(a.config?.mcp),n=e.getOrUndefined(c)?.servers[o];if(!n)return process.stderr.write(`The workspace doesn't offer the MCP server ${o} anymore
49
+ `),1;return process.stdout.write(`${JSON.stringify(n.headers??{})}
50
+ `),0}async function se(){let{ConsoleStore:o}=await import("./chunk-mpmqsnkz.js"),{ConsoleCredentials:e}=await import("./chunk-kvqewrn5.js"),t=await f(e.logout(o.make()));if(process.stdout.write(t?`Signed out of OpenCode Console
51
+ `:`Not signed in
52
+ `),process.env.OPENCODE_API_KEY)process.stdout.write(`OPENCODE_API_KEY is still set, so opencode-console keeps using that key
53
+ `);return 0}async function re(){let{ConsoleStore:o}=await import("./chunk-mpmqsnkz.js"),{ConsoleCredentials:e}=await import("./chunk-kvqewrn5.js"),{WorkspaceSnapshot:t}=await import("./chunk-c9kvdzct.js"),{WorkspaceSync:s}=await import("./chunk-hpy9mszv.js"),r=o.make(),a=e.read(r),c=a?(await f(s.sync(r))).snapshot:void 0,n=t.policies(c),i=a&&{server:a.server,credential:a.type==="key"?"OPENCODE_API_KEY":"device",email:a.type==="oauth"?a.email:void 0,workspace:c?.organization??e.organization(a),synced:n&&c?new Date(c.fetched).toISOString():void 0,policies:n?.length,models:t.models(c),needs:c?.status};if(g.json===!0)return process.stdout.write(`${JSON.stringify({signedIn:Boolean(i),...i})}
54
+ `),0;if(!i)return process.stdout.write(`${_}
55
+ `),0;let l=[["Signed in",i.credential==="OPENCODE_API_KEY"?"with OPENCODE_API_KEY":i.email??"yes"],...i.workspace?[["Workspace",i.workspace]]:[],["Console",i.server],["Policies",i.synced?`${m(i.policies??0,"policy","policies")}, synced at ${new Date(i.synced).toLocaleTimeString()}`:"not loaded yet, so tool calls are blocked"],["Models",i.models?`${i.models} from the workspace`:"none from the workspace"]];if(process.stdout.write(l.map(([d,p])=>`${d?.padEnd(10)} ${p}
56
+ `).join("")),i.needs)process.stdout.write(`
57
+ ${i.needs.message}${i.needs.url?`: ${i.needs.url}`:""}
58
+ `);return 0}async function ie(){let{ConsoleStore:o}=await import("./chunk-mpmqsnkz.js"),{WorkspaceSnapshot:e}=await import("./chunk-c9kvdzct.js"),{WorkspaceSync:t}=await import("./chunk-hpy9mszv.js"),s=o.make(),r=e.read(s)?.fetched,a=await f(t.sync(s,{force:g.quiet!==!0||process.env.OPENCODE_CONSOLE_FORCE==="1"}));if(a.snapshot?.config&&!a.error&&a.snapshot.fetched!==r){let{ClaudeCode:i}=await import("./chunk-2ktsq2gj.js"),{Codex:l}=await import("./chunk-nvh2a5rc.js");await f(i.refresh(s)).catch((d)=>{if(g.quiet!==!0)process.stderr.write(`Couldn't update Claude Code: ${h(d)}
59
+ `)}),await f(l.refresh(s)).catch((d)=>{if(g.quiet!==!0)process.stderr.write(`Couldn't update Codex: ${h(d)}
60
+ `)})}if(g.quiet===!0)return a.error?1:0;if(!a.snapshot&&!a.error)return process.stderr.write(`${_}
61
+ `),1;if(a.error){let i=e.policies(a.snapshot)?`
62
+ Policies from the last sync still apply.`:"";return process.stderr.write(`Couldn't sync: ${h(a.error)}${i}
63
+ `),1}let c=a.snapshot?.organization,n=e.policies(a.snapshot)?.length??0;return process.stdout.write(`Synced ${c?`${c}'s`:"the workspace"} config (${m(n,"policy","policies")})
64
+ `),0}async function ae(){let{ConsoleStore:o}=await import("./chunk-mpmqsnkz.js"),{ConsoleCredentials:e}=await import("./chunk-kvqewrn5.js"),t=await f(e.fresh(o.make()));if(!t)return process.stderr.write(`${_}
65
+ `),1;return process.stdout.write(`${t.type==="key"?t.key:t.access}
66
+ `),0}async function f(o){let{Effect:e,Layer:t}=await import("./chunk-p7wsm5k0.js"),{FetchHttpClient:s}=await import("./chunk-aym5xapq.js"),{WorkspaceSync:r}=await import("./chunk-hpy9mszv.js");return e.runPromise(o.pipe(e.provide(r.identify({version:Me,harness:k}).pipe(t.provide(s.layer)))))}async function A(o={}){let{ConsoleStore:e}=await import("./chunk-mpmqsnkz.js"),t=e.syncClaimFile(e.make());try{let s=e.modified(t);if(!o.always&&s!==void 0&&Date.now()-s<30000)return;e.write(t,"");let r=D()?[process.execPath]:[process.execPath,process.argv[1]];F(r[0],[...r.slice(1),"sync","--quiet",...k?["--harness",k]:[]],{detached:!0,stdio:"ignore",env:{...process.env,...o.force?{OPENCODE_CONSOLE_FORCE:"1"}:{}}}).on("error",()=>{return}).unref()}catch{return}}async function ce(o,e){let t=Date.now()+e;for(;;){let s=o();if(s!==void 0||Date.now()>=t)return s;await new Promise((r)=>setTimeout(r,25))}}async function b(o){let{ClaudeCodeHook:e}=await import("./chunk-kdkxhbxc.js"),t=e.denial(x,o);return process.stdout.write(t.stdout),process.stderr.write(t.stderr),t.code}async function de(o){let{execFile:e}=await import("node:child_process");return new Promise((t)=>e(o,["--version"],{timeout:1e4},(s,r)=>t(s?void 0:r.match(/\d+\.\d+\.\d+\S*/)?.[0])))}function T(o){return process.stdout.write(`${JSON.stringify({effect:"deny",message:o})}
67
+ `),2}function m(o,e,t){return`${o} ${o===1?e:t}`}function D(){return/^(\/\$bunfs\/|[A-Za-z]:[\\/]~BUN[\\/])/.test(process.argv[1]??"")}async function L(){let o=[];for await(let e of process.stdin)o.push(Buffer.from(e));return Buffer.concat(o).toString("utf8")}function h(o){return o instanceof Error?o.message:String(o)}function R(o){let e=g[o];return typeof e==="string"?e:void 0}function pe(){return`opencode-console ${Me}
68
+ Connect coding agents to an OpenCode Console workspace: its models, MCP servers, Library and policies.
69
+
70
+ Usage: opencode-console <command> [options]
71
+
72
+ Commands:
73
+ setup <claude-code|pi|codex>
74
+ Sign in if needed and set up Claude Code, Pi or Codex to use the
75
+ workspace (--remove undoes it)
76
+ login [--server <url>] Sign in to OpenCode Console and pick a workspace
77
+ logout Sign out and remove the stored workspace config
78
+ status [--json] Show the sign-in, workspace and config
79
+ sync Fetch the workspace config now
80
+ token Print an access token for auth helpers such as Claude Code's apiKeyHelper
81
+ and Codex's model provider auth
82
+ check Check a tool call against the workspace's policies. Reads
83
+ {"action": "...", "resources": [...]} on stdin, with optional
84
+ "directory", "path" and "shell"; exits 0 to allow, 2 to deny
85
+ hook <claude-code|codex>
86
+ Answer a Claude Code or Codex hook (setup registers it)
87
+ mcp-headers <server> Print a workspace MCP server's headers (setup registers it)
88
+
89
+ Options:
90
+ --server <url> The Console to sign in to (or set OPENCODE_CONSOLE_SERVER)
91
+ --harness <name/version> Identify the calling agent to the Console, e.g. claude-cli/2.1.304
92
+ (or set OPENCODE_CONSOLE_HARNESS)
93
+
94
+ Set OPENCODE_API_KEY to use a personal or service account key instead of signing in.
95
+ Set OPENCODE_CONSOLE_SERVER to use a Console other than https://opencode.ai/console.
96
+ `}
package/package.json CHANGED
@@ -1,6 +1,48 @@
1
1
  {
2
2
  "name": "@opencode/console",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.1",
4
+ "description": "Connect Claude Code, Pi and Codex to an OpenCode Console workspace and enforce its policies",
5
+ "keywords": [
6
+ "opencode",
7
+ "claude-code",
8
+ "codex",
9
+ "pi-package",
10
+ "coding-agent",
11
+ "policy"
12
+ ],
13
+ "homepage": "https://opencode.ai/console/integrations/claude-code",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/anomalyco/opencode-console.git",
17
+ "directory": "packages/cli"
18
+ },
19
+ "pi": {
20
+ "extensions": [
21
+ "./pi-extension.js"
22
+ ]
23
+ },
24
+ "peerDependencies": {
25
+ "@earendil-works/pi-ai": "*",
26
+ "@earendil-works/pi-coding-agent": "*"
27
+ },
28
+ "peerDependenciesMeta": {
29
+ "@earendil-works/pi-ai": {
30
+ "optional": true
31
+ },
32
+ "@earendil-works/pi-coding-agent": {
33
+ "optional": true
34
+ }
35
+ },
36
+ "license": "MIT",
37
+ "type": "module",
38
+ "bin": {
39
+ "opencode-console": "index.js"
40
+ },
41
+ "files": [
42
+ "*.js",
43
+ "THIRD_PARTY_LICENSES.md"
44
+ ],
45
+ "engines": {
46
+ "node": ">=22"
47
+ }
6
48
  }
@@ -0,0 +1,2 @@
1
+ import"./chunk-zdf3mvav.js";import"./chunk-2y9vn023.js";import"./chunk-p59r4b0j.js";import"./chunk-6rpbc10h.js";import{He,xt}from"./chunk-5q7mrvv1.js";import{gt,en}from"./chunk-frqdgjbd.js";import"./chunk-81fv1abj.js";import"./chunk-wjghq897.js";import"./chunk-6mydq7cv.js";import"./chunk-sn451nak.js";import{Ro,Mo,Fo,No,Do,Uo,Tn,Lo,On,Xn,it,Bo,zo}from"./chunk-03p95nje.js";import"./chunk-fzckrdm3.js";import{k,q,zt,vr,Kt}from"./chunk-bkr0zk6g.js";var S={};k(S,{PiExtension:()=>S,default:()=>O,install:()=>R});import{existsSync as B}from"node:fs";import T from"node:path";import{anthropicMessagesApi as j,createProvider as H,googleGenerativeAIApi as K,openAICompletionsApi as D,openAIResponsesApi as F}from"@earendil-works/pi-ai/compat";import{getBuiltinModels as G,getBuiltinProviders as b}from"@earendil-works/pi-ai/providers/all";import{VERSION as J}from"@earendil-works/pi-coding-agent";async function O(e){await R(e,Lo({harness:`pi/${J}`}))}var L=(e,n,o)=>{let a=b();return[...a.filter((t)=>t===e),...a.filter((t)=>t==="opencode"&&t!==e),...a.filter((t)=>t!==e&&t!=="opencode")].flatMap((t)=>G(t).filter((f)=>f.id===n&&f.api===o)).at(0)},U="opencode_workspace_instructions";async function R(e,n){let o=new Set,a=new Map,d=new Map,t=p(n),f=t?await Bo(n).catch(()=>{return}):void 0;if(Ro(f??{},L).forEach((s)=>{o.add(s.id),e.registerProvider(H({id:s.id,name:s.name,auth:{apiKey:{name:"OpenCode Console",resolve:()=>V(n)}},models:s.models,api:{"anthropic-messages":P(j()),"openai-responses":P(F()),"openai-completions":P(D()),"google-generative-ai":P(K())}}))}),t&&(await it(n).catch(()=>{return}))?.config)["opencode","opencode-go"].filter((s)=>!o.has(s)).forEach((s)=>{o.add(s),e.registerProvider(s,{models:[]})});if(t)await M(e,n,d).catch(()=>{return});let m=f&&Mo(f),h={},E=async(s)=>{let r=[...s.modelRegistry.getAll().map((c)=>c.provider),...b(),...s.modelRegistry.getRegisteredProviderIds(),...a.keys()],i=[...new Set(r)].filter((c)=>!o.has(c)),u=await Xn(n,i.map((c)=>({action:"provider.use",resources:[c]}))).catch(()=>{return});i.forEach((c,w)=>{let v=u?.[w]?.effect!=="allow";if(v&&!a.has(c)){let _=s.modelRegistry.getRegisteredNativeProvider(c);a.set(c,()=>{if(e.unregisterProvider(c),_)e.registerProvider(_)}),e.registerProvider(c,{models:[]})}let C=v?void 0:a.get(c);if(C)a.delete(c),C()}),h.fetched=(await it(n).catch(()=>{return}))?.fetched;let l=s.model,g=m&&s.modelRegistry.find(m.provider,m.id);if(g&&(!l||a.has(l.provider)))await e.setModel(g)},x=async(s)=>{let r=await it(n);if(r?.fetched!==h.fetched)await E(s);return r};e.on("session_start",async(s,r)=>{if(!p(n)){y(r,"OpenCode Console isn't signed in. Run `npx @opencode/console login`.","warning");return}let i=await it(n).catch(()=>{return});if(i?.status)y(r,`${i.status.message}${i.status.url?`: ${i.status.url}`:""}`,"warning");await E(r)}),e.on("resources_discover",async()=>{if(!p(n))return;let s=await zo(n).catch(()=>A(n));return B(s)?{skillPaths:[s]}:void 0}),e.on("before_agent_start",async(s,r)=>{if(!p(n))return;let i=s.systemPromptOptions,u=i.skills??[],l=await(async()=>{let g=await x(r),c=await Xn(n,u.map((w)=>({action:"skill",resources:[w.name]})));return{text:Uo(g?.config?gt(g.config).instructions:[]),skills:u.filter((w,v)=>c[v]?.effect==="allow")}})().catch(()=>({text:void 0,skills:[]}));if(l.text)i.sections={...i.sections,[U]:l.text};i.skills=l.skills}),e.on("tool_call",async(s,r)=>{let i=e.getAllTools(),u=i.find((c)=>c.name===s.toolName)?.namespace?.aliases?.[0],l=[...new Set([...i.flatMap((c)=>c.namespace?.aliases?.slice(0,1)??[]),...e.getMcpServers().map((c)=>c.name)])],g=await On(n,Fo(s,{cwd:r.cwd,server:u,servers:l,skills:A(n)}));return g?.effect==="deny"?{block:!0,reason:g.message}:void 0}),e.on("user_bash",async(s,r)=>{let i=await On(n,[No(s)]);if(i?.effect!=="deny")return;return y(r,i.message,"error"),{result:{output:`${i.message}
2
+ `,exitCode:1,cancelled:!1,truncated:!1}}}),e.on("input",async(s,r)=>{if(p(n))await x(r).catch(()=>{return});let i=Do(s.text);if(!i)return{action:"continue"};let u=await On(n,[{action:"skill",resources:[i]}]).catch((l)=>N(`/skill:${i}`,l));if(u?.effect!=="deny")return{action:"continue"};return y(r,u.message,"error"),{action:"handled"}}),e.on("before_provider_request",async(s,r)=>{let i=await I(n,r);if(i?.effect!=="deny")return;y(r,i.message,"error"),r.abort();return}),e.on("cache_warming_decision",async(s,r)=>(await I(n,r))?.effect==="deny"?{action:"stop"}:void 0),e.on("turn_start",()=>{if(p(n))M(e,n,d).catch(()=>{return})})}function p(e){return Kt(q(()=>He(e.store)!==void 0).pipe(vr(()=>!0)))}async function I(e,n){let o=n.model?.provider;if(!o||!p(e))return;return On(e,[{action:"provider.use",resources:[o]}]).catch((a)=>N(o,a))}function N(e,n){return{effect:"deny",message:`opencode-console couldn't check ${e}: ${n instanceof Error?n.message:String(n)}`}}var A=(e)=>T.join(Tn(e.store),"skills");async function M(e,n,o){let a=await it(n),d=a?.config?en(a.config):{};[...o.keys()].filter((t)=>!(t in d)).forEach((t)=>{o.delete(t),Kt(q(()=>e.unregisterMcpServer(t)).pipe(zt))}),Object.entries(d).forEach(([t,f])=>{let m={url:f.url,...f.headers?{headers:f.headers}:{}},h=JSON.stringify(m);if(o.get(t)===h)return;Kt(q(()=>{e.registerMcpServer(t,m),o.set(t,h)}).pipe(zt))})}async function V(e){let n=await e.run(xt(e.store));if(!n)return;return{auth:{apiKey:n.type==="key"?n.key:n.access},source:"OpenCode Console"}}function P(e){let n=(o)=>o?.sessionId?{...o,headers:{...o.headers,"x-opencode-session":o.sessionId}}:o;return{...e,stream:(o,a,d)=>e.stream(o,a,n(d)),streamSimple:(o,a,d)=>e.streamSimple(o,a,n(d))}}function y(e,n,o){if(e.hasUI)e.ui.notify(n,o)}export{S as PiExtension,O as default,R as install};