@duckmind/dm-darwin-x64 0.49.8 → 0.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +8 -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 x1,matchesKey as u}from"@duckmind/dm-tui";import{getModels as cj}from"@duckmind/dm-ai/compat";var w$=new Set(["openai-completions","openai-responses","anthropic-messages"]);function u$($,j){let J=j.replace(/\/+$/,"");if($==="anthropic-messages")return J.replace(/\/v1$/,"");return J}function V0($,j){if(!$)return!0;for(let J of j)if(new RegExp("^"+J.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*")+"$").test($))return!0;return!1}var Uj=128000,Ej=16000,Dj={input:0,output:0,cacheRead:0,cacheWrite:0},Rj=[/.*-thinking$/,/^gpt-5(\.\d+)?(-.*)?$/,/^gemini-3(\.\d+)?(-.*)?$/];function O$($){return Rj.some((j)=>j.test($))}var _j=[[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 H$($,j){let J=($??"").trim();return J?`${J}-${j}`:j}function U0($,j){let J=(j??"").trim(),Q=$.match(/^([a-z0-9]+-)(.*)$/);if(Q)return J?`${J}-${Q[1]}`:Q[1];return $}function E0($,j){for(let[J,Q,Y]of _j)if(J.has($))return{slug:H$(j,Q),api:Y};return{slug:H$(j,"misc"),api:"openai-completions"}}function Aj($){return $.replace(/[/:]/g," ").split(/[-_]/).filter(Boolean).map((j)=>j[0].toUpperCase()+j.slice(1)).join(" ")}function Y$($){return{id:$,name:Aj($),contextWindow:Uj,maxTokens:Ej,reasoning:O$($),cost:{...Dj}}}import{execSync as Hj}from"node:child_process";import{randomUUID as R0}from"node:crypto";import{chmodSync as g$,closeSync as D0,constants as Oj,copyFileSync as Gj,existsSync as M$,fsyncSync as Nj,linkSync as Wj,mkdirSync as kj,openSync as Tj,readFileSync as _0,renameSync as Bj,rmSync as v$,writeFileSync as Lj}from"node:fs";import{homedir as N$}from"node:os";import{dirname as k$,join as V$}from"node:path";import{fileURLToPath as Kj}from"node:url";var G$=!1;var K={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 f$=V$(N$(),".dm","agent","dm-cliproxy"),l=V$(f$,"config.json"),Fj=[V$(N$(),".pi","agent","pi-cliproxyapi","config.json"),V$(N$(),".config","pi-cliproxyapi","config.json")];function U$($){kj($,{recursive:!0,mode:448}),g$($,448)}function Z$($){if(M$($))g$($,384)}function Sj($){let j;try{j=JSON.parse(_0($,"utf8"))}catch{return}let J=j&&typeof j==="object"?j.proxy:void 0;for(let Q of[J?.apiKey,J?.usageKey]){if(typeof Q!=="string")continue;let Y=/^!cat\s+((?:~\/|\/)[^\s;&|`]+)$/.exec(Q.trim());if(!Y)continue;let Z=Y[1].replace(/^~/,N$());Z$(Z)}}function Ij(){return M$(V$(k$(Kj(import.meta.url)),"..",".git"))}function xj($=Fj,j=l,J=Ij()){if(M$(j))return;let Y=(typeof $==="string"?[$]:[...$]).find((z)=>M$(z));if(!Y)return;let Z;try{Z$(Y),Sj(Y),U$(k$(j)),Z=`${j}.${process.pid}.${R0()}.tmp`,Gj(Y,Z,Oj.COPYFILE_EXCL),g$(Z,384),Wj(Z,j),v$(Z),Z=void 0,K.info("legacy config copied to",j)}catch(z){if(Z)try{v$(Z,{force:!0})}catch(X){K.warn("failed to clean temporary config:",X)}K.warn("failed to migrate legacy config:",z)}}var W$={proxy:{endpoint:"",apiKey:""},builtinProviders:{},customProviders:{},discoveryExcludes:["*:*"],overrides:{},refreshIntervalMinutes:0,usageCacheTtlMs:30000};function T$(){if(xj(),!M$(l))return K.debug("config not found, using defaults at",l),structuredClone(W$);try{U$(k$(l)),Z$(l);let $=JSON.parse(_0(l,"utf8"));return nj($)}catch($){return K.error("failed to read config:",$,"— using defaults"),structuredClone(W$)}}function bj($,j=l){U$(k$(j));let J=`${j}.${process.pid}.${R0()}.tmp`,Q;try{Q=Tj(J,"wx",384),Lj(Q,JSON.stringify($,null,2)+`
|
|
2
|
+
`,{encoding:"utf8"}),Nj(Q),D0(Q),Q=void 0,Bj(J,j),Z$(j)}finally{if(Q!==void 0)D0(Q);v$(J,{force:!0})}}function B$($){bj($),K.info("config saved to",l)}function nj($){if(!$||typeof $!=="object")return structuredClone(W$);let j=$,J=structuredClone(W$),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 h($){if(!$)return"";let j=$.trim();if(j.startsWith("!"))try{return Hj(j.slice(1),{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).trim()}catch(J){let Q=J?.status,Y=typeof Q==="number"?` (exit ${Q})`:"";return K.warn(`failed to resolve "!" config value${Y}`),""}if(j.startsWith("$"))return process.env[j.slice(1)]??"";return j}import{createHash as Pj}from"node:crypto";import{existsSync as c1,readFileSync as l1,writeFileSync as yj}from"node:fs";import{dirname as Cj,join as wj}from"node:path";var uj=wj(f$,"discovery-cache.json");function A0($,j){return Pj("sha256").update($.trim().replace(/\/+$/,"")).update("\x00").update(j).digest("hex")}function h$($,j,J=uj){try{U$(Cj(J));let Q={savedAt:Date.now(),scope:j,discovery:$};yj(J,JSON.stringify(Q),{encoding:"utf8",mode:384}),Z$(J)}catch(Q){K.warn("failed to write discovery cache:",Q.message)}}var X$="dm-cliproxy/0.3.5",vj=5000;async function G0($,j){let J=new AbortController,Q=setTimeout(()=>J.abort(Error("timeout")),vj);try{return await fetch($,{...j,signal:J.signal})}finally{clearTimeout(Q)}}function gj($){return new URL("/.well-known/pi",new URL($).origin).toString()}async function fj($){let j=gj($.proxy.endpoint),J;try{J=await G0(j,{headers:{"User-Agent":X$,Accept:"application/json"}})}catch(X){return K.warn("well-known fetch failed:",X.message,"— falling back to /v1/models"),null}if(!J.ok)return K.warn(`well-known returned ${J.status} — falling back to /v1/models`),null;let Q;try{Q=await J.json()}catch{return K.warn("well-known returned non-JSON — falling back to /v1/models"),null}if(!Q||Q.schemaVersion!==1)return K.warn("well-known schemaVersion != 1 — falling back to /v1/models"),null;let Y=[],Z=Q.builtinProviders??{};for(let[X,q]of Object.entries(Z)){if(!q||!Array.isArray(q.models))continue;let V=q.models.map((M)=>({id:String(M.id),name:typeof M.name==="string"?M.name:String(M.id),reasoning:Boolean(M.reasoning??O$(String(M.id))),contextWindow:typeof M.contextWindow==="number"?M.contextWindow:200000,maxTokens:typeof M.maxTokens==="number"?M.maxTokens:16000,cost:M.cost??{input:0,output:0,cacheRead:0,cacheWrite:0}}));Y.push({name:X,api:q.api??"openai-responses",models:V})}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??O$(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:U0(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 hj($,j){let J=new URL("/v1/models",new URL($.proxy.endpoint).origin).toString(),Q=await G0(J,{headers:{Authorization:`Bearer ${j}`,Accept:"application/json","User-Agent":X$}});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 pj($,j){let J=j.discoveryExcludes,Q=new Map,Y=[],Z=0;for(let z of $){if(Z++,V0(z.id,J))continue;if(z.owned_by==="openai"){let M=Y$(z.id);H0(Q,"openai","openai-responses",O0(M));continue}if(z.owned_by==="anthropic"){let M=Y$(z.id);H0(Q,"anthropic","anthropic-messages",O0(M));continue}let{slug:X,api:q}=E0(z.owned_by,j.proxy.providerPrefix),V=Y$(z.id);Y.push({id:z.id,name:V.name??z.id,reasoning:V.reasoning??!1,contextWindow:V.contextWindow??128000,maxTokens:V.maxTokens??16000,cost:V.cost??{input:0,output:0,cacheRead:0,cacheWrite:0},api:q,suggestedProvider:X,ownedBy:z.owned_by})}return{source:"v1-models",upstreamVersion:null,builtinProviders:Array.from(Q.values()),customPool:Y,serverDiscoveryExcludes:[],upstreamTotal:Z}}function H0($,j,J,Q){let Y=$.get(j);if(!Y)Y={name:j,api:J,models:[]},$.set(j,Y);Y.models.push(Q)}function O0($){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 N0($,j){let J=A0($.proxy.endpoint,j),Q=await fj($);if(Q)return K.info(`discovery via /.well-known/pi: ${Q.builtinProviders.length} builtin, ${Q.customPool.length} custom`),h$(Q,J),Q;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 hj($,j),Z=pj(Y,$);return K.info(`discovery via /v1/models: ${Z.builtinProviders.length} builtin, ${Z.customPool.length} custom`),h$(Z,J),Z}function W0($){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}var k0=new WeakMap,p$=new WeakMap;function c$($){let j=(p$.get($)??0)+1;return p$.set($,j),j}function L$($,j){return j===void 0||j===(p$.get($)??0)}function T0($,j,J){let Q=k0.get($)??new Set;for(let Y of Q){if(j.has(Y))continue;$.unregisterProvider(Y),J.unregistered.push(Y)}k0.set($,new Set(j))}async function l$($,j,J,Q){let Y={registered:[],skipped:[],unregistered:[]};if(!L$($,Q))return Y.skipped.push({provider:"*",reason:"stale refresh generation"}),Y;let Z=new Set,z=W0(J),X=h(j.proxy.apiKey);if(!X)return K.warn("proxy apiKey is empty — dm.registerProvider calls will be skipped"),T0($,Z,Y),Y;let q=new Map;for(let M of J.builtinProviders)q.set(M.name,M.models.map((U)=>({id:U.id,name:U.name,reasoning:U.reasoning,contextWindow:U.contextWindow,maxTokens:U.maxTokens,cost:U.cost})));for(let[M,U]of Object.entries(j.builtinProviders)){if(!L$($,Q))return Y;if(!U?.enabled){Y.skipped.push({provider:M,reason:"disabled"});continue}if(!Array.isArray(U.models)||U.models.length===0){Y.skipped.push({provider:M,reason:"empty whitelist"});continue}let F=[];try{F=cj(M)}catch{}let T=new Map(F.map((N)=>[N.id,N])),H=new Map((q.get(M)??[]).map((N)=>[N.id,N])),D=[];for(let N of U.models){if(!z.has(N))continue;let G=T.get(N),n=H.get(N);if(G){D.push({id:G.id,name:G.name,reasoning:G.reasoning,contextWindow:G.contextWindow,maxTokens:G.maxTokens,cost:G.cost,input:G.input,api:G.api,thinkingLevelMap:G.thinkingLevelMap});continue}if(!n)continue;let j$=M==="anthropic"?"anthropic-messages":U.apiOverride??"openai-responses";D.push({id:n.id,name:n.name,reasoning:n.reasoning,contextWindow:n.contextWindow,maxTokens:n.maxTokens,cost:n.cost,input:["text"],api:j$})}if(D.length===0){Y.skipped.push({provider:M,reason:"no whitelisted models present on proxy"});continue}let A=U.apiOverride??D[0].api;if(!w$.has(A)){Y.skipped.push({provider:M,reason:`api "${A}" not in allowlist`});continue}let B=D.map((N)=>{let G=j.overrides[N.id]??{},n={id:N.id,name:typeof G.name==="string"?G.name:N.name,api:A,reasoning:typeof G.reasoning==="boolean"?G.reasoning:N.reasoning,input:N.input,cost:G.cost??N.cost,contextWindow:typeof G.contextWindow==="number"?G.contextWindow:N.contextWindow,maxTokens:typeof G.maxTokens==="number"?G.maxTokens:N.maxTokens};if(N.thinkingLevelMap)n.thinkingLevelMap=N.thinkingLevelMap;return n}),C={name:M,baseUrl:u$(A,j.proxy.endpoint),apiKey:X,authHeader:!0,api:A,models:B};$.registerProvider(M,C),Z.add(M),Y.registered.push({provider:M,modelCount:B.length,api:A})}let V=new Map(J.customPool.map((M)=>[M.id,M]));for(let[M,U]of Object.entries(j.customProviders)){if(!L$($,Q))return Y;if(!w$.has(U.api)){Y.skipped.push({provider:M,reason:`api "${U.api}" not in allowlist`});continue}let F=U.models.filter((D)=>z.has(D.id));if(F.length===0){Y.skipped.push({provider:M,reason:"no configured models present on proxy"});continue}let T=F.map((D)=>{let A=V.get(D.id),B=Y$(D.id),C=j.overrides[D.id]??{};return{id:D.id,name:D.name??A?.name??B.name??D.id,api:U.api,reasoning:lj(D.reasoning,A?.reasoning,B.reasoning,C.reasoning)??!1,input:["text"],cost:D.cost??A?.cost??B.cost??{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:B0(D.contextWindow,A?.contextWindow,B.contextWindow,C.contextWindow)??128000,maxTokens:B0(D.maxTokens,A?.maxTokens,B.maxTokens,C.maxTokens)??16000}}),H={name:M,baseUrl:u$(U.api,j.proxy.endpoint),apiKey:X,authHeader:!0,api:U.api,models:T};$.registerProvider(M,H),Z.add(M),Y.registered.push({provider:M,modelCount:T.length,api:U.api})}if(L$($,Q))T0($,Z,Y);return K.info(`applyAll: registered ${Y.registered.length} providers, skipped ${Y.skipped.length}, unregistered ${Y.unregistered.length}`),Y}function B0(...$){for(let j of $)if(typeof j==="number")return j;return}function lj(...$){for(let j of $)if(typeof j==="boolean")return j;return}var mj=15000,E$=null;function K$(){E$=null}async function L0($,j,J={}){if(!J.force&&E$&&Date.now()-E$.fetchedAt<$.usageCacheTtlMs)return E$.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")),mj),z;try{z=await fetch(Q,{headers:{"X-Plugin-Key":j,Accept:"application/json","User-Agent":X$},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 E$={fetchedAt:Date.now(),doc:X},K.debug("usage fetched, accounts:",X.accounts.length),X}import{visibleWidth as s$}from"@duckmind/dm-tui";import{visibleWidth as K0}from"@duckmind/dm-tui";function S($,j){let J=K0($);if(J===j)return $;if(J<j)return $+" ".repeat(j-J);return m$($,j)}function m$($,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=K0(Z);if(Q+z>j)break;J+=Z,Q+=z,Y++}return`${J}\x1B[0m`}var sj="│",oj="╭",ij="╮",rj="╰",dj="╯",D$="─";function r($,j){let J=Math.max(4,j.width);return[tj($,j.title,j.titleColor??"accent",J),...j.lines.map((Q)=>aj($,Q,J)),ej($,j.footer,J)]}function tj($,j,J,Q){let Y=j??"",Z=s$(Y),z=Math.max(0,Q-3-Z),X=Y?$.bold($.fg(J,Y)):"",q=`${oj}${D$}${X}${D$.repeat(z)}${ij}`;return $.fg("borderAccent",q)}function aj($,j,J){let Q=Math.max(0,J-2),Y=$.fg("borderAccent",sj);return`${Y}${S(j,Q)}${Y}`}function ej($,j,J){let Q=`${rj}${D$}`,Y=`${dj}`,Z=3;if(!j||!j.hint&&!j.badge){let H=Math.max(0,J-3);return $.fg("borderAccent",`${Q}${D$.repeat(H)}${Y}`)}let z=j.hint??"",X=j.badge??"",q=s$(z),V=s$(X),M=Math.max(0,J-3-q-V),U=$.fg("dim",z),F=X?$.fg("muted",X):"",T=D$.repeat(M);return`${$.fg("borderAccent",Q)}${U}${$.fg("borderAccent",T)}${F}${$.fg("borderAccent",Y)}`}function F$($){return Math.max(0,$-2)}import{existsSync as F0}from"node:fs";import{homedir as $1}from"node:os";import{getKeybindings as j1,Input as o$,matchesKey as J1}from"@duckmind/dm-tui";var Q1=[{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. Input is masked; blank keeps an existing key",required:!0,secret:!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. Input is masked; blank keeps it, '-' clears it",required:!1,secret:!0}];async function S0($,j=!1){let J=T$(),Q={endpoint:J.proxy.endpoint??"",apiKey:J.proxy.apiKey??"",providerPrefix:J.proxy.providerPrefix??"",usageKey:J.proxy.usageKey??""},Y=!1;for(let z of Q1){let X=Q[z.label]??"",q=z.secret?"":j?Q[z.label]??z.initialValue??"":Q[z.label]??"";if(!j&&q)continue;let V=z.secret&&X?{...z,required:!1}:z,M=await X1($,V,q||z.initialValue||"");if(M===void 0){Y=!0;break}let U=Z1(z,X,M);if(U===null){if(z.required){$.ui.notify(`${z.label} is required — aborted`,"warning"),Y=!0;break}}Q[z.label]=U??""}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 B$(Z),$.ui.notify(`saved to ${l}`,"info"),!0}function Y1($){if($.startsWith("!")||$.startsWith("$"))return $;if($.startsWith("~/")){let j=$.replace(/^~/,$1());return F0(j)?`!cat ${$}`:$}if($.startsWith("/"))return F0($)?`!cat ${$}`:$;return $}function Z1($,j,J){let Q=J.trim();if(!Q){if($.secret&&j)return j;return $.required?null:""}if($.secret&&!$.required&&Q==="-")return"";return $.label==="providerPrefix"||$.label==="endpoint"?Q:Y1(Q)}async function X1($,j,J){return $.ui.custom((Q,Y,Z,z)=>z1(Q,Y,j,J,z),{overlay:!0,overlayOptions:{width:100,maxHeight:"60%"}})}class I0{rawInput=new o$;displayInput=new o$;pasteActive=!1;get focused(){return this.rawInput.focused}set focused($){this.rawInput.focused=$,this.displayInput.focused=$}set onSubmit($){this.rawInput.onSubmit=$}set onEscape($){this.rawInput.onEscape=$}getValue(){return this.rawInput.getValue()}setValue($){this.rawInput.setValue($),this.displayInput.setValue("•".repeat($.length))}handleInput($){this.rawInput.handleInput($),this.displayInput.handleInput(this.maskInput($)),this.displayInput.setValue("•".repeat(this.rawInput.getValue().length))}render($){return this.displayInput.render($)}invalidate(){this.rawInput.invalidate(),this.displayInput.invalidate()}maskInput($){let j="";for(let J=0;J<$.length;){if($.startsWith("\x1B[200~",J)){this.pasteActive=!0,j+="\x1B[200~",J+=6;continue}if($.startsWith("\x1B[201~",J)){this.pasteActive=!1,j+="\x1B[201~",J+=6;continue}if(!this.pasteActive&&$.charCodeAt(J)===27)return $;let Q=$.codePointAt(J),Y=String.fromCodePoint(Q);j+=Q<32||Q===127?Y:"•",J+=Y.length}return j}}function z1($,j,J,Q,Y){let Z=J.secret?new I0:new o$;Z.setValue(Q),Z.focused=!0;let z=null,X=(q)=>{if(!q&&!J.required){Y("");return}if(!q&&J.required){z="required field",$.requestRender();return}if(J.validate){let V=q.trim();if(V&&!V.startsWith("!")&&!V.startsWith("$")){let M=J.validate(V);if(M){z=M,$.requestRender();return}}}Y(q)};return Z.onSubmit=X,Z.onEscape=()=>Y(void 0),{render(q){let V=F$(q),M=Z.render(V-4),U=["",` ${j.fg("dim",J.hint)}`,"",...M.map((F)=>` ${j.fg("accent",`❯ ${F}`)}`),"",z?` ${j.fg("error",`! ${z}`)}`:` ${j.fg("dim","enter = save · esc = cancel")}`];return r(j,{width:q,title:` setup: ${J.label} `,lines:U,footer:{hint:" enter = save · esc = cancel "}})},invalidate(){Z.invalidate()},handleInput(q){if(j1().matches(q,"tui.select.cancel")||J1(q,"escape")){Y(void 0);return}z=null,Z.handleInput(q),$.requestRender()}}}import{visibleWidth as S$}from"@duckmind/dm-tui";function x0($,j,J,Q){let Y=$.fg("borderAccent","│"),Z=j.map((z,X)=>{let q=`${X+1} ${z.label}`;return X===J?$.bold($.fg("accent",` ${q} `)):$.fg("dim",` ${q} `)});return S(` ${Z.join(Y)}`,Q)}function b0($,j,J){let Q=j.join($.fg("dim"," "));return S(` ${Q}`,J)}function n0($,j){return $.fg("borderAccent","─".repeat(Math.max(0,j)))}function d($,j,J){let Q=$.slice(j,j+J);while(Q.length<J)Q.push("");return Q}function I$($,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)),q=X+Z;if($<q)X=Math.max(0,$-Z);let V=X+Q-1;if(j>V)X=Math.min(z,j-(Q-1));return X}function x$($,j,J){let Q=Math.max(0,J-j);return Math.max(0,Math.min($,Q))}import{matchesKey as t}from"@duckmind/dm-tui";import{existsSync as q1,readFileSync as M1}from"node:fs";import{homedir as y0}from"node:os";import{join as C0}from"node:path";var V1=C0(y0(),".dm","models.json"),U1=C0(y0(),".dm","auth.json");function P0($){if(!q1($))return null;try{return JSON.parse(M1($,"utf8"))}catch{return null}}function w0($){let j=[],J=new Set([...Object.keys($.builtinProviders),...Object.keys($.customProviders)]),Q=P0(V1);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=P0(U1);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 u0($){let{theme:j,cfg:J}=$,Q=0,Y=()=>{let X=$.getDiscovery(),q=(H)=>j.fg("success",H),V=(H)=>j.fg("error",H),M=(H)=>j.fg("dim",H),U=[];U.push(`${M("endpoint")} ${J.proxy.endpoint||V("(unset)")}`),U.push(`${M("apiKey")} ${h(J.proxy.apiKey)?q("resolves"):V("empty after resolution")}`),U.push(`${M("usageKey")} ${J.proxy.usageKey?h(J.proxy.usageKey)?q("resolves"):V("set but empty"):M("not configured")}`),U.push(`${M("user-agent")} ${X$}`),U.push(""),U.push(`${M("discovery")} source=${X.source}`),U.push(`${M("upstream")} v=${X.upstreamVersion??"(unknown)"} · ${X.upstreamTotal} ids`);let F=X.builtinProviders.map((H)=>`${H.name}=${H.models.length}`).join(", ")||M("(none)");U.push(`${M("built-in")} ${F}`),U.push(`${M("custom pool")} ${X.customPool.length} models`);let T=w0(J);if(U.push(""),T.length===0)U.push(`${M("conflicts")} ${q("none")}`);else{U.push(`${M("conflicts")}`);for(let H of T)U.push(` ${j.fg("warning",`[${H.kind}]`)} ${H.detail}`)}return U};return{id:"diagnostics",label:"Diagnostics",render:(X,q)=>{let V=Y();return Q=x$(Q,q,V.length),d(V,Q,q).map((M)=>S(` ${M}`,X))},handleInput:(X)=>{let q=Y().length;if(t(X,"up")||t(X,"k"))return Q=Math.max(0,Q-1),!0;if(t(X,"down")||t(X,"j"))return Q=Math.min(Math.max(0,q-1),Q+1),!0;if(t(X,"pageUp")||t(X,"b"))return Q=Math.max(0,Q-10),!0;if(t(X,"pageDown")||t(X,"f"))return Q=Math.min(Math.max(0,q-1),Q+10),!0;return!1},footerHint:()=>" ↑↓ scroll · r refresh discovery "}}import{matchesKey as k}from"@duckmind/dm-tui";function i$($){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 E1($){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 $$($,j){if(j.kind==="builtin")return[...$.builtinProviders[j.name]?.models??[]];return $.customProviders[j.name]?.models.map((J)=>J.id)??[]}function v0($,j,J){if(j.kind==="builtin"){let Z=J.builtinModelIds.get(j.name)??[],z=new Set($$($,j));return Z.filter((X)=>!z.has(X))}let Q=E1($),Y=new Set($$($,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 D1($){return{id:$.id,name:$.name,contextWindow:$.contextWindow,maxTokens:$.maxTokens,reasoning:$.reasoning,cost:$.cost}}function g0($,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(D1(J));$.customProviders[j.name]=Q}function f0($,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 r$($,j){if($===j)return!0;let J=["openai-completions","openai-responses"];if(J.includes($)&&J.includes(j))return!0;return!1}function h0($,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 p0($,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 R1,getProviders as _1}from"@duckmind/dm-ai/compat";function d$($,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 q;try{let M=R1(z).find((U)=>X.includes(U.id));if(M)q=M.api}catch{}if(!q){let V=X[0];q=j.byId.get(V)?.suggestedApi??"openai-responses"}if(J.push({kind:"builtin",name:z,api:q,subtitle:`built-in · ${q}`}),!$.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 A1,matchesKey as z$}from"@duckmind/dm-tui";async function c0($,j){return $.ui.custom((J,Q,Y,Z)=>H1(Q,`Remove custom group “${j}”?`,"All model assignments in this group will be discarded.",Z),{overlay:!0,overlayOptions:{width:80,maxHeight:"40%"}})}function H1($,j,J,Q){return{render(Y){return r($,{width:Y,title:" confirm ",titleColor:"error",lines:["",` ${$.bold(j)}`,` ${$.fg("dim",J)}`,""],footer:{hint:" y / enter = remove · n / esc = cancel "}})},invalidate(){},handleInput(Y){if(A1().matches(Y,"tui.select.cancel")||z$(Y,"escape")||z$(Y,"n")||z$(Y,"q")){Q(!1);return}if(z$(Y,"y")||z$(Y,"enter")||z$(Y,"return")){Q(!0);return}}}}import{getKeybindings as O1,Input as G1,matchesKey as N1}from"@duckmind/dm-tui";async function l0($,j){let J=H$(j,"group");return $.ui.custom((Q,Y,Z,z)=>W1(Q,Y,J,z),{overlay:!0,overlayOptions:{width:80,maxHeight:"40%"}})}function W1($,j,J,Q){let Y=new G1;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=F$(z),q=J?`name shown in /model picker, e.g. ${J}`:"letters / digits / dot / dash / underscore",V=Y.render(X-4),M=["",` ${j.fg("dim",q)}`,"",...V.map((U)=>` ${j.fg("accent",`❯ ${U}`)}`),"",Z?` ${j.fg("error",`! ${Z}`)}`:""];return r(j,{width:z,title:" new custom group ",lines:M,footer:{hint:" enter = create · esc = cancel "}})},invalidate(){Y.invalidate()},handleInput(z){if(O1().matches(z,"tui.select.cancel")||N1(z,"escape")){Q(null);return}Z=null,Y.handleInput(z),$.requestRender()}}}import{visibleWidth as k1}from"@duckmind/dm-tui";function t$($,j,J){if(!j)return" ";if(J)return $.fg("accent","▶ ");return $.fg("muted","▸ ")}function m0($,j){let J=k1($);if(J===j)return $;if(J>j)return m$($,j);return S($,j)}function s0($,j,J){let{theme:Q,width:Y,isCursor:Z,isFocused:z}=J,X=t$(Q,Z,z),q=$.kind==="builtin"?j.builtinProviders[$.name]?.models.length??0:j.customProviders[$.name]?.models.length??0,V=$.kind==="builtin"?Q.fg("accent","B"):Q.fg("warning","C"),M=`${Q.fg("dim","[")}${V}${Q.fg("dim","]")}`,U=q>0?Q.fg("success","●"):Q.fg("dim","○"),F=q>0?Q.fg("success",String(q).padStart(2)):Q.fg("dim"," 0"),T=Z&&z?Q.bold(Q.fg("accent",$.name)):Z?Q.bold($.name):$.name,H=Q.fg("dim",$.api),D=`${X}${M} ${T} ${U}${F} ${H}`;return m0(D,Y)}function o0($,j,J,Q){let Y=t$($,j,J),Z=j&&J?$.bold($.fg("accent","+ new custom group…")):$.fg("accent","+ new custom group…");return S(`${Y}${Z}`,Q)}function a$($,j,J,Q,Y){let{theme:Z,width:z,isCursor:X,isFocused:q}=Y,V=t$(Z,X,q),M=J==="assigned"?Z.fg("success","☑"):Z.fg("dim","☐"),U=Q?` ${Z.fg("warning","⚠")}`:"",F=X&&q?Z.fg("accent",$):$,T=j?.reasoning?` ${Z.fg("accent","✨")}`:"",H=j?Z.fg("muted",` · ${j.suggestedApi}`):Z.fg("error"," · not on proxy"),D=`${V}${M} ${F}${U}${T}${H}`;return m0(D,z)}function i0($,j,J){let Q=`${$.fg("borderAccent","──")} ${$.fg("warning",j)} ${$.fg("borderAccent","──")}`;return S(` ${Q}`,J)}function e$($,j,J){return S(` ${$.fg("dim",j)}`,J)}function r0($,j,J,Q){let Y=Q?$.bold($.fg("accent","❚ ")):$.fg("dim"," ");return S(`${Y}${j}`,J)}function d0($){let{tui:j,theme:J,ctx:Q,cfg:Y}=$,Z=$.onChange??(()=>{}),z=i$($.getDiscovery()),X=d$(Y,z),q="providers",V=0,M=0,U=0,F=0,T=0,H=0,D="",A=!1,B=()=>{if(X.length===0)return null;let E=Math.max(0,Math.min(V,X.length-1));return X[E]??null},C=(E)=>{let O=p0(v0(Y,E,z),z,D);return h0(O,z)},N=(E)=>C(E).flatMap((O)=>O.ids),G=()=>{X=d$(Y,z);let E=Math.max(0,X.length);if(V>E)V=E;let O=B();if(O){let b=$$(Y,O).length,W=N(O).length;if(M>=b)M=Math.max(0,b-1);if(U>=W)U=Math.max(0,W-1)}},n=()=>{z=i$($.getDiscovery()),G()},j$=(E)=>{let O=["providers","assigned","pool"],b=O.indexOf(q);q=E?O[(b-1+O.length)%O.length]:O[(b+1)%O.length]},_=(E)=>{if(q==="providers"){let W=X.length+1;V=Math.max(0,Math.min(V+E,W-1));return}let O=B();if(!O)return;if(q==="assigned"){let W=$$(Y,O).length;if(W===0)return;M=Math.max(0,Math.min(M+E,W-1));return}let b=N(O).length;if(b===0)return;U=Math.max(0,Math.min(U+E,b-1))},x=async()=>{if(q==="providers"){if(V===X.length){let W=await l0(Q,Y.proxy.providerPrefix);if(W&&!Y.customProviders[W]){if(Y.customProviders[W]={api:"openai-completions",models:[]},Z(),G(),V=X.findIndex((I)=>I.kind==="custom"&&I.name===W),V<0)V=X.length-1;q="pool"}j.requestRender();return}q="pool";return}let E=B();if(!E)return;if(q==="assigned"){let W=$$(Y,E)[M];if(!W)return;f0(Y,E,W),Z(),G();return}let O=N(E)[U];if(!O)return;let b=z.byId.get(O);if(!b)return;g0(Y,E,b),Z(),G()},p=async()=>{if(q!=="providers")return;let E=B();if(!E||E.kind!=="custom")return;if(!await c0(Q,E.name)){j.requestRender();return}if(delete Y.customProviders[E.name],Z(),G(),V>=X.length)V=Math.max(0,X.length-1);j.requestRender()},v=(E,O)=>c(E,O);function c(E,O){let b=Math.max(70,E),W=Math.min(56,Math.max(34,Math.floor(b*0.4))),I=b-W-1,s=Math.max(8,O),o=Math.max(5,Math.floor((s-1)/2)),$0=s-o,m=B(),q$=0,b$=0,n$=0,j0=0,P$=0,J0=0,a=[];a.push(J$(" providers ",W,q==="providers"));for(let L=0;L<X.length;L++){let g=X[L],w=q==="providers"&&L===V;if(w)q$=a.length,b$=q$;a.push(s0(g,Y,{theme:J,width:W,isCursor:w,isFocused:q==="providers"}))}{let L=q==="providers"&&V===X.length;if(L)q$=a.length,b$=q$;a.push(o0(J,L,q==="providers",W))}let e=[],Xj=m?`assigned to ${J.bold(m.name)} ${J.fg("dim",`· ${m.api}`)}`:J.fg("dim","no provider selected");if(e.push(J$(" assigned ",I,q==="assigned")),e.push(r0(J,Xj,I,q==="assigned")),m){let L=$$(Y,m);if(L.length===0)e.push(e$(J,"(nothing assigned yet)",I));for(let g=0;g<L.length;g++){let w=L[g],f=z.byId.get(w),A$=q==="assigned"&&g===M;if(A$)n$=e.length,j0=n$;let Q$=f?!r$(m.api,f.suggestedApi):!1;e.push(a$(w,f,"assigned",Q$,{theme:J,width:I,isCursor:A$,isFocused:q==="assigned"}))}}let i=[];if(i.push(P(I,q==="pool")),m){let L=C(m);if(L.reduce((w,f)=>w+f.ids.length,0)===0)i.push(e$(J,D?`(no matches for "${D}")`:"(no models available)",I));else{let w=0;for(let f of L){let A$=i.length;i.push(i0(J,f.label,I));for(let Q$=0;Q$<f.ids.length;Q$++){let q0=f.ids[Q$],C$=z.byId.get(q0),M0=q==="pool"&&w===U;if(M0)P$=i.length,J0=Q$===0?A$:P$;let Vj=C$?!r$(m.api,C$.suggestedApi):!1;i.push(a$(q0,C$,"pool",Vj,{theme:J,width:I,isCursor:M0,isFocused:q==="pool"})),w++}}}}let zj=Math.max(1,$0-1),Q0=I$(b$,q$,F,s,a.length,1),Y0=I$(q==="assigned"?j0:0,q==="assigned"?n$:0,T,o,e.length,2),Z0=I$(q==="pool"?J0:0,q==="pool"?P$:0,H,zj,i.length,1);F=Q0,T=Y0,H=Z0;let X0=d(a,Q0,s),qj=d(e,Y0,o),Mj=d(i,Z0,$0),z0=J.fg("borderAccent","│"),y$=[];for(let L=0;L<s;L++){let g=S(X0[L]??"",W),w=L<o?qj[L]:Mj[L-o],f=S(w,I);y$.push(`${g}${z0}${f}`)}let _$=o;if(_$>0&&_$<s){let L=S(X0[_$]??"",W),g=J.fg("borderAccent","─".repeat(I));y$[_$]=`${L}${z0}${g}`}return y$}function J$(E,O,b){let W=b?J.bold(J.fg("accent",E)):J.fg("muted",E),I=J.fg("borderAccent","─".repeat(Math.max(0,O-S$(E)-1)));return S(`${W}${I}`,O)}function P(E,O){let W=O?J.bold(J.fg("accent"," available pool ")):J.fg("muted"," available pool "),I="";if(A)I=`${J.fg("dim"," /")}${J.fg("accent",D)}${J.fg("accent","█")} `;else if(D)I=`${J.fg("dim"," /")}${J.fg("warning",D)} `;let s=S$(" available pool ")+S$(I),o=J.fg("borderAccent","─".repeat(Math.max(0,E-s-1)));return S(`${W}${I}${o}`,E)}function R$(E){if(A){if(k(E,"escape"))return D="",A=!1,U=0,!0;if(k(E,"enter")||k(E,"return"))return A=!1,!0;if(k(E,"backspace")||k(E,"delete"))return D=D.slice(0,-1),U=0,!0;if(E.length===1&&E>=" "&&E!=="")return D+=E,U=0,!0;return!0}if(k(E,"tab"))return j$(!1),!0;if(k(E,"shift+tab"))return j$(!0),!0;if(k(E,"/"))return q="pool",A=!0,!0;if(k(E,"enter")||k(E,"return")||k(E,"space"))return x().then(()=>!0);if(q==="providers"&&(k(E,"d")||k(E,"delete")||k(E,"backspace")))return p().then(()=>!0);if(k(E,"up")||k(E,"k"))return _(-1),!0;if(k(E,"down")||k(E,"j"))return _(1),!0;if(k(E,"pageUp")||k(E,"b"))return _(-8),!0;if(k(E,"pageDown")||k(E,"f"))return _(8),!0;if(k(E,"left")||k(E,"h"))return q="providers",!0;if(k(E,"right")||k(E,"l")){if(q==="providers")q="assigned";else if(q==="assigned")q="pool";return!0}return!1}function Zj(){if(A)return" type to filter · ↵ apply · esc clear ";return" tab ↔ panel · ↑↓ nav · ↵ move · / filter · d remove group "}return{id:"models",label:"Models",render:v,handleInput:R$,footerHint:Zj,rebuild:n}}import{matchesKey as y}from"@duckmind/dm-tui";var R={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 t0($,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(`${R.dim}generated ${$.generatedAt}${R.reset}`),$.unsupportedProviders.length>0)J.push(`${R.dim}providers without quota lookup:${R.reset} ${$.unsupportedProviders.join(", ")}`);if(Y>0)J.push(`${R.dim}hidden disabled accounts:${R.reset} ${Y} ${R.dim2}(press d to show)${R.reset}`);for(let[Z,z]of Array.from(Q.entries()).sort()){J.push(""),J.push(`${R.bold}${R.accent}▌ ${Z}${R.reset}`);for(let X of z){if(J.push(B1(X)),!X.supported){J.push(` ${R.dim2}(provider not quota-aware)${R.reset}`);continue}if(X.error){if(j.verbose)for(let V of T1(X.error,88))J.push(` ${R.red}${V}${R.reset}`);continue}let q=X.groups??[];if(q.length===0){J.push(` ${R.dim2}(no active quota windows)${R.reset}`);continue}for(let V of q)J.push(K1(V))}}return J.push(""),J.push(`${R.dim}legend:${R.reset} ${a0} ok ${e0} error/unavailable ${$j} disabled ${R.green}✓N${R.reset}/${R.red}✗N${R.reset} request counters ${R.dim}v = verbose, d = show disabled${R.reset}`),J}function T1($,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 B1($){let j=L1($),J=`${R.green}✓${$.success}${R.reset} ${R.red}✗${$.failed}${R.reset}`,Q=Qj($.label,36);return` ${j} ${R.bold}${Q}${R.reset} ${J}`}var a0=`${R.green}●${R.reset}`,e0=`${R.yellow}⚠${R.reset}`,$j=`${R.dim2}⊘${R.reset}`;function L1($){if($.disabled)return $j;if($.unavailable||$.error||$.status&&$.status!=="active")return e0;return a0}function K1($){let j=Jj($.remainingFraction),J=Math.round(j*100),Q=F1(j),Y=$.resetTime?` ${R.dim}reset ${I1($.resetTime)}${R.reset}`:"",Z=Qj($.label,28).padEnd(28," ");return` ${Q} ${S1(J,j)} ${Z}${Y}`}function F1($){let j=Jj($),J=Math.round(j*18),Q=jj(j),Y=R.dim2,Z="█".repeat(J),z="░".repeat(18-J);return`${Y}[${Q}${Z}${Y}${z}]${R.reset}`}function S1($,j){return`${jj(j)}${String($).padStart(3)}%${R.reset}`}function jj($){if($>=0.4)return R.green;if($>=0.15)return R.yellow;return R.red}function I1($){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 Jj($){return Math.max(0,Math.min(1,$))}function Qj($,j){if($.length<=j)return $;return`${$.slice(0,j-1)}…`}function Yj($){let{tui:j,theme:J,cfg:Q}=$,Y="idle",Z=null,z="",X=0,q=!1,V=!1,M=(D)=>{Y="loading",j.requestRender();let A=h(Q.proxy.usageKey);L0(Q,A,{force:D}).then((B)=>{Z=B,Y="ready",X=0,j.requestRender()}).catch((B)=>{z=B.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 t0(Z,{showDisabled:q,verbose:V})};return{id:"usage",label:"Usage",render:(D,A)=>{let B=U();return X=x$(X,A,B.length),d(B,X,A).map((C)=>S(` ${C}`,D))},handleInput:(D)=>{if(y(D,"d"))return q=!q,X=0,!0;if(y(D,"v"))return V=!V,X=0,!0;let A=U().length;if(y(D,"up")||y(D,"k"))return X=Math.max(0,X-1),!0;if(y(D,"down")||y(D,"j"))return X=Math.min(Math.max(0,A-1),X+1),!0;if(y(D,"pageUp")||y(D,"b"))return X=Math.max(0,X-10),!0;if(y(D,"pageDown")||y(D,"f"))return X=Math.min(Math.max(0,A-1),X+10),!0;if(y(D,"home")||y(D,"g"))return X=0,!0;if(y(D,"end")||y(D,"shift+g"))return X=Math.max(0,A-1),!0;return!1},footerHint:()=>{let D=q?J.fg("success","[d disabled]"):"d disabled",A=V?J.fg("success","[v verbose]"):"v verbose";return` ↑↓ scroll · ${D} · ${A} `},onActivate:()=>{if(Y==="idle")M(!1)},reload:()=>{if(K$(),Y!=="idle")M(!0)}}}function kJ($){let{dm:j,ctx:J,tui:Q,theme:Y,cfg:Z,done:z}=$,X=$.discovery,q=!1,V="",M=d0({tui:Q,theme:Y,ctx:J,cfg:Z,getDiscovery:()=>X,onChange:()=>{q=!0,V=""}}),U=Yj({tui:Q,theme:Y,cfg:Z}),F=u0({theme:Y,cfg:Z,getDiscovery:()=>X}),T=[M,U,F],H=0,D=()=>T[H],A=(_)=>{if(_<0||_>=T.length||_===H)return;H=_,D().onActivate?.(),Q.requestRender()},B=()=>{V=Y.fg("dim","saving…"),B$(Z),Q.requestRender();let _=c$(j);l$(j,Z,X,_).then((x)=>{q=!1,V=Y.fg("success",`✓ settings saved · ${x.registered.length} registered, ${x.skipped.length} skipped`),Q.requestRender()}).catch((x)=>{V=Y.fg("error",`save failed: ${x.message}`),Q.requestRender()})},C=async()=>{V=Y.fg("dim","refreshing…"),Q.requestRender();try{let _=c$(j),x=h(Z.proxy.apiKey);X=await N0(Z,x),K$(),M.rebuild(),U.reload();let p=await l$(j,Z,X,_);V=Y.fg("success",`✓ refreshed · ${p.registered.length} providers (${X.source})`)}catch(_){V=Y.fg("error",`refresh failed: ${_.message}`)}Q.requestRender()},N=async()=>{if(!await S0(J,!0)){Q.requestRender();return}let x=T$();Z.proxy={...Z.proxy,...x.proxy},await C()},G=()=>{let _=Z.proxy.endpoint||"(unset)",x=_.length>40?`…${_.slice(-39)}`:_,p=Boolean(h(Z.proxy.apiKey)),v=0,c=0;for(let P of Object.values(Z.builtinProviders)){if(P.enabled&&P.models.length>0)v++;c+=P.models.length}for(let P of Object.values(Z.customProviders)){if(P.models.length>0)v++;c+=P.models.length}let J$=V?V:q?Y.fg("warning","● unsaved — press s to save"):Y.fg("dim","✓ saved");return[`${Y.fg("dim","endpoint")} ${x}`,`${Y.fg("dim","key")} ${p?Y.fg("success","✓"):Y.fg("error","✗")}`,`${Y.fg("dim","providers")} ${v}`,`${Y.fg("dim","models")} ${c}`,J$]},n=(_)=>{let x=Q.rows??40,v=Math.max(16,Math.min(x-6,38))-2,c=Math.max(72,_-2),J$=Math.max(6,v-3),P=[];return P.push(b0(Y,G(),c)),P.push(x0(Y,T.map((R$)=>({id:R$.id,label:R$.label})),H,c)),P.push(n0(Y,c)),P.push(...D().render(c,J$)),r(Y,{width:_,title:" /cliproxy ",lines:P,footer:{hint:D().footerHint(),badge:" [ ] tab · r refresh · e setup · s save · q close "}})},j$=(_)=>{if(x1().matches(_,"tui.select.cancel")||u(_,"q")||u(_,"escape"))return z(),!0;if(u(_,"]")||u(_,"tab"))return A((H+1)%T.length),!0;if(u(_,"[")||u(_,"shift+tab"))return A((H-1+T.length)%T.length),!0;if(u(_,"1"))return A(0),!0;if(u(_,"2"))return A(1),!0;if(u(_,"3"))return A(2),!0;if(u(_,"r"))return C().then(()=>!0);if(u(_,"e"))return N().then(()=>!0);if(u(_,"s"))return B(),!0;return!1};return{render:n,invalidate(){},handleInput(_){let x=D().handleInput(_);if(x instanceof Promise){V="",x.then((v)=>{if(v)Q.requestRender()});return}if(x){V="",Q.requestRender();return}let p=j$(_);if(p instanceof Promise)p.then((v)=>{if(v)Q.requestRender()});else if(p)Q.requestRender()}}}export{kJ as buildHub};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var M$=!1;function w$($){M$=$}var K={info(...$){if(!M$)console.log("[dm-cliproxy]",...$)},warn(...$){if(!M$)console.warn("[dm-cliproxy]",...$)},error(...$){if(!M$)console.error("[dm-cliproxy]",...$)},debug(...$){if(!M$&&(process.env.DM_CLIPROXY_DEBUG||process.env.PI_CLIPROXYAPI_DEBUG))console.log("[dm-cliproxy]","[debug]",...$)}};import{getKeybindings as n1,matchesKey as u}from"@duckmind/dm-tui";import{getModels as mj}from"@duckmind/dm-ai/compat";var u$=new Set(["openai-completions","openai-responses","anthropic-messages"]);function v$($,j){let J=j.replace(/\/+$/,"");if($==="anthropic-messages")return J.replace(/\/v1$/,"");return J}function U0($,j){if(!$)return!0;for(let J of j)if(new RegExp("^"+J.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*")+"$").test($))return!0;return!1}var Dj=128000,Rj=16000,_j={input:0,output:0,cacheRead:0,cacheWrite:0},Aj=[/.*-thinking$/,/^gpt-5(\.\d+)?(-.*)?$/,/^gemini-3(\.\d+)?(-.*)?$/];function G$($){return Aj.some((j)=>j.test($))}var Oj=[[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 H$($,j){let J=($??"").trim();return J?`${J}-${j}`:j}function E0($,j){let J=(j??"").trim(),Y=$.match(/^([a-z0-9]+-)(.*)$/);if(Y)return J?`${J}-${Y[1]}`:Y[1];return $}function D0($,j){for(let[J,Y,Z]of Oj)if(J.has($))return{slug:H$(j,Y),api:Z};return{slug:H$(j,"misc"),api:"openai-completions"}}function Hj($){return $.replace(/[/:]/g," ").split(/[-_]/).filter(Boolean).map((j)=>j[0].toUpperCase()+j.slice(1)).join(" ")}function Z$($){return{id:$,name:Hj($),contextWindow:Dj,maxTokens:Rj,reasoning:G$($),cost:{..._j}}}import{execSync as Gj}from"node:child_process";import{randomUUID as _0}from"node:crypto";import{chmodSync as f$,closeSync as R0,constants as Nj,copyFileSync as Wj,existsSync as V$,fsyncSync as kj,linkSync as Tj,mkdirSync as Bj,openSync as Lj,readFileSync as A0,renameSync as Kj,rmSync as g$,writeFileSync as Fj}from"node:fs";import{homedir as N$}from"node:os";import{dirname as k$,join as U$}from"node:path";import{fileURLToPath as Sj}from"node:url";var h$=U$(N$(),".dm","agent","dm-cliproxy"),l=U$(h$,"config.json"),Ij=[U$(N$(),".pi","agent","pi-cliproxyapi","config.json"),U$(N$(),".config","pi-cliproxyapi","config.json")];function E$($){Bj($,{recursive:!0,mode:448}),f$($,448)}function X$($){if(V$($))f$($,384)}function bj($){let j;try{j=JSON.parse(A0($,"utf8"))}catch{return}let J=j&&typeof j==="object"?j.proxy:void 0;for(let Y of[J?.apiKey,J?.usageKey]){if(typeof Y!=="string")continue;let Z=/^!cat\s+((?:~\/|\/)[^\s;&|`]+)$/.exec(Y.trim());if(!Z)continue;let X=Z[1].replace(/^~/,N$());X$(X)}}function xj(){return V$(U$(k$(Sj(import.meta.url)),"..",".git"))}function nj($=Ij,j=l,J=xj()){if(V$(j))return;let Z=(typeof $==="string"?[$]:[...$]).find((z)=>V$(z));if(!Z)return;let X;try{X$(Z),bj(Z),E$(k$(j)),X=`${j}.${process.pid}.${_0()}.tmp`,Wj(Z,X,Nj.COPYFILE_EXCL),f$(X,384),Tj(X,j),g$(X),X=void 0,K.info("legacy config copied to",j)}catch(z){if(X)try{g$(X,{force:!0})}catch(Q){K.warn("failed to clean temporary config:",Q)}K.warn("failed to migrate legacy config:",z)}}var W$={proxy:{endpoint:"",apiKey:""},builtinProviders:{},customProviders:{},discoveryExcludes:["*:*"],overrides:{},refreshIntervalMinutes:0,usageCacheTtlMs:30000};function T$(){if(nj(),!V$(l))return K.debug("config not found, using defaults at",l),structuredClone(W$);try{E$(k$(l)),X$(l);let $=JSON.parse(A0(l,"utf8"));return yj($)}catch($){return K.error("failed to read config:",$,"— using defaults"),structuredClone(W$)}}function Pj($,j=l){E$(k$(j));let J=`${j}.${process.pid}.${_0()}.tmp`,Y;try{Y=Lj(J,"wx",384),Fj(Y,JSON.stringify($,null,2)+`
|
|
2
|
+
`,{encoding:"utf8"}),kj(Y),R0(Y),Y=void 0,Kj(J,j),X$(j)}finally{if(Y!==void 0)R0(Y);g$(J,{force:!0})}}function B$($){Pj($),K.info("config saved to",l)}function yj($){if(!$||typeof $!=="object")return structuredClone(W$);let j=$,J=structuredClone(W$),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 h($){if(!$)return"";let j=$.trim();if(j.startsWith("!"))try{return Gj(j.slice(1),{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).trim()}catch(J){let Y=J?.status,Z=typeof Y==="number"?` (exit ${Y})`:"";return K.warn(`failed to resolve "!" config value${Z}`),""}if(j.startsWith("$"))return process.env[j.slice(1)]??"";return j}import{createHash as Cj}from"node:crypto";import{existsSync as m1,readFileSync as s1,writeFileSync as wj}from"node:fs";import{dirname as uj,join as vj}from"node:path";var gj=vj(h$,"discovery-cache.json");function O0($,j){return Cj("sha256").update($.trim().replace(/\/+$/,"")).update("\x00").update(j).digest("hex")}function p$($,j,J=gj){try{E$(uj(J));let Y={savedAt:Date.now(),scope:j,discovery:$};wj(J,JSON.stringify(Y),{encoding:"utf8",mode:384}),X$(J)}catch(Y){K.warn("failed to write discovery cache:",Y.message)}}var Q$="dm-cliproxy/0.3.5",fj=5000;async function N0($,j){let J=new AbortController,Y=setTimeout(()=>J.abort(Error("timeout")),fj);try{return await fetch($,{...j,signal:J.signal})}finally{clearTimeout(Y)}}function hj($){return new URL("/.well-known/pi",new URL($).origin).toString()}async function pj($){let j=hj($.proxy.endpoint),J;try{J=await N0(j,{headers:{"User-Agent":Q$,Accept:"application/json"}})}catch(Q){return K.warn("well-known fetch failed:",Q.message,"— falling back to /v1/models"),null}if(!J.ok)return K.warn(`well-known returned ${J.status} — falling back to /v1/models`),null;let Y;try{Y=await J.json()}catch{return K.warn("well-known returned non-JSON — falling back to /v1/models"),null}if(!Y||Y.schemaVersion!==1)return K.warn("well-known schemaVersion != 1 — falling back to /v1/models"),null;let Z=[],X=Y.builtinProviders??{};for(let[Q,q]of Object.entries(X)){if(!q||!Array.isArray(q.models))continue;let V=q.models.map((M)=>({id:String(M.id),name:typeof M.name==="string"?M.name:String(M.id),reasoning:Boolean(M.reasoning??G$(String(M.id))),contextWindow:typeof M.contextWindow==="number"?M.contextWindow:200000,maxTokens:typeof M.maxTokens==="number"?M.maxTokens:16000,cost:M.cost??{input:0,output:0,cacheRead:0,cacheWrite:0}}));Z.push({name:Q,api:q.api??"openai-responses",models:V})}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:E0(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 cj($,j){let J=new URL("/v1/models",new URL($.proxy.endpoint).origin).toString(),Y=await N0(J,{headers:{Authorization:`Bearer ${j}`,Accept:"application/json","User-Agent":Q$}});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++,U0(z.id,J))continue;if(z.owned_by==="openai"){let M=Z$(z.id);H0(Y,"openai","openai-responses",G0(M));continue}if(z.owned_by==="anthropic"){let M=Z$(z.id);H0(Y,"anthropic","anthropic-messages",G0(M));continue}let{slug:Q,api:q}=D0(z.owned_by,j.proxy.providerPrefix),V=Z$(z.id);Z.push({id:z.id,name:V.name??z.id,reasoning:V.reasoning??!1,contextWindow:V.contextWindow??128000,maxTokens:V.maxTokens??16000,cost:V.cost??{input:0,output:0,cacheRead:0,cacheWrite:0},api:q,suggestedProvider:Q,ownedBy:z.owned_by})}return{source:"v1-models",upstreamVersion:null,builtinProviders:Array.from(Y.values()),customPool:Z,serverDiscoveryExcludes:[],upstreamTotal:X}}function H0($,j,J,Y){let Z=$.get(j);if(!Z)Z={name:j,api:J,models:[]},$.set(j,Z);Z.models.push(Y)}function G0($){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 W0($,j){let J=O0($.proxy.endpoint,j),Y=await pj($);if(Y)return K.info(`discovery via /.well-known/pi: ${Y.builtinProviders.length} builtin, ${Y.customPool.length} custom`),p$(Y,J),Y;if(!j)throw Error("well-known unavailable AND proxy apiKey is empty — cannot fall back to /v1/models. Set proxy.apiKey in config.");let Z=await cj($,j),X=lj(Z,$);return K.info(`discovery via /v1/models: ${X.builtinProviders.length} builtin, ${X.customPool.length} custom`),p$(X,J),X}function k0($){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}var T0=new WeakMap,c$=new WeakMap;function l$($){let j=(c$.get($)??0)+1;return c$.set($,j),j}function L$($,j){return j===void 0||j===(c$.get($)??0)}function B0($,j,J){let Y=T0.get($)??new Set;for(let Z of Y){if(j.has(Z))continue;$.unregisterProvider(Z),J.unregistered.push(Z)}T0.set($,new Set(j))}async function m$($,j,J,Y){let Z={registered:[],skipped:[],unregistered:[]};if(!L$($,Y))return Z.skipped.push({provider:"*",reason:"stale refresh generation"}),Z;let X=new Set,z=k0(J),Q=h(j.proxy.apiKey);if(!Q)return K.warn("proxy apiKey is empty — dm.registerProvider calls will be skipped"),B0($,X,Z),Z;let q=new Map;for(let M of J.builtinProviders)q.set(M.name,M.models.map((U)=>({id:U.id,name:U.name,reasoning:U.reasoning,contextWindow:U.contextWindow,maxTokens:U.maxTokens,cost:U.cost})));for(let[M,U]of Object.entries(j.builtinProviders)){if(!L$($,Y))return Z;if(!U?.enabled){Z.skipped.push({provider:M,reason:"disabled"});continue}if(!Array.isArray(U.models)||U.models.length===0){Z.skipped.push({provider:M,reason:"empty whitelist"});continue}let F=[];try{F=mj(M)}catch{}let T=new Map(F.map((N)=>[N.id,N])),O=new Map((q.get(M)??[]).map((N)=>[N.id,N])),D=[];for(let N of U.models){if(!z.has(N))continue;let G=T.get(N),n=O.get(N);if(G){D.push({id:G.id,name:G.name,reasoning:G.reasoning,contextWindow:G.contextWindow,maxTokens:G.maxTokens,cost:G.cost,input:G.input,api:G.api,thinkingLevelMap:G.thinkingLevelMap});continue}if(!n)continue;let j$=M==="anthropic"?"anthropic-messages":U.apiOverride??"openai-responses";D.push({id:n.id,name:n.name,reasoning:n.reasoning,contextWindow:n.contextWindow,maxTokens:n.maxTokens,cost:n.cost,input:["text"],api:j$})}if(D.length===0){Z.skipped.push({provider:M,reason:"no whitelisted models present on proxy"});continue}let A=U.apiOverride??D[0].api;if(!u$.has(A)){Z.skipped.push({provider:M,reason:`api "${A}" not in allowlist`});continue}let B=D.map((N)=>{let G=j.overrides[N.id]??{},n={id:N.id,name:typeof G.name==="string"?G.name:N.name,api:A,reasoning:typeof G.reasoning==="boolean"?G.reasoning:N.reasoning,input:N.input,cost:G.cost??N.cost,contextWindow:typeof G.contextWindow==="number"?G.contextWindow:N.contextWindow,maxTokens:typeof G.maxTokens==="number"?G.maxTokens:N.maxTokens};if(N.thinkingLevelMap)n.thinkingLevelMap=N.thinkingLevelMap;return n}),C={name:M,baseUrl:v$(A,j.proxy.endpoint),apiKey:Q,authHeader:!0,api:A,models:B};$.registerProvider(M,C),X.add(M),Z.registered.push({provider:M,modelCount:B.length,api:A})}let V=new Map(J.customPool.map((M)=>[M.id,M]));for(let[M,U]of Object.entries(j.customProviders)){if(!L$($,Y))return Z;if(!u$.has(U.api)){Z.skipped.push({provider:M,reason:`api "${U.api}" not in allowlist`});continue}let F=U.models.filter((D)=>z.has(D.id));if(F.length===0){Z.skipped.push({provider:M,reason:"no configured models present on proxy"});continue}let T=F.map((D)=>{let A=V.get(D.id),B=Z$(D.id),C=j.overrides[D.id]??{};return{id:D.id,name:D.name??A?.name??B.name??D.id,api:U.api,reasoning:sj(D.reasoning,A?.reasoning,B.reasoning,C.reasoning)??!1,input:["text"],cost:D.cost??A?.cost??B.cost??{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:L0(D.contextWindow,A?.contextWindow,B.contextWindow,C.contextWindow)??128000,maxTokens:L0(D.maxTokens,A?.maxTokens,B.maxTokens,C.maxTokens)??16000}}),O={name:M,baseUrl:v$(U.api,j.proxy.endpoint),apiKey:Q,authHeader:!0,api:U.api,models:T};$.registerProvider(M,O),X.add(M),Z.registered.push({provider:M,modelCount:T.length,api:U.api})}if(L$($,Y))B0($,X,Z);return K.info(`applyAll: registered ${Z.registered.length} providers, skipped ${Z.skipped.length}, unregistered ${Z.unregistered.length}`),Z}function L0(...$){for(let j of $)if(typeof j==="number")return j;return}function sj(...$){for(let j of $)if(typeof j==="boolean")return j;return}var oj=15000,D$=null;function K$(){D$=null}async function K0($,j,J={}){if(!J.force&&D$&&Date.now()-D$.fetchedAt<$.usageCacheTtlMs)return D$.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")),oj),z;try{z=await fetch(Y,{headers:{"X-Plugin-Key":j,Accept:"application/json","User-Agent":Q$},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 D$={fetchedAt:Date.now(),doc:Q},K.debug("usage fetched, accounts:",Q.accounts.length),Q}import{visibleWidth as o$}from"@duckmind/dm-tui";import{visibleWidth as F0}from"@duckmind/dm-tui";function S($,j){let J=F0($);if(J===j)return $;if(J<j)return $+" ".repeat(j-J);return s$($,j)}function s$($,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=F0(X);if(Y+z>j)break;J+=X,Y+=z,Z++}return`${J}\x1B[0m`}var ij="│",rj="╭",dj="╮",tj="╰",aj="╯",R$="─";function r($,j){let J=Math.max(4,j.width);return[ej($,j.title,j.titleColor??"accent",J),...j.lines.map((Y)=>$1($,Y,J)),j1($,j.footer,J)]}function ej($,j,J,Y){let Z=j??"",X=o$(Z),z=Math.max(0,Y-3-X),Q=Z?$.bold($.fg(J,Z)):"",q=`${rj}${R$}${Q}${R$.repeat(z)}${dj}`;return $.fg("borderAccent",q)}function $1($,j,J){let Y=Math.max(0,J-2),Z=$.fg("borderAccent",ij);return`${Z}${S(j,Y)}${Z}`}function j1($,j,J){let Y=`${tj}${R$}`,Z=`${aj}`,X=3;if(!j||!j.hint&&!j.badge){let O=Math.max(0,J-3);return $.fg("borderAccent",`${Y}${R$.repeat(O)}${Z}`)}let z=j.hint??"",Q=j.badge??"",q=o$(z),V=o$(Q),M=Math.max(0,J-3-q-V),U=$.fg("dim",z),F=Q?$.fg("muted",Q):"",T=R$.repeat(M);return`${$.fg("borderAccent",Y)}${U}${$.fg("borderAccent",T)}${F}${$.fg("borderAccent",Z)}`}function F$($){return Math.max(0,$-2)}import{existsSync as S0}from"node:fs";import{homedir as J1}from"node:os";import{getKeybindings as Y1,Input as i$,matchesKey as Z1}from"@duckmind/dm-tui";var X1=[{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. Input is masked; blank keeps an existing key",required:!0,secret:!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. Input is masked; blank keeps it, '-' clears it",required:!1,secret:!0}];async function I0($,j=!1){let J=T$(),Y={endpoint:J.proxy.endpoint??"",apiKey:J.proxy.apiKey??"",providerPrefix:J.proxy.providerPrefix??"",usageKey:J.proxy.usageKey??""},Z=!1;for(let z of X1){let Q=Y[z.label]??"",q=z.secret?"":j?Y[z.label]??z.initialValue??"":Y[z.label]??"";if(!j&&q)continue;let V=z.secret&&Q?{...z,required:!1}:z,M=await q1($,V,q||z.initialValue||"");if(M===void 0){Z=!0;break}let U=z1(z,Q,M);if(U===null){if(z.required){$.ui.notify(`${z.label} is required — aborted`,"warning"),Z=!0;break}}Y[z.label]=U??""}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 B$(X),$.ui.notify(`saved to ${l}`,"info"),!0}function Q1($){if($.startsWith("!")||$.startsWith("$"))return $;if($.startsWith("~/")){let j=$.replace(/^~/,J1());return S0(j)?`!cat ${$}`:$}if($.startsWith("/"))return S0($)?`!cat ${$}`:$;return $}function z1($,j,J){let Y=J.trim();if(!Y){if($.secret&&j)return j;return $.required?null:""}if($.secret&&!$.required&&Y==="-")return"";return $.label==="providerPrefix"||$.label==="endpoint"?Y:Q1(Y)}async function q1($,j,J){return $.ui.custom((Y,Z,X,z)=>M1(Y,Z,j,J,z),{overlay:!0,overlayOptions:{width:100,maxHeight:"60%"}})}class b0{rawInput=new i$;displayInput=new i$;pasteActive=!1;get focused(){return this.rawInput.focused}set focused($){this.rawInput.focused=$,this.displayInput.focused=$}set onSubmit($){this.rawInput.onSubmit=$}set onEscape($){this.rawInput.onEscape=$}getValue(){return this.rawInput.getValue()}setValue($){this.rawInput.setValue($),this.displayInput.setValue("•".repeat($.length))}handleInput($){this.rawInput.handleInput($),this.displayInput.handleInput(this.maskInput($)),this.displayInput.setValue("•".repeat(this.rawInput.getValue().length))}render($){return this.displayInput.render($)}invalidate(){this.rawInput.invalidate(),this.displayInput.invalidate()}maskInput($){let j="";for(let J=0;J<$.length;){if($.startsWith("\x1B[200~",J)){this.pasteActive=!0,j+="\x1B[200~",J+=6;continue}if($.startsWith("\x1B[201~",J)){this.pasteActive=!1,j+="\x1B[201~",J+=6;continue}if(!this.pasteActive&&$.charCodeAt(J)===27)return $;let Y=$.codePointAt(J),Z=String.fromCodePoint(Y);j+=Y<32||Y===127?Z:"•",J+=Z.length}return j}}function M1($,j,J,Y,Z){let X=J.secret?new b0:new i$;X.setValue(Y),X.focused=!0;let z=null,Q=(q)=>{if(!q&&!J.required){Z("");return}if(!q&&J.required){z="required field",$.requestRender();return}if(J.validate){let V=q.trim();if(V&&!V.startsWith("!")&&!V.startsWith("$")){let M=J.validate(V);if(M){z=M,$.requestRender();return}}}Z(q)};return X.onSubmit=Q,X.onEscape=()=>Z(void 0),{render(q){let V=F$(q),M=X.render(V-4),U=["",` ${j.fg("dim",J.hint)}`,"",...M.map((F)=>` ${j.fg("accent",`❯ ${F}`)}`),"",z?` ${j.fg("error",`! ${z}`)}`:` ${j.fg("dim","enter = save · esc = cancel")}`];return r(j,{width:q,title:` setup: ${J.label} `,lines:U,footer:{hint:" enter = save · esc = cancel "}})},invalidate(){X.invalidate()},handleInput(q){if(Y1().matches(q,"tui.select.cancel")||Z1(q,"escape")){Z(void 0);return}z=null,X.handleInput(q),$.requestRender()}}}import{visibleWidth as S$}from"@duckmind/dm-tui";function x0($,j,J,Y){let Z=$.fg("borderAccent","│"),X=j.map((z,Q)=>{let q=`${Q+1} ${z.label}`;return Q===J?$.bold($.fg("accent",` ${q} `)):$.fg("dim",` ${q} `)});return S(` ${X.join(Z)}`,Y)}function n0($,j,J){let Y=j.join($.fg("dim"," "));return S(` ${Y}`,J)}function P0($,j){return $.fg("borderAccent","─".repeat(Math.max(0,j)))}function d($,j,J){let Y=$.slice(j,j+J);while(Y.length<J)Y.push("");return Y}function I$($,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)),q=Q+X;if($<q)Q=Math.max(0,$-X);let V=Q+Y-1;if(j>V)Q=Math.min(z,j-(Y-1));return Q}function b$($,j,J){let Y=Math.max(0,J-j);return Math.max(0,Math.min($,Y))}import{matchesKey as t}from"@duckmind/dm-tui";import{existsSync as V1,readFileSync as U1}from"node:fs";import{homedir as C0}from"node:os";import{join as w0}from"node:path";var E1=w0(C0(),".dm","models.json"),D1=w0(C0(),".dm","auth.json");function y0($){if(!V1($))return null;try{return JSON.parse(U1($,"utf8"))}catch{return null}}function u0($){let j=[],J=new Set([...Object.keys($.builtinProviders),...Object.keys($.customProviders)]),Y=y0(E1);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=y0(D1);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 v0($){let{theme:j,cfg:J}=$,Y=0,Z=()=>{let Q=$.getDiscovery(),q=(O)=>j.fg("success",O),V=(O)=>j.fg("error",O),M=(O)=>j.fg("dim",O),U=[];U.push(`${M("endpoint")} ${J.proxy.endpoint||V("(unset)")}`),U.push(`${M("apiKey")} ${h(J.proxy.apiKey)?q("resolves"):V("empty after resolution")}`),U.push(`${M("usageKey")} ${J.proxy.usageKey?h(J.proxy.usageKey)?q("resolves"):V("set but empty"):M("not configured")}`),U.push(`${M("user-agent")} ${Q$}`),U.push(""),U.push(`${M("discovery")} source=${Q.source}`),U.push(`${M("upstream")} v=${Q.upstreamVersion??"(unknown)"} · ${Q.upstreamTotal} ids`);let F=Q.builtinProviders.map((O)=>`${O.name}=${O.models.length}`).join(", ")||M("(none)");U.push(`${M("built-in")} ${F}`),U.push(`${M("custom pool")} ${Q.customPool.length} models`);let T=u0(J);if(U.push(""),T.length===0)U.push(`${M("conflicts")} ${q("none")}`);else{U.push(`${M("conflicts")}`);for(let O of T)U.push(` ${j.fg("warning",`[${O.kind}]`)} ${O.detail}`)}return U};return{id:"diagnostics",label:"Diagnostics",render:(Q,q)=>{let V=Z();return Y=b$(Y,q,V.length),d(V,Y,q).map((M)=>S(` ${M}`,Q))},handleInput:(Q)=>{let q=Z().length;if(t(Q,"up")||t(Q,"k"))return Y=Math.max(0,Y-1),!0;if(t(Q,"down")||t(Q,"j"))return Y=Math.min(Math.max(0,q-1),Y+1),!0;if(t(Q,"pageUp")||t(Q,"b"))return Y=Math.max(0,Y-10),!0;if(t(Q,"pageDown")||t(Q,"f"))return Y=Math.min(Math.max(0,q-1),Y+10),!0;return!1},footerHint:()=>" ↑↓ scroll · r refresh discovery "}}import{matchesKey as k}from"@duckmind/dm-tui";function r$($){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 R1($){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 $$($,j){if(j.kind==="builtin")return[...$.builtinProviders[j.name]?.models??[]];return $.customProviders[j.name]?.models.map((J)=>J.id)??[]}function g0($,j,J){if(j.kind==="builtin"){let X=J.builtinModelIds.get(j.name)??[],z=new Set($$($,j));return X.filter((Q)=>!z.has(Q))}let Y=R1($),Z=new Set($$($,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 f0($,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 h0($,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 d$($,j){if($===j)return!0;let J=["openai-completions","openai-responses"];if(J.includes($)&&J.includes(j))return!0;return!1}function p0($,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 c0($,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 A1,getProviders as O1}from"@duckmind/dm-ai/compat";function t$($,j){let J=[],Y=new Set(j.builtinModelIds.keys()),Z=new Set(O1()),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 q;try{let M=A1(z).find((U)=>Q.includes(U.id));if(M)q=M.api}catch{}if(!q){let V=Q[0];q=j.byId.get(V)?.suggestedApi??"openai-responses"}if(J.push({kind:"builtin",name:z,api:q,subtitle:`built-in · ${q}`}),!$.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 H1,matchesKey as z$}from"@duckmind/dm-tui";async function l0($,j){return $.ui.custom((J,Y,Z,X)=>G1(Y,`Remove custom group “${j}”?`,"All model assignments in this group will be discarded.",X),{overlay:!0,overlayOptions:{width:80,maxHeight:"40%"}})}function G1($,j,J,Y){return{render(Z){return r($,{width:Z,title:" confirm ",titleColor:"error",lines:["",` ${$.bold(j)}`,` ${$.fg("dim",J)}`,""],footer:{hint:" y / enter = remove · n / esc = cancel "}})},invalidate(){},handleInput(Z){if(H1().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 N1,Input as W1,matchesKey as k1}from"@duckmind/dm-tui";async function m0($,j){let J=H$(j,"group");return $.ui.custom((Y,Z,X,z)=>T1(Y,Z,J,z),{overlay:!0,overlayOptions:{width:80,maxHeight:"40%"}})}function T1($,j,J,Y){let Z=new W1;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=F$(z),q=J?`name shown in /model picker, e.g. ${J}`:"letters / digits / dot / dash / underscore",V=Z.render(Q-4),M=["",` ${j.fg("dim",q)}`,"",...V.map((U)=>` ${j.fg("accent",`❯ ${U}`)}`),"",X?` ${j.fg("error",`! ${X}`)}`:""];return r(j,{width:z,title:" new custom group ",lines:M,footer:{hint:" enter = create · esc = cancel "}})},invalidate(){Z.invalidate()},handleInput(z){if(N1().matches(z,"tui.select.cancel")||k1(z,"escape")){Y(null);return}X=null,Z.handleInput(z),$.requestRender()}}}import{visibleWidth as B1}from"@duckmind/dm-tui";function a$($,j,J){if(!j)return" ";if(J)return $.fg("accent","▶ ");return $.fg("muted","▸ ")}function s0($,j){let J=B1($);if(J===j)return $;if(J>j)return s$($,j);return S($,j)}function o0($,j,J){let{theme:Y,width:Z,isCursor:X,isFocused:z}=J,Q=a$(Y,X,z),q=$.kind==="builtin"?j.builtinProviders[$.name]?.models.length??0:j.customProviders[$.name]?.models.length??0,V=$.kind==="builtin"?Y.fg("accent","B"):Y.fg("warning","C"),M=`${Y.fg("dim","[")}${V}${Y.fg("dim","]")}`,U=q>0?Y.fg("success","●"):Y.fg("dim","○"),F=q>0?Y.fg("success",String(q).padStart(2)):Y.fg("dim"," 0"),T=X&&z?Y.bold(Y.fg("accent",$.name)):X?Y.bold($.name):$.name,O=Y.fg("dim",$.api),D=`${Q}${M} ${T} ${U}${F} ${O}`;return s0(D,Z)}function i0($,j,J,Y){let Z=a$($,j,J),X=j&&J?$.bold($.fg("accent","+ new custom group…")):$.fg("accent","+ new custom group…");return S(`${Z}${X}`,Y)}function e$($,j,J,Y,Z){let{theme:X,width:z,isCursor:Q,isFocused:q}=Z,V=a$(X,Q,q),M=J==="assigned"?X.fg("success","☑"):X.fg("dim","☐"),U=Y?` ${X.fg("warning","⚠")}`:"",F=Q&&q?X.fg("accent",$):$,T=j?.reasoning?` ${X.fg("accent","✨")}`:"",O=j?X.fg("muted",` · ${j.suggestedApi}`):X.fg("error"," · not on proxy"),D=`${V}${M} ${F}${U}${T}${O}`;return s0(D,z)}function r0($,j,J){let Y=`${$.fg("borderAccent","──")} ${$.fg("warning",j)} ${$.fg("borderAccent","──")}`;return S(` ${Y}`,J)}function $0($,j,J){return S(` ${$.fg("dim",j)}`,J)}function d0($,j,J,Y){let Z=Y?$.bold($.fg("accent","❚ ")):$.fg("dim"," ");return S(`${Z}${j}`,J)}function t0($){let{tui:j,theme:J,ctx:Y,cfg:Z}=$,X=$.onChange??(()=>{}),z=r$($.getDiscovery()),Q=t$(Z,z),q="providers",V=0,M=0,U=0,F=0,T=0,O=0,D="",A=!1,B=()=>{if(Q.length===0)return null;let E=Math.max(0,Math.min(V,Q.length-1));return Q[E]??null},C=(E)=>{let H=c0(g0(Z,E,z),z,D);return p0(H,z)},N=(E)=>C(E).flatMap((H)=>H.ids),G=()=>{Q=t$(Z,z);let E=Math.max(0,Q.length);if(V>E)V=E;let H=B();if(H){let x=$$(Z,H).length,W=N(H).length;if(M>=x)M=Math.max(0,x-1);if(U>=W)U=Math.max(0,W-1)}},n=()=>{z=r$($.getDiscovery()),G()},j$=(E)=>{let H=["providers","assigned","pool"],x=H.indexOf(q);q=E?H[(x-1+H.length)%H.length]:H[(x+1)%H.length]},_=(E)=>{if(q==="providers"){let W=Q.length+1;V=Math.max(0,Math.min(V+E,W-1));return}let H=B();if(!H)return;if(q==="assigned"){let W=$$(Z,H).length;if(W===0)return;M=Math.max(0,Math.min(M+E,W-1));return}let x=N(H).length;if(x===0)return;U=Math.max(0,Math.min(U+E,x-1))},b=async()=>{if(q==="providers"){if(V===Q.length){let W=await m0(Y,Z.proxy.providerPrefix);if(W&&!Z.customProviders[W]){if(Z.customProviders[W]={api:"openai-completions",models:[]},X(),G(),V=Q.findIndex((I)=>I.kind==="custom"&&I.name===W),V<0)V=Q.length-1;q="pool"}j.requestRender();return}q="pool";return}let E=B();if(!E)return;if(q==="assigned"){let W=$$(Z,E)[M];if(!W)return;h0(Z,E,W),X(),G();return}let H=N(E)[U];if(!H)return;let x=z.byId.get(H);if(!x)return;f0(Z,E,x),X(),G()},p=async()=>{if(q!=="providers")return;let E=B();if(!E||E.kind!=="custom")return;if(!await l0(Y,E.name)){j.requestRender();return}if(delete Z.customProviders[E.name],X(),G(),V>=Q.length)V=Math.max(0,Q.length-1);j.requestRender()},v=(E,H)=>c(E,H);function c(E,H){let x=Math.max(70,E),W=Math.min(56,Math.max(34,Math.floor(x*0.4))),I=x-W-1,s=Math.max(8,H),o=Math.max(5,Math.floor((s-1)/2)),j0=s-o,m=B(),q$=0,x$=0,n$=0,J0=0,P$=0,Y0=0,a=[];a.push(J$(" providers ",W,q==="providers"));for(let L=0;L<Q.length;L++){let g=Q[L],w=q==="providers"&&L===V;if(w)q$=a.length,x$=q$;a.push(o0(g,Z,{theme:J,width:W,isCursor:w,isFocused:q==="providers"}))}{let L=q==="providers"&&V===Q.length;if(L)q$=a.length,x$=q$;a.push(i0(J,L,q==="providers",W))}let e=[],qj=m?`assigned to ${J.bold(m.name)} ${J.fg("dim",`· ${m.api}`)}`:J.fg("dim","no provider selected");if(e.push(J$(" assigned ",I,q==="assigned")),e.push(d0(J,qj,I,q==="assigned")),m){let L=$$(Z,m);if(L.length===0)e.push($0(J,"(nothing assigned yet)",I));for(let g=0;g<L.length;g++){let w=L[g],f=z.byId.get(w),O$=q==="assigned"&&g===M;if(O$)n$=e.length,J0=n$;let Y$=f?!d$(m.api,f.suggestedApi):!1;e.push(e$(w,f,"assigned",Y$,{theme:J,width:I,isCursor:O$,isFocused:q==="assigned"}))}}let i=[];if(i.push(P(I,q==="pool")),m){let L=C(m);if(L.reduce((w,f)=>w+f.ids.length,0)===0)i.push($0(J,D?`(no matches for "${D}")`:"(no models available)",I));else{let w=0;for(let f of L){let O$=i.length;i.push(r0(J,f.label,I));for(let Y$=0;Y$<f.ids.length;Y$++){let M0=f.ids[Y$],C$=z.byId.get(M0),V0=q==="pool"&&w===U;if(V0)P$=i.length,Y0=Y$===0?O$:P$;let Ej=C$?!d$(m.api,C$.suggestedApi):!1;i.push(e$(M0,C$,"pool",Ej,{theme:J,width:I,isCursor:V0,isFocused:q==="pool"})),w++}}}}let Mj=Math.max(1,j0-1),Z0=I$(x$,q$,F,s,a.length,1),X0=I$(q==="assigned"?J0:0,q==="assigned"?n$:0,T,o,e.length,2),Q0=I$(q==="pool"?Y0:0,q==="pool"?P$:0,O,Mj,i.length,1);F=Z0,T=X0,O=Q0;let z0=d(a,Z0,s),Vj=d(e,X0,o),Uj=d(i,Q0,j0),q0=J.fg("borderAccent","│"),y$=[];for(let L=0;L<s;L++){let g=S(z0[L]??"",W),w=L<o?Vj[L]:Uj[L-o],f=S(w,I);y$.push(`${g}${q0}${f}`)}let A$=o;if(A$>0&&A$<s){let L=S(z0[A$]??"",W),g=J.fg("borderAccent","─".repeat(I));y$[A$]=`${L}${q0}${g}`}return y$}function J$(E,H,x){let W=x?J.bold(J.fg("accent",E)):J.fg("muted",E),I=J.fg("borderAccent","─".repeat(Math.max(0,H-S$(E)-1)));return S(`${W}${I}`,H)}function P(E,H){let W=H?J.bold(J.fg("accent"," available pool ")):J.fg("muted"," available pool "),I="";if(A)I=`${J.fg("dim"," /")}${J.fg("accent",D)}${J.fg("accent","█")} `;else if(D)I=`${J.fg("dim"," /")}${J.fg("warning",D)} `;let s=S$(" available pool ")+S$(I),o=J.fg("borderAccent","─".repeat(Math.max(0,E-s-1)));return S(`${W}${I}${o}`,E)}function _$(E){if(A){if(k(E,"escape"))return D="",A=!1,U=0,!0;if(k(E,"enter")||k(E,"return"))return A=!1,!0;if(k(E,"backspace")||k(E,"delete"))return D=D.slice(0,-1),U=0,!0;if(E.length===1&&E>=" "&&E!=="")return D+=E,U=0,!0;return!0}if(k(E,"tab"))return j$(!1),!0;if(k(E,"shift+tab"))return j$(!0),!0;if(k(E,"/"))return q="pool",A=!0,!0;if(k(E,"enter")||k(E,"return")||k(E,"space"))return b().then(()=>!0);if(q==="providers"&&(k(E,"d")||k(E,"delete")||k(E,"backspace")))return p().then(()=>!0);if(k(E,"up")||k(E,"k"))return _(-1),!0;if(k(E,"down")||k(E,"j"))return _(1),!0;if(k(E,"pageUp")||k(E,"b"))return _(-8),!0;if(k(E,"pageDown")||k(E,"f"))return _(8),!0;if(k(E,"left")||k(E,"h"))return q="providers",!0;if(k(E,"right")||k(E,"l")){if(q==="providers")q="assigned";else if(q==="assigned")q="pool";return!0}return!1}function zj(){if(A)return" type to filter · ↵ apply · esc clear ";return" tab ↔ panel · ↑↓ nav · ↵ move · / filter · d remove group "}return{id:"models",label:"Models",render:v,handleInput:_$,footerHint:zj,rebuild:n}}import{matchesKey as y}from"@duckmind/dm-tui";var R={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 a0($,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(`${R.dim}generated ${$.generatedAt}${R.reset}`),$.unsupportedProviders.length>0)J.push(`${R.dim}providers without quota lookup:${R.reset} ${$.unsupportedProviders.join(", ")}`);if(Z>0)J.push(`${R.dim}hidden disabled accounts:${R.reset} ${Z} ${R.dim2}(press d to show)${R.reset}`);for(let[X,z]of Array.from(Y.entries()).sort()){J.push(""),J.push(`${R.bold}${R.accent}▌ ${X}${R.reset}`);for(let Q of z){if(J.push(K1(Q)),!Q.supported){J.push(` ${R.dim2}(provider not quota-aware)${R.reset}`);continue}if(Q.error){if(j.verbose)for(let V of L1(Q.error,88))J.push(` ${R.red}${V}${R.reset}`);continue}let q=Q.groups??[];if(q.length===0){J.push(` ${R.dim2}(no active quota windows)${R.reset}`);continue}for(let V of q)J.push(S1(V))}}return J.push(""),J.push(`${R.dim}legend:${R.reset} ${e0} ok ${$j} error/unavailable ${jj} disabled ${R.green}✓N${R.reset}/${R.red}✗N${R.reset} request counters ${R.dim}v = verbose, d = show disabled${R.reset}`),J}function L1($,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 K1($){let j=F1($),J=`${R.green}✓${$.success}${R.reset} ${R.red}✗${$.failed}${R.reset}`,Y=Zj($.label,36);return` ${j} ${R.bold}${Y}${R.reset} ${J}`}var e0=`${R.green}●${R.reset}`,$j=`${R.yellow}⚠${R.reset}`,jj=`${R.dim2}⊘${R.reset}`;function F1($){if($.disabled)return jj;if($.unavailable||$.error||$.status&&$.status!=="active")return $j;return e0}function S1($){let j=Yj($.remainingFraction),J=Math.round(j*100),Y=I1(j),Z=$.resetTime?` ${R.dim}reset ${x1($.resetTime)}${R.reset}`:"",X=Zj($.label,28).padEnd(28," ");return` ${Y} ${b1(J,j)} ${X}${Z}`}function I1($){let j=Yj($),J=Math.round(j*18),Y=Jj(j),Z=R.dim2,X="█".repeat(J),z="░".repeat(18-J);return`${Z}[${Y}${X}${Z}${z}]${R.reset}`}function b1($,j){return`${Jj(j)}${String($).padStart(3)}%${R.reset}`}function Jj($){if($>=0.4)return R.green;if($>=0.15)return R.yellow;return R.red}function x1($){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 Yj($){return Math.max(0,Math.min(1,$))}function Zj($,j){if($.length<=j)return $;return`${$.slice(0,j-1)}…`}function Xj($){let{tui:j,theme:J,cfg:Y}=$,Z="idle",X=null,z="",Q=0,q=!1,V=!1,M=(D)=>{Z="loading",j.requestRender();let A=h(Y.proxy.usageKey);K0(Y,A,{force:D}).then((B)=>{X=B,Z="ready",Q=0,j.requestRender()}).catch((B)=>{z=B.message,Z="error",j.requestRender()})},U=()=>{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 a0(X,{showDisabled:q,verbose:V})};return{id:"usage",label:"Usage",render:(D,A)=>{let B=U();return Q=b$(Q,A,B.length),d(B,Q,A).map((C)=>S(` ${C}`,D))},handleInput:(D)=>{if(y(D,"d"))return q=!q,Q=0,!0;if(y(D,"v"))return V=!V,Q=0,!0;let A=U().length;if(y(D,"up")||y(D,"k"))return Q=Math.max(0,Q-1),!0;if(y(D,"down")||y(D,"j"))return Q=Math.min(Math.max(0,A-1),Q+1),!0;if(y(D,"pageUp")||y(D,"b"))return Q=Math.max(0,Q-10),!0;if(y(D,"pageDown")||y(D,"f"))return Q=Math.min(Math.max(0,A-1),Q+10),!0;if(y(D,"home")||y(D,"g"))return Q=0,!0;if(y(D,"end")||y(D,"shift+g"))return Q=Math.max(0,A-1),!0;return!1},footerHint:()=>{let D=q?J.fg("success","[d disabled]"):"d disabled",A=V?J.fg("success","[v verbose]"):"v verbose";return` ↑↓ scroll · ${D} · ${A} `},onActivate:()=>{if(Z==="idle")M(!1)},reload:()=>{if(K$(),Z!=="idle")M(!0)}}}function Qj($){let{dm:j,ctx:J,tui:Y,theme:Z,cfg:X,done:z}=$,Q=$.discovery,q=!1,V="",M=t0({tui:Y,theme:Z,ctx:J,cfg:X,getDiscovery:()=>Q,onChange:()=>{q=!0,V=""}}),U=Xj({tui:Y,theme:Z,cfg:X}),F=v0({theme:Z,cfg:X,getDiscovery:()=>Q}),T=[M,U,F],O=0,D=()=>T[O],A=(_)=>{if(_<0||_>=T.length||_===O)return;O=_,D().onActivate?.(),Y.requestRender()},B=()=>{V=Z.fg("dim","saving…"),B$(X),Y.requestRender();let _=l$(j);m$(j,X,Q,_).then((b)=>{q=!1,V=Z.fg("success",`✓ settings saved · ${b.registered.length} registered, ${b.skipped.length} skipped`),Y.requestRender()}).catch((b)=>{V=Z.fg("error",`save failed: ${b.message}`),Y.requestRender()})},C=async()=>{V=Z.fg("dim","refreshing…"),Y.requestRender();try{let _=l$(j),b=h(X.proxy.apiKey);Q=await W0(X,b),K$(),M.rebuild(),U.reload();let p=await m$(j,X,Q,_);V=Z.fg("success",`✓ refreshed · ${p.registered.length} providers (${Q.source})`)}catch(_){V=Z.fg("error",`refresh failed: ${_.message}`)}Y.requestRender()},N=async()=>{if(!await I0(J,!0)){Y.requestRender();return}let b=T$();X.proxy={...X.proxy,...b.proxy},await C()},G=()=>{let _=X.proxy.endpoint||"(unset)",b=_.length>40?`…${_.slice(-39)}`:_,p=Boolean(h(X.proxy.apiKey)),v=0,c=0;for(let P of Object.values(X.builtinProviders)){if(P.enabled&&P.models.length>0)v++;c+=P.models.length}for(let P of Object.values(X.customProviders)){if(P.models.length>0)v++;c+=P.models.length}let J$=V?V:q?Z.fg("warning","● unsaved — press s to save"):Z.fg("dim","✓ saved");return[`${Z.fg("dim","endpoint")} ${b}`,`${Z.fg("dim","key")} ${p?Z.fg("success","✓"):Z.fg("error","✗")}`,`${Z.fg("dim","providers")} ${v}`,`${Z.fg("dim","models")} ${c}`,J$]},n=(_)=>{let b=Y.rows??40,v=Math.max(16,Math.min(b-6,38))-2,c=Math.max(72,_-2),J$=Math.max(6,v-3),P=[];return P.push(n0(Z,G(),c)),P.push(x0(Z,T.map((_$)=>({id:_$.id,label:_$.label})),O,c)),P.push(P0(Z,c)),P.push(...D().render(c,J$)),r(Z,{width:_,title:" /cliproxy ",lines:P,footer:{hint:D().footerHint(),badge:" [ ] tab · r refresh · e setup · s save · q close "}})},j$=(_)=>{if(n1().matches(_,"tui.select.cancel")||u(_,"q")||u(_,"escape"))return z(),!0;if(u(_,"]")||u(_,"tab"))return A((O+1)%T.length),!0;if(u(_,"[")||u(_,"shift+tab"))return A((O-1+T.length)%T.length),!0;if(u(_,"1"))return A(0),!0;if(u(_,"2"))return A(1),!0;if(u(_,"3"))return A(2),!0;if(u(_,"r"))return C().then(()=>!0);if(u(_,"e"))return N().then(()=>!0);if(u(_,"s"))return B(),!0;return!1};return{render:n,invalidate(){},handleInput(_){let b=D().handleInput(_);if(b instanceof Promise){V="",b.then((v)=>{if(v)Y.requestRender()});return}if(b){V="",Y.requestRender();return}let p=j$(_);if(p instanceof Promise)p.then((v)=>{if(v)Y.requestRender()});else if(p)Y.requestRender()}}}async function FJ($,j,J,Y){if(!j.hasUI){j.ui.notify("interactive UI required for /cliproxy","warning");return}let Z=structuredClone(J);w$(!0);try{await j.ui.custom((X,z,Q,q)=>Qj({dm:$,ctx:j,tui:X,theme:z,cfg:Z,discovery:Y,done:q}),{overlay:!0,overlayOptions:{width:170,maxHeight:"94%"}})}finally{w$(!1)}}export{FJ 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 Y}from"@duckmind/dm-tui";import{execSync as U}from"node:child_process";import{homedir as H}from"node:os";import{dirname as T,join as Q}from"node:path";var r=!1;var v={info(...n){if(!r)console.log("[dm-cliproxy]",...n)},warn(...n){if(!r)console.warn("[dm-cliproxy]",...n)},error(...n){if(!r)console.error("[dm-cliproxy]",...n)},debug(...n){if(!r&&(process.env.DM_CLIPROXY_DEBUG||process.env.PI_CLIPROXYAPI_DEBUG))console.log("[dm-cliproxy]","[debug]",...n)}};var K=Q(H(),".dm","agent","dm-cliproxy"),g=Q(K,"config.json"),h=[Q(H(),".pi","agent","pi-cliproxyapi","config.json"),Q(H(),".config","pi-cliproxyapi","config.json")];function W(n){if(!n)return"";let $=n.trim();if($.startsWith("!"))try{return U($.slice(1),{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).trim()}catch(s){let o=s?.status,M=typeof o==="number"?` (exit ${o})`:"";return v.warn(`failed to resolve "!" config value${M}`),""}if($.startsWith("$"))return process.env[$.slice(1)]??"";return $}import{existsSync as x,readFileSync as B}from"node:fs";import{homedir as O}from"node:os";import{join as R}from"node:path";var G=R(O(),".dm","models.json"),I=R(O(),".dm","auth.json");function q(n){if(!x(n))return null;try{return JSON.parse(B(n,"utf8"))}catch{return null}}function C(n){let $=[],s=new Set([...Object.keys(n.builtinProviders),...Object.keys(n.customProviders)]),o=q(G);if(o&&typeof o==="object"){for(let J of Object.keys(o))if(s.has(J))$.push({kind:"models.json",provider:J,detail:`provider "${J}" has user overrides in ~/.dm/models.json which DM merges on top of our registration`})}let M=q(I);if(M&&typeof M==="object"){for(let J of Object.keys(M))if(s.has(J))$.push({kind:"auth.json",provider:J,detail:`provider "${J}" has user-set credentials in ~/.dm/auth.json which take priority over our apiKey`})}return $}import{dirname as $n,join as N}from"node:path";var jn=N(K,"discovery-cache.json");var L="dm-cliproxy/0.3.5";import{visibleWidth as t}from"@duckmind/dm-tui";function X(n,$){let s=t(n);if(s===$)return n;if(s<$)return n+" ".repeat($-s);return w(n,$)}function w(n,$){if($<=0)return"\x1B[0m";let s="",o=0,M=0;while(M<n.length){let J=n[M];if(J==="\x1B"&&n[M+1]==="["){let j=n.indexOf("m",M+2);if(j>=0){s+=n.slice(M,j+1),M=j+1;continue}}let z=t(J);if(o+z>$)break;s+=J,o+=z,M++}return`${s}\x1B[0m`}import{visibleWidth as Xn}from"@duckmind/dm-tui";function p(n,$,s){let o=n.slice($,$+s);while(o.length<s)o.push("");return o}function A(n,$,s){let o=Math.max(0,s-$);return Math.max(0,Math.min(n,o))}function An(n){let{theme:$,cfg:s}=n,o=0,M=()=>{let j=n.getDiscovery(),f=(D)=>$.fg("success",D),Z=(D)=>$.fg("error",D),u=(D)=>$.fg("dim",D),V=[];V.push(`${u("endpoint")} ${s.proxy.endpoint||Z("(unset)")}`),V.push(`${u("apiKey")} ${W(s.proxy.apiKey)?f("resolves"):Z("empty after resolution")}`),V.push(`${u("usageKey")} ${s.proxy.usageKey?W(s.proxy.usageKey)?f("resolves"):Z("set but empty"):u("not configured")}`),V.push(`${u("user-agent")} ${L}`),V.push(""),V.push(`${u("discovery")} source=${j.source}`),V.push(`${u("upstream")} v=${j.upstreamVersion??"(unknown)"} · ${j.upstreamTotal} ids`);let E=j.builtinProviders.map((D)=>`${D.name}=${D.models.length}`).join(", ")||u("(none)");V.push(`${u("built-in")} ${E}`),V.push(`${u("custom pool")} ${j.customPool.length} models`);let k=C(s);if(V.push(""),k.length===0)V.push(`${u("conflicts")} ${f("none")}`);else{V.push(`${u("conflicts")}`);for(let D of k)V.push(` ${$.fg("warning",`[${D.kind}]`)} ${D.detail}`)}return V};return{id:"diagnostics",label:"Diagnostics",render:(j,f)=>{let Z=M();return o=A(o,f,Z.length),p(Z,o,f).map((u)=>X(` ${u}`,j))},handleInput:(j)=>{let f=M().length;if(Y(j,"up")||Y(j,"k"))return o=Math.max(0,o-1),!0;if(Y(j,"down")||Y(j,"j"))return o=Math.min(Math.max(0,f-1),o+1),!0;if(Y(j,"pageUp")||Y(j,"b"))return o=Math.max(0,o-10),!0;if(Y(j,"pageDown")||Y(j,"f"))return o=Math.min(Math.max(0,f-1),o+10),!0;return!1},footerHint:()=>" ↑↓ scroll · r refresh discovery "}}export{An 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 D}from"node:os";import{dirname as V0,join as G}from"node:path";var L=!1;var R={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 k=G(D(),".dm","agent","dm-cliproxy"),Z0=G(k,"config.json"),X0=[G(D(),".pi","agent","pi-cliproxyapi","config.json"),G(D(),".config","pi-cliproxyapi","config.json")];function T(J){if(!J)return"";let $=J.trim();if($.startsWith("!"))try{return p($.slice(1),{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).trim()}catch(Q){let Z=Q?.status,Y=typeof Z==="number"?` (exit ${Z})`:"";return R.warn(`failed to resolve "!" config value${Y}`),""}if($.startsWith("$"))return process.env[$.slice(1)]??"";return $}import{dirname as A0,join as y}from"node:path";var R0=y(k,"discovery-cache.json");var I="dm-cliproxy/0.3.5";var f=15000,W=null;function _(){W=null}async function F(J,$,Q={}){if(!Q.force&&W&&Date.now()-W.fetchedAt<J.usageCacheTtlMs)return W.doc;if(!$)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(),Y=new AbortController,j=setTimeout(()=>Y.abort(Error("timeout")),f),z;try{z=await fetch(Z,{headers:{"X-Plugin-Key":$,Accept:"application/json","User-Agent":I},signal:Y.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 W={fetchedAt:Date.now(),doc:X},R.debug("usage fetched, accounts:",X.accounts.length),X}import{visibleWidth as N}from"@duckmind/dm-tui";function K(J,$){let Q=N(J);if(Q===$)return J;if(Q<$)return J+" ".repeat($-Q);return h(J,$)}function h(J,$){if($<=0)return"\x1B[0m";let Q="",Z=0,Y=0;while(Y<J.length){let j=J[Y];if(j==="\x1B"&&J[Y+1]==="["){let X=J.indexOf("m",Y+2);if(X>=0){Q+=J.slice(Y,X+1),Y=X+1;continue}}let z=N(j);if(Z+z>$)break;Q+=j,Z+=z,Y++}return`${Q}\x1B[0m`}var V={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,$={}){let Q=[],Z=new Map,Y=0;for(let j of J.accounts){if(!$.showDisabled&&j.disabled){Y++;continue}let z=Z.get(j.provider)??[];z.push(j),Z.set(j.provider,z)}if(Q.push(`${V.dim}generated ${J.generatedAt}${V.reset}`),J.unsupportedProviders.length>0)Q.push(`${V.dim}providers without quota lookup:${V.reset} ${J.unsupportedProviders.join(", ")}`);if(Y>0)Q.push(`${V.dim}hidden disabled accounts:${V.reset} ${Y} ${V.dim2}(press d to show)${V.reset}`);for(let[j,z]of Array.from(Z.entries()).sort()){Q.push(""),Q.push(`${V.bold}${V.accent}▌ ${j}${V.reset}`);for(let X of z){if(Q.push(c(X)),!X.supported){Q.push(` ${V.dim2}(provider not quota-aware)${V.reset}`);continue}if(X.error){if($.verbose)for(let A of r(X.error,88))Q.push(` ${V.red}${A}${V.reset}`);continue}let H=X.groups??[];if(H.length===0){Q.push(` ${V.dim2}(no active quota windows)${V.reset}`);continue}for(let A of H)Q.push(d(A))}}return Q.push(""),Q.push(`${V.dim}legend:${V.reset} ${S} ok ${v} error/unavailable ${n} disabled ${V.green}✓N${V.reset}/${V.red}✗N${V.reset} request counters ${V.dim}v = verbose, d = show disabled${V.reset}`),Q}function r(J,$){if(J.length<=$)return[J];let Q=[],Z=J;while(Z.length>$){let Y=Z.lastIndexOf(" ",$);if(Y<$*0.6)Y=$;Q.push(Z.slice(0,Y)),Z=Z.slice(Y).replace(/^\s+/,"")}if(Z)Q.push(Z);return Q}function c(J){let $=l(J),Q=`${V.green}✓${J.success}${V.reset} ${V.red}✗${J.failed}${V.reset}`,Z=u(J.label,36);return` ${$} ${V.bold}${Z}${V.reset} ${Q}`}var S=`${V.green}●${V.reset}`,v=`${V.yellow}⚠${V.reset}`,n=`${V.dim2}⊘${V.reset}`;function l(J){if(J.disabled)return n;if(J.unavailable||J.error||J.status&&J.status!=="active")return v;return S}function d(J){let $=b(J.remainingFraction),Q=Math.round($*100),Z=o($),Y=J.resetTime?` ${V.dim}reset ${i(J.resetTime)}${V.reset}`:"",j=u(J.label,28).padEnd(28," ");return` ${Z} ${m(Q,$)} ${j}${Y}`}function o(J){let $=b(J),Q=Math.round($*18),Z=x($),Y=V.dim2,j="█".repeat(Q),z="░".repeat(18-Q);return`${Y}[${Z}${j}${Y}${z}]${V.reset}`}function m(J,$){return`${x($)}${String(J).padStart(3)}%${V.reset}`}function x(J){if(J>=0.4)return V.green;if(J>=0.15)return V.yellow;return V.red}function i(J){let $=Date.parse(J);if(!Number.isFinite($))return J;let Q=$-Date.now();if(Q<=0)return"now";let Z=Math.round(Q/60000);if(Z<60)return`${Z}m`;let Y=Math.round(Z/60);if(Y<48)return`${Y}h`;return`${Math.round(Y/24)}d`}function b(J){return Math.max(0,Math.min(1,J))}function u(J,$){if(J.length<=$)return J;return`${J.slice(0,$-1)}…`}import{visibleWidth as u0}from"@duckmind/dm-tui";function C(J,$,Q){let Z=J.slice($,$+Q);while(Z.length<Q)Z.push("");return Z}function P(J,$,Q){let Z=Math.max(0,Q-$);return Math.max(0,Math.min(J,Z))}function c0(J){let{tui:$,theme:Q,cfg:Z}=J,Y="idle",j=null,z="",X=0,H=!1,A=!1,B=(M)=>{Y="loading",$.requestRender();let E=T(Z.proxy.usageKey);F(Z,E,{force:M}).then((U)=>{j=U,Y="ready",X=0,$.requestRender()}).catch((U)=>{z=U.message,Y="error",$.requestRender()})},O=()=>{if(Y==="idle"||Y==="loading")return[Q.fg("dim"," loading usage…")];if(Y==="error")return[Q.fg("error",` usage failed: ${z}`)];if(!j)return[Q.fg("dim"," (no data)")];return w(j,{showDisabled:H,verbose:A})};return{id:"usage",label:"Usage",render:(M,E)=>{let U=O();return X=P(X,E,U.length),C(U,X,E).map((g)=>K(` ${g}`,M))},handleInput:(M)=>{if(q(M,"d"))return H=!H,X=0,!0;if(q(M,"v"))return A=!A,X=0,!0;let E=O().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=H?Q.fg("success","[d disabled]"):"d disabled",E=A?Q.fg("success","[v verbose]"):"v verbose";return` ↑↓ scroll · ${M} · ${E} `},onActivate:()=>{if(Y==="idle")B(!1)},reload:()=>{if(_(),Y!=="idle")B(!0)}}}export{c0 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 w}from"node:fs";import{homedir as LJ}from"node:os";import{getKeybindings as BJ,Input as I,matchesKey as RJ}from"@duckmind/dm-tui";import{execSync as c}from"node:child_process";import{randomUUID as F}from"node:crypto";import{chmodSync as T,closeSync as C,constants as h,copyFileSync as l,existsSync as L,fsyncSync as d,linkSync as n,mkdirSync as s,openSync as o,readFileSync as S,renameSync as i,rmSync as D,writeFileSync as a}from"node:fs";import{homedir as H}from"node:os";import{dirname as G,join as B}from"node:path";import{fileURLToPath as r}from"node:url";var V=!1;var E={info(...J){if(!V)console.log("[dm-cliproxy]",...J)},warn(...J){if(!V)console.warn("[dm-cliproxy]",...J)},error(...J){if(!V)console.error("[dm-cliproxy]",...J)},debug(...J){if(!V&&(process.env.DM_CLIPROXY_DEBUG||process.env.PI_CLIPROXYAPI_DEBUG))console.log("[dm-cliproxy]","[debug]",...J)}};var t=B(H(),".dm","agent","dm-cliproxy"),q=B(t,"config.json"),e=[B(H(),".pi","agent","pi-cliproxyapi","config.json"),B(H(),".config","pi-cliproxyapi","config.json")];function k(J){s(J,{recursive:!0,mode:448}),T(J,448)}function N(J){if(L(J))T(J,384)}function JJ(J){let Q;try{Q=JSON.parse(S(J,"utf8"))}catch{return}let X=Q&&typeof Q==="object"?Q.proxy:void 0;for(let Z of[X?.apiKey,X?.usageKey]){if(typeof Z!=="string")continue;let Y=/^!cat\s+((?:~\/|\/)[^\s;&|`]+)$/.exec(Z.trim());if(!Y)continue;let z=Y[1].replace(/^~/,H());N(z)}}function QJ(){return L(B(G(r(import.meta.url)),"..",".git"))}function XJ(J=e,Q=q,X=QJ()){if(L(Q))return;let Y=(typeof J==="string"?[J]:[...J]).find(($)=>L($));if(!Y)return;let z;try{N(Y),JJ(Y),k(G(Q)),z=`${Q}.${process.pid}.${F()}.tmp`,l(Y,z,h.COPYFILE_EXCL),T(z,384),n(z,Q),D(z),z=void 0,E.info("legacy config copied to",Q)}catch($){if(z)try{D(z,{force:!0})}catch(M){E.warn("failed to clean temporary config:",M)}E.warn("failed to migrate legacy config:",$)}}var O={proxy:{endpoint:"",apiKey:""},builtinProviders:{},customProviders:{},discoveryExcludes:["*:*"],overrides:{},refreshIntervalMinutes:0,usageCacheTtlMs:30000};function b(){if(XJ(),!L(q))return E.debug("config not found, using defaults at",q),structuredClone(O);try{k(G(q)),N(q);let J=JSON.parse(S(q,"utf8"));return YJ(J)}catch(J){return E.error("failed to read config:",J,"— using defaults"),structuredClone(O)}}function ZJ(J,Q=q){k(G(Q));let X=`${Q}.${process.pid}.${F()}.tmp`,Z;try{Z=o(X,"wx",384),a(Z,JSON.stringify(J,null,2)+`
|
|
2
|
+
`,{encoding:"utf8"}),d(Z),C(Z),Z=void 0,i(X,Q),N(Q)}finally{if(Z!==void 0)C(Z);D(X,{force:!0})}}function x(J){ZJ(J),E.info("config saved to",q)}function YJ(J){if(!J||typeof J!=="object")return structuredClone(O);let Q=J,X=structuredClone(O),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 v(J){if(!J)return"";let Q=J.trim();if(Q.startsWith("!"))try{return c(Q.slice(1),{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).trim()}catch(X){let Z=X?.status,Y=typeof Z==="number"?` (exit ${Z})`:"";return E.warn(`failed to resolve "!" config value${Y}`),""}if(Q.startsWith("$"))return process.env[Q.slice(1)]??"";return Q}import{visibleWidth as A}from"@duckmind/dm-tui";import{visibleWidth as P}from"@duckmind/dm-tui";function y(J,Q){let X=P(J);if(X===Q)return J;if(X<Q)return J+" ".repeat(Q-X);return $J(J,Q)}function $J(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 M=J.indexOf("m",Y+2);if(M>=0){X+=J.slice(Y,M+1),Y=M+1;continue}}let $=P(z);if(Z+$>Q)break;X+=z,Z+=$,Y++}return`${X}\x1B[0m`}var zJ="│",KJ="╭",MJ="╮",jJ="╰",qJ="╯",R="─";function f(J,Q){let X=Math.max(4,Q.width);return[WJ(J,Q.title,Q.titleColor??"accent",X),...Q.lines.map((Z)=>EJ(J,Z,X)),UJ(J,Q.footer,X)]}function WJ(J,Q,X,Z){let Y=Q??"",z=A(Y),$=Math.max(0,Z-3-z),M=Y?J.bold(J.fg(X,Y)):"",K=`${KJ}${R}${M}${R.repeat($)}${MJ}`;return J.fg("borderAccent",K)}function EJ(J,Q,X){let Z=Math.max(0,X-2),Y=J.fg("borderAccent",zJ);return`${Y}${y(Q,Z)}${Y}`}function UJ(J,Q,X){let Z=`${jJ}${R}`,Y=`${qJ}`,z=3;if(!Q||!Q.hint&&!Q.badge){let p=Math.max(0,X-3);return J.fg("borderAccent",`${Z}${R.repeat(p)}${Y}`)}let $=Q.hint??"",M=Q.badge??"",K=A($),j=A(M),W=Math.max(0,X-3-K-j),U=J.fg("dim",$),_=M?J.fg("muted",M):"",u=R.repeat(W);return`${J.fg("borderAccent",Z)}${U}${J.fg("borderAccent",u)}${_}${J.fg("borderAccent",Y)}`}function g(J){return Math.max(0,J-2)}var VJ=[{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. Input is masked; blank keeps an existing key",required:!0,secret:!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. Input is masked; blank keeps it, '-' clears it",required:!1,secret:!0}];async function cJ(J){let Q=b(),X=Boolean(Q.proxy.endpoint),Z=Boolean(v(Q.proxy.apiKey));if(X&&Z)return!1;if(!J.hasUI)return!1;return HJ(J,!0)}async function HJ(J,Q=!1){let X=b(),Z={endpoint:X.proxy.endpoint??"",apiKey:X.proxy.apiKey??"",providerPrefix:X.proxy.providerPrefix??"",usageKey:X.proxy.usageKey??""},Y=!1;for(let $ of VJ){let M=Z[$.label]??"",K=$.secret?"":Q?Z[$.label]??$.initialValue??"":Z[$.label]??"";if(!Q&&K)continue;let j=$.secret&&M?{...$,required:!1}:$,W=await NJ(J,j,K||$.initialValue||"");if(W===void 0){Y=!0;break}let U=GJ($,M,W);if(U===null){if($.required){J.ui.notify(`${$.label} is required — aborted`,"warning"),Y=!0;break}}Z[$.label]=U??""}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 x(z),J.ui.notify(`saved to ${q}`,"info"),!0}function OJ(J){if(J.startsWith("!")||J.startsWith("$"))return J;if(J.startsWith("~/")){let Q=J.replace(/^~/,LJ());return w(Q)?`!cat ${J}`:J}if(J.startsWith("/"))return w(J)?`!cat ${J}`:J;return J}function GJ(J,Q,X){let Z=X.trim();if(!Z){if(J.secret&&Q)return Q;return J.required?null:""}if(J.secret&&!J.required&&Z==="-")return"";return J.label==="providerPrefix"||J.label==="endpoint"?Z:OJ(Z)}async function NJ(J,Q,X){return J.ui.custom((Z,Y,z,$)=>_J(Z,Y,Q,X,$),{overlay:!0,overlayOptions:{width:100,maxHeight:"60%"}})}class m{rawInput=new I;displayInput=new I;pasteActive=!1;get focused(){return this.rawInput.focused}set focused(J){this.rawInput.focused=J,this.displayInput.focused=J}set onSubmit(J){this.rawInput.onSubmit=J}set onEscape(J){this.rawInput.onEscape=J}getValue(){return this.rawInput.getValue()}setValue(J){this.rawInput.setValue(J),this.displayInput.setValue("•".repeat(J.length))}handleInput(J){this.rawInput.handleInput(J),this.displayInput.handleInput(this.maskInput(J)),this.displayInput.setValue("•".repeat(this.rawInput.getValue().length))}render(J){return this.displayInput.render(J)}invalidate(){this.rawInput.invalidate(),this.displayInput.invalidate()}maskInput(J){let Q="";for(let X=0;X<J.length;){if(J.startsWith("\x1B[200~",X)){this.pasteActive=!0,Q+="\x1B[200~",X+=6;continue}if(J.startsWith("\x1B[201~",X)){this.pasteActive=!1,Q+="\x1B[201~",X+=6;continue}if(!this.pasteActive&&J.charCodeAt(X)===27)return J;let Z=J.codePointAt(X),Y=String.fromCodePoint(Z);Q+=Z<32||Z===127?Y:"•",X+=Y.length}return Q}}function _J(J,Q,X,Z,Y){let z=X.secret?new m:new I;z.setValue(Z),z.focused=!0;let $=null,M=(K)=>{if(!K&&!X.required){Y("");return}if(!K&&X.required){$="required field",J.requestRender();return}if(X.validate){let j=K.trim();if(j&&!j.startsWith("!")&&!j.startsWith("$")){let W=X.validate(j);if(W){$=W,J.requestRender();return}}}Y(K)};return z.onSubmit=M,z.onEscape=()=>Y(void 0),{render(K){let j=g(K),W=z.render(j-4),U=["",` ${Q.fg("dim",X.hint)}`,"",...W.map((_)=>` ${Q.fg("accent",`❯ ${_}`)}`),"",$?` ${Q.fg("error",`! ${$}`)}`:` ${Q.fg("dim","enter = save · esc = cancel")}`];return f(Q,{width:K,title:` setup: ${X.label} `,lines:U,footer:{hint:" enter = save · esc = cancel "}})},invalidate(){z.invalidate()},handleInput(K){if(BJ().matches(K,"tui.select.cancel")||RJ(K,"escape")){Y(void 0);return}$=null,z.handleInput(K),J.requestRender()}}}export{cJ as runSetupIfNeeded,HJ as runSetup,GJ as resolveWizardValue,_J as buildStepOverlay};
|
|
@@ -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{createHash as O}from"node:crypto";import{existsSync as j,readFileSync as B,statSync as x,unlinkSync as L,writeFileSync as E}from"node:fs";import{dirname as V,join as K}from"node:path";import{chmodSync as R,closeSync as D,constants as C,copyFileSync as _,existsSync as w,fsyncSync as F,linkSync as k,mkdirSync as N,openSync as S,readFileSync as v,renameSync as f,rmSync as p,writeFileSync as u}from"node:fs";import{homedir as q}from"node:os";import{dirname as g,join as $}from"node:path";var Y=!1;var Z={info(...J){if(!Y)console.log("[dm-cliproxy]",...J)},warn(...J){if(!Y)console.warn("[dm-cliproxy]",...J)},error(...J){if(!Y)console.error("[dm-cliproxy]",...J)},debug(...J){if(!Y&&(process.env.DM_CLIPROXY_DEBUG||process.env.PI_CLIPROXYAPI_DEBUG))console.log("[dm-cliproxy]","[debug]",...J)}};var b=$(q(),".dm","agent","dm-cliproxy"),s=$(b,"config.json"),P=[$(q(),".pi","agent","pi-cliproxyapi","config.json"),$(q(),".config","pi-cliproxyapi","config.json")];function z(J){N(J,{recursive:!0,mode:448}),R(J,448)}function X(J){if(w(J))R(J,384)}var U=K(b,"usage-cache.json"),H=K(b,"usage-cache.lock"),G=120000,I=30000;function t(J,Q,W=b){let M=O("sha256").update(J.trim().replace(/\/+$/,"")).update("\x00").update(Q).digest("hex").slice(0,24);return{cachePath:K(W,`usage-cache-${M}.json`),lockPath:K(W,`usage-cache-${M}.lock`)}}function r(J=U){if(!j(J))return null;try{z(V(J)),X(J);let Q=JSON.parse(B(J,"utf8"));if(!Q||typeof Q.fetchedAt!=="number"||!Q.doc||!Array.isArray(Q.doc.accounts))return null;return{doc:Q.doc,ageMs:Date.now()-Q.fetchedAt}}catch(Q){return Z.warn("failed to read usage cache:",Q.message),null}}function a(J){return J<G}function e(J,Q=U){try{z(V(Q));let W={fetchedAt:Date.now(),doc:J};E(Q,JSON.stringify(W),{encoding:"utf8",mode:384}),X(Q)}catch(W){Z.warn("failed to write usage cache:",W.message)}}function JJ(J=H){let Q=`${process.pid}@${Date.now()}`;if(j(J))try{z(V(J)),X(J);let W=x(J);if(Date.now()-W.mtimeMs>I)Z.debug("removing stale usage lock"),L(J);else return null}catch{return null}try{return z(V(J)),E(J,Q,{flag:"wx",mode:384}),X(J),Q}catch{return null}}function QJ(J,Q=H){try{if(X(Q),B(Q,"utf8").trim()===J)return L(Q),!0;return!1}catch{return!1}}export{e as writeUsageCache,t as usageCachePaths,JJ as tryAcquireUsageLock,QJ as releaseUsageLock,r as readUsageCache,a as isUsageFresh,H as USAGE_LOCK_PATH,G as USAGE_CACHE_TTL_MS,U as USAGE_CACHE_PATH};
|