@cortexkit/opencode-openai-auth 0.5.1 → 0.6.0

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.
Files changed (51) hide show
  1. package/README.md +2 -1
  2. package/dist/cli.js +1 -1
  3. package/dist/commands.d.ts +16 -0
  4. package/dist/core/accounts.d.ts +22 -0
  5. package/dist/core/oauth.d.ts +1 -1
  6. package/dist/core/refresh-all-quota.d.ts +3 -0
  7. package/dist/core/reset-credits.d.ts +114 -0
  8. package/dist/index-87145jkw.js +2 -0
  9. package/dist/{index-rfgyxxxq.js → index-dz9a4xwy.js} +1 -1
  10. package/dist/{index-zkzb0twr.js → index-e08r33g5.js} +2 -2
  11. package/dist/{index-s5fbqqwx.js → index-hxpv25e8.js} +1 -1
  12. package/dist/index-meg0ng0z.js +2 -0
  13. package/dist/{index-vrdc90yd.js → index-n00ybbbq.js} +1 -1
  14. package/dist/{index-6rnw2cgs.js → index-nwy7ec7p.js} +1 -1
  15. package/dist/{index-wpd7mg3p.js → index-s2vhsb2v.js} +1 -1
  16. package/dist/index-zddpw2sa.js +89 -0
  17. package/dist/index.d.ts +30 -1
  18. package/dist/index.js +123 -73
  19. package/dist/quota-normalize-vf2pj6n7.js +1 -0
  20. package/dist/quota-normalize.d.ts +1 -0
  21. package/dist/rpc/port-file.js +1 -1
  22. package/dist/rpc/protocol.d.ts +1 -1
  23. package/dist/rpc/rpc-client.d.ts +2 -1
  24. package/dist/rpc/rpc-client.js +1 -1
  25. package/dist/rpc/rpc-dir.js +1 -1
  26. package/dist/rpc/rpc-server.d.ts +1 -0
  27. package/dist/sidebar-state.d.ts +2 -0
  28. package/dist/sidebar-state.js +1 -1
  29. package/dist/{token-5hdnazxp.js → token-esc14v6e.js} +1 -1
  30. package/dist/token-util-qkpkvy5t.js +1 -0
  31. package/dist/tui-preferences.js +1 -1
  32. package/dist/version.d.ts +1 -1
  33. package/dist/ws-pool.d.ts +1 -0
  34. package/package.json +3 -3
  35. package/src/rpc/protocol.ts +1 -0
  36. package/src/rpc/rpc-client.ts +7 -3
  37. package/src/rpc/rpc-server.ts +24 -4
  38. package/src/sidebar-state.ts +62 -3
  39. package/src/tui/command-dialogs.tsx +245 -0
  40. package/src/tui-compiled/rpc/protocol.ts +1 -0
  41. package/src/tui-compiled/rpc/rpc-client.ts +7 -3
  42. package/src/tui-compiled/sidebar-state.ts +62 -3
  43. package/src/tui-compiled/tui/command-dialogs.tsx +162 -1
  44. package/src/tui-compiled/tui.tsx +1 -1
  45. package/src/tui-compiled/util/error.ts +9 -0
  46. package/src/tui.tsx +4 -1
  47. package/dist/index-2ng03cby.js +0 -2
  48. package/dist/index-j1364eag.js +0 -89
  49. package/dist/index-wnxfzjfr.js +0 -2
  50. package/dist/quota-normalize-n02dfdx0.js +0 -1
  51. package/dist/token-util-3d2nj45d.js +0 -1
@@ -0,0 +1 @@
1
+ import{c as a,d as b,e as c,f as d,g as e}from"./index-87145jkw.js";import"./index-s2vhsb2v.js";export{a as toResetIso,d as normalizeWsFrame,e as normalizeWham,b as normalizeQuotaHeaders,c as isCompleteQuotaHeaderFrame};
@@ -36,6 +36,7 @@ interface WhamUsageResponse {
36
36
  rate_limit: WhamRateLimits;
37
37
  rate_limit_reset_credits?: {
38
38
  available_count?: number;
39
+ applicable_available_count?: number;
39
40
  } | null;
40
41
  }
41
42
  export declare function normalizeWham(json: WhamUsageResponse): OAuthQuotaSnapshot;
