opencode-with-claude 1.10.3 → 1.10.4

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 CHANGED
@@ -13,7 +13,7 @@ Works with both OpenCode generations: the 1.x line (`opencode`) and OpenCode 2 (
13
13
  **Compared to running the proxy yourself:**
14
14
 
15
15
  - **One process to think about** — OpenCode owns the proxy lifecycle (start/stop) instead of you juggling two things.
16
- - **Several OpenCode windows at once** — each instance gets its own proxy on an OS-assigned port, so ports do not collide and you avoid session issues from sharing one proxy across instances.
16
+ - **Several OpenCode windows at once** — each process gets its own proxy (port 3456 when available, otherwise an OS-assigned port). Project instances within the same process share that proxy, including concurrent plugin initialization.
17
17
  - **Explicit session headers** — the plugin adds session tracking on outgoing API calls, so the proxy does not have to infer sessions from fingerprints alone. OpenCode's hidden title and summary requests are kept off the session's turn lease, so the first message of a fresh session does not race them.
18
18
 
19
19
  ## How It Works
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{scrubOpencodeFingerprints as xe}from"@rynfar/meridian-plugin-opencode-scrub";var w=new Set(["title","summary"]),E="compaction",Q={build:"primary",plan:"primary",general:"subagent",explore:"subagent",title:"primary",summary:"primary",compaction:"primary"},Z=["x-opencode-session","x-session-affinity","x-session-id","x-parent-session-id"],ee=["x-meridian-source","x-opencode-agent-mode","x-opencode-agent-name"];function x(e){return String(e??"unknown").replace(/[^\x20-\x7E]/g,"").trim()||"unknown"}function A(e){return e==="subagent"?"subagent":"primary"}function h(e,n,r){if(typeof n=="string")return A(n);let t=e.toLowerCase(),o=r.get(t);return o!==void 0?A(o):Q[t]??"primary"}function R(e,n){let r=n.toLowerCase();for(let t of Object.keys(e))t.toLowerCase()===r&&delete e[t]}function v(e,n){R(e,"anthropic-beta");for(let r of Z)R(e,r);for(let r of ee)R(e,r);n.detached?e["x-meridian-source"]="subagent-".concat(n.agentName):(e["x-opencode-session"]=n.sessionID,n.source&&(e["x-meridian-source"]=n.source)),e["x-opencode-agent-mode"]=n.detached?"subagent":n.agentMode,e["x-opencode-agent-name"]=n.agentName}var ne=/authenticat|credentials|expired|not logged in|exit(?:ed)? with code|crash|unhealthy|401|402|billing|subscription/i,re=/rate.limit|429|overloaded|503|stale.session|timeout|timed out/i;function C(e){return(n,r)=>e.app.log({body:{service:"opencode-with-claude",level:n,message:r}})}function M(){return async(e,n)=>{e!=="debug"&&console.error("[opencode-with-claude] ".concat(e,": ").concat(n))}}function D(e){return ne.test(e)?"error":re.test(e)?"warn":"debug"}import{existsSync as te,readFileSync as oe}from"fs";import{homedir as ie}from"os";import{join as S}from"path";var O=()=>S(ie(),".config","meridian"),N=()=>S(O(),"profiles.json"),F=()=>S(O(),"settings.json");function p(e,n){e?.("warn","[opencode-with-claude] ".concat(n))}function T(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function $(e,n,r){if(!Array.isArray(e))return p(r,"".concat(n," must be a JSON array of profile objects; got ").concat(typeof e,". Ignoring.")),[];let t=[];for(let o of e){if(!T(o)||typeof o.id!="string"||!o.id){p(r,"".concat(n,': dropping profile without a string "id" field.'));continue}let s={id:o.id};(o.type==="claude-max"||o.type==="api"||o.type==="oauth-token")&&(s.type=o.type),typeof o.claudeConfigDir=="string"&&(s.claudeConfigDir=o.claudeConfigDir),typeof o.apiKey=="string"&&(s.apiKey=o.apiKey),typeof o.baseUrl=="string"&&(s.baseUrl=o.baseUrl),typeof o.oauthToken=="string"&&(s.oauthToken=o.oauthToken),t.push(s)}return t}function _(e,n){if(te(e))try{return JSON.parse(oe(e,"utf8"))}catch(r){let t=r instanceof Error?r.message:String(r);p(n,"failed to parse ".concat(e,": ").concat(t));return}}function se(e){let n=process.env.MERIDIAN_PROFILES;if(n)try{return $(JSON.parse(n),"MERIDIAN_PROFILES",e)}catch(r){let t=r instanceof Error?r.message:String(r);p(e,"failed to parse MERIDIAN_PROFILES env var: ".concat(t));return}}function ae(e){let n=_(N(),e);return n===void 0?[]:$(n,N(),e)}function de(e){let n=_(F(),e);if(!T(n))return;let r=n.activeProfile;if(r!==void 0){if(typeof r!="string"||!r){p(e,"".concat(F(),': "activeProfile" must be a non-empty string; ignoring.'));return}return r}}function U(e){let n=[],r="none",t=se(e);if(t)n=t,r="env";else{let i=ae(e);i.length>0&&(n=i,r="disk")}let o,s="none",d=process.env.MERIDIAN_DEFAULT_PROFILE?.trim();if(d)o=d,s="env";else{let i=de(e);i&&(o=i,s="disk")}return o&&n.length>0&&!n.some(i=>i.id===o)&&(p(e,'default profile "'.concat(o,'" (from ').concat(s,") not found among configured profiles; ignoring.")),o=void 0,s="none"),{profiles:n,defaultProfile:o,sources:{profiles:r,defaultProfile:s}}}function H(e){if(e.profiles.length===0)return;let n=e.profiles.map(s=>s.id).join(", "),r=e.defaultProfile??e.profiles[0]?.id,t=e.sources.profiles,o=e.sources.defaultProfile==="none"?"first":e.sources.defaultProfile;return"loaded ".concat(e.profiles.length," meridian profile(s) from ").concat(t,": ").concat(n," (active: ").concat(r," [").concat(o,"])")}import{existsSync as ce,readFileSync as fe}from"fs";import{createRequire as ue}from"module";import{dirname as j,join as le}from"path";import{startProxyServer as ge}from"@rynfar/meridian";process.env.MERIDIAN_PASSTHROUGH??="true";var pe=process.platform==="win32",q=3456,W="127.0.0.1",G="@rynfar/meridian";function me(){try{let e=j(ue(import.meta.url).resolve(G));for(let n=0;n<5;n++){let r=le(e,"package.json");if(ce(r)){let o=JSON.parse(fe(r,"utf8"));if(o.name===G&&typeof o.version=="string")return o.version}let t=j(e);if(t===e)break;e=t}return}catch{return}}function ye(e){return e.includes(":")&&!e.startsWith("[")?"[".concat(e,"]"):e}function k(){let e=process.env.MERIDIAN_HOST?.trim()||process.env.CLAUDE_PROXY_HOST?.trim()||W;return e.startsWith("[")&&e.endsWith("]")?e.slice(1,-1):e}function Pe(e=k()){return e==="0.0.0.0"?W:e==="::"||e==="[::]"?"::1":e}function b(e,n=k()){return"http://".concat(ye(Pe(n)),":").concat(e)}async function J(e){let{port:n=q,log:r,profiles:t,defaultProfile:o}=e,s=k(),d=me(),i=console.error;console.error=(...l)=>{let u=l.map(String).join(" ");if(u.startsWith("[PROXY]")){r?.(D(u),u);return}i.apply(console,l)};let a=l=>new Promise((u,L)=>{ge({port:l,host:s,silent:!0,profiles:t,defaultProfile:o,version:d}).then(g=>{let P=Y=>{L(Y)};g.server.once("error",P),g.server.listening?(g.server.removeListener("error",P),u(g)):g.server.once("listening",()=>{g.server.removeListener("error",P),u(g)})},L)}),c=async l=>{try{return await a(l)}catch(u){if(l!==0&&u instanceof Error&&"code"in u&&u.code==="EADDRINUSE")return r?.("info","Port ".concat(l," in use, starting on a random port instead...")),a(0);throw u}},f;try{f=await c(typeof n=="string"?parseInt(n,10):n)}catch(l){throw console.error=i,l}let I=f.server.address()?.port??f.config?.port??q;return r?.("info","Claude Max proxy running on port ".concat(I)),{port:I,close:async()=>{console.error=i,await f.close()}}}function Re(e){if(typeof e!="object"||e===null)return{};let n=e,r={};return typeof n.daysUntilRenewal=="number"&&Number.isFinite(n.daysUntilRenewal)&&(r.daysUntilRenewal=n.daysUntilRenewal),typeof n.renewalRequiredSoon=="boolean"&&(r.renewalRequiredSoon=n.renewalRequiredSoon),r}function we(e){return e===void 0?"soon":e<=0?"today":e===1?"in 1 day":"in ".concat(e," days")}async function K(e,n){try{let r=await fetch(b(e)+"/health",{signal:AbortSignal.timeout(5e3)}),t=await r.json(),o=t.version,s=typeof o=="string"&&o!=="unknown"?o:void 0,d=Re(t.auth);if(s&&n?.("info","[claude-max] meridian ".concat(s)),d.renewalRequiredSoon&&n?.("warn","[claude-max] Claude login expires ".concat(we(d.daysUntilRenewal),". Run 'claude login' to renew \u2014 the proxy cannot refresh it for you.")),t.status==="healthy")return{ok:!0,version:s,...d};if(t.status==="degraded"){let a=typeof t.error=="string"?t.error:"Could not verify auth status";return n?.("warn","[claude-max] ".concat(a,". Requests may still work \u2014 if they hang, try running 'claude login' in your terminal.")),{ok:!0,message:a,version:s,...d}}let i=typeof t.error=="string"?t.error:"Proxy health check returned status: ".concat(t.status??r.status);return n?.("error","[claude-max] ".concat(i)),{ok:!1,message:i,version:s,...d}}catch(r){let t=r instanceof Error?r.message:String(r);return n?.("error","[claude-max] Health check failed: ".concat(t)),{ok:!1,message:"Health check failed: ".concat(t)}}}function z(e){let n=!1,r=()=>{n||(n=!0,e.close())};process.on("exit",r),process.on("SIGINT",r),pe||process.on("SIGTERM",r)}var V="opencode-with-claude",y="anthropic",he=4096;async function B(e){let n=U(e),r=H(n);r&&e("info",r);let t=process.env.CLAUDE_PROXY_PORT||3456,o=await J({port:t,log:e,profiles:n.profiles,defaultProfile:n.defaultProfile}),s=b(o.port);return e("info","proxy ready at ".concat(s)),z(o),K(o.port,e),{proxy:o,baseURL:s}}function X(e){let n=e.join("\n\n"),r=xe(n);return r===n?void 0:r}var ve=async({client:e})=>{let n=C(e),r=new Map,t=new Map,o=(d,i)=>"".concat(d,"\0").concat(i),{baseURL:s}=await B(n);return{async config(d){for(let[a,c]of Object.entries(d.agent??{}))c?.mode&&r.set(a.toLowerCase(),c.mode);let i=d.provider?.anthropic;i&&(i.options||(i.options={}),i.options.baseURL=s)},async"chat.message"(d,i){let a=o(d.sessionID,i.message.id);if(t.delete(a),t.set(a,!0),t.size>he){let c=t.keys().next().value;c!==void 0&&t.delete(c)}},async"experimental.chat.system.transform"(d,i){if(d.model.providerID!==y)return;let a=X(i.system);a!==void 0&&i.system.splice(0,i.system.length,a)},async"chat.headers"(d,i){if(d.model.providerID!==y)return;let a=d.agent,c=typeof a=="object"&&a!==null,f=x(c?a.name:a),m={sessionID:d.sessionID,agentName:f,agentMode:h(f,c?a.mode:void 0,r),detached:w.has(f.toLowerCase())};v(i.headers,m),i.headers["x-opencode-request"]=d.message.id,i.headers["x-opencode-request-kind"]=t.has(o(d.sessionID,d.message.id))?"human":"synthetic"}}};function Se(e,n){let r=x(e.agent),t=r.toLowerCase(),o=e.kind==="title"||e.kind==="generate"||w.has(t),s=e.kind==="compaction"||t===E;return{sessionID:String(e.sessionID),agentName:r,agentMode:s?"primary":h(r,void 0,n),detached:o,source:s&&!o?"subagent-compaction":void 0}}var ke=async e=>{let n=M(),r=new Map,t=[],{proxy:o,baseURL:s}=await B(n),d="".concat(s,"/v1"),i=async()=>{let a=await Promise.allSettled(t.splice(0).map(f=>f.dispose()));await o.close();let c=a.flatMap(f=>f.status==="rejected"?[f.reason]:[]);if(c.length>0)throw new AggregateError(c,"".concat(V,": failed to dispose hooks"))};try{t.push(await e.agent.transform(a=>{r.clear();for(let c of a.list())r.set(String(c.id).toLowerCase(),c.mode)})),t.push(await e.session.hook("model.request",a=>{a.baseURL=d,v(a.headers,Se(a,r))},{providerID:y}));for(let a of["context","compaction","title","generate"])t.push(await e.session.hook(a,c=>{let f=X(c.system.map(m=>m.text));f!==void 0&&c.system.splice(0,c.system.length,{type:"text",text:f})},{providerID:y}))}catch(a){throw await i().catch(()=>{}),a}return i},be={id:V,server:ve,setup:ke},Ge=be;export{Ge as default};
1
+ import{scrubOpencodeFingerprints as xe}from"@rynfar/meridian-plugin-opencode-scrub";var h=new Set(["title","summary"]),C="compaction",ee={build:"primary",plan:"primary",general:"subagent",explore:"subagent",title:"primary",summary:"primary",compaction:"primary"},ne=["x-opencode-session","x-session-affinity","x-session-id","x-parent-session-id"],re=["x-meridian-source","x-opencode-agent-mode","x-opencode-agent-name"];function x(e){return String(e??"unknown").replace(/[^\x20-\x7E]/g,"").trim()||"unknown"}function E(e){return e==="subagent"?"subagent":"primary"}function v(e,n,r){if(typeof n=="string")return E(n);let o=e.toLowerCase(),t=r.get(o);return t!==void 0?E(t):ee[o]??"primary"}function w(e,n){let r=n.toLowerCase();for(let o of Object.keys(e))o.toLowerCase()===r&&delete e[o]}function S(e,n){w(e,"anthropic-beta");for(let r of ne)w(e,r);for(let r of re)w(e,r);n.detached?e["x-meridian-source"]="subagent-".concat(n.agentName):(e["x-opencode-session"]=n.sessionID,n.source&&(e["x-meridian-source"]=n.source)),e["x-opencode-agent-mode"]=n.detached?"subagent":n.agentMode,e["x-opencode-agent-name"]=n.agentName}var te=/authenticat|credentials|expired|not logged in|exit(?:ed)? with code|crash|unhealthy|401|402|billing|subscription/i,oe=/rate.limit|429|overloaded|503|stale.session|timeout|timed out/i;function M(e){return(n,r)=>e.app.log({body:{service:"opencode-with-claude",level:n,message:r}})}function D(){return async(e,n)=>{e!=="debug"&&console.error("[opencode-with-claude] ".concat(e,": ").concat(n))}}function N(e){return te.test(e)?"error":oe.test(e)?"warn":"debug"}import{existsSync as ie,readFileSync as se}from"fs";import{homedir as ae}from"os";import{join as L}from"path";var O=()=>L(ae(),".config","meridian"),F=()=>L(O(),"profiles.json"),T=()=>L(O(),"settings.json");function m(e,n){e?.("warn","[opencode-with-claude] ".concat(n))}function $(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function U(e,n,r){if(!Array.isArray(e))return m(r,"".concat(n," must be a JSON array of profile objects; got ").concat(typeof e,". Ignoring.")),[];let o=[];for(let t of e){if(!$(t)||typeof t.id!="string"||!t.id){m(r,"".concat(n,': dropping profile without a string "id" field.'));continue}let a={id:t.id};(t.type==="claude-max"||t.type==="api"||t.type==="oauth-token")&&(a.type=t.type),typeof t.claudeConfigDir=="string"&&(a.claudeConfigDir=t.claudeConfigDir),typeof t.apiKey=="string"&&(a.apiKey=t.apiKey),typeof t.baseUrl=="string"&&(a.baseUrl=t.baseUrl),typeof t.oauthToken=="string"&&(a.oauthToken=t.oauthToken),o.push(a)}return o}function _(e,n){if(ie(e))try{return JSON.parse(se(e,"utf8"))}catch(r){let o=r instanceof Error?r.message:String(r);m(n,"failed to parse ".concat(e,": ").concat(o));return}}function de(e){let n=process.env.MERIDIAN_PROFILES;if(n)try{return U(JSON.parse(n),"MERIDIAN_PROFILES",e)}catch(r){let o=r instanceof Error?r.message:String(r);m(e,"failed to parse MERIDIAN_PROFILES env var: ".concat(o));return}}function ce(e){let n=_(F(),e);return n===void 0?[]:U(n,F(),e)}function ue(e){let n=_(T(),e);if(!$(n))return;let r=n.activeProfile;if(r!==void 0){if(typeof r!="string"||!r){m(e,"".concat(T(),': "activeProfile" must be a non-empty string; ignoring.'));return}return r}}function H(e){let n=[],r="none",o=de(e);if(o)n=o,r="env";else{let i=ce(e);i.length>0&&(n=i,r="disk")}let t,a="none",d=process.env.MERIDIAN_DEFAULT_PROFILE?.trim();if(d)t=d,a="env";else{let i=ue(e);i&&(t=i,a="disk")}return t&&n.length>0&&!n.some(i=>i.id===t)&&(m(e,'default profile "'.concat(t,'" (from ').concat(a,") not found among configured profiles; ignoring.")),t=void 0,a="none"),{profiles:n,defaultProfile:t,sources:{profiles:r,defaultProfile:a}}}function j(e){if(e.profiles.length===0)return;let n=e.profiles.map(a=>a.id).join(", "),r=e.defaultProfile??e.profiles[0]?.id,o=e.sources.profiles,t=e.sources.defaultProfile==="none"?"first":e.sources.defaultProfile;return"loaded ".concat(e.profiles.length," meridian profile(s) from ").concat(o,": ").concat(n," (active: ").concat(r," [").concat(t,"])")}import{existsSync as fe,readFileSync as le}from"fs";import{createRequire as ge}from"module";import{dirname as q,join as pe}from"path";import{startProxyServer as me}from"@rynfar/meridian";process.env.MERIDIAN_PASSTHROUGH??="true";var G=process.platform==="win32",W=3456,K="127.0.0.1",J="@rynfar/meridian";function ye(){try{let e=q(ge(import.meta.url).resolve(J));for(let n=0;n<5;n++){let r=pe(e,"package.json");if(fe(r)){let t=JSON.parse(le(r,"utf8"));if(t.name===J&&typeof t.version=="string")return t.version}let o=q(e);if(o===e)break;e=o}return}catch{return}}function Re(e){return e.includes(":")&&!e.startsWith("[")?"[".concat(e,"]"):e}function b(){let e=process.env.MERIDIAN_HOST?.trim()||process.env.CLAUDE_PROXY_HOST?.trim()||K;return e.startsWith("[")&&e.endsWith("]")?e.slice(1,-1):e}function Pe(e=b()){return e==="0.0.0.0"?K:e==="::"||e==="[::]"?"::1":e}function I(e,n=b()){return"http://".concat(Re(Pe(n)),":").concat(e)}async function z(e){let{port:n=W,log:r,profiles:o,defaultProfile:t}=e,a=b(),d=ye(),i=console.error;console.error=(...l)=>{let f=l.map(String).join(" ");if(f.startsWith("[PROXY]")){r?.(N(f),f);return}i.apply(console,l)};let s=l=>new Promise((f,A)=>{me({port:l,host:a,silent:!0,profiles:o,defaultProfile:t,version:d}).then(g=>{let P=Z=>{A(Z)};g.server.once("error",P),g.server.listening?(g.server.removeListener("error",P),f(g)):g.server.once("listening",()=>{g.server.removeListener("error",P),f(g)})},A)}),c=async l=>{try{return await s(l)}catch(f){if(l!==0&&f instanceof Error&&"code"in f&&f.code==="EADDRINUSE")return r?.("info","Port ".concat(l," in use, starting on a random port instead...")),s(0);throw f}},u;try{u=await c(typeof n=="string"?parseInt(n,10):n)}catch(l){throw console.error=i,l}let k=u.server.address()?.port??u.config?.port??W;return r?.("info","Claude Max proxy running on port ".concat(k)),{port:k,close:async()=>{console.error=i,await u.close()}}}function we(e){if(typeof e!="object"||e===null)return{};let n=e,r={};return typeof n.daysUntilRenewal=="number"&&Number.isFinite(n.daysUntilRenewal)&&(r.daysUntilRenewal=n.daysUntilRenewal),typeof n.renewalRequiredSoon=="boolean"&&(r.renewalRequiredSoon=n.renewalRequiredSoon),r}function he(e){return e===void 0?"soon":e<=0?"today":e===1?"in 1 day":"in ".concat(e," days")}async function V(e,n){try{let r=await fetch(I(e)+"/health",{signal:AbortSignal.timeout(5e3)}),o=await r.json(),t=o.version,a=typeof t=="string"&&t!=="unknown"?t:void 0,d=we(o.auth);if(a&&n?.("info","[claude-max] meridian ".concat(a)),d.renewalRequiredSoon&&n?.("warn","[claude-max] Claude login expires ".concat(he(d.daysUntilRenewal),". Run 'claude login' to renew \u2014 the proxy cannot refresh it for you.")),o.status==="healthy")return{ok:!0,version:a,...d};if(o.status==="degraded"){let s=typeof o.error=="string"?o.error:"Could not verify auth status";return n?.("warn","[claude-max] ".concat(s,". Requests may still work \u2014 if they hang, try running 'claude login' in your terminal.")),{ok:!0,message:s,version:a,...d}}let i=typeof o.error=="string"?o.error:"Proxy health check returned status: ".concat(o.status??r.status);return n?.("error","[claude-max] ".concat(i)),{ok:!1,message:i,version:a,...d}}catch(r){let o=r instanceof Error?r.message:String(r);return n?.("error","[claude-max] Health check failed: ".concat(o)),{ok:!1,message:"Health check failed: ".concat(o)}}}function B(e){let n=!1,r=()=>{n||(n=!0,e.close())};return process.on("exit",r),process.on("SIGINT",r),G||process.on("SIGTERM",r),()=>{process.removeListener("exit",r),process.removeListener("SIGINT",r),G||process.removeListener("SIGTERM",r)}}var X="opencode-with-claude",R="anthropic",ve=4096,p;async function Y(e){for(;p?.closing;)await p.closing;let n=p??={ready:Se(e),users:0};n.users++;let r;try{r=await n.ready}catch(t){throw p===n&&(p=void 0),t}let o=!1;return{baseURL:r.baseURL,release:async()=>{o||(o=!0,!(--n.users>0)&&(n.closing=r.proxy.close().finally(()=>{p===n&&(p=void 0)}),await n.closing))}}}async function Se(e){let n=H(e),r=j(n);r&&e("info",r);let o=process.env.CLAUDE_PROXY_PORT||3456,t=await z({port:o,log:e,profiles:n.profiles,defaultProfile:n.defaultProfile}),a=I(t.port);e("info","proxy ready at ".concat(a));let d=B(t),i=t.close,s;return t.close=()=>(d(),s??=i()),V(t.port,e),{proxy:t,baseURL:a}}function Q(e){let n=e.join("\n\n"),r=xe(n);return r===n?void 0:r}var Le=async({client:e})=>{let n=M(e),r=new Map,o=new Map,t=(d,i)=>"".concat(d,"\0").concat(i),{baseURL:a}=await Y(n);return{async config(d){for(let[s,c]of Object.entries(d.agent??{}))c?.mode&&r.set(s.toLowerCase(),c.mode);let i=d.provider?.anthropic;i&&(i.options||(i.options={}),i.options.baseURL=a)},async"chat.message"(d,i){let s=t(d.sessionID,i.message.id);if(o.delete(s),o.set(s,!0),o.size>ve){let c=o.keys().next().value;c!==void 0&&o.delete(c)}},async"experimental.chat.system.transform"(d,i){if(d.model.providerID!==R)return;let s=Q(i.system);s!==void 0&&i.system.splice(0,i.system.length,s)},async"chat.headers"(d,i){if(d.model.providerID!==R)return;let s=d.agent,c=typeof s=="object"&&s!==null,u=x(c?s.name:s),y={sessionID:d.sessionID,agentName:u,agentMode:v(u,c?s.mode:void 0,r),detached:h.has(u.toLowerCase())};S(i.headers,y),i.headers["x-opencode-request"]=d.message.id,i.headers["x-opencode-request-kind"]=o.has(t(d.sessionID,d.message.id))?"human":"synthetic"}}};function be(e,n){let r=x(e.agent),o=r.toLowerCase(),t=e.kind==="title"||e.kind==="generate"||h.has(o),a=e.kind==="compaction"||o===C;return{sessionID:String(e.sessionID),agentName:r,agentMode:a?"primary":v(r,void 0,n),detached:t,source:a&&!t?"subagent-compaction":void 0}}var Ie=async e=>{let n=D(),r=new Map,o=[],{release:t,baseURL:a}=await Y(n),d="".concat(a,"/v1"),i=async()=>{let s=await Promise.allSettled(o.splice(0).map(u=>u.dispose()));await t();let c=s.flatMap(u=>u.status==="rejected"?[u.reason]:[]);if(c.length>0)throw new AggregateError(c,"".concat(X,": failed to dispose hooks"))};try{o.push(await e.agent.transform(s=>{r.clear();for(let c of s.list())r.set(String(c.id).toLowerCase(),c.mode)})),o.push(await e.session.hook("model.request",s=>{s.baseURL=d,S(s.headers,be(s,r))},{providerID:R}));for(let s of["context","compaction","title","generate"])o.push(await e.session.hook(s,c=>{let u=Q(c.system.map(y=>y.text));u!==void 0&&c.system.splice(0,c.system.length,{type:"text",text:u})},{providerID:R}))}catch(s){throw await i().catch(()=>{}),s}return i},ke={id:X,server:Le,setup:Ie},Je=ke;export{Je as default};
package/dist/proxy.d.ts CHANGED
@@ -43,4 +43,4 @@ export interface HealthResult {
43
43
  renewalRequiredSoon?: boolean;
44
44
  }
45
45
  export declare function checkProxyHealth(port: string | number, log: LogFn | undefined): Promise<HealthResult>;
46
- export declare function registerCleanup(proxy: ProxyHandle): void;
46
+ export declare function registerCleanup(proxy: ProxyHandle): () => void;
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "opencode-with-claude",
3
3
  "description": "OpenCode plugin to use your Claude Max subscription via Meridian proxy",
4
- "version": "1.10.3",
4
+ "version": "1.10.4",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "dependencies": {
9
- "@rynfar/meridian": "1.71.1",
9
+ "@rynfar/meridian": "1.76.5",
10
10
  "@rynfar/meridian-plugin-opencode-scrub": "0.2.0"
11
11
  },
12
12
  "devDependencies": {