@duckmind/dm-darwin-x64 0.49.8 → 0.49.9
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/dm +0 -0
- package/extensions/.dm-extensions.json +44 -15
- package/extensions/dm-cliproxy/NOTICE.md +12 -0
- package/extensions/dm-cliproxy/index.js +2 -0
- package/extensions/dm-cliproxy/package.json +20 -0
- package/extensions/dm-cliproxy/scripts/check-config-migration.js +10 -0
- package/extensions/dm-cliproxy/src/apply.js +1 -0
- package/extensions/dm-cliproxy/src/cache.js +1 -0
- package/extensions/dm-cliproxy/src/commands.js +2 -0
- package/extensions/dm-cliproxy/src/compat.js +1 -0
- package/extensions/dm-cliproxy/src/config.js +2 -0
- package/extensions/dm-cliproxy/src/conflicts.js +1 -0
- package/extensions/dm-cliproxy/src/fetch-models.js +1 -0
- package/extensions/dm-cliproxy/src/fetch-usage.js +1 -0
- package/extensions/dm-cliproxy/src/log.js +1 -0
- package/extensions/dm-cliproxy/src/status-quota.js +1 -0
- package/extensions/dm-cliproxy/src/ui-frame.js +1 -0
- package/extensions/dm-cliproxy/src/ui-hub/hub.js +2 -0
- package/extensions/dm-cliproxy/src/ui-hub/index.js +2 -0
- package/extensions/dm-cliproxy/src/ui-hub/shell.js +1 -0
- package/extensions/dm-cliproxy/src/ui-hub/types.js +0 -0
- package/extensions/dm-cliproxy/src/ui-hub/view-diagnostics.js +1 -0
- package/extensions/dm-cliproxy/src/ui-hub/view-models.js +1 -0
- package/extensions/dm-cliproxy/src/ui-hub/view-usage.js +1 -0
- package/extensions/dm-cliproxy/src/ui-picker/catalog.js +1 -0
- package/extensions/dm-cliproxy/src/ui-picker/mutate.js +1 -0
- package/extensions/dm-cliproxy/src/ui-picker/prompt-confirm.js +1 -0
- package/extensions/dm-cliproxy/src/ui-picker/prompt-name.js +1 -0
- package/extensions/dm-cliproxy/src/ui-picker/providers.js +1 -0
- package/extensions/dm-cliproxy/src/ui-picker/render-text.js +1 -0
- package/extensions/dm-cliproxy/src/ui-picker/rows.js +1 -0
- package/extensions/dm-cliproxy/src/ui-picker/types.js +0 -0
- package/extensions/dm-cliproxy/src/ui-setup.js +2 -0
- package/extensions/dm-cliproxy/src/ui-usage.js +1 -0
- package/extensions/dm-cliproxy/src/usage-shared-cache.js +1 -0
- package/extensions/dm-subagents/src/extension/doctor.js +10 -10
- package/extensions/dm-subagents/src/extension/fanout-child.js +129 -129
- package/extensions/dm-subagents/src/extension/index.js +179 -179
- package/extensions/dm-subagents/src/extension/rpc.js +5 -5
- package/extensions/dm-subagents/src/extension/schemas.js +1 -1
- package/extensions/dm-subagents/src/extension/tool-description.js +2 -2
- package/extensions/dm-subagents/src/intercom/native-supervisor-channel.js +5 -5
- package/extensions/dm-subagents/src/runs/background/async-execution.js +19 -19
- package/extensions/dm-subagents/src/runs/background/async-job-tracker.js +10 -10
- package/extensions/dm-subagents/src/runs/background/async-resume.js +5 -5
- package/extensions/dm-subagents/src/runs/background/async-status.js +8 -8
- package/extensions/dm-subagents/src/runs/background/fleet-view.js +14 -14
- package/extensions/dm-subagents/src/runs/background/result-watcher.js +5 -5
- package/extensions/dm-subagents/src/runs/background/run-id-resolver.js +3 -3
- package/extensions/dm-subagents/src/runs/background/run-status.js +20 -20
- package/extensions/dm-subagents/src/runs/background/stale-run-reconciler.js +7 -7
- package/extensions/dm-subagents/src/runs/background/subagent-runner.js +38 -38
- package/extensions/dm-subagents/src/runs/background/wait.js +7 -7
- package/extensions/dm-subagents/src/runs/foreground/chain-execution.js +58 -58
- package/extensions/dm-subagents/src/runs/foreground/execution.js +36 -36
- package/extensions/dm-subagents/src/runs/foreground/subagent-executor.js +129 -129
- package/extensions/dm-subagents/src/runs/shared/dm-args.js +1 -1
- package/extensions/dm-subagents/src/runs/shared/nested-events.js +6 -6
- package/extensions/dm-subagents/src/runs/shared/subagent-prompt-runtime.js +13 -13
- package/package.json +1 -1
- package/extensions/dm-9router-ext/package.json +0 -23
- package/extensions/dm-9router-ext/src/index.js +0 -5
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{getKeybindings as R1,matchesKey as C}from"@duckmind/dm-tui";import{getModels as Sj}from"@duckmind/dm-ai/compat";var b$=new Set(["openai-completions","openai-responses","anthropic-messages"]);function y$($,j){let J=j.replace(/\/+$/,"");if($==="anthropic-messages")return J.replace(/\/v1$/,"");return J}function Z0($,j){if(!$)return!0;for(let J of j)if(new RegExp("^"+J.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*")+"$").test($))return!0;return!1}var Qj=128000,Yj=16000,Zj={input:0,output:0,cacheRead:0,cacheWrite:0},Xj=[/.*-thinking$/,/^gpt-5(\.\d+)?(-.*)?$/,/^gemini-3(\.\d+)?(-.*)?$/];function R$($){return Xj.some((j)=>j.test($))}var zj=[[new Set(["zai"]),"glm","openai-completions"],[new Set(["Mistral"]),"mistral","openai-completions"],[new Set(["google","antigravity"]),"gemini","openai-completions"],[new Set(["Ollama","Ollama pay"]),"ollama","openai-completions"],[new Set(["Xiaomi"]),"mimo","openai-completions"],[new Set(["OpenRouter"]),"openrouter","openai-completions"],[new Set(["cerebras"]),"cerebras","openai-completions"]];function E$($,j){let J=($??"").trim();return J?`${J}-${j}`:j}function X0($,j){let J=(j??"").trim(),Q=$.match(/^([a-z0-9]+-)(.*)$/);if(Q)return J?`${J}-${Q[1]}`:Q[1];return $}function z0($,j){for(let[J,Q,Y]of zj)if(J.has($))return{slug:E$(j,Q),api:Y};return{slug:E$(j,"misc"),api:"openai-completions"}}function Vj($){return $.replace(/[/:]/g," ").split(/[-_]/).filter(Boolean).map((j)=>j[0].toUpperCase()+j.slice(1)).join(" ")}function J$($){return{id:$,name:Vj($),contextWindow:Qj,maxTokens:Yj,reasoning:R$($),cost:{...Zj}}}import{execSync as qj}from"node:child_process";import{randomUUID as V0}from"node:crypto";import{chmodSync as _$,constants as Mj,copyFileSync as q0,existsSync as A$,linkSync as nj,mkdirSync as M0,readFileSync as Dj,rmSync as w$,writeFileSync as Uj}from"node:fs";import{homedir as C$}from"node:os";import{dirname as X$,join as z$}from"node:path";import{fileURLToPath as Ej}from"node:url";var G$=!1;var B={info(...$){if(!G$)console.log("[dm-cliproxy]",...$)},warn(...$){if(!G$)console.warn("[dm-cliproxy]",...$)},error(...$){if(!G$)console.error("[dm-cliproxy]",...$)},debug(...$){if(!G$&&(process.env.DM_CLIPROXY_DEBUG||process.env.PI_CLIPROXYAPI_DEBUG))console.log("[dm-cliproxy]","[debug]",...$)}};var u$=z$(C$(),".dm","agent","dm-cliproxy"),w=z$(u$,"config.json"),Rj=[z$(C$(),".pi","agent","pi-cliproxyapi","config.json"),z$(C$(),".config","pi-cliproxyapi","config.json")];function Gj(){return A$(z$(X$(Ej(import.meta.url)),"..",".git"))}function _j($=Rj,j=w,J=Gj()){if(A$(j))return;let Y=(typeof $==="string"?[$]:[...$]).find((z)=>A$(z));if(!Y)return;let Z;try{M0(X$(j),{recursive:!0,mode:448}),_$(X$(j),448),Z=`${j}.${process.pid}.${V0()}.tmp`,q0(Y,Z,Mj.COPYFILE_EXCL),_$(Z,384),nj(Z,j),w$(Z),Z=void 0,B.info("legacy config copied to",j)}catch(z){if(Z)try{w$(Z,{force:!0})}catch(X){B.warn("failed to clean temporary config:",X)}B.warn("failed to migrate legacy config:",z)}}var O$={proxy:{endpoint:"",apiKey:""},builtinProviders:{},customProviders:{},discoveryExcludes:["*:*"],overrides:{},refreshIntervalMinutes:0,usageCacheTtlMs:30000};function H$(){if(_j(),!A$(w))return B.debug("config not found, using defaults at",w),structuredClone(O$);try{let $=JSON.parse(Dj(w,"utf8"));return Aj($)}catch($){return B.error("failed to read config:",$,"— using defaults"),structuredClone(O$)}}function W$($){M0(X$(w),{recursive:!0,mode:448}),_$(X$(w),448);let j=`${w}.${process.pid}.${V0()}.tmp`;try{Uj(j,JSON.stringify($,null,2)+`
|
|
2
|
+
`,{encoding:"utf8",flag:"wx",mode:384}),q0(j,w),_$(w,384)}finally{w$(j,{force:!0})}B.info("config saved to",w)}function Aj($){if(!$||typeof $!=="object")return structuredClone(O$);let j=$,J=structuredClone(O$),Q=j.proxy??{};if(J.proxy.endpoint=typeof Q.endpoint==="string"?Q.endpoint:J.proxy.endpoint,J.proxy.apiKey=typeof Q.apiKey==="string"?Q.apiKey:"",typeof Q.usageKey==="string")J.proxy.usageKey=Q.usageKey;if(typeof Q.providerPrefix==="string"&&Q.providerPrefix.trim())J.proxy.providerPrefix=Q.providerPrefix.trim();if(j.builtinProviders&&typeof j.builtinProviders==="object")J.builtinProviders=j.builtinProviders;if(j.customProviders&&typeof j.customProviders==="object")J.customProviders=j.customProviders;if(Array.isArray(j.discoveryExcludes))J.discoveryExcludes=j.discoveryExcludes.filter((Y)=>typeof Y==="string");if(j.overrides&&typeof j.overrides==="object")J.overrides=j.overrides;if(typeof j.refreshIntervalMinutes==="number")J.refreshIntervalMinutes=j.refreshIntervalMinutes;if(typeof j.usageCacheTtlMs==="number")J.usageCacheTtlMs=j.usageCacheTtlMs;return J}function g($){if(!$)return"";let j=$.trim();if(j.startsWith("!"))try{return qj(j.slice(1),{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).trim()}catch(J){let Q=J?.stderr?.toString?.()?.trim()??J.message;return B.warn(`failed to resolve "!" config value (${j}): ${Q}`),""}if(j.startsWith("$"))return process.env[j.slice(1)]??"";return j}import{chmodSync as Oj,existsSync as K1,mkdirSync as Hj,readFileSync as S1,writeFileSync as Wj}from"node:fs";import{dirname as n0,join as kj}from"node:path";var v$=kj(u$,"discovery-cache.json");function f$($){try{Hj(n0(v$),{recursive:!0,mode:448}),Oj(n0(v$),448);let j={savedAt:Date.now(),discovery:$};Wj(v$,JSON.stringify(j),{encoding:"utf8",mode:384})}catch(j){B.warn("failed to write discovery cache:",j.message)}}var Q$="dm-cliproxy/0.3.5",Nj=5000;async function E0($,j){let J=new AbortController,Q=setTimeout(()=>J.abort(Error("timeout")),Nj);try{return await fetch($,{...j,signal:J.signal})}finally{clearTimeout(Q)}}function Tj($){return new URL("/.well-known/pi",new URL($).origin).toString()}async function Bj($){let j=Tj($.proxy.endpoint),J;try{J=await E0(j,{headers:{"User-Agent":Q$,Accept:"application/json"}})}catch(X){return B.warn("well-known fetch failed:",X.message,"— falling back to /v1/models"),null}if(!J.ok)return B.warn(`well-known returned ${J.status} — falling back to /v1/models`),null;let Q;try{Q=await J.json()}catch{return B.warn("well-known returned non-JSON — falling back to /v1/models"),null}if(!Q||Q.schemaVersion!==1)return B.warn("well-known schemaVersion != 1 — falling back to /v1/models"),null;let Y=[],Z=Q.builtinProviders??{};for(let[X,V]of Object.entries(Z)){if(!V||!Array.isArray(V.models))continue;let q=V.models.map((n)=>({id:String(n.id),name:typeof n.name==="string"?n.name:String(n.id),reasoning:Boolean(n.reasoning??R$(String(n.id))),contextWindow:typeof n.contextWindow==="number"?n.contextWindow:200000,maxTokens:typeof n.maxTokens==="number"?n.maxTokens:16000,cost:n.cost??{input:0,output:0,cacheRead:0,cacheWrite:0}}));Y.push({name:X,api:V.api??"openai-responses",models:q})}let z=(Array.isArray(Q.customModelPool)?Q.customModelPool:[]).map((X)=>({id:String(X.id),name:typeof X.name==="string"?X.name:String(X.id),reasoning:Boolean(X.reasoning??R$(String(X.id))),contextWindow:typeof X.contextWindow==="number"?X.contextWindow:128000,maxTokens:typeof X.maxTokens==="number"?X.maxTokens:16000,cost:X.cost??{input:0,output:0,cacheRead:0,cacheWrite:0},api:X.api??"openai-completions",suggestedProvider:X0(typeof X.suggestedProviderName==="string"?X.suggestedProviderName:"misc",$.proxy.providerPrefix),ownedBy:typeof X.owned_by==="string"?X.owned_by:""}));return{source:"well-known",upstreamVersion:typeof Q?.upstream?.upstreamVersion==="string"?Q.upstream.upstreamVersion:null,builtinProviders:Y,customPool:z,serverDiscoveryExcludes:Array.isArray(Q.discoveryExcludes)?Q.discoveryExcludes.filter((X)=>typeof X==="string"):[],upstreamTotal:typeof Q?.counts?.upstreamTotal==="number"?Q.counts.upstreamTotal:0}}async function Lj($,j){let J=new URL("/v1/models",new URL($.proxy.endpoint).origin).toString(),Q=await E0(J,{headers:{Authorization:`Bearer ${j}`,Accept:"application/json","User-Agent":Q$}});if(!Q.ok)throw Error(`/v1/models returned ${Q.status}`);let Y=await Q.json();if(!Y?.data||!Array.isArray(Y.data))return[];return Y.data.map((Z)=>({id:typeof Z.id==="string"?Z.id:"",owned_by:typeof Z.owned_by==="string"?Z.owned_by:""})).filter((Z)=>Z.id)}function Kj($,j){let J=j.discoveryExcludes,Q=new Map,Y=[],Z=0;for(let z of $){if(Z++,Z0(z.id,J))continue;if(z.owned_by==="openai"){let n=J$(z.id);D0(Q,"openai","openai-responses",U0(n));continue}if(z.owned_by==="anthropic"){let n=J$(z.id);D0(Q,"anthropic","anthropic-messages",U0(n));continue}let{slug:X,api:V}=z0(z.owned_by,j.proxy.providerPrefix),q=J$(z.id);Y.push({id:z.id,name:q.name??z.id,reasoning:q.reasoning??!1,contextWindow:q.contextWindow??128000,maxTokens:q.maxTokens??16000,cost:q.cost??{input:0,output:0,cacheRead:0,cacheWrite:0},api:V,suggestedProvider:X,ownedBy:z.owned_by})}return{source:"v1-models",upstreamVersion:null,builtinProviders:Array.from(Q.values()),customPool:Y,serverDiscoveryExcludes:[],upstreamTotal:Z}}function D0($,j,J,Q){let Y=$.get(j);if(!Y)Y={name:j,api:J,models:[]},$.set(j,Y);Y.models.push(Q)}function U0($){return{id:$.id,name:$.name??$.id,reasoning:$.reasoning??!1,contextWindow:$.contextWindow??128000,maxTokens:$.maxTokens??16000,cost:$.cost??{input:0,output:0,cacheRead:0,cacheWrite:0}}}async function R0($,j){let J=await Bj($);if(J)return B.info(`discovery via /.well-known/pi: ${J.builtinProviders.length} builtin, ${J.customPool.length} custom`),f$(J),J;if(!j)throw Error("well-known unavailable AND proxy apiKey is empty — cannot fall back to /v1/models. Set proxy.apiKey in config.");let Q=await Lj($,j),Y=Kj(Q,$);return B.info(`discovery via /v1/models: ${Y.builtinProviders.length} builtin, ${Y.customPool.length} custom`),f$(Y),Y}function G0($){let j=new Set;for(let J of $.builtinProviders)for(let Q of J.models)j.add(Q.id);for(let J of $.customPool)j.add(J.id);return j}async function g$($,j,J){let Q={registered:[],skipped:[]},Y=G0(J),Z=g(j.proxy.apiKey);if(!Z)return B.warn("proxy apiKey is empty — dm.registerProvider calls will be skipped"),Q;let z=new Map;for(let V of J.builtinProviders)z.set(V.name,V.models.map((q)=>({id:q.id,name:q.name,reasoning:q.reasoning,contextWindow:q.contextWindow,maxTokens:q.maxTokens,cost:q.cost})));for(let[V,q]of Object.entries(j.builtinProviders)){if(!q?.enabled){Q.skipped.push({provider:V,reason:"disabled"});continue}if(!Array.isArray(q.models)||q.models.length===0){Q.skipped.push({provider:V,reason:"empty whitelist"});continue}let n=[];try{n=Sj(V)}catch{}let U=new Map(n.map((A)=>[A.id,A])),S=new Map((z.get(V)??[]).map((A)=>[A.id,A])),_=[];for(let A of q.models){if(!Y.has(A))continue;let W=U.get(A),P=S.get(A);if(W){_.push({id:W.id,name:W.name,reasoning:W.reasoning,contextWindow:W.contextWindow,maxTokens:W.maxTokens,cost:W.cost,input:W.input,api:W.api,thinkingLevelMap:W.thinkingLevelMap});continue}if(!P)continue;let p=V==="anthropic"?"anthropic-messages":q.apiOverride??"openai-responses";_.push({id:P.id,name:P.name,reasoning:P.reasoning,contextWindow:P.contextWindow,maxTokens:P.maxTokens,cost:P.cost,input:["text"],api:p})}if(_.length===0){Q.skipped.push({provider:V,reason:"no whitelisted models present on proxy"});continue}let G=q.apiOverride??_[0].api;if(!b$.has(G)){Q.skipped.push({provider:V,reason:`api "${G}" not in allowlist`});continue}let D=_.map((A)=>{let W=j.overrides[A.id]??{},P={id:A.id,name:typeof W.name==="string"?W.name:A.name,api:G,reasoning:typeof W.reasoning==="boolean"?W.reasoning:A.reasoning,input:A.input,cost:W.cost??A.cost,contextWindow:typeof W.contextWindow==="number"?W.contextWindow:A.contextWindow,maxTokens:typeof W.maxTokens==="number"?W.maxTokens:A.maxTokens};if(A.thinkingLevelMap)P.thinkingLevelMap=A.thinkingLevelMap;return P}),H={name:V,baseUrl:y$(G,j.proxy.endpoint),apiKey:Z,authHeader:!0,api:G,models:D};$.registerProvider(V,H),Q.registered.push({provider:V,modelCount:D.length,api:G})}let X=new Map(J.customPool.map((V)=>[V.id,V]));for(let[V,q]of Object.entries(j.customProviders)){if(!b$.has(q.api)){Q.skipped.push({provider:V,reason:`api "${q.api}" not in allowlist`});continue}let n=q.models.filter((_)=>Y.has(_.id));if(n.length===0){Q.skipped.push({provider:V,reason:"no configured models present on proxy"});continue}let U=n.map((_)=>{let G=X.get(_.id),D=J$(_.id),H=j.overrides[_.id]??{};return{id:_.id,name:_.name??G?.name??D.name??_.id,api:q.api,reasoning:Fj(_.reasoning,G?.reasoning,D.reasoning,H.reasoning)??!1,input:["text"],cost:_.cost??G?.cost??D.cost??{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:_0(_.contextWindow,G?.contextWindow,D.contextWindow,H.contextWindow)??128000,maxTokens:_0(_.maxTokens,G?.maxTokens,D.maxTokens,H.maxTokens)??16000}}),S={name:V,baseUrl:y$(q.api,j.proxy.endpoint),apiKey:Z,authHeader:!0,api:q.api,models:U};$.registerProvider(V,S),Q.registered.push({provider:V,modelCount:U.length,api:q.api})}return B.info(`applyAll: registered ${Q.registered.length} providers, skipped ${Q.skipped.length}`),Q}function _0(...$){for(let j of $)if(typeof j==="number")return j;return}function Fj(...$){for(let j of $)if(typeof j==="boolean")return j;return}var Pj=15000,V$=null;function k$(){V$=null}async function A0($,j,J={}){if(!J.force&&V$&&Date.now()-V$.fetchedAt<$.usageCacheTtlMs)return V$.doc;if(!j)throw Error("usage key not configured; set proxy.usageKey in config and rerun");let Q=new URL("/api/usage",new URL($.proxy.endpoint).origin).toString(),Y=new AbortController,Z=setTimeout(()=>Y.abort(Error("timeout")),Pj),z;try{z=await fetch(Q,{headers:{"X-Plugin-Key":j,Accept:"application/json","User-Agent":Q$},signal:Y.signal})}finally{clearTimeout(Z)}if(!z.ok)throw Error(`/api/usage returned ${z.status}`);let X=await z.json();if(!X||X.schemaVersion!==1||!Array.isArray(X.accounts))throw Error("/api/usage returned unexpected payload shape");return V$={fetchedAt:Date.now(),doc:X},B.debug("usage fetched, accounts:",X.accounts.length),X}import{visibleWidth as p$}from"@duckmind/dm-tui";import{visibleWidth as O0}from"@duckmind/dm-tui";function L($,j){let J=O0($);if(J===j)return $;if(J<j)return $+" ".repeat(j-J);return h$($,j)}function h$($,j){if(j<=0)return"\x1B[0m";let J="",Q=0,Y=0;while(Y<$.length){let Z=$[Y];if(Z==="\x1B"&&$[Y+1]==="["){let X=$.indexOf("m",Y+2);if(X>=0){J+=$.slice(Y,X+1),Y=X+1;continue}}let z=O0(Z);if(Q+z>j)break;J+=Z,Q+=z,Y++}return`${J}\x1B[0m`}var Ij="│",xj="╭",bj="╮",yj="╰",wj="╯",q$="─";function o($,j){let J=Math.max(4,j.width);return[Cj($,j.title,j.titleColor??"accent",J),...j.lines.map((Q)=>uj($,Q,J)),vj($,j.footer,J)]}function Cj($,j,J,Q){let Y=j??"",Z=p$(Y),z=Math.max(0,Q-3-Z),X=Y?$.bold($.fg(J,Y)):"",V=`${xj}${q$}${X}${q$.repeat(z)}${bj}`;return $.fg("borderAccent",V)}function uj($,j,J){let Q=Math.max(0,J-2),Y=$.fg("borderAccent",Ij);return`${Y}${L(j,Q)}${Y}`}function vj($,j,J){let Q=`${yj}${q$}`,Y=`${wj}`,Z=3;if(!j||!j.hint&&!j.badge){let G=Math.max(0,J-3);return $.fg("borderAccent",`${Q}${q$.repeat(G)}${Y}`)}let z=j.hint??"",X=j.badge??"",V=p$(z),q=p$(X),n=Math.max(0,J-3-V-q),U=$.fg("dim",z),S=X?$.fg("muted",X):"",_=q$.repeat(n);return`${$.fg("borderAccent",Q)}${U}${$.fg("borderAccent",_)}${S}${$.fg("borderAccent",Y)}`}function N$($){return Math.max(0,$-2)}import{existsSync as H0}from"node:fs";import{homedir as fj}from"node:os";import{getKeybindings as gj,Input as hj,matchesKey as pj}from"@duckmind/dm-tui";var cj=[{label:"endpoint",hint:"OpenAI-style base URL of your CliProxyAPI deployment, must include /v1",required:!0,validate:($)=>{try{if(!new URL($).pathname.endsWith("/v1"))return"must end with /v1";return null}catch{return"not a valid URL"}}},{label:"apiKey",hint:"CliProxyAPI bearer key. Accepts literal, $ENV_VAR, !cmd, or ~/path",required:!0},{label:"providerPrefix",hint:"Prefix for your custom provider names. Suggested groups become <prefix>-glm, <prefix>-gemini, etc. Use any short slug (letters/digits/dashes).",required:!0,validate:($)=>/^[a-z0-9][a-z0-9-]*$/i.test($)?null:"letters/digits/dashes only"},{label:"usageKey",hint:"Optional X-Plugin-Key for /api/usage. Leave blank to skip the Usage tab",required:!1}];async function W0($,j=!1){let J=H$(),Q={endpoint:J.proxy.endpoint??"",apiKey:J.proxy.apiKey??"",providerPrefix:J.proxy.providerPrefix??"",usageKey:J.proxy.usageKey??""},Y=!1;for(let z of cj){let X=j?Q[z.label]??z.initialValue??"":Q[z.label]??"";if(!j&&X)continue;let V=await mj($,z,X||z.initialValue||"");if(V===void 0){Y=!0;break}let q=V.trim();if(!q){if(z.required){$.ui.notify(`${z.label} is required — aborted`,"warning"),Y=!0;break}Q[z.label]="";continue}Q[z.label]=z.label==="providerPrefix"||z.label==="endpoint"?q:lj(q)}if(Y)return!1;let Z={...J};if(Z.proxy={...J.proxy,endpoint:Q.endpoint??"",apiKey:Q.apiKey??"",providerPrefix:Q.providerPrefix??""},Q.usageKey)Z.proxy.usageKey=Q.usageKey;else delete Z.proxy.usageKey;return W$(Z),$.ui.notify(`saved to ${w}`,"info"),!0}function lj($){if($.startsWith("!")||$.startsWith("$"))return $;if($.startsWith("~/")){let j=$.replace(/^~/,fj());return H0(j)?`!cat ${$}`:$}if($.startsWith("/"))return H0($)?`!cat ${$}`:$;return $}async function mj($,j,J){return $.ui.custom((Q,Y,Z,z)=>rj(Q,Y,j,J,z),{overlay:!0,overlayOptions:{width:100,maxHeight:"60%"}})}function rj($,j,J,Q,Y){let Z=new hj;Z.setValue(Q),Z.focused=!0;let z=null,X=(V)=>{if(!V&&!J.required){Y("");return}if(!V&&J.required){z="required field",$.requestRender();return}if(J.validate){let q=V.trim();if(q&&!q.startsWith("!")&&!q.startsWith("$")){let n=J.validate(q);if(n){z=n,$.requestRender();return}}}Y(V)};return Z.onSubmit=X,Z.onEscape=()=>Y(void 0),{render(V){let q=N$(V),n=Z.render(q-4),U=["",` ${j.fg("dim",J.hint)}`,"",...n.map((S)=>` ${j.fg("accent",`❯ ${S}`)}`),"",z?` ${j.fg("error",`! ${z}`)}`:` ${j.fg("dim","enter = save · esc = cancel")}`];return o(j,{width:V,title:` setup: ${J.label} `,lines:U,footer:{hint:" enter = save · esc = cancel "}})},invalidate(){Z.invalidate()},handleInput(V){if(gj().matches(V,"tui.select.cancel")||pj(V,"escape")){Y(void 0);return}z=null,Z.handleInput(V),$.requestRender()}}}import{visibleWidth as T$}from"@duckmind/dm-tui";function k0($,j,J,Q){let Y=$.fg("borderAccent","│"),Z=j.map((z,X)=>{let V=`${X+1} ${z.label}`;return X===J?$.bold($.fg("accent",` ${V} `)):$.fg("dim",` ${V} `)});return L(` ${Z.join(Y)}`,Q)}function N0($,j,J){let Q=j.join($.fg("dim"," "));return L(` ${Q}`,J)}function T0($,j){return $.fg("borderAccent","─".repeat(Math.max(0,j)))}function i($,j,J){let Q=$.slice(j,j+J);while(Q.length<J)Q.push("");return Q}function B$($,j,J,Q,Y,Z){if(Y<=Q)return 0;let z=Math.max(0,Y-Q);if(j<Z)return 0;let X=Math.max(0,Math.min(J,z)),V=X+Z;if($<V)X=Math.max(0,$-Z);let q=X+Q-1;if(j>q)X=Math.min(z,j-(Q-1));return X}function L$($,j,J){let Q=Math.max(0,J-j);return Math.max(0,Math.min($,Q))}import{matchesKey as d}from"@duckmind/dm-tui";import{existsSync as sj,readFileSync as oj}from"node:fs";import{homedir as L0}from"node:os";import{join as K0}from"node:path";var ij=K0(L0(),".dm","models.json"),dj=K0(L0(),".dm","auth.json");function B0($){if(!sj($))return null;try{return JSON.parse(oj($,"utf8"))}catch{return null}}function S0($){let j=[],J=new Set([...Object.keys($.builtinProviders),...Object.keys($.customProviders)]),Q=B0(ij);if(Q&&typeof Q==="object"){for(let Z of Object.keys(Q))if(J.has(Z))j.push({kind:"models.json",provider:Z,detail:`provider "${Z}" has user overrides in ~/.dm/models.json which DM merges on top of our registration`})}let Y=B0(dj);if(Y&&typeof Y==="object"){for(let Z of Object.keys(Y))if(J.has(Z))j.push({kind:"auth.json",provider:Z,detail:`provider "${Z}" has user-set credentials in ~/.dm/auth.json which take priority over our apiKey`})}return j}function F0($){let{theme:j,cfg:J}=$,Q=0,Y=()=>{let X=$.getDiscovery(),V=(G)=>j.fg("success",G),q=(G)=>j.fg("error",G),n=(G)=>j.fg("dim",G),U=[];U.push(`${n("endpoint")} ${J.proxy.endpoint||q("(unset)")}`),U.push(`${n("apiKey")} ${g(J.proxy.apiKey)?V("resolves"):q("empty after resolution")}`),U.push(`${n("usageKey")} ${J.proxy.usageKey?g(J.proxy.usageKey)?V("resolves"):q("set but empty"):n("not configured")}`),U.push(`${n("user-agent")} ${Q$}`),U.push(""),U.push(`${n("discovery")} source=${X.source}`),U.push(`${n("upstream")} v=${X.upstreamVersion??"(unknown)"} · ${X.upstreamTotal} ids`);let S=X.builtinProviders.map((G)=>`${G.name}=${G.models.length}`).join(", ")||n("(none)");U.push(`${n("built-in")} ${S}`),U.push(`${n("custom pool")} ${X.customPool.length} models`);let _=S0(J);if(U.push(""),_.length===0)U.push(`${n("conflicts")} ${V("none")}`);else{U.push(`${n("conflicts")}`);for(let G of _)U.push(` ${j.fg("warning",`[${G.kind}]`)} ${G.detail}`)}return U};return{id:"diagnostics",label:"Diagnostics",render:(X,V)=>{let q=Y();return Q=L$(Q,V,q.length),i(q,Q,V).map((n)=>L(` ${n}`,X))},handleInput:(X)=>{let V=Y().length;if(d(X,"up")||d(X,"k"))return Q=Math.max(0,Q-1),!0;if(d(X,"down")||d(X,"j"))return Q=Math.min(Math.max(0,V-1),Q+1),!0;if(d(X,"pageUp")||d(X,"b"))return Q=Math.max(0,Q-10),!0;if(d(X,"pageDown")||d(X,"f"))return Q=Math.min(Math.max(0,V-1),Q+10),!0;return!1},footerHint:()=>" ↑↓ scroll · r refresh discovery "}}import{matchesKey as N}from"@duckmind/dm-tui";function c$($){let j=new Map,J=new Map;for(let Y of $.builtinProviders){let Z=[];for(let z of Y.models)j.set(z.id,{id:z.id,name:z.name,suggestedApi:Y.api,subtitle:z.name&&z.name!==z.id?z.name:void 0,ownedBy:Y.name,reasoning:z.reasoning,contextWindow:z.contextWindow,maxTokens:z.maxTokens,cost:z.cost}),Z.push(z.id);J.set(Y.name,Z)}let Q=[];for(let Y of $.customPool){if(!j.has(Y.id))j.set(Y.id,{id:Y.id,name:Y.name,suggestedApi:Y.api,subtitle:Y.name&&Y.name!==Y.id?Y.name:void 0,origin:Y.suggestedProvider,ownedBy:Y.ownedBy,reasoning:Y.reasoning,contextWindow:Y.contextWindow,maxTokens:Y.maxTokens,cost:Y.cost});Q.push(Y.id)}return{byId:j,builtinModelIds:J,customPoolIds:Q}}function tj($){let j=new Map;for(let[J,Q]of Object.entries($.customProviders))for(let Y of Q.models)j.set(Y.id,J);return j}function e($,j){if(j.kind==="builtin")return[...$.builtinProviders[j.name]?.models??[]];return $.customProviders[j.name]?.models.map((J)=>J.id)??[]}function P0($,j,J){if(j.kind==="builtin"){let Z=J.builtinModelIds.get(j.name)??[],z=new Set(e($,j));return Z.filter((X)=>!z.has(X))}let Q=tj($),Y=new Set(e($,j));return J.customPoolIds.filter((Z)=>{if(Y.has(Z))return!1;let z=Q.get(Z);return z===void 0||z===j.name})}function aj($){return{id:$.id,name:$.name,contextWindow:$.contextWindow,maxTokens:$.maxTokens,reasoning:$.reasoning,cost:$.cost}}function I0($,j,J){if(j.kind==="builtin"){let Y=$.builtinProviders[j.name]??{enabled:!0,models:[]},Z=new Set(Y.models);Z.add(J.id),$.builtinProviders[j.name]={enabled:!0,apiOverride:Y.apiOverride??null,models:Array.from(Z).sort()};return}for(let[Y,Z]of Object.entries($.customProviders)){if(Y===j.name)continue;let z=Z.models.findIndex((X)=>X.id===J.id);if(z>=0)Z.models.splice(z,1)}let Q=$.customProviders[j.name]??{api:j.api,models:[]};if(!Q.models.some((Y)=>Y.id===J.id))Q.models.push(aj(J));$.customProviders[j.name]=Q}function x0($,j,J){if(j.kind==="builtin"){let Y=$.builtinProviders[j.name];if(!Y)return;Y.models=Y.models.filter((Z)=>Z!==J),Y.enabled=Y.models.length>0;return}let Q=$.customProviders[j.name];if(!Q)return;Q.models=Q.models.filter((Y)=>Y.id!==J)}function l$($,j){if($===j)return!0;let J=["openai-completions","openai-responses"];if(J.includes($)&&J.includes(j))return!0;return!1}function b0($,j){let J=new Map;for(let Q of $){let Y=j.byId.get(Q),Z=Y?.ownedBy||Y?.origin||"misc",z=J.get(Z)??[];z.push(Q),J.set(Z,z)}return Array.from(J.entries()).sort((Q,Y)=>Q[0].localeCompare(Y[0])).map(([Q,Y])=>({label:Q,ids:Y}))}function y0($,j,J){let Q=J.trim().toLowerCase();if(!Q)return $;return $.filter((Y)=>{if(Y.toLowerCase().includes(Q))return!0;let Z=j.byId.get(Y)?.name;return Z?Z.toLowerCase().includes(Q):!1})}import{getModels as ej,getProviders as $1}from"@duckmind/dm-ai/compat";function m$($,j){let J=[],Q=new Set(j.builtinModelIds.keys()),Y=new Set($1()),Z=new Set([...Q,...Y]);for(let z of Array.from(Z).sort()){let X=j.builtinModelIds.get(z);if(!X||X.length===0)continue;let V;try{let n=ej(z).find((U)=>X.includes(U.id));if(n)V=n.api}catch{}if(!V){let q=X[0];V=j.byId.get(q)?.suggestedApi??"openai-responses"}if(J.push({kind:"builtin",name:z,api:V,subtitle:`built-in · ${V}`}),!$.builtinProviders[z])$.builtinProviders[z]={enabled:!1,models:[]}}for(let z of Object.keys($.customProviders).sort()){let X=$.customProviders[z];J.push({kind:"custom",name:z,api:X.api,subtitle:`custom · ${X.api}`})}return J}import{getKeybindings as j1,matchesKey as Y$}from"@duckmind/dm-tui";async function w0($,j){return $.ui.custom((J,Q,Y,Z)=>J1(Q,`Remove custom group “${j}”?`,"All model assignments in this group will be discarded.",Z),{overlay:!0,overlayOptions:{width:80,maxHeight:"40%"}})}function J1($,j,J,Q){return{render(Y){return o($,{width:Y,title:" confirm ",titleColor:"error",lines:["",` ${$.bold(j)}`,` ${$.fg("dim",J)}`,""],footer:{hint:" y / enter = remove · n / esc = cancel "}})},invalidate(){},handleInput(Y){if(j1().matches(Y,"tui.select.cancel")||Y$(Y,"escape")||Y$(Y,"n")||Y$(Y,"q")){Q(!1);return}if(Y$(Y,"y")||Y$(Y,"enter")||Y$(Y,"return")){Q(!0);return}}}}import{getKeybindings as Q1,Input as Y1,matchesKey as Z1}from"@duckmind/dm-tui";async function C0($,j){let J=E$(j,"group");return $.ui.custom((Q,Y,Z,z)=>X1(Q,Y,J,z),{overlay:!0,overlayOptions:{width:80,maxHeight:"40%"}})}function X1($,j,J,Q){let Y=new Y1;if(J)Y.setValue(J);Y.focused=!0;let Z=null;return Y.onSubmit=(z)=>{let X=z.trim();if(!/^[a-z0-9][a-z0-9._-]*$/i.test(X)){Z="letters / digits / dot / dash / underscore only",$.requestRender();return}Q(X)},Y.onEscape=()=>Q(null),{render(z){let X=N$(z),V=J?`name shown in /model picker, e.g. ${J}`:"letters / digits / dot / dash / underscore",q=Y.render(X-4),n=["",` ${j.fg("dim",V)}`,"",...q.map((U)=>` ${j.fg("accent",`❯ ${U}`)}`),"",Z?` ${j.fg("error",`! ${Z}`)}`:""];return o(j,{width:z,title:" new custom group ",lines:n,footer:{hint:" enter = create · esc = cancel "}})},invalidate(){Y.invalidate()},handleInput(z){if(Q1().matches(z,"tui.select.cancel")||Z1(z,"escape")){Q(null);return}Z=null,Y.handleInput(z),$.requestRender()}}}import{visibleWidth as z1}from"@duckmind/dm-tui";function r$($,j,J){if(!j)return" ";if(J)return $.fg("accent","▶ ");return $.fg("muted","▸ ")}function u0($,j){let J=z1($);if(J===j)return $;if(J>j)return h$($,j);return L($,j)}function v0($,j,J){let{theme:Q,width:Y,isCursor:Z,isFocused:z}=J,X=r$(Q,Z,z),V=$.kind==="builtin"?j.builtinProviders[$.name]?.models.length??0:j.customProviders[$.name]?.models.length??0,q=$.kind==="builtin"?Q.fg("accent","B"):Q.fg("warning","C"),n=`${Q.fg("dim","[")}${q}${Q.fg("dim","]")}`,U=V>0?Q.fg("success","●"):Q.fg("dim","○"),S=V>0?Q.fg("success",String(V).padStart(2)):Q.fg("dim"," 0"),_=Z&&z?Q.bold(Q.fg("accent",$.name)):Z?Q.bold($.name):$.name,G=Q.fg("dim",$.api),D=`${X}${n} ${_} ${U}${S} ${G}`;return u0(D,Y)}function f0($,j,J,Q){let Y=r$($,j,J),Z=j&&J?$.bold($.fg("accent","+ new custom group…")):$.fg("accent","+ new custom group…");return L(`${Y}${Z}`,Q)}function s$($,j,J,Q,Y){let{theme:Z,width:z,isCursor:X,isFocused:V}=Y,q=r$(Z,X,V),n=J==="assigned"?Z.fg("success","☑"):Z.fg("dim","☐"),U=Q?` ${Z.fg("warning","⚠")}`:"",S=X&&V?Z.fg("accent",$):$,_=j?.reasoning?` ${Z.fg("accent","✨")}`:"",G=j?Z.fg("muted",` · ${j.suggestedApi}`):Z.fg("error"," · not on proxy"),D=`${q}${n} ${S}${U}${_}${G}`;return u0(D,z)}function g0($,j,J){let Q=`${$.fg("borderAccent","──")} ${$.fg("warning",j)} ${$.fg("borderAccent","──")}`;return L(` ${Q}`,J)}function o$($,j,J){return L(` ${$.fg("dim",j)}`,J)}function h0($,j,J,Q){let Y=Q?$.bold($.fg("accent","❚ ")):$.fg("dim"," ");return L(`${Y}${j}`,J)}function p0($){let{tui:j,theme:J,ctx:Q,cfg:Y}=$,Z=$.onChange??(()=>{}),z=c$($.getDiscovery()),X=m$(Y,z),V="providers",q=0,n=0,U=0,S=0,_=0,G=0,D="",H=!1,A=()=>{if(X.length===0)return null;let M=Math.max(0,Math.min(q,X.length-1));return X[M]??null},W=(M)=>{let O=y0(P0(Y,M,z),z,D);return b0(O,z)},P=(M)=>W(M).flatMap((O)=>O.ids),p=()=>{X=m$(Y,z);let M=Math.max(0,X.length);if(q>M)q=M;let O=A();if(O){let F=e(Y,O).length,k=P(O).length;if(n>=F)n=Math.max(0,F-1);if(U>=k)U=Math.max(0,k-1)}},K$=()=>{z=c$($.getDiscovery()),p()},M$=(M)=>{let O=["providers","assigned","pool"],F=O.indexOf(V);V=M?O[(F-1+O.length)%O.length]:O[(F+1)%O.length]},R=(M)=>{if(V==="providers"){let k=X.length+1;q=Math.max(0,Math.min(q+M,k-1));return}let O=A();if(!O)return;if(V==="assigned"){let k=e(Y,O).length;if(k===0)return;n=Math.max(0,Math.min(n+M,k-1));return}let F=P(O).length;if(F===0)return;U=Math.max(0,Math.min(U+M,F-1))},I=async()=>{if(V==="providers"){if(q===X.length){let k=await C0(Q,Y.proxy.providerPrefix);if(k&&!Y.customProviders[k]){if(Y.customProviders[k]={api:"openai-completions",models:[]},Z(),p(),q=X.findIndex((K)=>K.kind==="custom"&&K.name===k),q<0)q=X.length-1;V="pool"}j.requestRender();return}V="pool";return}let M=A();if(!M)return;if(V==="assigned"){let k=e(Y,M)[n];if(!k)return;x0(Y,M,k),Z(),p();return}let O=P(M)[U];if(!O)return;let F=z.byId.get(O);if(!F)return;I0(Y,M,F),Z(),p()},l=async()=>{if(V!=="providers")return;let M=A();if(!M||M.kind!=="custom")return;if(!await w0(Q,M.name)){j.requestRender();return}if(delete Y.customProviders[M.name],Z(),p(),q>=X.length)q=Math.max(0,X.length-1);j.requestRender()},u=(M,O)=>h(M,O);function h(M,O){let F=Math.max(70,M),k=Math.min(56,Math.max(34,Math.floor(F*0.4))),K=F-k-1,m=Math.max(8,O),r=Math.max(5,Math.floor((m-1)/2)),i$=m-r,c=A(),Z$=0,S$=0,F$=0,d$=0,P$=0,t$=0,t=[];t.push($$(" providers ",k,V==="providers"));for(let T=0;T<X.length;T++){let v=X[T],y=V==="providers"&&T===q;if(y)Z$=t.length,S$=Z$;t.push(v0(v,Y,{theme:J,width:k,isCursor:y,isFocused:V==="providers"}))}{let T=V==="providers"&&q===X.length;if(T)Z$=t.length,S$=Z$;t.push(f0(J,T,V==="providers",k))}let a=[],a0=c?`assigned to ${J.bold(c.name)} ${J.fg("dim",`· ${c.api}`)}`:J.fg("dim","no provider selected");if(a.push($$(" assigned ",K,V==="assigned")),a.push(h0(J,a0,K,V==="assigned")),c){let T=e(Y,c);if(T.length===0)a.push(o$(J,"(nothing assigned yet)",K));for(let v=0;v<T.length;v++){let y=T[v],f=z.byId.get(y),U$=V==="assigned"&&v===n;if(U$)F$=a.length,d$=F$;let j$=f?!l$(c.api,f.suggestedApi):!1;a.push(s$(y,f,"assigned",j$,{theme:J,width:K,isCursor:U$,isFocused:V==="assigned"}))}}let s=[];if(s.push(x(K,V==="pool")),c){let T=W(c);if(T.reduce((y,f)=>y+f.ids.length,0)===0)s.push(o$(J,D?`(no matches for "${D}")`:"(no models available)",K));else{let y=0;for(let f of T){let U$=s.length;s.push(g0(J,f.label,K));for(let j$=0;j$<f.ids.length;j$++){let Q0=f.ids[j$],x$=z.byId.get(Q0),Y0=V==="pool"&&y===U;if(Y0)P$=s.length,t$=j$===0?U$:P$;let Jj=x$?!l$(c.api,x$.suggestedApi):!1;s.push(s$(Q0,x$,"pool",Jj,{theme:J,width:K,isCursor:Y0,isFocused:V==="pool"})),y++}}}}let e0=Math.max(1,i$-1),a$=B$(S$,Z$,S,m,t.length,1),e$=B$(V==="assigned"?d$:0,V==="assigned"?F$:0,_,r,a.length,2),$0=B$(V==="pool"?t$:0,V==="pool"?P$:0,G,e0,s.length,1);S=a$,_=e$,G=$0;let j0=i(t,a$,m),$j=i(a,e$,r),jj=i(s,$0,i$),J0=J.fg("borderAccent","│"),I$=[];for(let T=0;T<m;T++){let v=L(j0[T]??"",k),y=T<r?$j[T]:jj[T-r],f=L(y,K);I$.push(`${v}${J0}${f}`)}let D$=r;if(D$>0&&D$<m){let T=L(j0[D$]??"",k),v=J.fg("borderAccent","─".repeat(K));I$[D$]=`${T}${J0}${v}`}return I$}function $$(M,O,F){let k=F?J.bold(J.fg("accent",M)):J.fg("muted",M),K=J.fg("borderAccent","─".repeat(Math.max(0,O-T$(M)-1)));return L(`${k}${K}`,O)}function x(M,O){let k=O?J.bold(J.fg("accent"," available pool ")):J.fg("muted"," available pool "),K="";if(H)K=`${J.fg("dim"," /")}${J.fg("accent",D)}${J.fg("accent","█")} `;else if(D)K=`${J.fg("dim"," /")}${J.fg("warning",D)} `;let m=T$(" available pool ")+T$(K),r=J.fg("borderAccent","─".repeat(Math.max(0,M-m-1)));return L(`${k}${K}${r}`,M)}function n$(M){if(H){if(N(M,"escape"))return D="",H=!1,U=0,!0;if(N(M,"enter")||N(M,"return"))return H=!1,!0;if(N(M,"backspace")||N(M,"delete"))return D=D.slice(0,-1),U=0,!0;if(M.length===1&&M>=" "&&M!=="")return D+=M,U=0,!0;return!0}if(N(M,"tab"))return M$(!1),!0;if(N(M,"shift+tab"))return M$(!0),!0;if(N(M,"/"))return V="pool",H=!0,!0;if(N(M,"enter")||N(M,"return")||N(M,"space"))return I().then(()=>!0);if(V==="providers"&&(N(M,"d")||N(M,"delete")||N(M,"backspace")))return l().then(()=>!0);if(N(M,"up")||N(M,"k"))return R(-1),!0;if(N(M,"down")||N(M,"j"))return R(1),!0;if(N(M,"pageUp")||N(M,"b"))return R(-8),!0;if(N(M,"pageDown")||N(M,"f"))return R(8),!0;if(N(M,"left")||N(M,"h"))return V="providers",!0;if(N(M,"right")||N(M,"l")){if(V==="providers")V="assigned";else if(V==="assigned")V="pool";return!0}return!1}function t0(){if(H)return" type to filter · ↵ apply · esc clear ";return" tab ↔ panel · ↑↓ nav · ↵ move · / filter · d remove group "}return{id:"models",label:"Models",render:u,handleInput:n$,footerHint:t0,rebuild:K$}}import{matchesKey as b}from"@duckmind/dm-tui";var E={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",accent:"\x1B[38;5;111m",muted:"\x1B[38;5;245m",dim2:"\x1B[38;5;240m",green:"\x1B[38;5;114m",yellow:"\x1B[38;5;179m",red:"\x1B[38;5;167m",greenBg:"\x1B[48;5;22m",yellowBg:"\x1B[48;5;94m",redBg:"\x1B[48;5;52m"};function c0($,j={}){let J=[],Q=new Map,Y=0;for(let Z of $.accounts){if(!j.showDisabled&&Z.disabled){Y++;continue}let z=Q.get(Z.provider)??[];z.push(Z),Q.set(Z.provider,z)}if(J.push(`${E.dim}generated ${$.generatedAt}${E.reset}`),$.unsupportedProviders.length>0)J.push(`${E.dim}providers without quota lookup:${E.reset} ${$.unsupportedProviders.join(", ")}`);if(Y>0)J.push(`${E.dim}hidden disabled accounts:${E.reset} ${Y} ${E.dim2}(press d to show)${E.reset}`);for(let[Z,z]of Array.from(Q.entries()).sort()){J.push(""),J.push(`${E.bold}${E.accent}▌ ${Z}${E.reset}`);for(let X of z){if(J.push(q1(X)),!X.supported){J.push(` ${E.dim2}(provider not quota-aware)${E.reset}`);continue}if(X.error){if(j.verbose)for(let q of V1(X.error,88))J.push(` ${E.red}${q}${E.reset}`);continue}let V=X.groups??[];if(V.length===0){J.push(` ${E.dim2}(no active quota windows)${E.reset}`);continue}for(let q of V)J.push(n1(q))}}return J.push(""),J.push(`${E.dim}legend:${E.reset} ${l0} ok ${m0} error/unavailable ${r0} disabled ${E.green}✓N${E.reset}/${E.red}✗N${E.reset} request counters ${E.dim}v = verbose, d = show disabled${E.reset}`),J}function V1($,j){if($.length<=j)return[$];let J=[],Q=$;while(Q.length>j){let Y=Q.lastIndexOf(" ",j);if(Y<j*0.6)Y=j;J.push(Q.slice(0,Y)),Q=Q.slice(Y).replace(/^\s+/,"")}if(Q)J.push(Q);return J}function q1($){let j=M1($),J=`${E.green}✓${$.success}${E.reset} ${E.red}✗${$.failed}${E.reset}`,Q=i0($.label,36);return` ${j} ${E.bold}${Q}${E.reset} ${J}`}var l0=`${E.green}●${E.reset}`,m0=`${E.yellow}⚠${E.reset}`,r0=`${E.dim2}⊘${E.reset}`;function M1($){if($.disabled)return r0;if($.unavailable||$.error||$.status&&$.status!=="active")return m0;return l0}function n1($){let j=o0($.remainingFraction),J=Math.round(j*100),Q=D1(j),Y=$.resetTime?` ${E.dim}reset ${E1($.resetTime)}${E.reset}`:"",Z=i0($.label,28).padEnd(28," ");return` ${Q} ${U1(J,j)} ${Z}${Y}`}function D1($){let j=o0($),J=Math.round(j*18),Q=s0(j),Y=E.dim2,Z="█".repeat(J),z="░".repeat(18-J);return`${Y}[${Q}${Z}${Y}${z}]${E.reset}`}function U1($,j){return`${s0(j)}${String($).padStart(3)}%${E.reset}`}function s0($){if($>=0.4)return E.green;if($>=0.15)return E.yellow;return E.red}function E1($){let j=Date.parse($);if(!Number.isFinite(j))return $;let J=j-Date.now();if(J<=0)return"now";let Q=Math.round(J/60000);if(Q<60)return`${Q}m`;let Y=Math.round(Q/60);if(Y<48)return`${Y}h`;return`${Math.round(Y/24)}d`}function o0($){return Math.max(0,Math.min(1,$))}function i0($,j){if($.length<=j)return $;return`${$.slice(0,j-1)}…`}function d0($){let{tui:j,theme:J,cfg:Q}=$,Y="idle",Z=null,z="",X=0,V=!1,q=!1,n=(D)=>{Y="loading",j.requestRender();let H=g(Q.proxy.usageKey);A0(Q,H,{force:D}).then((A)=>{Z=A,Y="ready",X=0,j.requestRender()}).catch((A)=>{z=A.message,Y="error",j.requestRender()})},U=()=>{if(Y==="idle"||Y==="loading")return[J.fg("dim"," loading usage…")];if(Y==="error")return[J.fg("error",` usage failed: ${z}`)];if(!Z)return[J.fg("dim"," (no data)")];return c0(Z,{showDisabled:V,verbose:q})};return{id:"usage",label:"Usage",render:(D,H)=>{let A=U();return X=L$(X,H,A.length),i(A,X,H).map((W)=>L(` ${W}`,D))},handleInput:(D)=>{if(b(D,"d"))return V=!V,X=0,!0;if(b(D,"v"))return q=!q,X=0,!0;let H=U().length;if(b(D,"up")||b(D,"k"))return X=Math.max(0,X-1),!0;if(b(D,"down")||b(D,"j"))return X=Math.min(Math.max(0,H-1),X+1),!0;if(b(D,"pageUp")||b(D,"b"))return X=Math.max(0,X-10),!0;if(b(D,"pageDown")||b(D,"f"))return X=Math.min(Math.max(0,H-1),X+10),!0;if(b(D,"home")||b(D,"g"))return X=0,!0;if(b(D,"end")||b(D,"shift+g"))return X=Math.max(0,H-1),!0;return!1},footerHint:()=>{let D=V?J.fg("success","[d disabled]"):"d disabled",H=q?J.fg("success","[v verbose]"):"v verbose";return` ↑↓ scroll · ${D} · ${H} `},onActivate:()=>{if(Y==="idle")n(!1)},reload:()=>{if(k$(),Y!=="idle")n(!0)}}}function XJ($){let{dm:j,ctx:J,tui:Q,theme:Y,cfg:Z,done:z}=$,X=$.discovery,V=!1,q="",n=p0({tui:Q,theme:Y,ctx:J,cfg:Z,getDiscovery:()=>X,onChange:()=>{V=!0,q=""}}),U=d0({tui:Q,theme:Y,cfg:Z}),S=F0({theme:Y,cfg:Z,getDiscovery:()=>X}),_=[n,U,S],G=0,D=()=>_[G],H=(R)=>{if(R<0||R>=_.length||R===G)return;G=R,D().onActivate?.(),Q.requestRender()},A=()=>{q=Y.fg("dim","saving…"),W$(Z),Q.requestRender(),g$(j,Z,X).then((R)=>{V=!1,q=Y.fg("success",`✓ settings saved · ${R.registered.length} registered, ${R.skipped.length} skipped`),Q.requestRender()}).catch((R)=>{q=Y.fg("error",`save failed: ${R.message}`),Q.requestRender()})},W=async()=>{q=Y.fg("dim","refreshing…"),Q.requestRender();try{let R=g(Z.proxy.apiKey);X=await R0(Z,R),k$(),n.rebuild(),U.reload();let I=await g$(j,Z,X);q=Y.fg("success",`✓ refreshed · ${I.registered.length} providers (${X.source})`)}catch(R){q=Y.fg("error",`refresh failed: ${R.message}`)}Q.requestRender()},P=async()=>{if(!await W0(J,!0)){Q.requestRender();return}let I=H$();Z.proxy={...Z.proxy,...I.proxy},await W()},p=()=>{let R=Z.proxy.endpoint||"(unset)",I=R.length>40?`…${R.slice(-39)}`:R,l=Boolean(g(Z.proxy.apiKey)),u=0,h=0;for(let x of Object.values(Z.builtinProviders)){if(x.enabled&&x.models.length>0)u++;h+=x.models.length}for(let x of Object.values(Z.customProviders)){if(x.models.length>0)u++;h+=x.models.length}let $$=q?q:V?Y.fg("warning","● unsaved — press s to save"):Y.fg("dim","✓ saved");return[`${Y.fg("dim","endpoint")} ${I}`,`${Y.fg("dim","key")} ${l?Y.fg("success","✓"):Y.fg("error","✗")}`,`${Y.fg("dim","providers")} ${u}`,`${Y.fg("dim","models")} ${h}`,$$]},K$=(R)=>{let I=Q.rows??40,u=Math.max(16,Math.min(I-6,38))-2,h=Math.max(72,R-2),$$=Math.max(6,u-3),x=[];return x.push(N0(Y,p(),h)),x.push(k0(Y,_.map((n$)=>({id:n$.id,label:n$.label})),G,h)),x.push(T0(Y,h)),x.push(...D().render(h,$$)),o(Y,{width:R,title:" /cliproxy ",lines:x,footer:{hint:D().footerHint(),badge:" [ ] tab · r refresh · e setup · s save · q close "}})},M$=(R)=>{if(R1().matches(R,"tui.select.cancel")||C(R,"q")||C(R,"escape"))return z(),!0;if(C(R,"]")||C(R,"tab"))return H((G+1)%_.length),!0;if(C(R,"[")||C(R,"shift+tab"))return H((G-1+_.length)%_.length),!0;if(C(R,"1"))return H(0),!0;if(C(R,"2"))return H(1),!0;if(C(R,"3"))return H(2),!0;if(C(R,"r"))return W().then(()=>!0);if(C(R,"e"))return P().then(()=>!0);if(C(R,"s"))return A(),!0;return!1};return{render:K$,invalidate(){},handleInput(R){let I=D().handleInput(R);if(I instanceof Promise){q="",I.then((u)=>{if(u)Q.requestRender()});return}if(I){q="",Q.requestRender();return}let l=M$(R);if(l instanceof Promise)l.then((u)=>{if(u)Q.requestRender()});else if(l)Q.requestRender()}}}export{XJ as buildHub};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var Q$=!1;function b$($){Q$=$}var B={info(...$){if(!Q$)console.log("[dm-cliproxy]",...$)},warn(...$){if(!Q$)console.warn("[dm-cliproxy]",...$)},error(...$){if(!Q$)console.error("[dm-cliproxy]",...$)},debug(...$){if(!Q$&&(process.env.DM_CLIPROXY_DEBUG||process.env.PI_CLIPROXYAPI_DEBUG))console.log("[dm-cliproxy]","[debug]",...$)}};import{getKeybindings as _1,matchesKey as C}from"@duckmind/dm-tui";import{getModels as Pj}from"@duckmind/dm-ai/compat";var y$=new Set(["openai-completions","openai-responses","anthropic-messages"]);function w$($,j){let J=j.replace(/\/+$/,"");if($==="anthropic-messages")return J.replace(/\/v1$/,"");return J}function Q0($,j){if(!$)return!0;for(let J of j)if(new RegExp("^"+J.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*")+"$").test($))return!0;return!1}var Xj=128000,Qj=16000,zj={input:0,output:0,cacheRead:0,cacheWrite:0},Vj=[/.*-thinking$/,/^gpt-5(\.\d+)?(-.*)?$/,/^gemini-3(\.\d+)?(-.*)?$/];function G$($){return Vj.some((j)=>j.test($))}var qj=[[new Set(["zai"]),"glm","openai-completions"],[new Set(["Mistral"]),"mistral","openai-completions"],[new Set(["google","antigravity"]),"gemini","openai-completions"],[new Set(["Ollama","Ollama pay"]),"ollama","openai-completions"],[new Set(["Xiaomi"]),"mimo","openai-completions"],[new Set(["OpenRouter"]),"openrouter","openai-completions"],[new Set(["cerebras"]),"cerebras","openai-completions"]];function R$($,j){let J=($??"").trim();return J?`${J}-${j}`:j}function z0($,j){let J=(j??"").trim(),Y=$.match(/^([a-z0-9]+-)(.*)$/);if(Y)return J?`${J}-${Y[1]}`:Y[1];return $}function V0($,j){for(let[J,Y,Z]of qj)if(J.has($))return{slug:R$(j,Y),api:Z};return{slug:R$(j,"misc"),api:"openai-completions"}}function Mj($){return $.replace(/[/:]/g," ").split(/[-_]/).filter(Boolean).map((j)=>j[0].toUpperCase()+j.slice(1)).join(" ")}function J$($){return{id:$,name:Mj($),contextWindow:Xj,maxTokens:Qj,reasoning:G$($),cost:{...zj}}}import{execSync as Dj}from"node:child_process";import{randomUUID as q0}from"node:crypto";import{chmodSync as _$,constants as Uj,copyFileSync as M0,existsSync as A$,linkSync as nj,mkdirSync as D0,readFileSync as Ej,rmSync as C$,writeFileSync as Rj}from"node:fs";import{homedir as u$}from"node:os";import{dirname as z$,join as V$}from"node:path";import{fileURLToPath as Gj}from"node:url";var v$=V$(u$(),".dm","agent","dm-cliproxy"),w=V$(v$,"config.json"),_j=[V$(u$(),".pi","agent","pi-cliproxyapi","config.json"),V$(u$(),".config","pi-cliproxyapi","config.json")];function Aj(){return A$(V$(z$(Gj(import.meta.url)),"..",".git"))}function Oj($=_j,j=w,J=Aj()){if(A$(j))return;let Z=(typeof $==="string"?[$]:[...$]).find((z)=>A$(z));if(!Z)return;let X;try{D0(z$(j),{recursive:!0,mode:448}),_$(z$(j),448),X=`${j}.${process.pid}.${q0()}.tmp`,M0(Z,X,Uj.COPYFILE_EXCL),_$(X,384),nj(X,j),C$(X),X=void 0,B.info("legacy config copied to",j)}catch(z){if(X)try{C$(X,{force:!0})}catch(Q){B.warn("failed to clean temporary config:",Q)}B.warn("failed to migrate legacy config:",z)}}var O$={proxy:{endpoint:"",apiKey:""},builtinProviders:{},customProviders:{},discoveryExcludes:["*:*"],overrides:{},refreshIntervalMinutes:0,usageCacheTtlMs:30000};function W$(){if(Oj(),!A$(w))return B.debug("config not found, using defaults at",w),structuredClone(O$);try{let $=JSON.parse(Ej(w,"utf8"));return Wj($)}catch($){return B.error("failed to read config:",$,"— using defaults"),structuredClone(O$)}}function H$($){D0(z$(w),{recursive:!0,mode:448}),_$(z$(w),448);let j=`${w}.${process.pid}.${q0()}.tmp`;try{Rj(j,JSON.stringify($,null,2)+`
|
|
2
|
+
`,{encoding:"utf8",flag:"wx",mode:384}),M0(j,w),_$(w,384)}finally{C$(j,{force:!0})}B.info("config saved to",w)}function Wj($){if(!$||typeof $!=="object")return structuredClone(O$);let j=$,J=structuredClone(O$),Y=j.proxy??{};if(J.proxy.endpoint=typeof Y.endpoint==="string"?Y.endpoint:J.proxy.endpoint,J.proxy.apiKey=typeof Y.apiKey==="string"?Y.apiKey:"",typeof Y.usageKey==="string")J.proxy.usageKey=Y.usageKey;if(typeof Y.providerPrefix==="string"&&Y.providerPrefix.trim())J.proxy.providerPrefix=Y.providerPrefix.trim();if(j.builtinProviders&&typeof j.builtinProviders==="object")J.builtinProviders=j.builtinProviders;if(j.customProviders&&typeof j.customProviders==="object")J.customProviders=j.customProviders;if(Array.isArray(j.discoveryExcludes))J.discoveryExcludes=j.discoveryExcludes.filter((Z)=>typeof Z==="string");if(j.overrides&&typeof j.overrides==="object")J.overrides=j.overrides;if(typeof j.refreshIntervalMinutes==="number")J.refreshIntervalMinutes=j.refreshIntervalMinutes;if(typeof j.usageCacheTtlMs==="number")J.usageCacheTtlMs=j.usageCacheTtlMs;return J}function g($){if(!$)return"";let j=$.trim();if(j.startsWith("!"))try{return Dj(j.slice(1),{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).trim()}catch(J){let Y=J?.stderr?.toString?.()?.trim()??J.message;return B.warn(`failed to resolve "!" config value (${j}): ${Y}`),""}if(j.startsWith("$"))return process.env[j.slice(1)]??"";return j}import{chmodSync as Hj,existsSync as L1,mkdirSync as kj,readFileSync as P1,writeFileSync as Nj}from"node:fs";import{dirname as U0,join as Tj}from"node:path";var f$=Tj(v$,"discovery-cache.json");function g$($){try{kj(U0(f$),{recursive:!0,mode:448}),Hj(U0(f$),448);let j={savedAt:Date.now(),discovery:$};Nj(f$,JSON.stringify(j),{encoding:"utf8",mode:384})}catch(j){B.warn("failed to write discovery cache:",j.message)}}var Y$="dm-cliproxy/0.3.5",Bj=5000;async function R0($,j){let J=new AbortController,Y=setTimeout(()=>J.abort(Error("timeout")),Bj);try{return await fetch($,{...j,signal:J.signal})}finally{clearTimeout(Y)}}function Kj($){return new URL("/.well-known/pi",new URL($).origin).toString()}async function Sj($){let j=Kj($.proxy.endpoint),J;try{J=await R0(j,{headers:{"User-Agent":Y$,Accept:"application/json"}})}catch(Q){return B.warn("well-known fetch failed:",Q.message,"— falling back to /v1/models"),null}if(!J.ok)return B.warn(`well-known returned ${J.status} — falling back to /v1/models`),null;let Y;try{Y=await J.json()}catch{return B.warn("well-known returned non-JSON — falling back to /v1/models"),null}if(!Y||Y.schemaVersion!==1)return B.warn("well-known schemaVersion != 1 — falling back to /v1/models"),null;let Z=[],X=Y.builtinProviders??{};for(let[Q,V]of Object.entries(X)){if(!V||!Array.isArray(V.models))continue;let q=V.models.map((D)=>({id:String(D.id),name:typeof D.name==="string"?D.name:String(D.id),reasoning:Boolean(D.reasoning??G$(String(D.id))),contextWindow:typeof D.contextWindow==="number"?D.contextWindow:200000,maxTokens:typeof D.maxTokens==="number"?D.maxTokens:16000,cost:D.cost??{input:0,output:0,cacheRead:0,cacheWrite:0}}));Z.push({name:Q,api:V.api??"openai-responses",models:q})}let z=(Array.isArray(Y.customModelPool)?Y.customModelPool:[]).map((Q)=>({id:String(Q.id),name:typeof Q.name==="string"?Q.name:String(Q.id),reasoning:Boolean(Q.reasoning??G$(String(Q.id))),contextWindow:typeof Q.contextWindow==="number"?Q.contextWindow:128000,maxTokens:typeof Q.maxTokens==="number"?Q.maxTokens:16000,cost:Q.cost??{input:0,output:0,cacheRead:0,cacheWrite:0},api:Q.api??"openai-completions",suggestedProvider:z0(typeof Q.suggestedProviderName==="string"?Q.suggestedProviderName:"misc",$.proxy.providerPrefix),ownedBy:typeof Q.owned_by==="string"?Q.owned_by:""}));return{source:"well-known",upstreamVersion:typeof Y?.upstream?.upstreamVersion==="string"?Y.upstream.upstreamVersion:null,builtinProviders:Z,customPool:z,serverDiscoveryExcludes:Array.isArray(Y.discoveryExcludes)?Y.discoveryExcludes.filter((Q)=>typeof Q==="string"):[],upstreamTotal:typeof Y?.counts?.upstreamTotal==="number"?Y.counts.upstreamTotal:0}}async function Fj($,j){let J=new URL("/v1/models",new URL($.proxy.endpoint).origin).toString(),Y=await R0(J,{headers:{Authorization:`Bearer ${j}`,Accept:"application/json","User-Agent":Y$}});if(!Y.ok)throw Error(`/v1/models returned ${Y.status}`);let Z=await Y.json();if(!Z?.data||!Array.isArray(Z.data))return[];return Z.data.map((X)=>({id:typeof X.id==="string"?X.id:"",owned_by:typeof X.owned_by==="string"?X.owned_by:""})).filter((X)=>X.id)}function Lj($,j){let J=j.discoveryExcludes,Y=new Map,Z=[],X=0;for(let z of $){if(X++,Q0(z.id,J))continue;if(z.owned_by==="openai"){let D=J$(z.id);n0(Y,"openai","openai-responses",E0(D));continue}if(z.owned_by==="anthropic"){let D=J$(z.id);n0(Y,"anthropic","anthropic-messages",E0(D));continue}let{slug:Q,api:V}=V0(z.owned_by,j.proxy.providerPrefix),q=J$(z.id);Z.push({id:z.id,name:q.name??z.id,reasoning:q.reasoning??!1,contextWindow:q.contextWindow??128000,maxTokens:q.maxTokens??16000,cost:q.cost??{input:0,output:0,cacheRead:0,cacheWrite:0},api:V,suggestedProvider:Q,ownedBy:z.owned_by})}return{source:"v1-models",upstreamVersion:null,builtinProviders:Array.from(Y.values()),customPool:Z,serverDiscoveryExcludes:[],upstreamTotal:X}}function n0($,j,J,Y){let Z=$.get(j);if(!Z)Z={name:j,api:J,models:[]},$.set(j,Z);Z.models.push(Y)}function E0($){return{id:$.id,name:$.name??$.id,reasoning:$.reasoning??!1,contextWindow:$.contextWindow??128000,maxTokens:$.maxTokens??16000,cost:$.cost??{input:0,output:0,cacheRead:0,cacheWrite:0}}}async function G0($,j){let J=await Sj($);if(J)return B.info(`discovery via /.well-known/pi: ${J.builtinProviders.length} builtin, ${J.customPool.length} custom`),g$(J),J;if(!j)throw Error("well-known unavailable AND proxy apiKey is empty — cannot fall back to /v1/models. Set proxy.apiKey in config.");let Y=await Fj($,j),Z=Lj(Y,$);return B.info(`discovery via /v1/models: ${Z.builtinProviders.length} builtin, ${Z.customPool.length} custom`),g$(Z),Z}function _0($){let j=new Set;for(let J of $.builtinProviders)for(let Y of J.models)j.add(Y.id);for(let J of $.customPool)j.add(J.id);return j}async function h$($,j,J){let Y={registered:[],skipped:[]},Z=_0(J),X=g(j.proxy.apiKey);if(!X)return B.warn("proxy apiKey is empty — dm.registerProvider calls will be skipped"),Y;let z=new Map;for(let V of J.builtinProviders)z.set(V.name,V.models.map((q)=>({id:q.id,name:q.name,reasoning:q.reasoning,contextWindow:q.contextWindow,maxTokens:q.maxTokens,cost:q.cost})));for(let[V,q]of Object.entries(j.builtinProviders)){if(!q?.enabled){Y.skipped.push({provider:V,reason:"disabled"});continue}if(!Array.isArray(q.models)||q.models.length===0){Y.skipped.push({provider:V,reason:"empty whitelist"});continue}let D=[];try{D=Pj(V)}catch{}let n=new Map(D.map((A)=>[A.id,A])),F=new Map((z.get(V)??[]).map((A)=>[A.id,A])),_=[];for(let A of q.models){if(!Z.has(A))continue;let H=n.get(A),P=F.get(A);if(H){_.push({id:H.id,name:H.name,reasoning:H.reasoning,contextWindow:H.contextWindow,maxTokens:H.maxTokens,cost:H.cost,input:H.input,api:H.api,thinkingLevelMap:H.thinkingLevelMap});continue}if(!P)continue;let p=V==="anthropic"?"anthropic-messages":q.apiOverride??"openai-responses";_.push({id:P.id,name:P.name,reasoning:P.reasoning,contextWindow:P.contextWindow,maxTokens:P.maxTokens,cost:P.cost,input:["text"],api:p})}if(_.length===0){Y.skipped.push({provider:V,reason:"no whitelisted models present on proxy"});continue}let G=q.apiOverride??_[0].api;if(!y$.has(G)){Y.skipped.push({provider:V,reason:`api "${G}" not in allowlist`});continue}let U=_.map((A)=>{let H=j.overrides[A.id]??{},P={id:A.id,name:typeof H.name==="string"?H.name:A.name,api:G,reasoning:typeof H.reasoning==="boolean"?H.reasoning:A.reasoning,input:A.input,cost:H.cost??A.cost,contextWindow:typeof H.contextWindow==="number"?H.contextWindow:A.contextWindow,maxTokens:typeof H.maxTokens==="number"?H.maxTokens:A.maxTokens};if(A.thinkingLevelMap)P.thinkingLevelMap=A.thinkingLevelMap;return P}),W={name:V,baseUrl:w$(G,j.proxy.endpoint),apiKey:X,authHeader:!0,api:G,models:U};$.registerProvider(V,W),Y.registered.push({provider:V,modelCount:U.length,api:G})}let Q=new Map(J.customPool.map((V)=>[V.id,V]));for(let[V,q]of Object.entries(j.customProviders)){if(!y$.has(q.api)){Y.skipped.push({provider:V,reason:`api "${q.api}" not in allowlist`});continue}let D=q.models.filter((_)=>Z.has(_.id));if(D.length===0){Y.skipped.push({provider:V,reason:"no configured models present on proxy"});continue}let n=D.map((_)=>{let G=Q.get(_.id),U=J$(_.id),W=j.overrides[_.id]??{};return{id:_.id,name:_.name??G?.name??U.name??_.id,api:q.api,reasoning:Ij(_.reasoning,G?.reasoning,U.reasoning,W.reasoning)??!1,input:["text"],cost:_.cost??G?.cost??U.cost??{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:A0(_.contextWindow,G?.contextWindow,U.contextWindow,W.contextWindow)??128000,maxTokens:A0(_.maxTokens,G?.maxTokens,U.maxTokens,W.maxTokens)??16000}}),F={name:V,baseUrl:w$(q.api,j.proxy.endpoint),apiKey:X,authHeader:!0,api:q.api,models:n};$.registerProvider(V,F),Y.registered.push({provider:V,modelCount:n.length,api:q.api})}return B.info(`applyAll: registered ${Y.registered.length} providers, skipped ${Y.skipped.length}`),Y}function A0(...$){for(let j of $)if(typeof j==="number")return j;return}function Ij(...$){for(let j of $)if(typeof j==="boolean")return j;return}var xj=15000,q$=null;function k$(){q$=null}async function O0($,j,J={}){if(!J.force&&q$&&Date.now()-q$.fetchedAt<$.usageCacheTtlMs)return q$.doc;if(!j)throw Error("usage key not configured; set proxy.usageKey in config and rerun");let Y=new URL("/api/usage",new URL($.proxy.endpoint).origin).toString(),Z=new AbortController,X=setTimeout(()=>Z.abort(Error("timeout")),xj),z;try{z=await fetch(Y,{headers:{"X-Plugin-Key":j,Accept:"application/json","User-Agent":Y$},signal:Z.signal})}finally{clearTimeout(X)}if(!z.ok)throw Error(`/api/usage returned ${z.status}`);let Q=await z.json();if(!Q||Q.schemaVersion!==1||!Array.isArray(Q.accounts))throw Error("/api/usage returned unexpected payload shape");return q$={fetchedAt:Date.now(),doc:Q},B.debug("usage fetched, accounts:",Q.accounts.length),Q}import{visibleWidth as c$}from"@duckmind/dm-tui";import{visibleWidth as W0}from"@duckmind/dm-tui";function K($,j){let J=W0($);if(J===j)return $;if(J<j)return $+" ".repeat(j-J);return p$($,j)}function p$($,j){if(j<=0)return"\x1B[0m";let J="",Y=0,Z=0;while(Z<$.length){let X=$[Z];if(X==="\x1B"&&$[Z+1]==="["){let Q=$.indexOf("m",Z+2);if(Q>=0){J+=$.slice(Z,Q+1),Z=Q+1;continue}}let z=W0(X);if(Y+z>j)break;J+=X,Y+=z,Z++}return`${J}\x1B[0m`}var bj="│",yj="╭",wj="╮",Cj="╰",uj="╯",M$="─";function o($,j){let J=Math.max(4,j.width);return[vj($,j.title,j.titleColor??"accent",J),...j.lines.map((Y)=>fj($,Y,J)),gj($,j.footer,J)]}function vj($,j,J,Y){let Z=j??"",X=c$(Z),z=Math.max(0,Y-3-X),Q=Z?$.bold($.fg(J,Z)):"",V=`${yj}${M$}${Q}${M$.repeat(z)}${wj}`;return $.fg("borderAccent",V)}function fj($,j,J){let Y=Math.max(0,J-2),Z=$.fg("borderAccent",bj);return`${Z}${K(j,Y)}${Z}`}function gj($,j,J){let Y=`${Cj}${M$}`,Z=`${uj}`,X=3;if(!j||!j.hint&&!j.badge){let G=Math.max(0,J-3);return $.fg("borderAccent",`${Y}${M$.repeat(G)}${Z}`)}let z=j.hint??"",Q=j.badge??"",V=c$(z),q=c$(Q),D=Math.max(0,J-3-V-q),n=$.fg("dim",z),F=Q?$.fg("muted",Q):"",_=M$.repeat(D);return`${$.fg("borderAccent",Y)}${n}${$.fg("borderAccent",_)}${F}${$.fg("borderAccent",Z)}`}function N$($){return Math.max(0,$-2)}import{existsSync as H0}from"node:fs";import{homedir as hj}from"node:os";import{getKeybindings as pj,Input as cj,matchesKey as lj}from"@duckmind/dm-tui";var mj=[{label:"endpoint",hint:"OpenAI-style base URL of your CliProxyAPI deployment, must include /v1",required:!0,validate:($)=>{try{if(!new URL($).pathname.endsWith("/v1"))return"must end with /v1";return null}catch{return"not a valid URL"}}},{label:"apiKey",hint:"CliProxyAPI bearer key. Accepts literal, $ENV_VAR, !cmd, or ~/path",required:!0},{label:"providerPrefix",hint:"Prefix for your custom provider names. Suggested groups become <prefix>-glm, <prefix>-gemini, etc. Use any short slug (letters/digits/dashes).",required:!0,validate:($)=>/^[a-z0-9][a-z0-9-]*$/i.test($)?null:"letters/digits/dashes only"},{label:"usageKey",hint:"Optional X-Plugin-Key for /api/usage. Leave blank to skip the Usage tab",required:!1}];async function k0($,j=!1){let J=W$(),Y={endpoint:J.proxy.endpoint??"",apiKey:J.proxy.apiKey??"",providerPrefix:J.proxy.providerPrefix??"",usageKey:J.proxy.usageKey??""},Z=!1;for(let z of mj){let Q=j?Y[z.label]??z.initialValue??"":Y[z.label]??"";if(!j&&Q)continue;let V=await sj($,z,Q||z.initialValue||"");if(V===void 0){Z=!0;break}let q=V.trim();if(!q){if(z.required){$.ui.notify(`${z.label} is required — aborted`,"warning"),Z=!0;break}Y[z.label]="";continue}Y[z.label]=z.label==="providerPrefix"||z.label==="endpoint"?q:rj(q)}if(Z)return!1;let X={...J};if(X.proxy={...J.proxy,endpoint:Y.endpoint??"",apiKey:Y.apiKey??"",providerPrefix:Y.providerPrefix??""},Y.usageKey)X.proxy.usageKey=Y.usageKey;else delete X.proxy.usageKey;return H$(X),$.ui.notify(`saved to ${w}`,"info"),!0}function rj($){if($.startsWith("!")||$.startsWith("$"))return $;if($.startsWith("~/")){let j=$.replace(/^~/,hj());return H0(j)?`!cat ${$}`:$}if($.startsWith("/"))return H0($)?`!cat ${$}`:$;return $}async function sj($,j,J){return $.ui.custom((Y,Z,X,z)=>oj(Y,Z,j,J,z),{overlay:!0,overlayOptions:{width:100,maxHeight:"60%"}})}function oj($,j,J,Y,Z){let X=new cj;X.setValue(Y),X.focused=!0;let z=null,Q=(V)=>{if(!V&&!J.required){Z("");return}if(!V&&J.required){z="required field",$.requestRender();return}if(J.validate){let q=V.trim();if(q&&!q.startsWith("!")&&!q.startsWith("$")){let D=J.validate(q);if(D){z=D,$.requestRender();return}}}Z(V)};return X.onSubmit=Q,X.onEscape=()=>Z(void 0),{render(V){let q=N$(V),D=X.render(q-4),n=["",` ${j.fg("dim",J.hint)}`,"",...D.map((F)=>` ${j.fg("accent",`❯ ${F}`)}`),"",z?` ${j.fg("error",`! ${z}`)}`:` ${j.fg("dim","enter = save · esc = cancel")}`];return o(j,{width:V,title:` setup: ${J.label} `,lines:n,footer:{hint:" enter = save · esc = cancel "}})},invalidate(){X.invalidate()},handleInput(V){if(pj().matches(V,"tui.select.cancel")||lj(V,"escape")){Z(void 0);return}z=null,X.handleInput(V),$.requestRender()}}}import{visibleWidth as T$}from"@duckmind/dm-tui";function N0($,j,J,Y){let Z=$.fg("borderAccent","│"),X=j.map((z,Q)=>{let V=`${Q+1} ${z.label}`;return Q===J?$.bold($.fg("accent",` ${V} `)):$.fg("dim",` ${V} `)});return K(` ${X.join(Z)}`,Y)}function T0($,j,J){let Y=j.join($.fg("dim"," "));return K(` ${Y}`,J)}function B0($,j){return $.fg("borderAccent","─".repeat(Math.max(0,j)))}function i($,j,J){let Y=$.slice(j,j+J);while(Y.length<J)Y.push("");return Y}function B$($,j,J,Y,Z,X){if(Z<=Y)return 0;let z=Math.max(0,Z-Y);if(j<X)return 0;let Q=Math.max(0,Math.min(J,z)),V=Q+X;if($<V)Q=Math.max(0,$-X);let q=Q+Y-1;if(j>q)Q=Math.min(z,j-(Y-1));return Q}function K$($,j,J){let Y=Math.max(0,J-j);return Math.max(0,Math.min($,Y))}import{matchesKey as d}from"@duckmind/dm-tui";import{existsSync as ij,readFileSync as dj}from"node:fs";import{homedir as S0}from"node:os";import{join as F0}from"node:path";var tj=F0(S0(),".dm","models.json"),aj=F0(S0(),".dm","auth.json");function K0($){if(!ij($))return null;try{return JSON.parse(dj($,"utf8"))}catch{return null}}function L0($){let j=[],J=new Set([...Object.keys($.builtinProviders),...Object.keys($.customProviders)]),Y=K0(tj);if(Y&&typeof Y==="object"){for(let X of Object.keys(Y))if(J.has(X))j.push({kind:"models.json",provider:X,detail:`provider "${X}" has user overrides in ~/.dm/models.json which DM merges on top of our registration`})}let Z=K0(aj);if(Z&&typeof Z==="object"){for(let X of Object.keys(Z))if(J.has(X))j.push({kind:"auth.json",provider:X,detail:`provider "${X}" has user-set credentials in ~/.dm/auth.json which take priority over our apiKey`})}return j}function P0($){let{theme:j,cfg:J}=$,Y=0,Z=()=>{let Q=$.getDiscovery(),V=(G)=>j.fg("success",G),q=(G)=>j.fg("error",G),D=(G)=>j.fg("dim",G),n=[];n.push(`${D("endpoint")} ${J.proxy.endpoint||q("(unset)")}`),n.push(`${D("apiKey")} ${g(J.proxy.apiKey)?V("resolves"):q("empty after resolution")}`),n.push(`${D("usageKey")} ${J.proxy.usageKey?g(J.proxy.usageKey)?V("resolves"):q("set but empty"):D("not configured")}`),n.push(`${D("user-agent")} ${Y$}`),n.push(""),n.push(`${D("discovery")} source=${Q.source}`),n.push(`${D("upstream")} v=${Q.upstreamVersion??"(unknown)"} · ${Q.upstreamTotal} ids`);let F=Q.builtinProviders.map((G)=>`${G.name}=${G.models.length}`).join(", ")||D("(none)");n.push(`${D("built-in")} ${F}`),n.push(`${D("custom pool")} ${Q.customPool.length} models`);let _=L0(J);if(n.push(""),_.length===0)n.push(`${D("conflicts")} ${V("none")}`);else{n.push(`${D("conflicts")}`);for(let G of _)n.push(` ${j.fg("warning",`[${G.kind}]`)} ${G.detail}`)}return n};return{id:"diagnostics",label:"Diagnostics",render:(Q,V)=>{let q=Z();return Y=K$(Y,V,q.length),i(q,Y,V).map((D)=>K(` ${D}`,Q))},handleInput:(Q)=>{let V=Z().length;if(d(Q,"up")||d(Q,"k"))return Y=Math.max(0,Y-1),!0;if(d(Q,"down")||d(Q,"j"))return Y=Math.min(Math.max(0,V-1),Y+1),!0;if(d(Q,"pageUp")||d(Q,"b"))return Y=Math.max(0,Y-10),!0;if(d(Q,"pageDown")||d(Q,"f"))return Y=Math.min(Math.max(0,V-1),Y+10),!0;return!1},footerHint:()=>" ↑↓ scroll · r refresh discovery "}}import{matchesKey as N}from"@duckmind/dm-tui";function l$($){let j=new Map,J=new Map;for(let Z of $.builtinProviders){let X=[];for(let z of Z.models)j.set(z.id,{id:z.id,name:z.name,suggestedApi:Z.api,subtitle:z.name&&z.name!==z.id?z.name:void 0,ownedBy:Z.name,reasoning:z.reasoning,contextWindow:z.contextWindow,maxTokens:z.maxTokens,cost:z.cost}),X.push(z.id);J.set(Z.name,X)}let Y=[];for(let Z of $.customPool){if(!j.has(Z.id))j.set(Z.id,{id:Z.id,name:Z.name,suggestedApi:Z.api,subtitle:Z.name&&Z.name!==Z.id?Z.name:void 0,origin:Z.suggestedProvider,ownedBy:Z.ownedBy,reasoning:Z.reasoning,contextWindow:Z.contextWindow,maxTokens:Z.maxTokens,cost:Z.cost});Y.push(Z.id)}return{byId:j,builtinModelIds:J,customPoolIds:Y}}function ej($){let j=new Map;for(let[J,Y]of Object.entries($.customProviders))for(let Z of Y.models)j.set(Z.id,J);return j}function e($,j){if(j.kind==="builtin")return[...$.builtinProviders[j.name]?.models??[]];return $.customProviders[j.name]?.models.map((J)=>J.id)??[]}function I0($,j,J){if(j.kind==="builtin"){let X=J.builtinModelIds.get(j.name)??[],z=new Set(e($,j));return X.filter((Q)=>!z.has(Q))}let Y=ej($),Z=new Set(e($,j));return J.customPoolIds.filter((X)=>{if(Z.has(X))return!1;let z=Y.get(X);return z===void 0||z===j.name})}function $1($){return{id:$.id,name:$.name,contextWindow:$.contextWindow,maxTokens:$.maxTokens,reasoning:$.reasoning,cost:$.cost}}function x0($,j,J){if(j.kind==="builtin"){let Z=$.builtinProviders[j.name]??{enabled:!0,models:[]},X=new Set(Z.models);X.add(J.id),$.builtinProviders[j.name]={enabled:!0,apiOverride:Z.apiOverride??null,models:Array.from(X).sort()};return}for(let[Z,X]of Object.entries($.customProviders)){if(Z===j.name)continue;let z=X.models.findIndex((Q)=>Q.id===J.id);if(z>=0)X.models.splice(z,1)}let Y=$.customProviders[j.name]??{api:j.api,models:[]};if(!Y.models.some((Z)=>Z.id===J.id))Y.models.push($1(J));$.customProviders[j.name]=Y}function b0($,j,J){if(j.kind==="builtin"){let Z=$.builtinProviders[j.name];if(!Z)return;Z.models=Z.models.filter((X)=>X!==J),Z.enabled=Z.models.length>0;return}let Y=$.customProviders[j.name];if(!Y)return;Y.models=Y.models.filter((Z)=>Z.id!==J)}function m$($,j){if($===j)return!0;let J=["openai-completions","openai-responses"];if(J.includes($)&&J.includes(j))return!0;return!1}function y0($,j){let J=new Map;for(let Y of $){let Z=j.byId.get(Y),X=Z?.ownedBy||Z?.origin||"misc",z=J.get(X)??[];z.push(Y),J.set(X,z)}return Array.from(J.entries()).sort((Y,Z)=>Y[0].localeCompare(Z[0])).map(([Y,Z])=>({label:Y,ids:Z}))}function w0($,j,J){let Y=J.trim().toLowerCase();if(!Y)return $;return $.filter((Z)=>{if(Z.toLowerCase().includes(Y))return!0;let X=j.byId.get(Z)?.name;return X?X.toLowerCase().includes(Y):!1})}import{getModels as j1,getProviders as J1}from"@duckmind/dm-ai/compat";function r$($,j){let J=[],Y=new Set(j.builtinModelIds.keys()),Z=new Set(J1()),X=new Set([...Y,...Z]);for(let z of Array.from(X).sort()){let Q=j.builtinModelIds.get(z);if(!Q||Q.length===0)continue;let V;try{let D=j1(z).find((n)=>Q.includes(n.id));if(D)V=D.api}catch{}if(!V){let q=Q[0];V=j.byId.get(q)?.suggestedApi??"openai-responses"}if(J.push({kind:"builtin",name:z,api:V,subtitle:`built-in · ${V}`}),!$.builtinProviders[z])$.builtinProviders[z]={enabled:!1,models:[]}}for(let z of Object.keys($.customProviders).sort()){let Q=$.customProviders[z];J.push({kind:"custom",name:z,api:Q.api,subtitle:`custom · ${Q.api}`})}return J}import{getKeybindings as Y1,matchesKey as Z$}from"@duckmind/dm-tui";async function C0($,j){return $.ui.custom((J,Y,Z,X)=>Z1(Y,`Remove custom group “${j}”?`,"All model assignments in this group will be discarded.",X),{overlay:!0,overlayOptions:{width:80,maxHeight:"40%"}})}function Z1($,j,J,Y){return{render(Z){return o($,{width:Z,title:" confirm ",titleColor:"error",lines:["",` ${$.bold(j)}`,` ${$.fg("dim",J)}`,""],footer:{hint:" y / enter = remove · n / esc = cancel "}})},invalidate(){},handleInput(Z){if(Y1().matches(Z,"tui.select.cancel")||Z$(Z,"escape")||Z$(Z,"n")||Z$(Z,"q")){Y(!1);return}if(Z$(Z,"y")||Z$(Z,"enter")||Z$(Z,"return")){Y(!0);return}}}}import{getKeybindings as X1,Input as Q1,matchesKey as z1}from"@duckmind/dm-tui";async function u0($,j){let J=R$(j,"group");return $.ui.custom((Y,Z,X,z)=>V1(Y,Z,J,z),{overlay:!0,overlayOptions:{width:80,maxHeight:"40%"}})}function V1($,j,J,Y){let Z=new Q1;if(J)Z.setValue(J);Z.focused=!0;let X=null;return Z.onSubmit=(z)=>{let Q=z.trim();if(!/^[a-z0-9][a-z0-9._-]*$/i.test(Q)){X="letters / digits / dot / dash / underscore only",$.requestRender();return}Y(Q)},Z.onEscape=()=>Y(null),{render(z){let Q=N$(z),V=J?`name shown in /model picker, e.g. ${J}`:"letters / digits / dot / dash / underscore",q=Z.render(Q-4),D=["",` ${j.fg("dim",V)}`,"",...q.map((n)=>` ${j.fg("accent",`❯ ${n}`)}`),"",X?` ${j.fg("error",`! ${X}`)}`:""];return o(j,{width:z,title:" new custom group ",lines:D,footer:{hint:" enter = create · esc = cancel "}})},invalidate(){Z.invalidate()},handleInput(z){if(X1().matches(z,"tui.select.cancel")||z1(z,"escape")){Y(null);return}X=null,Z.handleInput(z),$.requestRender()}}}import{visibleWidth as q1}from"@duckmind/dm-tui";function s$($,j,J){if(!j)return" ";if(J)return $.fg("accent","▶ ");return $.fg("muted","▸ ")}function v0($,j){let J=q1($);if(J===j)return $;if(J>j)return p$($,j);return K($,j)}function f0($,j,J){let{theme:Y,width:Z,isCursor:X,isFocused:z}=J,Q=s$(Y,X,z),V=$.kind==="builtin"?j.builtinProviders[$.name]?.models.length??0:j.customProviders[$.name]?.models.length??0,q=$.kind==="builtin"?Y.fg("accent","B"):Y.fg("warning","C"),D=`${Y.fg("dim","[")}${q}${Y.fg("dim","]")}`,n=V>0?Y.fg("success","●"):Y.fg("dim","○"),F=V>0?Y.fg("success",String(V).padStart(2)):Y.fg("dim"," 0"),_=X&&z?Y.bold(Y.fg("accent",$.name)):X?Y.bold($.name):$.name,G=Y.fg("dim",$.api),U=`${Q}${D} ${_} ${n}${F} ${G}`;return v0(U,Z)}function g0($,j,J,Y){let Z=s$($,j,J),X=j&&J?$.bold($.fg("accent","+ new custom group…")):$.fg("accent","+ new custom group…");return K(`${Z}${X}`,Y)}function o$($,j,J,Y,Z){let{theme:X,width:z,isCursor:Q,isFocused:V}=Z,q=s$(X,Q,V),D=J==="assigned"?X.fg("success","☑"):X.fg("dim","☐"),n=Y?` ${X.fg("warning","⚠")}`:"",F=Q&&V?X.fg("accent",$):$,_=j?.reasoning?` ${X.fg("accent","✨")}`:"",G=j?X.fg("muted",` · ${j.suggestedApi}`):X.fg("error"," · not on proxy"),U=`${q}${D} ${F}${n}${_}${G}`;return v0(U,z)}function h0($,j,J){let Y=`${$.fg("borderAccent","──")} ${$.fg("warning",j)} ${$.fg("borderAccent","──")}`;return K(` ${Y}`,J)}function i$($,j,J){return K(` ${$.fg("dim",j)}`,J)}function p0($,j,J,Y){let Z=Y?$.bold($.fg("accent","❚ ")):$.fg("dim"," ");return K(`${Z}${j}`,J)}function c0($){let{tui:j,theme:J,ctx:Y,cfg:Z}=$,X=$.onChange??(()=>{}),z=l$($.getDiscovery()),Q=r$(Z,z),V="providers",q=0,D=0,n=0,F=0,_=0,G=0,U="",W=!1,A=()=>{if(Q.length===0)return null;let M=Math.max(0,Math.min(q,Q.length-1));return Q[M]??null},H=(M)=>{let O=w0(I0(Z,M,z),z,U);return y0(O,z)},P=(M)=>H(M).flatMap((O)=>O.ids),p=()=>{Q=r$(Z,z);let M=Math.max(0,Q.length);if(q>M)q=M;let O=A();if(O){let L=e(Z,O).length,k=P(O).length;if(D>=L)D=Math.max(0,L-1);if(n>=k)n=Math.max(0,k-1)}},S$=()=>{z=l$($.getDiscovery()),p()},D$=(M)=>{let O=["providers","assigned","pool"],L=O.indexOf(V);V=M?O[(L-1+O.length)%O.length]:O[(L+1)%O.length]},R=(M)=>{if(V==="providers"){let k=Q.length+1;q=Math.max(0,Math.min(q+M,k-1));return}let O=A();if(!O)return;if(V==="assigned"){let k=e(Z,O).length;if(k===0)return;D=Math.max(0,Math.min(D+M,k-1));return}let L=P(O).length;if(L===0)return;n=Math.max(0,Math.min(n+M,L-1))},I=async()=>{if(V==="providers"){if(q===Q.length){let k=await u0(Y,Z.proxy.providerPrefix);if(k&&!Z.customProviders[k]){if(Z.customProviders[k]={api:"openai-completions",models:[]},X(),p(),q=Q.findIndex((S)=>S.kind==="custom"&&S.name===k),q<0)q=Q.length-1;V="pool"}j.requestRender();return}V="pool";return}let M=A();if(!M)return;if(V==="assigned"){let k=e(Z,M)[D];if(!k)return;b0(Z,M,k),X(),p();return}let O=P(M)[n];if(!O)return;let L=z.byId.get(O);if(!L)return;x0(Z,M,L),X(),p()},l=async()=>{if(V!=="providers")return;let M=A();if(!M||M.kind!=="custom")return;if(!await C0(Y,M.name)){j.requestRender();return}if(delete Z.customProviders[M.name],X(),p(),q>=Q.length)q=Math.max(0,Q.length-1);j.requestRender()},u=(M,O)=>h(M,O);function h(M,O){let L=Math.max(70,M),k=Math.min(56,Math.max(34,Math.floor(L*0.4))),S=L-k-1,m=Math.max(8,O),r=Math.max(5,Math.floor((m-1)/2)),d$=m-r,c=A(),X$=0,F$=0,L$=0,t$=0,P$=0,a$=0,t=[];t.push($$(" providers ",k,V==="providers"));for(let T=0;T<Q.length;T++){let v=Q[T],y=V==="providers"&&T===q;if(y)X$=t.length,F$=X$;t.push(f0(v,Z,{theme:J,width:k,isCursor:y,isFocused:V==="providers"}))}{let T=V==="providers"&&q===Q.length;if(T)X$=t.length,F$=X$;t.push(g0(J,T,V==="providers",k))}let a=[],$j=c?`assigned to ${J.bold(c.name)} ${J.fg("dim",`· ${c.api}`)}`:J.fg("dim","no provider selected");if(a.push($$(" assigned ",S,V==="assigned")),a.push(p0(J,$j,S,V==="assigned")),c){let T=e(Z,c);if(T.length===0)a.push(i$(J,"(nothing assigned yet)",S));for(let v=0;v<T.length;v++){let y=T[v],f=z.byId.get(y),E$=V==="assigned"&&v===D;if(E$)L$=a.length,t$=L$;let j$=f?!m$(c.api,f.suggestedApi):!1;a.push(o$(y,f,"assigned",j$,{theme:J,width:S,isCursor:E$,isFocused:V==="assigned"}))}}let s=[];if(s.push(x(S,V==="pool")),c){let T=H(c);if(T.reduce((y,f)=>y+f.ids.length,0)===0)s.push(i$(J,U?`(no matches for "${U}")`:"(no models available)",S));else{let y=0;for(let f of T){let E$=s.length;s.push(h0(J,f.label,S));for(let j$=0;j$<f.ids.length;j$++){let Z0=f.ids[j$],x$=z.byId.get(Z0),X0=V==="pool"&&y===n;if(X0)P$=s.length,a$=j$===0?E$:P$;let Zj=x$?!m$(c.api,x$.suggestedApi):!1;s.push(o$(Z0,x$,"pool",Zj,{theme:J,width:S,isCursor:X0,isFocused:V==="pool"})),y++}}}}let jj=Math.max(1,d$-1),e$=B$(F$,X$,F,m,t.length,1),$0=B$(V==="assigned"?t$:0,V==="assigned"?L$:0,_,r,a.length,2),j0=B$(V==="pool"?a$:0,V==="pool"?P$:0,G,jj,s.length,1);F=e$,_=$0,G=j0;let J0=i(t,e$,m),Jj=i(a,$0,r),Yj=i(s,j0,d$),Y0=J.fg("borderAccent","│"),I$=[];for(let T=0;T<m;T++){let v=K(J0[T]??"",k),y=T<r?Jj[T]:Yj[T-r],f=K(y,S);I$.push(`${v}${Y0}${f}`)}let n$=r;if(n$>0&&n$<m){let T=K(J0[n$]??"",k),v=J.fg("borderAccent","─".repeat(S));I$[n$]=`${T}${Y0}${v}`}return I$}function $$(M,O,L){let k=L?J.bold(J.fg("accent",M)):J.fg("muted",M),S=J.fg("borderAccent","─".repeat(Math.max(0,O-T$(M)-1)));return K(`${k}${S}`,O)}function x(M,O){let k=O?J.bold(J.fg("accent"," available pool ")):J.fg("muted"," available pool "),S="";if(W)S=`${J.fg("dim"," /")}${J.fg("accent",U)}${J.fg("accent","█")} `;else if(U)S=`${J.fg("dim"," /")}${J.fg("warning",U)} `;let m=T$(" available pool ")+T$(S),r=J.fg("borderAccent","─".repeat(Math.max(0,M-m-1)));return K(`${k}${S}${r}`,M)}function U$(M){if(W){if(N(M,"escape"))return U="",W=!1,n=0,!0;if(N(M,"enter")||N(M,"return"))return W=!1,!0;if(N(M,"backspace")||N(M,"delete"))return U=U.slice(0,-1),n=0,!0;if(M.length===1&&M>=" "&&M!=="")return U+=M,n=0,!0;return!0}if(N(M,"tab"))return D$(!1),!0;if(N(M,"shift+tab"))return D$(!0),!0;if(N(M,"/"))return V="pool",W=!0,!0;if(N(M,"enter")||N(M,"return")||N(M,"space"))return I().then(()=>!0);if(V==="providers"&&(N(M,"d")||N(M,"delete")||N(M,"backspace")))return l().then(()=>!0);if(N(M,"up")||N(M,"k"))return R(-1),!0;if(N(M,"down")||N(M,"j"))return R(1),!0;if(N(M,"pageUp")||N(M,"b"))return R(-8),!0;if(N(M,"pageDown")||N(M,"f"))return R(8),!0;if(N(M,"left")||N(M,"h"))return V="providers",!0;if(N(M,"right")||N(M,"l")){if(V==="providers")V="assigned";else if(V==="assigned")V="pool";return!0}return!1}function e0(){if(W)return" type to filter · ↵ apply · esc clear ";return" tab ↔ panel · ↑↓ nav · ↵ move · / filter · d remove group "}return{id:"models",label:"Models",render:u,handleInput:U$,footerHint:e0,rebuild:S$}}import{matchesKey as b}from"@duckmind/dm-tui";var E={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",accent:"\x1B[38;5;111m",muted:"\x1B[38;5;245m",dim2:"\x1B[38;5;240m",green:"\x1B[38;5;114m",yellow:"\x1B[38;5;179m",red:"\x1B[38;5;167m",greenBg:"\x1B[48;5;22m",yellowBg:"\x1B[48;5;94m",redBg:"\x1B[48;5;52m"};function l0($,j={}){let J=[],Y=new Map,Z=0;for(let X of $.accounts){if(!j.showDisabled&&X.disabled){Z++;continue}let z=Y.get(X.provider)??[];z.push(X),Y.set(X.provider,z)}if(J.push(`${E.dim}generated ${$.generatedAt}${E.reset}`),$.unsupportedProviders.length>0)J.push(`${E.dim}providers without quota lookup:${E.reset} ${$.unsupportedProviders.join(", ")}`);if(Z>0)J.push(`${E.dim}hidden disabled accounts:${E.reset} ${Z} ${E.dim2}(press d to show)${E.reset}`);for(let[X,z]of Array.from(Y.entries()).sort()){J.push(""),J.push(`${E.bold}${E.accent}▌ ${X}${E.reset}`);for(let Q of z){if(J.push(D1(Q)),!Q.supported){J.push(` ${E.dim2}(provider not quota-aware)${E.reset}`);continue}if(Q.error){if(j.verbose)for(let q of M1(Q.error,88))J.push(` ${E.red}${q}${E.reset}`);continue}let V=Q.groups??[];if(V.length===0){J.push(` ${E.dim2}(no active quota windows)${E.reset}`);continue}for(let q of V)J.push(n1(q))}}return J.push(""),J.push(`${E.dim}legend:${E.reset} ${m0} ok ${r0} error/unavailable ${s0} disabled ${E.green}✓N${E.reset}/${E.red}✗N${E.reset} request counters ${E.dim}v = verbose, d = show disabled${E.reset}`),J}function M1($,j){if($.length<=j)return[$];let J=[],Y=$;while(Y.length>j){let Z=Y.lastIndexOf(" ",j);if(Z<j*0.6)Z=j;J.push(Y.slice(0,Z)),Y=Y.slice(Z).replace(/^\s+/,"")}if(Y)J.push(Y);return J}function D1($){let j=U1($),J=`${E.green}✓${$.success}${E.reset} ${E.red}✗${$.failed}${E.reset}`,Y=d0($.label,36);return` ${j} ${E.bold}${Y}${E.reset} ${J}`}var m0=`${E.green}●${E.reset}`,r0=`${E.yellow}⚠${E.reset}`,s0=`${E.dim2}⊘${E.reset}`;function U1($){if($.disabled)return s0;if($.unavailable||$.error||$.status&&$.status!=="active")return r0;return m0}function n1($){let j=i0($.remainingFraction),J=Math.round(j*100),Y=E1(j),Z=$.resetTime?` ${E.dim}reset ${G1($.resetTime)}${E.reset}`:"",X=d0($.label,28).padEnd(28," ");return` ${Y} ${R1(J,j)} ${X}${Z}`}function E1($){let j=i0($),J=Math.round(j*18),Y=o0(j),Z=E.dim2,X="█".repeat(J),z="░".repeat(18-J);return`${Z}[${Y}${X}${Z}${z}]${E.reset}`}function R1($,j){return`${o0(j)}${String($).padStart(3)}%${E.reset}`}function o0($){if($>=0.4)return E.green;if($>=0.15)return E.yellow;return E.red}function G1($){let j=Date.parse($);if(!Number.isFinite(j))return $;let J=j-Date.now();if(J<=0)return"now";let Y=Math.round(J/60000);if(Y<60)return`${Y}m`;let Z=Math.round(Y/60);if(Z<48)return`${Z}h`;return`${Math.round(Z/24)}d`}function i0($){return Math.max(0,Math.min(1,$))}function d0($,j){if($.length<=j)return $;return`${$.slice(0,j-1)}…`}function t0($){let{tui:j,theme:J,cfg:Y}=$,Z="idle",X=null,z="",Q=0,V=!1,q=!1,D=(U)=>{Z="loading",j.requestRender();let W=g(Y.proxy.usageKey);O0(Y,W,{force:U}).then((A)=>{X=A,Z="ready",Q=0,j.requestRender()}).catch((A)=>{z=A.message,Z="error",j.requestRender()})},n=()=>{if(Z==="idle"||Z==="loading")return[J.fg("dim"," loading usage…")];if(Z==="error")return[J.fg("error",` usage failed: ${z}`)];if(!X)return[J.fg("dim"," (no data)")];return l0(X,{showDisabled:V,verbose:q})};return{id:"usage",label:"Usage",render:(U,W)=>{let A=n();return Q=K$(Q,W,A.length),i(A,Q,W).map((H)=>K(` ${H}`,U))},handleInput:(U)=>{if(b(U,"d"))return V=!V,Q=0,!0;if(b(U,"v"))return q=!q,Q=0,!0;let W=n().length;if(b(U,"up")||b(U,"k"))return Q=Math.max(0,Q-1),!0;if(b(U,"down")||b(U,"j"))return Q=Math.min(Math.max(0,W-1),Q+1),!0;if(b(U,"pageUp")||b(U,"b"))return Q=Math.max(0,Q-10),!0;if(b(U,"pageDown")||b(U,"f"))return Q=Math.min(Math.max(0,W-1),Q+10),!0;if(b(U,"home")||b(U,"g"))return Q=0,!0;if(b(U,"end")||b(U,"shift+g"))return Q=Math.max(0,W-1),!0;return!1},footerHint:()=>{let U=V?J.fg("success","[d disabled]"):"d disabled",W=q?J.fg("success","[v verbose]"):"v verbose";return` ↑↓ scroll · ${U} · ${W} `},onActivate:()=>{if(Z==="idle")D(!1)},reload:()=>{if(k$(),Z!=="idle")D(!0)}}}function a0($){let{dm:j,ctx:J,tui:Y,theme:Z,cfg:X,done:z}=$,Q=$.discovery,V=!1,q="",D=c0({tui:Y,theme:Z,ctx:J,cfg:X,getDiscovery:()=>Q,onChange:()=>{V=!0,q=""}}),n=t0({tui:Y,theme:Z,cfg:X}),F=P0({theme:Z,cfg:X,getDiscovery:()=>Q}),_=[D,n,F],G=0,U=()=>_[G],W=(R)=>{if(R<0||R>=_.length||R===G)return;G=R,U().onActivate?.(),Y.requestRender()},A=()=>{q=Z.fg("dim","saving…"),H$(X),Y.requestRender(),h$(j,X,Q).then((R)=>{V=!1,q=Z.fg("success",`✓ settings saved · ${R.registered.length} registered, ${R.skipped.length} skipped`),Y.requestRender()}).catch((R)=>{q=Z.fg("error",`save failed: ${R.message}`),Y.requestRender()})},H=async()=>{q=Z.fg("dim","refreshing…"),Y.requestRender();try{let R=g(X.proxy.apiKey);Q=await G0(X,R),k$(),D.rebuild(),n.reload();let I=await h$(j,X,Q);q=Z.fg("success",`✓ refreshed · ${I.registered.length} providers (${Q.source})`)}catch(R){q=Z.fg("error",`refresh failed: ${R.message}`)}Y.requestRender()},P=async()=>{if(!await k0(J,!0)){Y.requestRender();return}let I=W$();X.proxy={...X.proxy,...I.proxy},await H()},p=()=>{let R=X.proxy.endpoint||"(unset)",I=R.length>40?`…${R.slice(-39)}`:R,l=Boolean(g(X.proxy.apiKey)),u=0,h=0;for(let x of Object.values(X.builtinProviders)){if(x.enabled&&x.models.length>0)u++;h+=x.models.length}for(let x of Object.values(X.customProviders)){if(x.models.length>0)u++;h+=x.models.length}let $$=q?q:V?Z.fg("warning","● unsaved — press s to save"):Z.fg("dim","✓ saved");return[`${Z.fg("dim","endpoint")} ${I}`,`${Z.fg("dim","key")} ${l?Z.fg("success","✓"):Z.fg("error","✗")}`,`${Z.fg("dim","providers")} ${u}`,`${Z.fg("dim","models")} ${h}`,$$]},S$=(R)=>{let I=Y.rows??40,u=Math.max(16,Math.min(I-6,38))-2,h=Math.max(72,R-2),$$=Math.max(6,u-3),x=[];return x.push(T0(Z,p(),h)),x.push(N0(Z,_.map((U$)=>({id:U$.id,label:U$.label})),G,h)),x.push(B0(Z,h)),x.push(...U().render(h,$$)),o(Z,{width:R,title:" /cliproxy ",lines:x,footer:{hint:U().footerHint(),badge:" [ ] tab · r refresh · e setup · s save · q close "}})},D$=(R)=>{if(_1().matches(R,"tui.select.cancel")||C(R,"q")||C(R,"escape"))return z(),!0;if(C(R,"]")||C(R,"tab"))return W((G+1)%_.length),!0;if(C(R,"[")||C(R,"shift+tab"))return W((G-1+_.length)%_.length),!0;if(C(R,"1"))return W(0),!0;if(C(R,"2"))return W(1),!0;if(C(R,"3"))return W(2),!0;if(C(R,"r"))return H().then(()=>!0);if(C(R,"e"))return P().then(()=>!0);if(C(R,"s"))return A(),!0;return!1};return{render:S$,invalidate(){},handleInput(R){let I=U().handleInput(R);if(I instanceof Promise){q="",I.then((u)=>{if(u)Y.requestRender()});return}if(I){q="",Y.requestRender();return}let l=D$(R);if(l instanceof Promise)l.then((u)=>{if(u)Y.requestRender()});else if(l)Y.requestRender()}}}async function DJ($,j,J,Y){if(!j.hasUI){j.ui.notify("interactive UI required for /cliproxy","warning");return}let Z=structuredClone(J);b$(!0);try{await j.ui.custom((X,z,Q,V)=>a0({dm:$,ctx:j,tui:X,theme:z,cfg:Z,discovery:Y,done:V}),{overlay:!0,overlayOptions:{width:170,maxHeight:"94%"}})}finally{b$(!1)}}export{DJ as runHub};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{visibleWidth as Y}from"@duckmind/dm-tui";import{visibleWidth as O}from"@duckmind/dm-tui";function M(q,z){let D=O(q);if(D===z)return q;if(D<z)return q+" ".repeat(z-D);return Q(q,z)}function Q(q,z){if(z<=0)return"\x1B[0m";let D="",E=0,F=0;while(F<q.length){let J=q[F];if(J==="\x1B"&&q[F+1]==="["){let H=q.indexOf("m",F+2);if(H>=0){D+=q.slice(F,H+1),F=H+1;continue}}let K=O(J);if(E+K>z)break;D+=J,E+=K,F++}return`${D}\x1B[0m`}function _(q,z,D,E){let F=q.fg("borderAccent","│"),J=z.map((K,H)=>{let L=`${H+1} ${K.label}`;return H===D?q.bold(q.fg("accent",` ${L} `)):q.fg("dim",` ${L} `)});return M(` ${J.join(F)}`,E)}function $(q,z,D){let E=z.join(q.fg("dim"," "));return M(` ${E}`,D)}function j(q,z){return q.fg("borderAccent","─".repeat(Math.max(0,z)))}function G(q,z,D){let E=q.slice(z,z+D);while(E.length<D)E.push("");return E}function A(q,z,D,E,F,J){if(F<=E)return 0;let K=Math.max(0,F-E);if(z<J)return 0;let H=Math.max(0,Math.min(D,K)),L=H+J;if(q<L)H=Math.max(0,q-J);let P=H+E-1;if(z>P)H=Math.min(K,z-(E-1));return H}function N(q,z,D){let E=Math.max(0,D-z);return Math.max(0,Math.min(q,E))}export{Y as visibleWidth,G as takeSlice,_ as tabBar,$ as statusHeader,j as ruleLine,A as clampScroll,N as clampOffset};
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{matchesKey as v}from"@duckmind/dm-tui";import{execSync as L}from"node:child_process";import{homedir as c}from"node:os";import{dirname as I,join as Y}from"node:path";var V=!1;var J={info(...n){if(!V)console.log("[dm-cliproxy]",...n)},warn(...n){if(!V)console.warn("[dm-cliproxy]",...n)},error(...n){if(!V)console.error("[dm-cliproxy]",...n)},debug(...n){if(!V&&(process.env.DM_CLIPROXY_DEBUG||process.env.PI_CLIPROXYAPI_DEBUG))console.log("[dm-cliproxy]","[debug]",...n)}};var K=Y(c(),".dm","agent","dm-cliproxy"),_=Y(K,"config.json"),F=[Y(c(),".pi","agent","pi-cliproxyapi","config.json"),Y(c(),".config","pi-cliproxyapi","config.json")];function Q(n){if(!n)return"";let o=n.trim();if(o.startsWith("!"))try{return L(o.slice(1),{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).trim()}catch(r){let s=r?.stderr?.toString?.()?.trim()??r.message;return J.warn(`failed to resolve "!" config value (${o}): ${s}`),""}if(o.startsWith("$"))return process.env[o.slice(1)]??"";return o}import{existsSync as C,readFileSync as E}from"node:fs";import{homedir as X}from"node:os";import{join as k}from"node:path";var A=k(X(),".dm","models.json"),i=k(X(),".dm","auth.json");function W(n){if(!C(n))return null;try{return JSON.parse(E(n,"utf8"))}catch{return null}}function q(n){let o=[],r=new Set([...Object.keys(n.builtinProviders),...Object.keys(n.customProviders)]),s=W(A);if(s&&typeof s==="object"){for(let u of Object.keys(s))if(r.has(u))o.push({kind:"models.json",provider:u,detail:`provider "${u}" has user overrides in ~/.dm/models.json which DM merges on top of our registration`})}let f=W(i);if(f&&typeof f==="object"){for(let u of Object.keys(f))if(r.has(u))o.push({kind:"auth.json",provider:u,detail:`provider "${u}" has user-set credentials in ~/.dm/auth.json which take priority over our apiKey`})}return o}import{dirname as m,join as U}from"node:path";var sn=U(K,"discovery-cache.json");var H="dm-cliproxy/0.3.5";import{visibleWidth as h}from"@duckmind/dm-tui";function p(n,o){let r=h(n);if(r===o)return n;if(r<o)return n+" ".repeat(o-r);return S(n,o)}function S(n,o){if(o<=0)return"\x1B[0m";let r="",s=0,f=0;while(f<n.length){let u=n[f];if(u==="\x1B"&&n[f+1]==="["){let $=n.indexOf("m",f+2);if($>=0){r+=n.slice(f,$+1),f=$+1;continue}}let Z=h(u);if(s+Z>o)break;r+=u,s+=Z,f++}return`${r}\x1B[0m`}import{visibleWidth as cn}from"@duckmind/dm-tui";function R(n,o,r){let s=n.slice(o,o+r);while(s.length<r)s.push("");return s}function y(n,o,r){let s=Math.max(0,r-o);return Math.max(0,Math.min(n,s))}function Hn(n){let{theme:o,cfg:r}=n,s=0,f=()=>{let $=n.getDiscovery(),e=(D)=>o.fg("success",D),M=(D)=>o.fg("error",D),t=(D)=>o.fg("dim",D),j=[];j.push(`${t("endpoint")} ${r.proxy.endpoint||M("(unset)")}`),j.push(`${t("apiKey")} ${Q(r.proxy.apiKey)?e("resolves"):M("empty after resolution")}`),j.push(`${t("usageKey")} ${r.proxy.usageKey?Q(r.proxy.usageKey)?e("resolves"):M("set but empty"):t("not configured")}`),j.push(`${t("user-agent")} ${H}`),j.push(""),j.push(`${t("discovery")} source=${$.source}`),j.push(`${t("upstream")} v=${$.upstreamVersion??"(unknown)"} · ${$.upstreamTotal} ids`);let O=$.builtinProviders.map((D)=>`${D.name}=${D.models.length}`).join(", ")||t("(none)");j.push(`${t("built-in")} ${O}`),j.push(`${t("custom pool")} ${$.customPool.length} models`);let z=q(r);if(j.push(""),z.length===0)j.push(`${t("conflicts")} ${e("none")}`);else{j.push(`${t("conflicts")}`);for(let D of z)j.push(` ${o.fg("warning",`[${D.kind}]`)} ${D.detail}`)}return j};return{id:"diagnostics",label:"Diagnostics",render:($,e)=>{let M=f();return s=y(s,e,M.length),R(M,s,e).map((t)=>p(` ${t}`,$))},handleInput:($)=>{let e=f().length;if(v($,"up")||v($,"k"))return s=Math.max(0,s-1),!0;if(v($,"down")||v($,"j"))return s=Math.min(Math.max(0,e-1),s+1),!0;if(v($,"pageUp")||v($,"b"))return s=Math.max(0,s-10),!0;if(v($,"pageDown")||v($,"f"))return s=Math.min(Math.max(0,e-1),s+10),!0;return!1},footerHint:()=>" ↑↓ scroll · r refresh discovery "}}export{Hn as buildDiagnosticsView};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{matchesKey as D}from"@duckmind/dm-tui";function $0($){let q=new Map,J=new Map;for(let z of $.builtinProviders){let j=[];for(let Y of z.models)q.set(Y.id,{id:Y.id,name:Y.name,suggestedApi:z.api,subtitle:Y.name&&Y.name!==Y.id?Y.name:void 0,ownedBy:z.name,reasoning:Y.reasoning,contextWindow:Y.contextWindow,maxTokens:Y.maxTokens,cost:Y.cost}),j.push(Y.id);J.set(z.name,j)}let Q=[];for(let z of $.customPool){if(!q.has(z.id))q.set(z.id,{id:z.id,name:z.name,suggestedApi:z.api,subtitle:z.name&&z.name!==z.id?z.name:void 0,origin:z.suggestedProvider,ownedBy:z.ownedBy,reasoning:z.reasoning,contextWindow:z.contextWindow,maxTokens:z.maxTokens,cost:z.cost});Q.push(z.id)}return{byId:q,builtinModelIds:J,customPoolIds:Q}}function i0($){let q=new Map;for(let[J,Q]of Object.entries($.customProviders))for(let z of Q.models)q.set(z.id,J);return q}function b($,q){if(q.kind==="builtin")return[...$.builtinProviders[q.name]?.models??[]];return $.customProviders[q.name]?.models.map((J)=>J.id)??[]}function K0($,q,J){if(q.kind==="builtin"){let j=J.builtinModelIds.get(q.name)??[],Y=new Set(b($,q));return j.filter((V)=>!Y.has(V))}let Q=i0($),z=new Set(b($,q));return J.customPoolIds.filter((j)=>{if(z.has(j))return!1;let Y=Q.get(j);return Y===void 0||Y===q.name})}function r0($){return{id:$.id,name:$.name,contextWindow:$.contextWindow,maxTokens:$.maxTokens,reasoning:$.reasoning,cost:$.cost}}function B0($,q,J){if(q.kind==="builtin"){let z=$.builtinProviders[q.name]??{enabled:!0,models:[]},j=new Set(z.models);j.add(J.id),$.builtinProviders[q.name]={enabled:!0,apiOverride:z.apiOverride??null,models:Array.from(j).sort()};return}for(let[z,j]of Object.entries($.customProviders)){if(z===q.name)continue;let Y=j.models.findIndex((V)=>V.id===J.id);if(Y>=0)j.models.splice(Y,1)}let Q=$.customProviders[q.name]??{api:q.api,models:[]};if(!Q.models.some((z)=>z.id===J.id))Q.models.push(r0(J));$.customProviders[q.name]=Q}function H0($,q,J){if(q.kind==="builtin"){let z=$.builtinProviders[q.name];if(!z)return;z.models=z.models.filter((j)=>j!==J),z.enabled=z.models.length>0;return}let Q=$.customProviders[q.name];if(!Q)return;Q.models=Q.models.filter((z)=>z.id!==J)}function z0($,q){if($===q)return!0;let J=["openai-completions","openai-responses"];if(J.includes($)&&J.includes(q))return!0;return!1}function P0($,q){let J=new Map;for(let Q of $){let z=q.byId.get(Q),j=z?.ownedBy||z?.origin||"misc",Y=J.get(j)??[];Y.push(Q),J.set(j,Y)}return Array.from(J.entries()).sort((Q,z)=>Q[0].localeCompare(z[0])).map(([Q,z])=>({label:Q,ids:z}))}function k0($,q,J){let Q=J.trim().toLowerCase();if(!Q)return $;return $.filter((z)=>{if(z.toLowerCase().includes(Q))return!0;let j=q.byId.get(z)?.name;return j?j.toLowerCase().includes(Q):!1})}import{getModels as t0,getProviders as o0}from"@duckmind/dm-ai/compat";function q0($,q){let J=[],Q=new Set(q.builtinModelIds.keys()),z=new Set(o0()),j=new Set([...Q,...z]);for(let Y of Array.from(j).sort()){let V=q.builtinModelIds.get(Y);if(!V||V.length===0)continue;let X;try{let R=t0(Y).find((E)=>V.includes(E.id));if(R)X=R.api}catch{}if(!X){let G=V[0];X=q.byId.get(G)?.suggestedApi??"openai-responses"}if(J.push({kind:"builtin",name:Y,api:X,subtitle:`built-in · ${X}`}),!$.builtinProviders[Y])$.builtinProviders[Y]={enabled:!1,models:[]}}for(let Y of Object.keys($.customProviders).sort()){let V=$.customProviders[Y];J.push({kind:"custom",name:Y,api:V.api,subtitle:`custom · ${V.api}`})}return J}import{getKeybindings as j$,matchesKey as w}from"@duckmind/dm-tui";import{visibleWidth as Q0}from"@duckmind/dm-tui";import{visibleWidth as F0}from"@duckmind/dm-tui";function A($,q){let J=F0($);if(J===q)return $;if(J<q)return $+" ".repeat(q-J);return J0($,q)}function J0($,q){if(q<=0)return"\x1B[0m";let J="",Q=0,z=0;while(z<$.length){let j=$[z];if(j==="\x1B"&&$[z+1]==="["){let V=$.indexOf("m",z+2);if(V>=0){J+=$.slice(z,V+1),z=V+1;continue}}let Y=F0(j);if(Q+Y>q)break;J+=j,Q+=Y,z++}return`${J}\x1B[0m`}var e0="│",$$="╭",z$="╮",q$="╰",J$="╯",u="─";function p($,q){let J=Math.max(4,q.width);return[Q$($,q.title,q.titleColor??"accent",J),...q.lines.map((Q)=>Y$($,Q,J)),Z$($,q.footer,J)]}function Q$($,q,J,Q){let z=q??"",j=Q0(z),Y=Math.max(0,Q-3-j),V=z?$.bold($.fg(J,z)):"",X=`${$$}${u}${V}${u.repeat(Y)}${z$}`;return $.fg("borderAccent",X)}function Y$($,q,J){let Q=Math.max(0,J-2),z=$.fg("borderAccent",e0);return`${z}${A(q,Q)}${z}`}function Z$($,q,J){let Q=`${q$}${u}`,z=`${J$}`,j=3;if(!q||!q.hint&&!q.badge){let I=Math.max(0,J-3);return $.fg("borderAccent",`${Q}${u.repeat(I)}${z}`)}let Y=q.hint??"",V=q.badge??"",X=Q0(Y),G=Q0(V),R=Math.max(0,J-3-X-G),E=$.fg("dim",Y),k=V?$.fg("muted",V):"",F=u.repeat(R);return`${$.fg("borderAccent",Q)}${E}${$.fg("borderAccent",F)}${k}${$.fg("borderAccent",z)}`}function I0($){return Math.max(0,$-2)}async function W0($,q){return $.ui.custom((J,Q,z,j)=>V$(Q,`Remove custom group “${q}”?`,"All model assignments in this group will be discarded.",j),{overlay:!0,overlayOptions:{width:80,maxHeight:"40%"}})}function V$($,q,J,Q){return{render(z){return p($,{width:z,title:" confirm ",titleColor:"error",lines:["",` ${$.bold(q)}`,` ${$.fg("dim",J)}`,""],footer:{hint:" y / enter = remove · n / esc = cancel "}})},invalidate(){},handleInput(z){if(j$().matches(z,"tui.select.cancel")||w(z,"escape")||w(z,"n")||w(z,"q")){Q(!1);return}if(w(z,"y")||w(z,"enter")||w(z,"return")){Q(!0);return}}}}import{getKeybindings as X$,Input as _$,matchesKey as G$}from"@duckmind/dm-tui";function S0($,q){let J=($??"").trim();return J?`${J}-${q}`:q}async function x0($,q){let J=S0(q,"group");return $.ui.custom((Q,z,j,Y)=>U$(Q,z,J,Y),{overlay:!0,overlayOptions:{width:80,maxHeight:"40%"}})}function U$($,q,J,Q){let z=new _$;if(J)z.setValue(J);z.focused=!0;let j=null;return z.onSubmit=(Y)=>{let V=Y.trim();if(!/^[a-z0-9][a-z0-9._-]*$/i.test(V)){j="letters / digits / dot / dash / underscore only",$.requestRender();return}Q(V)},z.onEscape=()=>Q(null),{render(Y){let V=I0(Y),X=J?`name shown in /model picker, e.g. ${J}`:"letters / digits / dot / dash / underscore",G=z.render(V-4),R=["",` ${q.fg("dim",X)}`,"",...G.map((E)=>` ${q.fg("accent",`❯ ${E}`)}`),"",j?` ${q.fg("error",`! ${j}`)}`:""];return p(q,{width:Y,title:" new custom group ",lines:R,footer:{hint:" enter = create · esc = cancel "}})},invalidate(){z.invalidate()},handleInput(Y){if(X$().matches(Y,"tui.select.cancel")||G$(Y,"escape")){Q(null);return}j=null,z.handleInput(Y),$.requestRender()}}}import{visibleWidth as D$}from"@duckmind/dm-tui";function Y0($,q,J){if(!q)return" ";if(J)return $.fg("accent","▶ ");return $.fg("muted","▸ ")}function L0($,q){let J=D$($);if(J===q)return $;if(J>q)return J0($,q);return A($,q)}function y0($,q,J){let{theme:Q,width:z,isCursor:j,isFocused:Y}=J,V=Y0(Q,j,Y),X=$.kind==="builtin"?q.builtinProviders[$.name]?.models.length??0:q.customProviders[$.name]?.models.length??0,G=$.kind==="builtin"?Q.fg("accent","B"):Q.fg("warning","C"),R=`${Q.fg("dim","[")}${G}${Q.fg("dim","]")}`,E=X>0?Q.fg("success","●"):Q.fg("dim","○"),k=X>0?Q.fg("success",String(X).padStart(2)):Q.fg("dim"," 0"),F=j&&Y?Q.bold(Q.fg("accent",$.name)):j?Q.bold($.name):$.name,I=Q.fg("dim",$.api),T=`${V}${R} ${F} ${E}${k} ${I}`;return L0(T,z)}function b0($,q,J,Q){let z=Y0($,q,J),j=q&&J?$.bold($.fg("accent","+ new custom group…")):$.fg("accent","+ new custom group…");return A(`${z}${j}`,Q)}function Z0($,q,J,Q,z){let{theme:j,width:Y,isCursor:V,isFocused:X}=z,G=Y0(j,V,X),R=J==="assigned"?j.fg("success","☑"):j.fg("dim","☐"),E=Q?` ${j.fg("warning","⚠")}`:"",k=V&&X?j.fg("accent",$):$,F=q?.reasoning?` ${j.fg("accent","✨")}`:"",I=q?j.fg("muted",` · ${q.suggestedApi}`):j.fg("error"," · not on proxy"),T=`${G}${R} ${k}${E}${F}${I}`;return L0(T,Y)}function C0($,q,J){let Q=`${$.fg("borderAccent","──")} ${$.fg("warning",q)} ${$.fg("borderAccent","──")}`;return A(` ${Q}`,J)}function j0($,q,J){return A(` ${$.fg("dim",q)}`,J)}function n0($,q,J,Q){let z=Q?$.bold($.fg("accent","❚ ")):$.fg("dim"," ");return A(`${z}${q}`,J)}import{visibleWidth as l}from"@duckmind/dm-tui";function a($,q,J){let Q=$.slice(q,q+J);while(Q.length<J)Q.push("");return Q}function s($,q,J,Q,z,j){if(z<=Q)return 0;let Y=Math.max(0,z-Q);if(q<j)return 0;let V=Math.max(0,Math.min(J,Y)),X=V+j;if($<X)V=Math.max(0,$-j);let G=V+Q-1;if(q>G)V=Math.min(Y,q-(Q-1));return V}function a$($){let{tui:q,theme:J,ctx:Q,cfg:z}=$,j=$.onChange??(()=>{}),Y=$0($.getDiscovery()),V=q0(z,Y),X="providers",G=0,R=0,E=0,k=0,F=0,I=0,T="",C=!1,v=()=>{if(V.length===0)return null;let Z=Math.max(0,Math.min(G,V.length-1));return V[Z]??null},V0=(Z)=>{let _=k0(K0(z,Z,Y),Y,T);return P0(_,Y)},d=(Z)=>V0(Z).flatMap((_)=>_.ids),f=()=>{V=q0(z,Y);let Z=Math.max(0,V.length);if(G>Z)G=Z;let _=v();if(_){let M=b(z,_).length,U=d(_).length;if(R>=M)R=Math.max(0,M-1);if(E>=U)E=Math.max(0,U-1)}},w0=()=>{Y=$0($.getDiscovery()),f()},X0=(Z)=>{let _=["providers","assigned","pool"],M=_.indexOf(X);X=Z?_[(M-1+_.length)%_.length]:_[(M+1)%_.length]},m=(Z)=>{if(X==="providers"){let U=V.length+1;G=Math.max(0,Math.min(G+Z,U-1));return}let _=v();if(!_)return;if(X==="assigned"){let U=b(z,_).length;if(U===0)return;R=Math.max(0,Math.min(R+Z,U-1));return}let M=d(_).length;if(M===0)return;E=Math.max(0,Math.min(E+Z,M-1))},v0=async()=>{if(X==="providers"){if(G===V.length){let U=await x0(Q,z.proxy.providerPrefix);if(U&&!z.customProviders[U]){if(z.customProviders[U]={api:"openai-completions",models:[]},j(),f(),G=V.findIndex((O)=>O.kind==="custom"&&O.name===U),G<0)G=V.length-1;X="pool"}q.requestRender();return}X="pool";return}let Z=v();if(!Z)return;if(X==="assigned"){let U=b(z,Z)[R];if(!U)return;H0(z,Z,U),j(),f();return}let _=d(Z)[E];if(!_)return;let M=Y.byId.get(_);if(!M)return;B0(z,Z,M),j(),f()},f0=async()=>{if(X!=="providers")return;let Z=v();if(!Z||Z.kind!=="custom")return;if(!await W0(Q,Z.name)){q.requestRender();return}if(delete z.customProviders[Z.name],j(),f(),G>=V.length)G=Math.max(0,V.length-1);q.requestRender()},g0=(Z,_)=>u0(Z,_);function u0(Z,_){let M=Math.max(70,Z),U=Math.min(56,Math.max(34,Math.floor(M*0.4))),O=M-U-1,W=Math.max(8,_),S=Math.max(5,Math.floor((W-1)/2)),G0=W-S,P=v(),g=0,i=0,r=0,U0=0,t=0,D0=0,L=[];L.push(_0(" providers ",U,X==="providers"));for(let N=0;N<V.length;N++){let B=V[N],K=X==="providers"&&N===G;if(K)g=L.length,i=g;L.push(y0(B,z,{theme:J,width:U,isCursor:K,isFocused:X==="providers"}))}{let N=X==="providers"&&G===V.length;if(N)g=L.length,i=g;L.push(b0(J,N,X==="providers",U))}let y=[],p0=P?`assigned to ${J.bold(P.name)} ${J.fg("dim",`· ${P.api}`)}`:J.fg("dim","no provider selected");if(y.push(_0(" assigned ",O,X==="assigned")),y.push(n0(J,p0,O,X==="assigned")),P){let N=b(z,P);if(N.length===0)y.push(j0(J,"(nothing assigned yet)",O));for(let B=0;B<N.length;B++){let K=N[B],H=Y.byId.get(K),c=X==="assigned"&&B===R;if(c)r=y.length,U0=r;let n=H?!z0(P.api,H.suggestedApi):!1;y.push(Z0(K,H,"assigned",n,{theme:J,width:O,isCursor:c,isFocused:X==="assigned"}))}}let x=[];if(x.push(m0(O,X==="pool")),P){let N=V0(P);if(N.reduce((K,H)=>K+H.ids.length,0)===0)x.push(j0(J,T?`(no matches for "${T}")`:"(no models available)",O));else{let K=0;for(let H of N){let c=x.length;x.push(C0(J,H.label,O));for(let n=0;n<H.ids.length;n++){let A0=H.ids[n],e=Y.byId.get(A0),T0=X==="pool"&&K===E;if(T0)t=x.length,D0=n===0?c:t;let d0=e?!z0(P.api,e.suggestedApi):!1;x.push(Z0(A0,e,"pool",d0,{theme:J,width:O,isCursor:T0,isFocused:X==="pool"})),K++}}}}let l0=Math.max(1,G0-1),N0=s(i,g,k,W,L.length,1),O0=s(X==="assigned"?U0:0,X==="assigned"?r:0,F,S,y.length,2),E0=s(X==="pool"?D0:0,X==="pool"?t:0,I,l0,x.length,1);k=N0,F=O0,I=E0;let R0=a(L,N0,W),a0=a(y,O0,S),s0=a(x,E0,G0),M0=J.fg("borderAccent","│"),o=[];for(let N=0;N<W;N++){let B=A(R0[N]??"",U),K=N<S?a0[N]:s0[N-S],H=A(K,O);o.push(`${B}${M0}${H}`)}let h=S;if(h>0&&h<W){let N=A(R0[h]??"",U),B=J.fg("borderAccent","─".repeat(O));o[h]=`${N}${M0}${B}`}return o}function _0(Z,_,M){let U=M?J.bold(J.fg("accent",Z)):J.fg("muted",Z),O=J.fg("borderAccent","─".repeat(Math.max(0,_-l(Z)-1)));return A(`${U}${O}`,_)}function m0(Z,_){let U=_?J.bold(J.fg("accent"," available pool ")):J.fg("muted"," available pool "),O="";if(C)O=`${J.fg("dim"," /")}${J.fg("accent",T)}${J.fg("accent","█")} `;else if(T)O=`${J.fg("dim"," /")}${J.fg("warning",T)} `;let W=l(" available pool ")+l(O),S=J.fg("borderAccent","─".repeat(Math.max(0,Z-W-1)));return A(`${U}${O}${S}`,Z)}function h0(Z){if(C){if(D(Z,"escape"))return T="",C=!1,E=0,!0;if(D(Z,"enter")||D(Z,"return"))return C=!1,!0;if(D(Z,"backspace")||D(Z,"delete"))return T=T.slice(0,-1),E=0,!0;if(Z.length===1&&Z>=" "&&Z!=="")return T+=Z,E=0,!0;return!0}if(D(Z,"tab"))return X0(!1),!0;if(D(Z,"shift+tab"))return X0(!0),!0;if(D(Z,"/"))return X="pool",C=!0,!0;if(D(Z,"enter")||D(Z,"return")||D(Z,"space"))return v0().then(()=>!0);if(X==="providers"&&(D(Z,"d")||D(Z,"delete")||D(Z,"backspace")))return f0().then(()=>!0);if(D(Z,"up")||D(Z,"k"))return m(-1),!0;if(D(Z,"down")||D(Z,"j"))return m(1),!0;if(D(Z,"pageUp")||D(Z,"b"))return m(-8),!0;if(D(Z,"pageDown")||D(Z,"f"))return m(8),!0;if(D(Z,"left")||D(Z,"h"))return X="providers",!0;if(D(Z,"right")||D(Z,"l")){if(X==="providers")X="assigned";else if(X==="assigned")X="pool";return!0}return!1}function c0(){if(C)return" type to filter · ↵ apply · esc clear ";return" tab ↔ panel · ↑↓ nav · ↵ move · / filter · d remove group "}return{id:"models",label:"Models",render:g0,handleInput:h0,footerHint:c0,rebuild:w0}}export{a$ as buildModelsView};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{matchesKey as q}from"@duckmind/dm-tui";import{execSync as p}from"node:child_process";import{homedir as G}from"node:os";import{dirname as Y0,join as L}from"node:path";var D=!1;var W={info(...J){if(!D)console.log("[dm-cliproxy]",...J)},warn(...J){if(!D)console.warn("[dm-cliproxy]",...J)},error(...J){if(!D)console.error("[dm-cliproxy]",...J)},debug(...J){if(!D&&(process.env.DM_CLIPROXY_DEBUG||process.env.PI_CLIPROXYAPI_DEBUG))console.log("[dm-cliproxy]","[debug]",...J)}};var k=L(G(),".dm","agent","dm-cliproxy"),$0=L(k,"config.json"),X0=[L(G(),".pi","agent","pi-cliproxyapi","config.json"),L(G(),".config","pi-cliproxyapi","config.json")];function S(J){if(!J)return"";let Q=J.trim();if(Q.startsWith("!"))try{return p(Q.slice(1),{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).trim()}catch(V){let Z=V?.stderr?.toString?.()?.trim()??V.message;return W.warn(`failed to resolve "!" config value (${Q}): ${Z}`),""}if(Q.startsWith("$"))return process.env[Q.slice(1)]??"";return Q}import{dirname as q0,join as C}from"node:path";var R0=C(k,"discovery-cache.json");var n="dm-cliproxy/0.3.5";var h=15000,H=null;function O(){H=null}async function T(J,Q,V={}){if(!V.force&&H&&Date.now()-H.fetchedAt<J.usageCacheTtlMs)return H.doc;if(!Q)throw Error("usage key not configured; set proxy.usageKey in config and rerun");let Z=new URL("/api/usage",new URL(J.proxy.endpoint).origin).toString(),$=new AbortController,j=setTimeout(()=>$.abort(Error("timeout")),h),z;try{z=await fetch(Z,{headers:{"X-Plugin-Key":Q,Accept:"application/json","User-Agent":n},signal:$.signal})}finally{clearTimeout(j)}if(!z.ok)throw Error(`/api/usage returned ${z.status}`);let X=await z.json();if(!X||X.schemaVersion!==1||!Array.isArray(X.accounts))throw Error("/api/usage returned unexpected payload shape");return H={fetchedAt:Date.now(),doc:X},W.debug("usage fetched, accounts:",X.accounts.length),X}import{visibleWidth as F}from"@duckmind/dm-tui";function K(J,Q){let V=F(J);if(V===Q)return J;if(V<Q)return J+" ".repeat(Q-V);return f(J,Q)}function f(J,Q){if(Q<=0)return"\x1B[0m";let V="",Z=0,$=0;while($<J.length){let j=J[$];if(j==="\x1B"&&J[$+1]==="["){let X=J.indexOf("m",$+2);if(X>=0){V+=J.slice($,X+1),$=X+1;continue}}let z=F(j);if(Z+z>Q)break;V+=j,Z+=z,$++}return`${V}\x1B[0m`}var Y={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",accent:"\x1B[38;5;111m",muted:"\x1B[38;5;245m",dim2:"\x1B[38;5;240m",green:"\x1B[38;5;114m",yellow:"\x1B[38;5;179m",red:"\x1B[38;5;167m",greenBg:"\x1B[48;5;22m",yellowBg:"\x1B[48;5;94m",redBg:"\x1B[48;5;52m"};function w(J,Q={}){let V=[],Z=new Map,$=0;for(let j of J.accounts){if(!Q.showDisabled&&j.disabled){$++;continue}let z=Z.get(j.provider)??[];z.push(j),Z.set(j.provider,z)}if(V.push(`${Y.dim}generated ${J.generatedAt}${Y.reset}`),J.unsupportedProviders.length>0)V.push(`${Y.dim}providers without quota lookup:${Y.reset} ${J.unsupportedProviders.join(", ")}`);if($>0)V.push(`${Y.dim}hidden disabled accounts:${Y.reset} ${$} ${Y.dim2}(press d to show)${Y.reset}`);for(let[j,z]of Array.from(Z.entries()).sort()){V.push(""),V.push(`${Y.bold}${Y.accent}▌ ${j}${Y.reset}`);for(let X of z){if(V.push(r(X)),!X.supported){V.push(` ${Y.dim2}(provider not quota-aware)${Y.reset}`);continue}if(X.error){if(Q.verbose)for(let A of c(X.error,88))V.push(` ${Y.red}${A}${Y.reset}`);continue}let R=X.groups??[];if(R.length===0){V.push(` ${Y.dim2}(no active quota windows)${Y.reset}`);continue}for(let A of R)V.push(o(A))}}return V.push(""),V.push(`${Y.dim}legend:${Y.reset} ${I} ok ${_} error/unavailable ${N} disabled ${Y.green}✓N${Y.reset}/${Y.red}✗N${Y.reset} request counters ${Y.dim}v = verbose, d = show disabled${Y.reset}`),V}function c(J,Q){if(J.length<=Q)return[J];let V=[],Z=J;while(Z.length>Q){let $=Z.lastIndexOf(" ",Q);if($<Q*0.6)$=Q;V.push(Z.slice(0,$)),Z=Z.slice($).replace(/^\s+/,"")}if(Z)V.push(Z);return V}function r(J){let Q=l(J),V=`${Y.green}✓${J.success}${Y.reset} ${Y.red}✗${J.failed}${Y.reset}`,Z=b(J.label,36);return` ${Q} ${Y.bold}${Z}${Y.reset} ${V}`}var I=`${Y.green}●${Y.reset}`,_=`${Y.yellow}⚠${Y.reset}`,N=`${Y.dim2}⊘${Y.reset}`;function l(J){if(J.disabled)return N;if(J.unavailable||J.error||J.status&&J.status!=="active")return _;return I}function o(J){let Q=P(J.remainingFraction),V=Math.round(Q*100),Z=i(Q),$=J.resetTime?` ${Y.dim}reset ${m(J.resetTime)}${Y.reset}`:"",j=b(J.label,28).padEnd(28," ");return` ${Z} ${d(V,Q)} ${j}${$}`}function i(J){let Q=P(J),V=Math.round(Q*18),Z=x(Q),$=Y.dim2,j="█".repeat(V),z="░".repeat(18-V);return`${$}[${Z}${j}${$}${z}]${Y.reset}`}function d(J,Q){return`${x(Q)}${String(J).padStart(3)}%${Y.reset}`}function x(J){if(J>=0.4)return Y.green;if(J>=0.15)return Y.yellow;return Y.red}function m(J){let Q=Date.parse(J);if(!Number.isFinite(Q))return J;let V=Q-Date.now();if(V<=0)return"now";let Z=Math.round(V/60000);if(Z<60)return`${Z}m`;let $=Math.round(Z/60);if($<48)return`${$}h`;return`${Math.round($/24)}d`}function P(J){return Math.max(0,Math.min(1,J))}function b(J,Q){if(J.length<=Q)return J;return`${J.slice(0,Q-1)}…`}import{visibleWidth as N0}from"@duckmind/dm-tui";function u(J,Q,V){let Z=J.slice(Q,Q+V);while(Z.length<V)Z.push("");return Z}function y(J,Q,V){let Z=Math.max(0,V-Q);return Math.max(0,Math.min(J,Z))}function h0(J){let{tui:Q,theme:V,cfg:Z}=J,$="idle",j=null,z="",X=0,R=!1,A=!1,B=(M)=>{$="loading",Q.requestRender();let E=S(Z.proxy.usageKey);T(Z,E,{force:M}).then((U)=>{j=U,$="ready",X=0,Q.requestRender()}).catch((U)=>{z=U.message,$="error",Q.requestRender()})},v=()=>{if($==="idle"||$==="loading")return[V.fg("dim"," loading usage…")];if($==="error")return[V.fg("error",` usage failed: ${z}`)];if(!j)return[V.fg("dim"," (no data)")];return w(j,{showDisabled:R,verbose:A})};return{id:"usage",label:"Usage",render:(M,E)=>{let U=v();return X=y(X,E,U.length),u(U,X,E).map((g)=>K(` ${g}`,M))},handleInput:(M)=>{if(q(M,"d"))return R=!R,X=0,!0;if(q(M,"v"))return A=!A,X=0,!0;let E=v().length;if(q(M,"up")||q(M,"k"))return X=Math.max(0,X-1),!0;if(q(M,"down")||q(M,"j"))return X=Math.min(Math.max(0,E-1),X+1),!0;if(q(M,"pageUp")||q(M,"b"))return X=Math.max(0,X-10),!0;if(q(M,"pageDown")||q(M,"f"))return X=Math.min(Math.max(0,E-1),X+10),!0;if(q(M,"home")||q(M,"g"))return X=0,!0;if(q(M,"end")||q(M,"shift+g"))return X=Math.max(0,E-1),!0;return!1},footerHint:()=>{let M=R?V.fg("success","[d disabled]"):"d disabled",E=A?V.fg("success","[v verbose]"):"v verbose";return` ↑↓ scroll · ${M} · ${E} `},onActivate:()=>{if($==="idle")B(!1)},reload:()=>{if(O(),$!=="idle")B(!0)}}}export{h0 as buildUsageView};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function B(q){let k=new Map,x=new Map;for(let g of q.builtinProviders){let A=[];for(let j of g.models)k.set(j.id,{id:j.id,name:j.name,suggestedApi:g.api,subtitle:j.name&&j.name!==j.id?j.name:void 0,ownedBy:g.name,reasoning:j.reasoning,contextWindow:j.contextWindow,maxTokens:j.maxTokens,cost:j.cost}),A.push(j.id);x.set(g.name,A)}let z=[];for(let g of q.customPool){if(!k.has(g.id))k.set(g.id,{id:g.id,name:g.name,suggestedApi:g.api,subtitle:g.name&&g.name!==g.id?g.name:void 0,origin:g.suggestedProvider,ownedBy:g.ownedBy,reasoning:g.reasoning,contextWindow:g.contextWindow,maxTokens:g.maxTokens,cost:g.cost});z.push(g.id)}return{byId:k,builtinModelIds:x,customPoolIds:z}}export{B as buildCatalog};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function N(j){let z=new Map;for(let[D,G]of Object.entries(j.customProviders))for(let C of G.models)z.set(C.id,D);return z}function L(j,z){if(z.kind==="builtin")return[...j.builtinProviders[z.name]?.models??[]];return j.customProviders[z.name]?.models.map((D)=>D.id)??[]}function Q(j,z,D){if(z.kind==="builtin"){let H=D.builtinModelIds.get(z.name)??[],J=new Set(L(j,z));return H.filter((K)=>!J.has(K))}let G=N(j),C=new Set(L(j,z));return D.customPoolIds.filter((H)=>{if(C.has(H))return!1;let J=G.get(H);return J===void 0||J===z.name})}function V(j){return{id:j.id,name:j.name,contextWindow:j.contextWindow,maxTokens:j.maxTokens,reasoning:j.reasoning,cost:j.cost}}function Y(j,z,D){if(z.kind==="builtin"){let C=j.builtinProviders[z.name]??{enabled:!0,models:[]},H=new Set(C.models);H.add(D.id),j.builtinProviders[z.name]={enabled:!0,apiOverride:C.apiOverride??null,models:Array.from(H).sort()};return}for(let[C,H]of Object.entries(j.customProviders)){if(C===z.name)continue;let J=H.models.findIndex((K)=>K.id===D.id);if(J>=0)H.models.splice(J,1)}let G=j.customProviders[z.name]??{api:z.api,models:[]};if(!G.models.some((C)=>C.id===D.id))G.models.push(V(D));j.customProviders[z.name]=G}function Z(j,z,D){if(z.kind==="builtin"){let C=j.builtinProviders[z.name];if(!C)return;C.models=C.models.filter((H)=>H!==D),C.enabled=C.models.length>0;return}let G=j.customProviders[z.name];if(!G)return;G.models=G.models.filter((C)=>C.id!==D)}function _(j,z){if(j===z)return!0;let D=["openai-completions","openai-responses"];if(D.includes(j)&&D.includes(z))return!0;return!1}function W(j,z){let D=new Map;for(let G of j){let C=z.byId.get(G),H=C?.ownedBy||C?.origin||"misc",J=D.get(H)??[];J.push(G),D.set(H,J)}return Array.from(D.entries()).sort((G,C)=>G[0].localeCompare(C[0])).map(([G,C])=>({label:G,ids:C}))}function X(j,z,D){let G=D.trim().toLowerCase();if(!G)return j;return j.filter((C)=>{if(C.toLowerCase().includes(G))return!0;let H=z.byId.get(C)?.name;return H?H.toLowerCase().includes(G):!1})}function $(j,z,D,G=""){let C=X(Q(j,z,D),D,G);return W(C,D).flatMap((H)=>H.ids)}export{Q as poolFor,$ as poolDisplayOrder,W as groupPoolByOwnedBy,X as filterModelIds,Z as detachModel,N as claimedBy,Y as attachModel,L as assignedIdsFor,_ as apiCompatible};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{getKeybindings as Z,matchesKey as v}from"@duckmind/dm-tui";import{visibleWidth as $}from"@duckmind/dm-tui";import{visibleWidth as p}from"@duckmind/dm-tui";function K(n,u){let y=p(n);if(y===u)return n;if(y<u)return n+" ".repeat(u-y);return z(n,u)}function z(n,u){if(u<=0)return"\x1B[0m";let y="",g=0,r=0;while(r<n.length){let m=n[r];if(m==="\x1B"&&n[r+1]==="["){let C=n.indexOf("m",r+2);if(C>=0){y+=n.slice(r,C+1),r=C+1;continue}}let x=p(m);if(g+x>u)break;y+=m,g+=x,r++}return`${y}\x1B[0m`}var F="│",I="╭",J="╮",M="╰",Q="╯",c="─";function _(n,u){let y=Math.max(4,u.width);return[T(n,u.title,u.titleColor??"accent",y),...u.lines.map((g)=>X(n,g,y)),Y(n,u.footer,y)]}function T(n,u,y,g){let r=u??"",m=$(r),x=Math.max(0,g-3-m),C=r?n.bold(n.fg(y,r)):"",P=`${I}${c}${C}${c.repeat(x)}${J}`;return n.fg("borderAccent",P)}function X(n,u,y){let g=Math.max(0,y-2),r=n.fg("borderAccent",F);return`${r}${K(u,g)}${r}`}function Y(n,u,y){let g=`${M}${c}`,r=`${Q}`,m=3;if(!u||!u.hint&&!u.badge){let j=Math.max(0,y-3);return n.fg("borderAccent",`${g}${c.repeat(j)}${r}`)}let x=u.hint??"",C=u.badge??"",P=$(x),k=$(C),q=Math.max(0,y-3-P-k),E=n.fg("dim",x),O=C?n.fg("muted",C):"",f=c.repeat(q);return`${n.fg("borderAccent",g)}${E}${n.fg("borderAccent",f)}${O}${n.fg("borderAccent",r)}`}async function V(n,u){return n.ui.custom((y,g,r,m)=>o(g,`Remove custom group “${u}”?`,"All model assignments in this group will be discarded.",m),{overlay:!0,overlayOptions:{width:80,maxHeight:"40%"}})}function o(n,u,y,g){return{render(r){return _(n,{width:r,title:" confirm ",titleColor:"error",lines:["",` ${n.bold(u)}`,` ${n.fg("dim",y)}`,""],footer:{hint:" y / enter = remove · n / esc = cancel "}})},invalidate(){},handleInput(r){if(Z().matches(r,"tui.select.cancel")||v(r,"escape")||v(r,"n")||v(r,"q")){g(!1);return}if(v(r,"y")||v(r,"enter")||v(r,"return")){g(!0);return}}}}export{V as confirmRemoveProvider};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{getKeybindings as _,Input as D,matchesKey as E}from"@duckmind/dm-tui";function Q(n,u){let c=(n??"").trim();return c?`${c}-${u}`:u}import{visibleWidth as J}from"@duckmind/dm-tui";import{visibleWidth as Y}from"@duckmind/dm-tui";function Z(n,u){let c=Y(n);if(c===u)return n;if(c<u)return n+" ".repeat(u-c);return a(n,u)}function a(n,u){if(u<=0)return"\x1B[0m";let c="",q=0,$=0;while($<n.length){let k=n[$];if(k==="\x1B"&&n[$+1]==="["){let y=n.indexOf("m",$+2);if(y>=0){c+=n.slice($,y+1),$=y+1;continue}}let r=Y(k);if(q+r>u)break;c+=k,q+=r,$++}return`${c}\x1B[0m`}var X="│",F="╭",H="╮",L="╰",N="╯",K="─";function l(n,u){let c=Math.max(4,u.width);return[G(n,u.title,u.titleColor??"accent",c),...u.lines.map((q)=>O(n,q,c)),P(n,u.footer,c)]}function G(n,u,c,q){let $=u??"",k=J($),r=Math.max(0,q-3-k),y=$?n.bold(n.fg(c,$)):"",z=`${F}${K}${y}${K.repeat(r)}${H}`;return n.fg("borderAccent",z)}function O(n,u,c){let q=Math.max(0,c-2),$=n.fg("borderAccent",X);return`${$}${Z(u,q)}${$}`}function P(n,u,c){let q=`${L}${K}`,$=`${N}`,k=3;if(!u||!u.hint&&!u.badge){let V=Math.max(0,c-3);return n.fg("borderAccent",`${q}${K.repeat(V)}${$}`)}let r=u.hint??"",y=u.badge??"",z=J(r),g=J(y),j=Math.max(0,c-3-z-g),I=n.fg("dim",r),v=y?n.fg("muted",y):"",M=K.repeat(j);return`${n.fg("borderAccent",q)}${I}${n.fg("borderAccent",M)}${v}${n.fg("borderAccent",$)}`}function C(n){return Math.max(0,n-2)}async function p(n,u){let c=Q(u,"group");return n.ui.custom((q,$,k,r)=>U(q,$,c,r),{overlay:!0,overlayOptions:{width:80,maxHeight:"40%"}})}function U(n,u,c,q){let $=new D;if(c)$.setValue(c);$.focused=!0;let k=null;return $.onSubmit=(r)=>{let y=r.trim();if(!/^[a-z0-9][a-z0-9._-]*$/i.test(y)){k="letters / digits / dot / dash / underscore only",n.requestRender();return}q(y)},$.onEscape=()=>q(null),{render(r){let y=C(r),z=c?`name shown in /model picker, e.g. ${c}`:"letters / digits / dot / dash / underscore",g=$.render(y-4),j=["",` ${u.fg("dim",z)}`,"",...g.map((I)=>` ${u.fg("accent",`❯ ${I}`)}`),"",k?` ${u.fg("error",`! ${k}`)}`:""];return l(u,{width:r,title:" new custom group ",lines:j,footer:{hint:" enter = create · esc = cancel "}})},invalidate(){$.invalidate()},handleInput(r){if(_().matches(r,"tui.select.cancel")||E(r,"escape")){q(null);return}k=null,$.handleInput(r),n.requestRender()}}}export{p as promptNewProviderName};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{getModels as L,getProviders as O}from"@duckmind/dm-ai/compat";function R(B,C){let D=[],G=new Set(C.builtinModelIds.keys()),H=new Set(O()),J=new Set([...G,...H]);for(let j of Array.from(J).sort()){let q=C.builtinModelIds.get(j);if(!q||q.length===0)continue;let z;try{let F=L(j).find((K)=>q.includes(K.id));if(F)z=F.api}catch{}if(!z){let E=q[0];z=C.byId.get(E)?.suggestedApi??"openai-responses"}if(D.push({kind:"builtin",name:j,api:z,subtitle:`built-in · ${z}`}),!B.builtinProviders[j])B.builtinProviders[j]={enabled:!1,models:[]}}for(let j of Object.keys(B.customProviders).sort()){let q=B.customProviders[j];D.push({kind:"custom",name:j,api:q.api,subtitle:`custom · ${q.api}`})}return D}export{R as collectProviders};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{visibleWidth as F}from"@duckmind/dm-tui";function K(j,q){let x=F(j);if(x===q)return j;if(x<q)return j+" ".repeat(q-x);return H(j,q)}function H(j,q){if(q<=0)return"\x1B[0m";let x="",D=0,y=0;while(y<j.length){let z=j[y];if(z==="\x1B"&&j[y+1]==="["){let B=j.indexOf("m",y+2);if(B>=0){x+=j.slice(y,B+1),y=B+1;continue}}let E=F(z);if(D+E>q)break;x+=z,D+=E,y++}return`${x}\x1B[0m`}export{H as truncateAnsi,K as pad};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{visibleWidth as I}from"@duckmind/dm-tui";import{visibleWidth as D}from"@duckmind/dm-tui";function Q(j,q){let z=D(j);if(z===q)return j;if(z<q)return j+" ".repeat(q-z);return y(j,q)}function y(j,q){if(q<=0)return"\x1B[0m";let z="",E=0,J=0;while(J<j.length){let H=j[J];if(H==="\x1B"&&j[J+1]==="["){let K=j.indexOf("m",J+2);if(K>=0){z+=j.slice(J,K+1),J=K+1;continue}}let O=D(H);if(E+O>q)break;z+=H,E+=O,J++}return`${z}\x1B[0m`}function B(j,q,z){if(!q)return" ";if(z)return j.fg("accent","▶ ");return j.fg("muted","▸ ")}function G(j,q){let z=I(j);if(z===q)return j;if(z>q)return y(j,q);return Q(j,q)}function A(j,q,z){let{theme:E,width:J,isCursor:H,isFocused:O}=z,K=B(E,H,O),P=j.kind==="builtin"?q.builtinProviders[j.name]?.models.length??0:q.customProviders[j.name]?.models.length??0,U=j.kind==="builtin"?E.fg("accent","B"):E.fg("warning","C"),V=`${E.fg("dim","[")}${U}${E.fg("dim","]")}`,X=P>0?E.fg("success","●"):E.fg("dim","○"),Y=P>0?E.fg("success",String(P).padStart(2)):E.fg("dim"," 0"),Z=H&&O?E.bold(E.fg("accent",j.name)):H?E.bold(j.name):j.name,_=E.fg("dim",j.api),$=`${K}${V} ${Z} ${X}${Y} ${_}`;return G($,J)}function M(j,q,z,E){let J=B(j,q,z),H=q&&z?j.bold(j.fg("accent","+ new custom group…")):j.fg("accent","+ new custom group…");return Q(`${J}${H}`,E)}function S(j,q,z,E,J){let{theme:H,width:O,isCursor:K,isFocused:P}=J,U=B(H,K,P),V=z==="assigned"?H.fg("success","☑"):H.fg("dim","☐"),X=E?` ${H.fg("warning","⚠")}`:"",Y=K&&P?H.fg("accent",j):j,Z=q?.reasoning?` ${H.fg("accent","✨")}`:"",_=q?H.fg("muted",` · ${q.suggestedApi}`):H.fg("error"," · not on proxy"),$=`${U}${V} ${Y}${X}${Z}${_}`;return G($,O)}function W(j,q,z){let E=`${j.fg("borderAccent","──")} ${j.fg("warning",q)} ${j.fg("borderAccent","──")}`;return Q(` ${E}`,z)}function v(j,q,z){return Q(` ${j.fg("dim",q)}`,z)}function f(j,q,z,E){let J=E?j.bold(j.fg("accent","❚ ")):j.fg("dim"," ");return Q(`${J}${q}`,z)}export{W as renderSubheader,A as renderProviderRow,f as renderPanelHeader,M as renderNewProviderRow,S as renderModelRow,v as renderEmpty};
|
|
File without changes
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{existsSync as f}from"node:fs";import{homedir as YJ}from"node:os";import{getKeybindings as $J,Input as zJ,matchesKey as MJ}from"@duckmind/dm-tui";import{execSync as g}from"node:child_process";import{randomUUID as T}from"node:crypto";import{chmodSync as B,constants as w,copyFileSync as A,existsSync as R,linkSync as p,mkdirSync as I,readFileSync as c,rmSync as G,writeFileSync as m}from"node:fs";import{homedir as N}from"node:os";import{dirname as D,join as E}from"node:path";import{fileURLToPath as h}from"node:url";var L=!1;var W={info(...J){if(!L)console.log("[dm-cliproxy]",...J)},warn(...J){if(!L)console.warn("[dm-cliproxy]",...J)},error(...J){if(!L)console.error("[dm-cliproxy]",...J)},debug(...J){if(!L&&(process.env.DM_CLIPROXY_DEBUG||process.env.PI_CLIPROXYAPI_DEBUG))console.log("[dm-cliproxy]","[debug]",...J)}};var l=E(N(),".dm","agent","dm-cliproxy"),q=E(l,"config.json"),d=[E(N(),".pi","agent","pi-cliproxyapi","config.json"),E(N(),".config","pi-cliproxyapi","config.json")];function s(){return R(E(D(h(import.meta.url)),"..",".git"))}function n(J=d,Q=q,X=s()){if(R(Q))return;let Y=(typeof J==="string"?[J]:[...J]).find(($)=>R($));if(!Y)return;let z;try{I(D(Q),{recursive:!0,mode:448}),B(D(Q),448),z=`${Q}.${process.pid}.${T()}.tmp`,A(Y,z,w.COPYFILE_EXCL),B(z,384),p(z,Q),G(z),z=void 0,W.info("legacy config copied to",Q)}catch($){if(z)try{G(z,{force:!0})}catch(K){W.warn("failed to clean temporary config:",K)}W.warn("failed to migrate legacy config:",$)}}var H={proxy:{endpoint:"",apiKey:""},builtinProviders:{},customProviders:{},discoveryExcludes:["*:*"],overrides:{},refreshIntervalMinutes:0,usageCacheTtlMs:30000};function _(){if(n(),!R(q))return W.debug("config not found, using defaults at",q),structuredClone(H);try{let J=JSON.parse(c(q,"utf8"));return o(J)}catch(J){return W.error("failed to read config:",J,"— using defaults"),structuredClone(H)}}function F(J){I(D(q),{recursive:!0,mode:448}),B(D(q),448);let Q=`${q}.${process.pid}.${T()}.tmp`;try{m(Q,JSON.stringify(J,null,2)+`
|
|
2
|
+
`,{encoding:"utf8",flag:"wx",mode:384}),A(Q,q),B(q,384)}finally{G(Q,{force:!0})}W.info("config saved to",q)}function o(J){if(!J||typeof J!=="object")return structuredClone(H);let Q=J,X=structuredClone(H),Z=Q.proxy??{};if(X.proxy.endpoint=typeof Z.endpoint==="string"?Z.endpoint:X.proxy.endpoint,X.proxy.apiKey=typeof Z.apiKey==="string"?Z.apiKey:"",typeof Z.usageKey==="string")X.proxy.usageKey=Z.usageKey;if(typeof Z.providerPrefix==="string"&&Z.providerPrefix.trim())X.proxy.providerPrefix=Z.providerPrefix.trim();if(Q.builtinProviders&&typeof Q.builtinProviders==="object")X.builtinProviders=Q.builtinProviders;if(Q.customProviders&&typeof Q.customProviders==="object")X.customProviders=Q.customProviders;if(Array.isArray(Q.discoveryExcludes))X.discoveryExcludes=Q.discoveryExcludes.filter((Y)=>typeof Y==="string");if(Q.overrides&&typeof Q.overrides==="object")X.overrides=Q.overrides;if(typeof Q.refreshIntervalMinutes==="number")X.refreshIntervalMinutes=Q.refreshIntervalMinutes;if(typeof Q.usageCacheTtlMs==="number")X.usageCacheTtlMs=Q.usageCacheTtlMs;return X}function C(J){if(!J)return"";let Q=J.trim();if(Q.startsWith("!"))try{return g(Q.slice(1),{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).trim()}catch(X){let Z=X?.stderr?.toString?.()?.trim()??X.message;return W.warn(`failed to resolve "!" config value (${Q}): ${Z}`),""}if(Q.startsWith("$"))return process.env[Q.slice(1)]??"";return Q}import{visibleWidth as b}from"@duckmind/dm-tui";import{visibleWidth as S}from"@duckmind/dm-tui";function v(J,Q){let X=S(J);if(X===Q)return J;if(X<Q)return J+" ".repeat(Q-X);return a(J,Q)}function a(J,Q){if(Q<=0)return"\x1B[0m";let X="",Z=0,Y=0;while(Y<J.length){let z=J[Y];if(z==="\x1B"&&J[Y+1]==="["){let K=J.indexOf("m",Y+2);if(K>=0){X+=J.slice(Y,K+1),Y=K+1;continue}}let $=S(z);if(Z+$>Q)break;X+=z,Z+=$,Y++}return`${X}\x1B[0m`}var i="│",r="╭",t="╮",e="╰",JJ="╯",U="─";function x(J,Q){let X=Math.max(4,Q.width);return[QJ(J,Q.title,Q.titleColor??"accent",X),...Q.lines.map((Z)=>XJ(J,Z,X)),ZJ(J,Q.footer,X)]}function QJ(J,Q,X,Z){let Y=Q??"",z=b(Y),$=Math.max(0,Z-3-z),K=Y?J.bold(J.fg(X,Y)):"",M=`${r}${U}${K}${U.repeat($)}${t}`;return J.fg("borderAccent",M)}function XJ(J,Q,X){let Z=Math.max(0,X-2),Y=J.fg("borderAccent",i);return`${Y}${v(Q,Z)}${Y}`}function ZJ(J,Q,X){let Z=`${e}${U}`,Y=`${JJ}`,z=3;if(!Q||!Q.hint&&!Q.badge){let u=Math.max(0,X-3);return J.fg("borderAccent",`${Z}${U.repeat(u)}${Y}`)}let $=Q.hint??"",K=Q.badge??"",M=b($),j=b(K),V=Math.max(0,X-3-M-j),O=J.fg("dim",$),k=K?J.fg("muted",K):"",y=U.repeat(V);return`${J.fg("borderAccent",Z)}${O}${J.fg("borderAccent",y)}${k}${J.fg("borderAccent",Y)}`}function P(J){return Math.max(0,J-2)}var KJ=[{label:"endpoint",hint:"OpenAI-style base URL of your CliProxyAPI deployment, must include /v1",required:!0,validate:(J)=>{try{if(!new URL(J).pathname.endsWith("/v1"))return"must end with /v1";return null}catch{return"not a valid URL"}}},{label:"apiKey",hint:"CliProxyAPI bearer key. Accepts literal, $ENV_VAR, !cmd, or ~/path",required:!0},{label:"providerPrefix",hint:"Prefix for your custom provider names. Suggested groups become <prefix>-glm, <prefix>-gemini, etc. Use any short slug (letters/digits/dashes).",required:!0,validate:(J)=>/^[a-z0-9][a-z0-9-]*$/i.test(J)?null:"letters/digits/dashes only"},{label:"usageKey",hint:"Optional X-Plugin-Key for /api/usage. Leave blank to skip the Usage tab",required:!1}];async function vJ(J){let Q=_(),X=Boolean(Q.proxy.endpoint),Z=Boolean(C(Q.proxy.apiKey));if(X&&Z)return!1;if(!J.hasUI)return!1;return jJ(J,!0)}async function jJ(J,Q=!1){let X=_(),Z={endpoint:X.proxy.endpoint??"",apiKey:X.proxy.apiKey??"",providerPrefix:X.proxy.providerPrefix??"",usageKey:X.proxy.usageKey??""},Y=!1;for(let $ of KJ){let K=Q?Z[$.label]??$.initialValue??"":Z[$.label]??"";if(!Q&&K)continue;let M=await WJ(J,$,K||$.initialValue||"");if(M===void 0){Y=!0;break}let j=M.trim();if(!j){if($.required){J.ui.notify(`${$.label} is required — aborted`,"warning"),Y=!0;break}Z[$.label]="";continue}Z[$.label]=$.label==="providerPrefix"||$.label==="endpoint"?j:qJ(j)}if(Y)return!1;let z={...X};if(z.proxy={...X.proxy,endpoint:Z.endpoint??"",apiKey:Z.apiKey??"",providerPrefix:Z.providerPrefix??""},Z.usageKey)z.proxy.usageKey=Z.usageKey;else delete z.proxy.usageKey;return F(z),J.ui.notify(`saved to ${q}`,"info"),!0}function qJ(J){if(J.startsWith("!")||J.startsWith("$"))return J;if(J.startsWith("~/")){let Q=J.replace(/^~/,YJ());return f(Q)?`!cat ${J}`:J}if(J.startsWith("/"))return f(J)?`!cat ${J}`:J;return J}async function WJ(J,Q,X){return J.ui.custom((Z,Y,z,$)=>VJ(Z,Y,Q,X,$),{overlay:!0,overlayOptions:{width:100,maxHeight:"60%"}})}function VJ(J,Q,X,Z,Y){let z=new zJ;z.setValue(Z),z.focused=!0;let $=null,K=(M)=>{if(!M&&!X.required){Y("");return}if(!M&&X.required){$="required field",J.requestRender();return}if(X.validate){let j=M.trim();if(j&&!j.startsWith("!")&&!j.startsWith("$")){let V=X.validate(j);if(V){$=V,J.requestRender();return}}}Y(M)};return z.onSubmit=K,z.onEscape=()=>Y(void 0),{render(M){let j=P(M),V=z.render(j-4),O=["",` ${Q.fg("dim",X.hint)}`,"",...V.map((k)=>` ${Q.fg("accent",`❯ ${k}`)}`),"",$?` ${Q.fg("error",`! ${$}`)}`:` ${Q.fg("dim","enter = save · esc = cancel")}`];return x(Q,{width:M,title:` setup: ${X.label} `,lines:O,footer:{hint:" enter = save · esc = cancel "}})},invalidate(){z.invalidate()},handleInput(M){if($J().matches(M,"tui.select.cancel")||MJ(M,"escape")){Y(void 0);return}$=null,z.handleInput(M),J.requestRender()}}}export{vJ as runSetupIfNeeded,jJ as runSetup};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var j={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",accent:"\x1B[38;5;111m",muted:"\x1B[38;5;245m",dim2:"\x1B[38;5;240m",green:"\x1B[38;5;114m",yellow:"\x1B[38;5;179m",red:"\x1B[38;5;167m",greenBg:"\x1B[48;5;22m",yellowBg:"\x1B[48;5;94m",redBg:"\x1B[48;5;52m"};function y(k,M={}){let J=[],Q=new Map,U=0;for(let V of k.accounts){if(!M.showDisabled&&V.disabled){U++;continue}let X=Q.get(V.provider)??[];X.push(V),Q.set(V.provider,X)}if(J.push(`${j.dim}generated ${k.generatedAt}${j.reset}`),k.unsupportedProviders.length>0)J.push(`${j.dim}providers without quota lookup:${j.reset} ${k.unsupportedProviders.join(", ")}`);if(U>0)J.push(`${j.dim}hidden disabled accounts:${j.reset} ${U} ${j.dim2}(press d to show)${j.reset}`);for(let[V,X]of Array.from(Q.entries()).sort()){J.push(""),J.push(`${j.bold}${j.accent}▌ ${V}${j.reset}`);for(let Y of X){if(J.push(L(Y)),!Y.supported){J.push(` ${j.dim2}(provider not quota-aware)${j.reset}`);continue}if(Y.error){if(M.verbose)for(let Z of K(Y.error,88))J.push(` ${j.red}${Z}${j.reset}`);continue}let $=Y.groups??[];if($.length===0){J.push(` ${j.dim2}(no active quota windows)${j.reset}`);continue}for(let Z of $)J.push(B(Z))}}return J.push(""),J.push(`${j.dim}legend:${j.reset} ${q} ok ${w} error/unavailable ${z} disabled ${j.green}✓N${j.reset}/${j.red}✗N${j.reset} request counters ${j.dim}v = verbose, d = show disabled${j.reset}`),J}function K(k,M){if(k.length<=M)return[k];let J=[],Q=k;while(Q.length>M){let U=Q.lastIndexOf(" ",M);if(U<M*0.6)U=M;J.push(Q.slice(0,U)),Q=Q.slice(U).replace(/^\s+/,"")}if(Q)J.push(Q);return J}function L(k){let M=W(k),J=`${j.green}✓${k.success}${j.reset} ${j.red}✗${k.failed}${j.reset}`,Q=E(k.label,36);return` ${M} ${j.bold}${Q}${j.reset} ${J}`}var q=`${j.green}●${j.reset}`,w=`${j.yellow}⚠${j.reset}`,z=`${j.dim2}⊘${j.reset}`;function W(k){if(k.disabled)return z;if(k.unavailable||k.error||k.status&&k.status!=="active")return w;return q}function B(k){let M=H(k.remainingFraction),J=Math.round(M*100),Q=R(M),U=k.resetTime?` ${j.dim}reset ${T(k.resetTime)}${j.reset}`:"",V=E(k.label,28).padEnd(28," ");return` ${Q} ${S(J,M)} ${V}${U}`}function R(k){let M=H(k),J=Math.round(M*18),Q=G(M),U=j.dim2,V="█".repeat(J),X="░".repeat(18-J);return`${U}[${Q}${V}${U}${X}]${j.reset}`}function S(k,M){return`${G(M)}${String(k).padStart(3)}%${j.reset}`}function G(k){if(k>=0.4)return j.green;if(k>=0.15)return j.yellow;return j.red}function T(k){let M=Date.parse(k);if(!Number.isFinite(M))return k;let J=M-Date.now();if(J<=0)return"now";let Q=Math.round(J/60000);if(Q<60)return`${Q}m`;let U=Math.round(Q/60);if(U<48)return`${U}h`;return`${Math.round(U/24)}d`}function H(k){return Math.max(0,Math.min(1,k))}function E(k,M){if(k.length<=M)return k;return`${k.slice(0,M-1)}…`}export{y as renderUsage};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{chmodSync as R,existsSync as V,mkdirSync as B,readFileSync as q,statSync as D,unlinkSync as M,writeFileSync as j}from"node:fs";import{join as K}from"node:path";import{homedir as Y}from"node:os";import{dirname as N,join as z}from"node:path";var b=!1;var Z={info(...J){if(!b)console.log("[dm-cliproxy]",...J)},warn(...J){if(!b)console.warn("[dm-cliproxy]",...J)},error(...J){if(!b)console.error("[dm-cliproxy]",...J)},debug(...J){if(!b&&(process.env.DM_CLIPROXY_DEBUG||process.env.PI_CLIPROXYAPI_DEBUG))console.log("[dm-cliproxy]","[debug]",...J)}};var W=z(Y(),".dm","agent","dm-cliproxy"),f=z(W,"config.json"),v=[z(Y(),".pi","agent","pi-cliproxyapi","config.json"),z(Y(),".config","pi-cliproxyapi","config.json")];var $=K(W,"usage-cache.json"),X=K(W,"usage-cache.lock"),w=120000,L=30000;function G(){if(!V($))return null;try{let J=JSON.parse(q($,"utf8"));if(!J||typeof J.fetchedAt!=="number"||!J.doc||!Array.isArray(J.doc.accounts))return null;return{doc:J.doc,ageMs:Date.now()-J.fetchedAt}}catch(J){return Z.warn("failed to read usage cache:",J.message),null}}function F(J){return J<w}function u(J){try{B(W,{recursive:!0,mode:448}),R(W,448);let Q={fetchedAt:Date.now(),doc:J};j($,JSON.stringify(Q),{encoding:"utf8",mode:384})}catch(Q){Z.warn("failed to write usage cache:",Q.message)}}function C(){let J=`${process.pid}@${Date.now()}`;if(V(X))try{let Q=D(X);if(Date.now()-Q.mtimeMs>L)Z.debug("removing stale usage lock"),M(X);else return null}catch{return null}try{return j(X,J,{flag:"wx",mode:384}),J}catch{return null}}function A(J){try{if(q(X,"utf8").trim()===J)return M(X),!0;return!1}catch{return!1}}export{u as writeUsageCache,C as tryAcquireUsageLock,A as releaseUsageLock,G as readUsageCache,F as isUsageFresh,X as USAGE_LOCK_PATH,w as USAGE_CACHE_TTL_MS,$ as USAGE_CACHE_PATH};
|