@@ -1 +1 @@
1
- import{ua as a,va as b,wa as c}from"../index-zkzb0twr.js";import"../index-s5fbqqwx.js";import"../index-wpd7mg3p.js";export{a as writePortFile,b as sweepRpcState,c as discoverPortFile};
1
+ import{va as a,wa as b,xa as c}from"../index-e08r33g5.js";import"../index-hxpv25e8.js";import"../index-s2vhsb2v.js";export{a as writePortFile,b as sweepRpcState,c as discoverPortFile};
@@ -1,4 +1,4 @@
1
- export type CommandModalName = 'openai-quota' | 'openai-account' | 'openai-routing' | 'openai-killswitch' | 'openai-dump' | 'openai-logging' | 'openai-cachekeep';
1
+ export type CommandModalName = 'openai-quota' | 'openai-account' | 'openai-routing' | 'openai-killswitch' | 'openai-dump' | 'openai-logging' | 'openai-cachekeep' | 'openai-reset';
2
2
  export interface OpenDialogPayload {
3
3
  command: CommandModalName;
4
4
  text: string;
@@ -2,6 +2,7 @@ import { type PortFileEntry } from './port-file';
2
2
  import type { ApplyRequest, ApplyResult, RpcNotification } from './protocol';
3
3
  export interface RpcClient {
4
4
  pending: (lastReceivedId: number, sessionId?: string) => Promise<RpcNotification[]>;
5
- apply: (request: ApplyRequest) => Promise<ApplyResult>;
5
+ apply: (request: ApplyRequest, timeoutMs?: number) => Promise<ApplyResult>;
6
6
  }
7
+ export declare const DEFAULT_RPC_TIMEOUT_MS = 2000;
7
8
  export declare function createRpcClient(dir: string, expectedPid?: number, onSelected?: (entry: PortFileEntry | null) => void): RpcClient;
@@ -1 +1 @@
1
- import{wa as c}from"../index-zkzb0twr.js";import"../index-s5fbqqwx.js";import"../index-wpd7mg3p.js";async function p(n,r,l,o,i){let t=await c(n,r);if(l?.(t),!t)return null;let e=new AbortController,s=setTimeout(()=>e.abort(),2000);try{let a=await fetch(`http://127.0.0.1:${t.port}/rpc/${o}`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${t.token}`},body:JSON.stringify(i),signal:e.signal});if(!a.ok)return null;return await a.json()}catch{return null}finally{clearTimeout(s)}}function y(n,r,l){let o=!1,i=(t)=>{if(o)return;o=!0,l?.(t)};return{async pending(t,e){return(await p(n,r,i,"pending-notifications",{lastReceivedId:t,sessionId:e}))?.messages??[]},async apply(t){return await p(n,r,i,"apply",{...t})??{text:"apply failed",knobs:{}}}}}export{y as createRpcClient};
1
+ import{xa as c}from"../index-e08r33g5.js";import"../index-hxpv25e8.js";import"../index-s2vhsb2v.js";var y=2000;async function p(n,r,s,o,i,e=y){let t=await c(n,r);if(s?.(t),!t)return null;let l=new AbortController,u=setTimeout(()=>l.abort(),e);try{let a=await fetch(`http://127.0.0.1:${t.port}/rpc/${o}`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${t.token}`},body:JSON.stringify(i),signal:l.signal});if(!a.ok)return null;return await a.json()}catch{return null}finally{clearTimeout(u)}}function m(n,r,s){let o=!1,i=(e)=>{if(o)return;o=!0,s?.(e)};return{async pending(e,t){return(await p(n,r,i,"pending-notifications",{lastReceivedId:e,sessionId:t}))?.messages??[]},async apply(e,t){return await p(n,r,i,"apply",{...e},t)??{text:"apply failed",knobs:{}}}}}export{m as createRpcClient,y as DEFAULT_RPC_TIMEOUT_MS};
@@ -1 +1 @@
1
- import{Aa as a,Ba as b,Ca as c}from"../index-rfgyxxxq.js";import"../index-wpd7mg3p.js";export{a as tmpdir,c as resolveRpcDir,b as getRpcDir};
1
+ import{Ba as a,Ca as b,Da as c}from"../index-dz9a4xwy.js";import"../index-s2vhsb2v.js";export{a as tmpdir,c as resolveRpcDir,b as getRpcDir};
@@ -12,5 +12,6 @@ export interface RpcServerOptions {
12
12
  drain: typeof drainNotifications;
13
13
  apply: (request: ApplyRequest) => Promise<ApplyResult>;
14
14
  timeoutMs?: number;
15
+ receiptTimeoutMs?: number;
15
16
  }
16
17
  export declare function startRpcServer(options: RpcServerOptions): Promise<RpcServerHandle>;
@@ -38,6 +38,7 @@ export interface ActiveRoutingEntry {
38
38
  export type ActiveRoutingMap = Record<string, ActiveRoutingEntry>;
39
39
  export interface StickyAssignment {
40
40
  accountId: string;
41
+ wireAccountId?: string;
41
42
  assignedAt: number;
42
43
  lastSeenAt: number;
43
44
  inputBytes: number;
@@ -55,6 +56,7 @@ export interface ResolveStickyAssignmentInput {
55
56
  validPinnedAccountIds: readonly string[];
56
57
  excludeAccountIds?: readonly string[];
57
58
  quotaCheckedAtByAccount: Readonly<Record<string, number | undefined>>;
59
+ wireAccountIdByAccount?: Readonly<Record<string, string | undefined>>;
58
60
  choose: (pendingBytes: ReadonlyMap<string, number>) => StickyAssignmentChoice | undefined;
59
61
  }
60
62
  export interface SidebarState {
@@ -1 +1 @@
1
- import{$ as j,S as a,T as b,U as c,V as d,W as e,X as f,Y as g,Z as h,_ as i,aa as k,ba as l,ca as m,da as n,ea as o,fa as p,ga as q,ha as r,ia as s,ja as t,ka as u,la as v,ma as w,na as x,oa as y,pa as z,qa as A,ra as B,sa as C}from"./index-wnxfzjfr.js";import"./index-vrdc90yd.js";import"./index-s5fbqqwx.js";import"./index-wpd7mg3p.js";export{u as upsertSidebarActiveRouting,s as setSidebarState,t as setSidebarMachineState,v as setSidebarLegacyRouting,x as resolveSidebarStickyAssignment,o as resolveSessionStickyAccount,p as resolveSessionSidebarRouting,A as resolveActiveAccount,w as removeSidebarActiveRouting,r as pruneStickyAssignments,q as pruneActiveRouting,h as normalizeSidebarState,l as isUsableRoutingEntry,n as isQuotaExhausted,e as hashSidebarSessionId,f as getSidebarStateFile,i as getSidebarState,b as getPresentQuotaWindows,B as getCollapsedQuotaSummary,a as formatWindowLabel,m as exhaustedQuotaResetAt,z as drainSidebarWrites,C as computeQuotaPacing,y as clearSidebarStickyAssignment,d as STICKY_ASSIGNMENT_MAX_ENTRIES,c as STICKY_ASSIGNMENT_MAX_AGE_MS,g as DEFAULT_SIDEBAR_STATE,k as ACTIVE_ROUTING_MAX_ENTRIES,j as ACTIVE_ROUTING_MAX_AGE_MS};
1
+ import{$ as i,T as a,U as b,V as c,W as d,X as e,Y as f,Z as g,_ as h,aa as j,ba as k,ca as l,da as m,ea as n,fa as o,ga as p,ha as q,ia as r,ja as s,ka as t,la as u,ma as v,na as w,oa as x,pa as y,qa as z,ra as A,sa as B,ta as C}from"./index-meg0ng0z.js";import"./index-n00ybbbq.js";import"./index-hxpv25e8.js";import"./index-s2vhsb2v.js";export{u as upsertSidebarActiveRouting,s as setSidebarState,t as setSidebarMachineState,v as setSidebarLegacyRouting,x as resolveSidebarStickyAssignment,o as resolveSessionStickyAccount,p as resolveSessionSidebarRouting,A as resolveActiveAccount,w as removeSidebarActiveRouting,r as pruneStickyAssignments,q as pruneActiveRouting,h as normalizeSidebarState,l as isUsableRoutingEntry,n as isQuotaExhausted,e as hashSidebarSessionId,f as getSidebarStateFile,i as getSidebarState,b as getPresentQuotaWindows,B as getCollapsedQuotaSummary,a as formatWindowLabel,m as exhaustedQuotaResetAt,z as drainSidebarWrites,C as computeQuotaPacing,y as clearSidebarStickyAssignment,d as STICKY_ASSIGNMENT_MAX_ENTRIES,c as STICKY_ASSIGNMENT_MAX_AGE_MS,g as DEFAULT_SIDEBAR_STATE,k as ACTIVE_ROUTING_MAX_ENTRIES,j as ACTIVE_ROUTING_MAX_AGE_MS};
@@ -1 +1 @@
1
- import{a as U,b as V}from"./index-6rnw2cgs.js";import{Ea as R}from"./index-wpd7mg3p.js";var E=R((M,Q)=>{var{defineProperty:H,getOwnPropertyDescriptor:W,getOwnPropertyNames:X}=Object,Y=Object.prototype.hasOwnProperty,Z=(z,q)=>{for(var B in q)H(z,B,{get:q[B],enumerable:!0})},$=(z,q,B,F)=>{if(q&&typeof q==="object"||typeof q==="function"){for(let v of X(q))if(!Y.call(z,v)&&v!==B)H(z,v,{get:()=>q[v],enumerable:!(F=W(q,v))||F.enumerable})}return z},A=(z)=>$(H({},"__esModule",{value:!0}),z),L={};Z(L,{refreshToken:()=>D});Q.exports=A(L);var K=U(),G=V();async function D(z){let q=z?.project,B=z?.team;if(!q&&!B){let v=(0,G.findProjectInfo)();q=v.projectId,B=v.teamId}else if(!q||!B){let v=(0,G.findProjectInfo)();q=q??v.projectId,B=B??v.teamId}if(!q)throw new K.VercelOidcTokenError("Failed to refresh OIDC token: No project specified. Try re-linking your project with `vc link`");let F=(0,G.loadToken)(q);if(!F||(0,G.isExpired)((0,G.getTokenPayload)(F.token),z?.expirationBufferMs)){let v=await(0,G.getVercelToken)({expirationBufferMs:z?.expirationBufferMs});if(F=await(0,G.getVercelOidcToken)(v,q,B),!F)throw new K.VercelOidcTokenError("Failed to refresh OIDC token");(0,G.saveToken)(F,q)}process.env.VERCEL_OIDC_TOKEN=F.token;return}});export default E();
1
+ import{a as U,b as V}from"./index-nwy7ec7p.js";import{Fa as R}from"./index-s2vhsb2v.js";var E=R((M,Q)=>{var{defineProperty:H,getOwnPropertyDescriptor:W,getOwnPropertyNames:X}=Object,Y=Object.prototype.hasOwnProperty,Z=(z,q)=>{for(var B in q)H(z,B,{get:q[B],enumerable:!0})},$=(z,q,B,F)=>{if(q&&typeof q==="object"||typeof q==="function"){for(let v of X(q))if(!Y.call(z,v)&&v!==B)H(z,v,{get:()=>q[v],enumerable:!(F=W(q,v))||F.enumerable})}return z},A=(z)=>$(H({},"__esModule",{value:!0}),z),L={};Z(L,{refreshToken:()=>D});Q.exports=A(L);var K=U(),G=V();async function D(z){let q=z?.project,B=z?.team;if(!q&&!B){let v=(0,G.findProjectInfo)();q=v.projectId,B=v.teamId}else if(!q||!B){let v=(0,G.findProjectInfo)();q=q??v.projectId,B=B??v.teamId}if(!q)throw new K.VercelOidcTokenError("Failed to refresh OIDC token: No project specified. Try re-linking your project with `vc link`");let F=(0,G.loadToken)(q);if(!F||(0,G.isExpired)((0,G.getTokenPayload)(F.token),z?.expirationBufferMs)){let v=await(0,G.getVercelToken)({expirationBufferMs:z?.expirationBufferMs});if(F=await(0,G.getVercelOidcToken)(v,q,B),!F)throw new K.VercelOidcTokenError("Failed to refresh OIDC token");(0,G.saveToken)(F,q)}process.env.VERCEL_OIDC_TOKEN=F.token;return}});export default E();
@@ -0,0 +1 @@
1
+ import{b as a}from"./index-nwy7ec7p.js";import"./index-s2vhsb2v.js";export default a();
@@ -1,4 +1,4 @@
1
- import{Da as P,Ea as C,Ga as _}from"./index-wpd7mg3p.js";var g=C((T,L)=>{(function(Q){if(typeof L==="object"&&typeof L.exports==="object"){var J=Q(_,T);if(J!==void 0)L.exports=J}else if(typeof define==="function"&&define.amd)define(["require","exports","./impl/format","./impl/edit","./impl/scanner","./impl/parser"],Q)})(function(Q,J){Object.defineProperty(J,"__esModule",{value:!0}),J.applyEdits=J.modify=J.format=J.printParseErrorCode=J.ParseErrorCode=J.stripComments=J.visit=J.getNodeValue=J.getNodePath=J.findNodeAtOffset=J.findNodeAtLocation=J.parseTree=J.parse=J.getLocation=J.SyntaxKind=J.ScanError=J.createScanner=void 0;let X=Q("./impl/format"),Z=Q("./impl/edit"),G=Q("./impl/scanner"),$=Q("./impl/parser");J.createScanner=G.createScanner;var W;(function(z){z[z.None=0]="None",z[z.UnexpectedEndOfComment=1]="UnexpectedEndOfComment",z[z.UnexpectedEndOfString=2]="UnexpectedEndOfString",z[z.UnexpectedEndOfNumber=3]="UnexpectedEndOfNumber",z[z.InvalidUnicode=4]="InvalidUnicode",z[z.InvalidEscapeCharacter=5]="InvalidEscapeCharacter",z[z.InvalidCharacter=6]="InvalidCharacter"})(W||(J.ScanError=W={}));var H;(function(z){z[z.OpenBraceToken=1]="OpenBraceToken",z[z.CloseBraceToken=2]="CloseBraceToken",z[z.OpenBracketToken=3]="OpenBracketToken",z[z.CloseBracketToken=4]="CloseBracketToken",z[z.CommaToken=5]="CommaToken",z[z.ColonToken=6]="ColonToken",z[z.NullKeyword=7]="NullKeyword",z[z.TrueKeyword=8]="TrueKeyword",z[z.FalseKeyword=9]="FalseKeyword",z[z.StringLiteral=10]="StringLiteral",z[z.NumericLiteral=11]="NumericLiteral",z[z.LineCommentTrivia=12]="LineCommentTrivia",z[z.BlockCommentTrivia=13]="BlockCommentTrivia",z[z.LineBreakTrivia=14]="LineBreakTrivia",z[z.Trivia=15]="Trivia",z[z.Unknown=16]="Unknown",z[z.EOF=17]="EOF"})(H||(J.SyntaxKind=H={})),J.getLocation=$.getLocation,J.parse=$.parse,J.parseTree=$.parseTree,J.findNodeAtLocation=$.findNodeAtLocation,J.findNodeAtOffset=$.findNodeAtOffset,J.getNodePath=$.getNodePath,J.getNodeValue=$.getNodeValue,J.visit=$.visit,J.stripComments=$.stripComments;var q;(function(z){z[z.InvalidSymbol=1]="InvalidSymbol",z[z.InvalidNumberFormat=2]="InvalidNumberFormat",z[z.PropertyNameExpected=3]="PropertyNameExpected",z[z.ValueExpected=4]="ValueExpected",z[z.ColonExpected=5]="ColonExpected",z[z.CommaExpected=6]="CommaExpected",z[z.CloseBraceExpected=7]="CloseBraceExpected",z[z.CloseBracketExpected=8]="CloseBracketExpected",z[z.EndOfFileExpected=9]="EndOfFileExpected",z[z.InvalidCommentToken=10]="InvalidCommentToken",z[z.UnexpectedEndOfComment=11]="UnexpectedEndOfComment",z[z.UnexpectedEndOfString=12]="UnexpectedEndOfString",z[z.UnexpectedEndOfNumber=13]="UnexpectedEndOfNumber",z[z.InvalidUnicode=14]="InvalidUnicode",z[z.InvalidEscapeCharacter=15]="InvalidEscapeCharacter",z[z.InvalidCharacter=16]="InvalidCharacter"})(q||(J.ParseErrorCode=q={}));function D(z){switch(z){case 1:return"InvalidSymbol";case 2:return"InvalidNumberFormat";case 3:return"PropertyNameExpected";case 4:return"ValueExpected";case 5:return"ColonExpected";case 6:return"CommaExpected";case 7:return"CloseBraceExpected";case 8:return"CloseBracketExpected";case 9:return"EndOfFileExpected";case 10:return"InvalidCommentToken";case 11:return"UnexpectedEndOfComment";case 12:return"UnexpectedEndOfString";case 13:return"UnexpectedEndOfNumber";case 14:return"InvalidUnicode";case 15:return"InvalidEscapeCharacter";case 16:return"InvalidCharacter"}return"<unknown ParseErrorCode>"}J.printParseErrorCode=D;function m(z,U,j){return X.format(z,U,j)}J.format=m;function f(z,U,j,A){return Z.setProperty(z,U,j,A)}J.modify=f;function u(z,U){let j=U.slice(0).sort((I,Y)=>{let F=I.offset-Y.offset;if(F===0)return I.length-Y.length;return F}),A=z.length;for(let I=j.length-1;I>=0;I--){let Y=j[I];if(Y.offset+Y.length<=A)z=Z.applyEdit(z,Y);else throw Error("Overlapping edit");A=Y.offset}return z}J.applyEdits=u})});var M=P(g(),1);import{watch as K}from"node:fs";import{mkdir as c,readFile as O,rename as y,writeFile as S}from"node:fs/promises";import{homedir as E}from"node:os";import{basename as l,dirname as v,join as k}from"node:path";var p="OPENCODE_TUI_PREFERENCES_FILE",x="tui-preferences.jsonc";function w(){let Q=process.env[p];if(Q)return Q;let J=process.env.OPENCODE_CONFIG_DIR||k(process.env.XDG_CONFIG_HOME||k(E(),".config"),"opencode");return k(J,x)}function N(Q){return typeof Q==="object"&&Q!==null&&!Array.isArray(Q)}async function Xz(){try{let Q=await O(w(),"utf8"),J=[],X=M.parse(Q,J,{allowTrailingComma:!0});if(J.length>0)return{};return N(X)?X:{}}catch{return{}}}var i="openai-auth",s=160,b={forceToTop:!1,order:s,startCollapsed:!1,rememberCollapsed:!0,collapsed:null,pollMs:1500,refreshDebounceMs:200,header:{label:"OPENAI",showVersion:!0},sections:{quota:!0,fallbackAccounts:!0,routing:!0,health:!0,pacing:!0},appearance:{barWidth:10,barFilledChar:"█",barEmptyChar:"░",warnThreshold:50,errorThreshold:80}};function V(Q,J){return typeof Q==="boolean"?Q:J}function B(Q,J,X,Z){if(typeof Q!=="number"||!Number.isFinite(Q))return J;return Math.min(Math.max(Math.round(Q),X),Z)}function d(Q,J,X){if(typeof Q!=="string"||Q.length===0)return J;return Q.slice(0,X)}function h(Q,J){if(typeof Q!=="string")return J;return[...Q][0]??J}function Zz(Q){let J=Q[i];if(!N(J))return structuredClone(b);let X=b,Z=N(J.header)?J.header:{},G=N(J.sections)?J.sections:{},$=N(J.appearance)?J.appearance:{},W=B($.warnThreshold,X.appearance.warnThreshold,0,99),H=Math.max(B($.errorThreshold,X.appearance.errorThreshold,0,100),Math.min(W+1,100));return{forceToTop:V(J.forceToTop,X.forceToTop),order:B(J.order,X.order,-1e4,1e4),startCollapsed:V(J.startCollapsed,X.startCollapsed),rememberCollapsed:V(J.rememberCollapsed,X.rememberCollapsed),collapsed:typeof J.collapsed==="boolean"?J.collapsed:null,pollMs:B(J.pollMs,X.pollMs,500,30000),refreshDebounceMs:B(J.refreshDebounceMs,X.refreshDebounceMs,50,5000),header:{label:d(Z.label,X.header.label,20),showVersion:V(Z.showVersion,X.header.showVersion)},sections:{quota:V(G.quota,X.sections.quota),fallbackAccounts:V(G.fallbackAccounts,X.sections.fallbackAccounts),routing:V(G.routing,X.sections.routing),health:V(G.health,X.sections.health),pacing:V(G.pacing,X.sections.pacing)},appearance:{barWidth:B($.barWidth,X.appearance.barWidth,4,40),barFilledChar:h($.barFilledChar,X.appearance.barFilledChar),barEmptyChar:h($.barEmptyChar,X.appearance.barEmptyChar),warnThreshold:W,errorThreshold:H}}}var n=-1e5;function $z(Q,J,X){let Z=Q[J];if(!N(Z))return X;if(Z.forceToTop===!0)return n+Object.keys(Q).indexOf(J);return B(Z.order,X,-1e4,1e4)}var t=`// Shared preferences for opencode TUI plugins.
1
+ import{Ea as P,Fa as C,Ha as _}from"./index-s2vhsb2v.js";var g=C((T,L)=>{(function(Q){if(typeof L==="object"&&typeof L.exports==="object"){var J=Q(_,T);if(J!==void 0)L.exports=J}else if(typeof define==="function"&&define.amd)define(["require","exports","./impl/format","./impl/edit","./impl/scanner","./impl/parser"],Q)})(function(Q,J){Object.defineProperty(J,"__esModule",{value:!0}),J.applyEdits=J.modify=J.format=J.printParseErrorCode=J.ParseErrorCode=J.stripComments=J.visit=J.getNodeValue=J.getNodePath=J.findNodeAtOffset=J.findNodeAtLocation=J.parseTree=J.parse=J.getLocation=J.SyntaxKind=J.ScanError=J.createScanner=void 0;let X=Q("./impl/format"),Z=Q("./impl/edit"),G=Q("./impl/scanner"),$=Q("./impl/parser");J.createScanner=G.createScanner;var W;(function(z){z[z.None=0]="None",z[z.UnexpectedEndOfComment=1]="UnexpectedEndOfComment",z[z.UnexpectedEndOfString=2]="UnexpectedEndOfString",z[z.UnexpectedEndOfNumber=3]="UnexpectedEndOfNumber",z[z.InvalidUnicode=4]="InvalidUnicode",z[z.InvalidEscapeCharacter=5]="InvalidEscapeCharacter",z[z.InvalidCharacter=6]="InvalidCharacter"})(W||(J.ScanError=W={}));var H;(function(z){z[z.OpenBraceToken=1]="OpenBraceToken",z[z.CloseBraceToken=2]="CloseBraceToken",z[z.OpenBracketToken=3]="OpenBracketToken",z[z.CloseBracketToken=4]="CloseBracketToken",z[z.CommaToken=5]="CommaToken",z[z.ColonToken=6]="ColonToken",z[z.NullKeyword=7]="NullKeyword",z[z.TrueKeyword=8]="TrueKeyword",z[z.FalseKeyword=9]="FalseKeyword",z[z.StringLiteral=10]="StringLiteral",z[z.NumericLiteral=11]="NumericLiteral",z[z.LineCommentTrivia=12]="LineCommentTrivia",z[z.BlockCommentTrivia=13]="BlockCommentTrivia",z[z.LineBreakTrivia=14]="LineBreakTrivia",z[z.Trivia=15]="Trivia",z[z.Unknown=16]="Unknown",z[z.EOF=17]="EOF"})(H||(J.SyntaxKind=H={})),J.getLocation=$.getLocation,J.parse=$.parse,J.parseTree=$.parseTree,J.findNodeAtLocation=$.findNodeAtLocation,J.findNodeAtOffset=$.findNodeAtOffset,J.getNodePath=$.getNodePath,J.getNodeValue=$.getNodeValue,J.visit=$.visit,J.stripComments=$.stripComments;var q;(function(z){z[z.InvalidSymbol=1]="InvalidSymbol",z[z.InvalidNumberFormat=2]="InvalidNumberFormat",z[z.PropertyNameExpected=3]="PropertyNameExpected",z[z.ValueExpected=4]="ValueExpected",z[z.ColonExpected=5]="ColonExpected",z[z.CommaExpected=6]="CommaExpected",z[z.CloseBraceExpected=7]="CloseBraceExpected",z[z.CloseBracketExpected=8]="CloseBracketExpected",z[z.EndOfFileExpected=9]="EndOfFileExpected",z[z.InvalidCommentToken=10]="InvalidCommentToken",z[z.UnexpectedEndOfComment=11]="UnexpectedEndOfComment",z[z.UnexpectedEndOfString=12]="UnexpectedEndOfString",z[z.UnexpectedEndOfNumber=13]="UnexpectedEndOfNumber",z[z.InvalidUnicode=14]="InvalidUnicode",z[z.InvalidEscapeCharacter=15]="InvalidEscapeCharacter",z[z.InvalidCharacter=16]="InvalidCharacter"})(q||(J.ParseErrorCode=q={}));function D(z){switch(z){case 1:return"InvalidSymbol";case 2:return"InvalidNumberFormat";case 3:return"PropertyNameExpected";case 4:return"ValueExpected";case 5:return"ColonExpected";case 6:return"CommaExpected";case 7:return"CloseBraceExpected";case 8:return"CloseBracketExpected";case 9:return"EndOfFileExpected";case 10:return"InvalidCommentToken";case 11:return"UnexpectedEndOfComment";case 12:return"UnexpectedEndOfString";case 13:return"UnexpectedEndOfNumber";case 14:return"InvalidUnicode";case 15:return"InvalidEscapeCharacter";case 16:return"InvalidCharacter"}return"<unknown ParseErrorCode>"}J.printParseErrorCode=D;function m(z,U,j){return X.format(z,U,j)}J.format=m;function f(z,U,j,A){return Z.setProperty(z,U,j,A)}J.modify=f;function u(z,U){let j=U.slice(0).sort((I,Y)=>{let F=I.offset-Y.offset;if(F===0)return I.length-Y.length;return F}),A=z.length;for(let I=j.length-1;I>=0;I--){let Y=j[I];if(Y.offset+Y.length<=A)z=Z.applyEdit(z,Y);else throw Error("Overlapping edit");A=Y.offset}return z}J.applyEdits=u})});var M=P(g(),1);import{watch as K}from"node:fs";import{mkdir as c,readFile as O,rename as y,writeFile as S}from"node:fs/promises";import{homedir as E}from"node:os";import{basename as l,dirname as v,join as k}from"node:path";var p="OPENCODE_TUI_PREFERENCES_FILE",x="tui-preferences.jsonc";function w(){let Q=process.env[p];if(Q)return Q;let J=process.env.OPENCODE_CONFIG_DIR||k(process.env.XDG_CONFIG_HOME||k(E(),".config"),"opencode");return k(J,x)}function N(Q){return typeof Q==="object"&&Q!==null&&!Array.isArray(Q)}async function Xz(){try{let Q=await O(w(),"utf8"),J=[],X=M.parse(Q,J,{allowTrailingComma:!0});if(J.length>0)return{};return N(X)?X:{}}catch{return{}}}var i="openai-auth",s=160,b={forceToTop:!1,order:s,startCollapsed:!1,rememberCollapsed:!0,collapsed:null,pollMs:1500,refreshDebounceMs:200,header:{label:"OPENAI",showVersion:!0},sections:{quota:!0,fallbackAccounts:!0,routing:!0,health:!0,pacing:!0},appearance:{barWidth:10,barFilledChar:"█",barEmptyChar:"░",warnThreshold:50,errorThreshold:80}};function V(Q,J){return typeof Q==="boolean"?Q:J}function B(Q,J,X,Z){if(typeof Q!=="number"||!Number.isFinite(Q))return J;return Math.min(Math.max(Math.round(Q),X),Z)}function d(Q,J,X){if(typeof Q!=="string"||Q.length===0)return J;return Q.slice(0,X)}function h(Q,J){if(typeof Q!=="string")return J;return[...Q][0]??J}function Zz(Q){let J=Q[i];if(!N(J))return structuredClone(b);let X=b,Z=N(J.header)?J.header:{},G=N(J.sections)?J.sections:{},$=N(J.appearance)?J.appearance:{},W=B($.warnThreshold,X.appearance.warnThreshold,0,99),H=Math.max(B($.errorThreshold,X.appearance.errorThreshold,0,100),Math.min(W+1,100));return{forceToTop:V(J.forceToTop,X.forceToTop),order:B(J.order,X.order,-1e4,1e4),startCollapsed:V(J.startCollapsed,X.startCollapsed),rememberCollapsed:V(J.rememberCollapsed,X.rememberCollapsed),collapsed:typeof J.collapsed==="boolean"?J.collapsed:null,pollMs:B(J.pollMs,X.pollMs,500,30000),refreshDebounceMs:B(J.refreshDebounceMs,X.refreshDebounceMs,50,5000),header:{label:d(Z.label,X.header.label,20),showVersion:V(Z.showVersion,X.header.showVersion)},sections:{quota:V(G.quota,X.sections.quota),fallbackAccounts:V(G.fallbackAccounts,X.sections.fallbackAccounts),routing:V(G.routing,X.sections.routing),health:V(G.health,X.sections.health),pacing:V(G.pacing,X.sections.pacing)},appearance:{barWidth:B($.barWidth,X.appearance.barWidth,4,40),barFilledChar:h($.barFilledChar,X.appearance.barFilledChar),barEmptyChar:h($.barEmptyChar,X.appearance.barEmptyChar),warnThreshold:W,errorThreshold:H}}}var n=-1e5;function $z(Q,J,X){let Z=Q[J];if(!N(Z))return X;if(Z.forceToTop===!0)return n+Object.keys(Q).indexOf(J);return B(Z.order,X,-1e4,1e4)}var t=`// Shared preferences for opencode TUI plugins.
2
2
  // One top-level key per plugin (short name). See each plugin's README for
3
3
  // its supported settings. This file is safe to hand-edit; plugins update
4
4
  // individual keys in place and preserve comments.
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const PackageVersion = "0.5.1";
1
+ export declare const PackageVersion = "0.6.0";
package/dist/ws-pool.d.ts CHANGED
@@ -48,6 +48,7 @@ export declare function createWebSocketFetch(options?: CreateWebSocketFetchOptio
48
48
  };
49
49
  export declare const CODEX_BODY_KEY_ORDER: string[];
50
50
  export declare function orderCodexBody(body: Record<string, unknown>): Record<string, unknown>;
51
+ export declare function advanceTurn(entry: PoolEntry, body: Record<string, unknown>, fullBody?: Record<string, unknown>): void;
51
52
  export declare function applyTurnId(entry: PoolEntry, body: Record<string, unknown>, fullBody?: Record<string, unknown>): Record<string, unknown>;
52
53
  export { hasWebSocketResponsesLiteMetadata, sanitizeHttpFallbackBody, } from './codex-http';
53
54
  export declare function withoutInternalHeaders<T extends {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/opencode-openai-auth",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "repository": {
@@ -61,8 +61,8 @@
61
61
  "@opencode-ai/plugin": "*"
62
62
  },
63
63
  "dependencies": {
64
- "@opentui/core": ">=0.4.5",
65
- "@opentui/solid": ">=0.4.5",
64
+ "@opentui/core": ">=0.5.1",
65
+ "@opentui/solid": ">=0.5.1",
66
66
  "ai": "^7.0.48",
67
67
  "jsonc-parser": "^3.3.1",
68
68
  "solid-js": "1.9.12"
@@ -6,6 +6,7 @@ export type CommandModalName =
6
6
  | 'openai-dump'
7
7
  | 'openai-logging'
8
8
  | 'openai-cachekeep'
9
+ | 'openai-reset'
9
10
 
10
11
  export interface OpenDialogPayload {
11
12
  command: CommandModalName
@@ -6,21 +6,24 @@ export interface RpcClient {
6
6
  lastReceivedId: number,
7
7
  sessionId?: string,
8
8
  ) => Promise<RpcNotification[]>
9
- apply: (request: ApplyRequest) => Promise<ApplyResult>
9
+ apply: (request: ApplyRequest, timeoutMs?: number) => Promise<ApplyResult>
10
10
  }
11
11
 
12
+ export const DEFAULT_RPC_TIMEOUT_MS = 2_000
13
+
12
14
  async function call<T>(
13
15
  dir: string,
14
16
  expectedPid: number | undefined,
15
17
  onSelected: ((entry: PortFileEntry | null) => void) | undefined,
16
18
  method: string,
17
19
  params: Record<string, unknown>,
20
+ timeoutMs = DEFAULT_RPC_TIMEOUT_MS,
18
21
  ): Promise<T | null> {
19
22
  const entry = await discoverPortFile(dir, expectedPid)
20
23
  onSelected?.(entry)
21
24
  if (!entry) return null
22
25
  const controller = new AbortController()
23
- const timer = setTimeout(() => controller.abort(), 2_000)
26
+ const timer = setTimeout(() => controller.abort(), timeoutMs)
24
27
  try {
25
28
  const res = await fetch(`http://127.0.0.1:${entry.port}/rpc/${method}`, {
26
29
  method: 'POST',
@@ -62,7 +65,7 @@ export function createRpcClient(
62
65
  )
63
66
  return out?.messages ?? []
64
67
  },
65
- async apply(request) {
68
+ async apply(request, timeoutMs) {
66
69
  const out = await call<ApplyResult>(
67
70
  dir,
68
71
  expectedPid,
@@ -71,6 +74,7 @@ export function createRpcClient(
71
74
  {
72
75
  ...request,
73
76
  },
77
+ timeoutMs,
74
78
  )
75
79
  return out ?? { text: 'apply failed', knobs: {} }
76
80
  },
@@ -25,7 +25,10 @@ export interface RpcServerOptions {
25
25
  sweepRoot?: string
26
26
  drain: typeof drainNotifications
27
27
  apply: (request: ApplyRequest) => Promise<ApplyResult>
28
+ // Bounds handler execution via the socket inactivity timer.
28
29
  timeoutMs?: number
30
+ // Bounds request delivery only (requestTimeout/headersTimeout).
31
+ receiptTimeoutMs?: number
29
32
  }
30
33
 
31
34
  function readBody(req: IncomingMessage): Promise<string> {
@@ -57,15 +60,32 @@ export async function startRpcServer(
57
60
  options: RpcServerOptions,
58
61
  ): Promise<RpcServerHandle> {
59
62
  const token = randomBytes(32).toString('hex')
60
- const timeoutMs = options.timeoutMs ?? 2000
63
+ // Two different bounds, deliberately not one value.
64
+ //
65
+ // requestTimeout/headersTimeout bound how long a client may take to DELIVER
66
+ // a request; they do not bound handler execution. A receipt bound of 500ms
67
+ // still returns 200 for a 3s handler. Over loopback with a 1 MiB body cap,
68
+ // seconds is already generous.
69
+ //
70
+ // The inactivity timer is the one that can kill a working handler: it
71
+ // destroys the socket out from under it. It must therefore outlast the
72
+ // slowest legitimate apply — a reset redemption is bounded by a 60s consume
73
+ // call — or the response is lost server-side no matter what deadline the
74
+ // client passed. Fast commands respond in milliseconds regardless.
75
+ //
76
+ // Collapsing these back into a single value reintroduces one of two bugs:
77
+ // a receipt bound that aborts a slow reset, or a socket timer that leaves
78
+ // every endpoint holding a dead connection for 90s.
79
+ const handlerTimeoutMs = options.timeoutMs ?? 90_000
80
+ const receiptTimeoutMs = options.receiptTimeoutMs ?? 2_000
61
81
  const server = createServer((req, res) => {
62
- req.setTimeout(timeoutMs, () => {
82
+ req.setTimeout(handlerTimeoutMs, () => {
63
83
  req.socket.destroy()
64
84
  })
65
85
  void dispatch(req, res)
66
86
  })
67
- server.requestTimeout = timeoutMs
68
- server.headersTimeout = timeoutMs
87
+ server.requestTimeout = receiptTimeoutMs
88
+ server.headersTimeout = receiptTimeoutMs
69
89
 
70
90
  async function dispatch(req: IncomingMessage, res: ServerResponse) {
71
91
  const json = (status: number, value: unknown) => {
@@ -100,6 +100,7 @@ export type ActiveRoutingMap = Record<string, ActiveRoutingEntry>
100
100
 
101
101
  export interface StickyAssignment {
102
102
  accountId: string
103
+ wireAccountId?: string
103
104
  assignedAt: number
104
105
  lastSeenAt: number
105
106
  inputBytes: number
@@ -120,6 +121,7 @@ export interface ResolveStickyAssignmentInput {
120
121
  validPinnedAccountIds: readonly string[]
121
122
  excludeAccountIds?: readonly string[]
122
123
  quotaCheckedAtByAccount: Readonly<Record<string, number | undefined>>
124
+ wireAccountIdByAccount?: Readonly<Record<string, string | undefined>>
123
125
  choose: (
124
126
  pendingBytes: ReadonlyMap<string, number>,
125
127
  ) => StickyAssignmentChoice | undefined
@@ -256,12 +258,14 @@ function normalizeStickyAssignments(
256
258
  ) {
257
259
  continue
258
260
  }
261
+ const wireAccountId = assignment.wireAccountId
259
262
  normalized[sessionHash] = {
260
263
  accountId: assignment.accountId,
261
264
  assignedAt: assignment.assignedAt,
262
265
  lastSeenAt: assignment.lastSeenAt,
263
266
  inputBytes: assignment.inputBytes,
264
267
  ...(quotaCheckedAt === undefined ? {} : { quotaCheckedAt }),
268
+ ...(typeof wireAccountId === 'string' ? { wireAccountId } : {}),
265
269
  }
266
270
  }
267
271
 
@@ -652,10 +656,32 @@ function stickyAssignmentNeedsMetadataUpdate(
652
656
  assignment: StickyAssignment,
653
657
  requestBytes: number,
654
658
  now: number,
659
+ wireAccountId: string | undefined,
655
660
  ): boolean {
656
661
  return (
657
662
  requestBytes > assignment.inputBytes ||
658
- now - assignment.lastSeenAt >= STICKY_ASSIGNMENT_LAST_SEEN_TOUCH_MS
663
+ now - assignment.lastSeenAt >= STICKY_ASSIGNMENT_LAST_SEEN_TOUCH_MS ||
664
+ (assignment.wireAccountId === undefined && wireAccountId !== undefined)
665
+ )
666
+ }
667
+
668
+ function hasStickyIdentityMismatch(
669
+ assignment: StickyAssignment,
670
+ wireAccountId: string | undefined,
671
+ ): boolean {
672
+ // True only when both sides know their ChatGPT account and those accounts
673
+ // differ, which means the slot this session was placed on now holds a
674
+ // different account than it did at placement.
675
+ //
676
+ // An unknown on either side deliberately reports no mismatch. A session is
677
+ // pinned to keep its prompt cache warm, and treating missing data as a
678
+ // change would place sessions again for no reason and throw those caches
679
+ // away — worse than leaving a rare wrong pin in place until real evidence
680
+ // arrives.
681
+ return (
682
+ typeof assignment.wireAccountId === 'string' &&
683
+ typeof wireAccountId === 'string' &&
684
+ assignment.wireAccountId !== wireAccountId
659
685
  )
660
686
  }
661
687
 
@@ -692,9 +718,11 @@ function readonlyPendingBytes(
692
718
  function pendingBytesForAssignments(
693
719
  assignments: StickyAssignmentMap | undefined,
694
720
  quotaCheckedAtByAccount: Readonly<Record<string, number | undefined>>,
721
+ excludedSessionHash?: string,
695
722
  ): ReadonlyMap<string, number> {
696
723
  const pendingBytes = new Map<string, number>()
697
- for (const assignment of Object.values(assignments ?? {})) {
724
+ for (const [sessionHash, assignment] of Object.entries(assignments ?? {})) {
725
+ if (sessionHash === excludedSessionHash) continue
698
726
  if (
699
727
  assignment.quotaCheckedAt !==
700
728
  quotaCheckedAtByAccount[assignment.accountId]
@@ -1178,10 +1206,15 @@ export async function resolveSidebarStickyAssignment(
1178
1206
  excludedAccountIds,
1179
1207
  input.now,
1180
1208
  ) &&
1209
+ !hasStickyIdentityMismatch(
1210
+ existing,
1211
+ input.wireAccountIdByAccount?.[existing.accountId],
1212
+ ) &&
1181
1213
  !stickyAssignmentNeedsMetadataUpdate(
1182
1214
  existing,
1183
1215
  input.requestBytes,
1184
1216
  input.now,
1217
+ input.wireAccountIdByAccount?.[existing.accountId],
1185
1218
  )
1186
1219
  ) {
1187
1220
  return existing
@@ -1202,23 +1235,38 @@ export async function resolveSidebarStickyAssignment(
1202
1235
  stickyAssignments,
1203
1236
  )
1204
1237
  const current = stickyAssignments?.[sessionHash]
1238
+ const currentIdentityMismatch =
1239
+ current !== undefined &&
1240
+ hasStickyIdentityMismatch(
1241
+ current,
1242
+ input.wireAccountIdByAccount?.[current.accountId],
1243
+ )
1205
1244
  if (
1206
1245
  isValidStickyAssignment(
1207
1246
  current,
1208
1247
  validPinnedAccountIds,
1209
1248
  excludedAccountIds,
1210
1249
  input.now,
1211
- )
1250
+ ) &&
1251
+ !currentIdentityMismatch
1212
1252
  ) {
1213
1253
  const metadataNeedsUpdate = stickyAssignmentNeedsMetadataUpdate(
1214
1254
  current,
1215
1255
  input.requestBytes,
1216
1256
  input.now,
1257
+ input.wireAccountIdByAccount?.[current.accountId],
1217
1258
  )
1218
1259
  const assignment = metadataNeedsUpdate
1219
1260
  ? {
1220
1261
  ...current,
1221
1262
  inputBytes: Math.max(current.inputBytes, input.requestBytes),
1263
+ ...(current.wireAccountId === undefined &&
1264
+ input.wireAccountIdByAccount?.[current.accountId] !== undefined
1265
+ ? {
1266
+ wireAccountId:
1267
+ input.wireAccountIdByAccount?.[current.accountId],
1268
+ }
1269
+ : {}),
1222
1270
  ...(input.now - current.lastSeenAt >=
1223
1271
  STICKY_ASSIGNMENT_LAST_SEEN_TOUCH_MS
1224
1272
  ? { lastSeenAt: input.now }
@@ -1241,6 +1289,12 @@ export async function resolveSidebarStickyAssignment(
1241
1289
  pendingBytesForAssignments(
1242
1290
  stickyAssignments,
1243
1291
  input.quotaCheckedAtByAccount,
1292
+ // Pending bytes weigh how much traffic each account is already
1293
+ // committed to, so the session being placed must not weigh its own
1294
+ // stale entry: that entry belongs to the account it is moving off,
1295
+ // and counting it would bias placement away from a perfectly good
1296
+ // destination. Other sessions' entries still count.
1297
+ currentIdentityMismatch ? sessionHash : undefined,
1244
1298
  ),
1245
1299
  )
1246
1300
  if (!choice) {
@@ -1261,6 +1315,11 @@ export async function resolveSidebarStickyAssignment(
1261
1315
  ...(choice.quotaCheckedAt === undefined
1262
1316
  ? {}
1263
1317
  : { quotaCheckedAt: choice.quotaCheckedAt }),
1318
+ ...(input.wireAccountIdByAccount?.[choice.accountId] === undefined
1319
+ ? {}
1320
+ : {
1321
+ wireAccountId: input.wireAccountIdByAccount?.[choice.accountId],
1322
+ }),
1264
1323
  }
1265
1324
  return {
1266
1325
  ...latest,