@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.
Files changed (62) hide show
  1. package/dm +0 -0
  2. package/extensions/.dm-extensions.json +44 -15
  3. package/extensions/dm-cliproxy/NOTICE.md +12 -0
  4. package/extensions/dm-cliproxy/index.js +2 -0
  5. package/extensions/dm-cliproxy/package.json +20 -0
  6. package/extensions/dm-cliproxy/scripts/check-config-migration.js +8 -0
  7. package/extensions/dm-cliproxy/src/apply.js +1 -0
  8. package/extensions/dm-cliproxy/src/cache.js +1 -0
  9. package/extensions/dm-cliproxy/src/commands.js +2 -0
  10. package/extensions/dm-cliproxy/src/compat.js +1 -0
  11. package/extensions/dm-cliproxy/src/config.js +2 -0
  12. package/extensions/dm-cliproxy/src/conflicts.js +1 -0
  13. package/extensions/dm-cliproxy/src/fetch-models.js +1 -0
  14. package/extensions/dm-cliproxy/src/fetch-usage.js +1 -0
  15. package/extensions/dm-cliproxy/src/log.js +1 -0
  16. package/extensions/dm-cliproxy/src/status-quota.js +1 -0
  17. package/extensions/dm-cliproxy/src/ui-frame.js +1 -0
  18. package/extensions/dm-cliproxy/src/ui-hub/hub.js +2 -0
  19. package/extensions/dm-cliproxy/src/ui-hub/index.js +2 -0
  20. package/extensions/dm-cliproxy/src/ui-hub/shell.js +1 -0
  21. package/extensions/dm-cliproxy/src/ui-hub/types.js +0 -0
  22. package/extensions/dm-cliproxy/src/ui-hub/view-diagnostics.js +1 -0
  23. package/extensions/dm-cliproxy/src/ui-hub/view-models.js +1 -0
  24. package/extensions/dm-cliproxy/src/ui-hub/view-usage.js +1 -0
  25. package/extensions/dm-cliproxy/src/ui-picker/catalog.js +1 -0
  26. package/extensions/dm-cliproxy/src/ui-picker/mutate.js +1 -0
  27. package/extensions/dm-cliproxy/src/ui-picker/prompt-confirm.js +1 -0
  28. package/extensions/dm-cliproxy/src/ui-picker/prompt-name.js +1 -0
  29. package/extensions/dm-cliproxy/src/ui-picker/providers.js +1 -0
  30. package/extensions/dm-cliproxy/src/ui-picker/render-text.js +1 -0
  31. package/extensions/dm-cliproxy/src/ui-picker/rows.js +1 -0
  32. package/extensions/dm-cliproxy/src/ui-picker/types.js +0 -0
  33. package/extensions/dm-cliproxy/src/ui-setup.js +2 -0
  34. package/extensions/dm-cliproxy/src/ui-usage.js +1 -0
  35. package/extensions/dm-cliproxy/src/usage-shared-cache.js +1 -0
  36. package/extensions/dm-subagents/src/extension/doctor.js +10 -10
  37. package/extensions/dm-subagents/src/extension/fanout-child.js +129 -129
  38. package/extensions/dm-subagents/src/extension/index.js +179 -179
  39. package/extensions/dm-subagents/src/extension/rpc.js +5 -5
  40. package/extensions/dm-subagents/src/extension/schemas.js +1 -1
  41. package/extensions/dm-subagents/src/extension/tool-description.js +2 -2
  42. package/extensions/dm-subagents/src/intercom/native-supervisor-channel.js +5 -5
  43. package/extensions/dm-subagents/src/runs/background/async-execution.js +19 -19
  44. package/extensions/dm-subagents/src/runs/background/async-job-tracker.js +10 -10
  45. package/extensions/dm-subagents/src/runs/background/async-resume.js +5 -5
  46. package/extensions/dm-subagents/src/runs/background/async-status.js +8 -8
  47. package/extensions/dm-subagents/src/runs/background/fleet-view.js +14 -14
  48. package/extensions/dm-subagents/src/runs/background/result-watcher.js +5 -5
  49. package/extensions/dm-subagents/src/runs/background/run-id-resolver.js +3 -3
  50. package/extensions/dm-subagents/src/runs/background/run-status.js +20 -20
  51. package/extensions/dm-subagents/src/runs/background/stale-run-reconciler.js +7 -7
  52. package/extensions/dm-subagents/src/runs/background/subagent-runner.js +38 -38
  53. package/extensions/dm-subagents/src/runs/background/wait.js +7 -7
  54. package/extensions/dm-subagents/src/runs/foreground/chain-execution.js +58 -58
  55. package/extensions/dm-subagents/src/runs/foreground/execution.js +36 -36
  56. package/extensions/dm-subagents/src/runs/foreground/subagent-executor.js +129 -129
  57. package/extensions/dm-subagents/src/runs/shared/dm-args.js +1 -1
  58. package/extensions/dm-subagents/src/runs/shared/nested-events.js +6 -6
  59. package/extensions/dm-subagents/src/runs/shared/subagent-prompt-runtime.js +13 -13
  60. package/package.json +1 -1
  61. package/extensions/dm-9router-ext/package.json +0 -23
  62. package/extensions/dm-9router-ext/src/index.js +0 -5
package/dm CHANGED
Binary file
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "status": "ok",
3
- "prepared_at": "2026-07-11T19:37:30.028039+00:00",
3
+ "prepared_at": "2026-07-12T11:45:43.264428+00:00",
4
4
  "managed_entries": [
5
5
  {
6
6
  "id": "dm-context",
@@ -43,8 +43,8 @@
43
43
  "bundle_mode": "source-package"
44
44
  },
45
45
  {
46
- "id": "dm-9router-ext",
47
- "target_dir": "extensions/dm-9router-ext",
46
+ "id": "dm-cliproxy",
47
+ "target_dir": "extensions/dm-cliproxy",
48
48
  "bundle_mode": "source-package-with-runtime-deps"
49
49
  },
50
50
  {
@@ -237,8 +237,8 @@
237
237
  "src/tui/render.js"
238
238
  ],
239
239
  "file_count": 93,
240
- "before_bytes": 1545518,
241
- "after_bytes": 3105293,
240
+ "before_bytes": 1544913,
241
+ "after_bytes": 3104479,
242
242
  "externals": [
243
243
  "@duckmind/dm-agent-core",
244
244
  "@duckmind/dm-ai",
@@ -563,20 +563,21 @@
563
563
  }
564
564
  },
565
565
  {
566
- "id": "dm-9router-ext",
567
- "staged_dir": "extensions/dm-9router-ext",
566
+ "id": "dm-cliproxy",
567
+ "staged_dir": "extensions/dm-cliproxy",
568
568
  "bundle_mode": "source-package-with-runtime-deps",
569
569
  "dependencies_installed": false,
570
570
  "dependency_mode": "platform-package-dependency",
571
571
  "dependencies_declared": [
572
+ "@duckmind/dm-ai",
572
573
  "@duckmind/dm-coding-agent",
573
- "typebox"
574
+ "@duckmind/dm-tui"
574
575
  ],
575
576
  "dependency_patches": [
576
577
  "dm.extensions ts->js",
577
- "main ts->js",
578
578
  "drop-devDependencies",
579
579
  "drop-peerDependencies",
580
+ "drop-repository",
580
581
  "drop-scripts",
581
582
  "drop-files"
582
583
  ],
@@ -586,18 +587,46 @@
586
587
  "javascript_bundle_minify": {
587
588
  "tool": "bun build --minify",
588
589
  "files": [
589
- "src/index.js"
590
+ "index.js",
591
+ "scripts/check-config-migration.js",
592
+ "src/apply.js",
593
+ "src/cache.js",
594
+ "src/commands.js",
595
+ "src/compat.js",
596
+ "src/config.js",
597
+ "src/conflicts.js",
598
+ "src/fetch-models.js",
599
+ "src/fetch-usage.js",
600
+ "src/log.js",
601
+ "src/status-quota.js",
602
+ "src/ui-frame.js",
603
+ "src/ui-hub/hub.js",
604
+ "src/ui-hub/index.js",
605
+ "src/ui-hub/shell.js",
606
+ "src/ui-hub/types.js",
607
+ "src/ui-hub/view-diagnostics.js",
608
+ "src/ui-hub/view-models.js",
609
+ "src/ui-hub/view-usage.js",
610
+ "src/ui-picker/catalog.js",
611
+ "src/ui-picker/mutate.js",
612
+ "src/ui-picker/prompt-confirm.js",
613
+ "src/ui-picker/prompt-name.js",
614
+ "src/ui-picker/providers.js",
615
+ "src/ui-picker/render-text.js",
616
+ "src/ui-picker/rows.js",
617
+ "src/ui-picker/types.js",
618
+ "src/ui-setup.js",
619
+ "src/ui-usage.js",
620
+ "src/usage-shared-cache.js"
590
621
  ],
591
- "file_count": 1,
592
- "before_bytes": 17239,
593
- "after_bytes": 6534,
622
+ "file_count": 31,
623
+ "before_bytes": 136442,
624
+ "after_bytes": 255164,
594
625
  "externals": [
595
626
  "@duckmind/dm-agent-core",
596
627
  "@duckmind/dm-ai",
597
628
  "@duckmind/dm-coding-agent",
598
629
  "@duckmind/dm-tui",
599
- "@types/node",
600
- "typebox",
601
630
  "typescript"
602
631
  ]
603
632
  }
@@ -0,0 +1,12 @@
1
+ # dm-cliproxy provenance notice
2
+
3
+ - Upstream technical source: `https://github.com/abix5/pi-cliproxyapi.git`
4
+ - Pinned revision: `b0ce7712f95eab9035b85dfa05aee0352b40c546`
5
+ - Upstream tag at review time: `v0.3.5`
6
+ - Upstream package metadata declares the MIT license. The pinned tree does not
7
+ contain a standalone license file, so this notice preserves that limitation
8
+ instead of inventing license text.
9
+
10
+ Allowed technical compatibility strings in the DM adaptation are limited to
11
+ the upstream URL/name, the `/.well-known/pi` discovery route, and legacy config
12
+ paths used by copy-only migration.
@@ -0,0 +1,2 @@
1
+ import{getModels as Uj}from"@duckmind/dm-ai/compat";var o$=new Set(["openai-completions","openai-responses","anthropic-messages"]);function d$($,j){let J=j.replace(/\/+$/,"");if($==="anthropic-messages")return J.replace(/\/v1$/,"");return J}function T0($,j){if(!$)return!0;for(let J of j)if(new RegExp("^"+J.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*")+"$").test($))return!0;return!1}var g1=128000,p1=16000,h1={input:0,output:0,cacheRead:0,cacheWrite:0},m1=[/.*-thinking$/,/^gpt-5(\.\d+)?(-.*)?$/,/^gemini-3(\.\d+)?(-.*)?$/];function I$($){return m1.some((j)=>j.test($))}var l1=[[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 k$($,j){let J=($??"").trim();return J?`${J}-${j}`:j}function L0($,j){let J=(j??"").trim(),Z=$.match(/^([a-z0-9]+-)(.*)$/);if(Z)return J?`${J}-${Z[1]}`:Z[1];return $}function k0($,j){for(let[J,Z,X]of l1)if(J.has($))return{slug:k$(j,Z),api:X};return{slug:k$(j,"misc"),api:"openai-completions"}}function c1($){return $.replace(/[/:]/g," ").split(/[-_]/).filter(Boolean).map((j)=>j[0].toUpperCase()+j.slice(1)).join(" ")}function E$($){return{id:$,name:c1($),contextWindow:g1,maxTokens:p1,reasoning:I$($),cost:{...h1}}}import{execSync as s1}from"node:child_process";import{randomUUID as K0}from"node:crypto";import{chmodSync as a$,closeSync as I0,constants as i1,copyFileSync as o1,existsSync as O$,fsyncSync as d1,linkSync as r1,mkdirSync as t1,openSync as a1,readFileSync as F0,renameSync as e1,rmSync as t$,writeFileSync as $j}from"node:fs";import{homedir as K$}from"node:os";import{dirname as S$,join as U$}from"node:path";import{fileURLToPath as jj}from"node:url";var H$=!1;function r$($){H$=$}var H={info(...$){if(!H$)console.log("[dm-cliproxy]",...$)},warn(...$){if(!H$)console.warn("[dm-cliproxy]",...$)},error(...$){if(!H$)console.error("[dm-cliproxy]",...$)},debug(...$){if(!H$&&(process.env.DM_CLIPROXY_DEBUG||process.env.PI_CLIPROXYAPI_DEBUG))console.log("[dm-cliproxy]","[debug]",...$)}};var Y$=U$(K$(),".dm","agent","dm-cliproxy"),o=U$(Y$,"config.json"),Jj=[U$(K$(),".pi","agent","pi-cliproxyapi","config.json"),U$(K$(),".config","pi-cliproxyapi","config.json")];function l($){t1($,{recursive:!0,mode:448}),a$($,448)}function u($){if(O$($))a$($,384)}function Zj($){let j;try{j=JSON.parse(F0($,"utf8"))}catch{return}let J=j&&typeof j==="object"?j.proxy:void 0;for(let Z of[J?.apiKey,J?.usageKey]){if(typeof Z!=="string")continue;let X=/^!cat\s+((?:~\/|\/)[^\s;&|`]+)$/.exec(Z.trim());if(!X)continue;let z=X[1].replace(/^~/,K$());u(z)}}function Xj(){return O$(U$(S$(jj(import.meta.url)),"..",".git"))}function zj($=Jj,j=o,J=Xj()){if(O$(j))return;let X=(typeof $==="string"?[$]:[...$]).find((q)=>O$(q));if(!X)return;let z;try{u(X),Zj(X),l(S$(j)),z=`${j}.${process.pid}.${K0()}.tmp`,o1(X,z,i1.COPYFILE_EXCL),a$(z,384),r1(z,j),t$(z),z=void 0,H.info("legacy config copied to",j)}catch(q){if(z)try{t$(z,{force:!0})}catch(Y){H.warn("failed to clean temporary config:",Y)}H.warn("failed to migrate legacy config:",q)}}var F$={proxy:{endpoint:"",apiKey:""},builtinProviders:{},customProviders:{},discoveryExcludes:["*:*"],overrides:{},refreshIntervalMinutes:0,usageCacheTtlMs:30000};function f(){if(zj(),!O$(o))return H.debug("config not found, using defaults at",o),structuredClone(F$);try{l(S$(o)),u(o);let $=JSON.parse(F0(o,"utf8"));return qj($)}catch($){return H.error("failed to read config:",$,"— using defaults"),structuredClone(F$)}}function Yj($,j=o){l(S$(j));let J=`${j}.${process.pid}.${K0()}.tmp`,Z;try{Z=a1(J,"wx",384),$j(Z,JSON.stringify($,null,2)+`
2
+ `,{encoding:"utf8"}),d1(Z),I0(Z),Z=void 0,e1(J,j),u(j)}finally{if(Z!==void 0)I0(Z);t$(J,{force:!0})}}function b$($){Yj($),H.info("config saved to",o)}function qj($){if(!$||typeof $!=="object")return structuredClone(F$);let j=$,J=structuredClone(F$),Z=j.proxy??{};if(J.proxy.endpoint=typeof Z.endpoint==="string"?Z.endpoint:J.proxy.endpoint,J.proxy.apiKey=typeof Z.apiKey==="string"?Z.apiKey:"",typeof Z.usageKey==="string")J.proxy.usageKey=Z.usageKey;if(typeof Z.providerPrefix==="string"&&Z.providerPrefix.trim())J.proxy.providerPrefix=Z.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((X)=>typeof X==="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 x($){if(!$)return"";let j=$.trim();if(j.startsWith("!"))try{return s1(j.slice(1),{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).trim()}catch(J){let Z=J?.status,X=typeof Z==="number"?` (exit ${Z})`:"";return H.warn(`failed to resolve "!" config value${X}`),""}if(j.startsWith("$"))return process.env[j.slice(1)]??"";return j}import{createHash as Qj}from"node:crypto";import{existsSync as Mj,readFileSync as Vj,writeFileSync as Ej}from"node:fs";import{dirname as S0,join as Dj}from"node:path";var b0=Dj(Y$,"discovery-cache.json");function x$($,j){return Qj("sha256").update($.trim().replace(/\/+$/,"")).update("\x00").update(j).digest("hex")}function x0($,j=b0){if(!Mj(j))return null;try{l(S0(j)),u(j);let J=JSON.parse(Vj(j,"utf8"));if(!J||typeof J.savedAt!=="number"||J.scope!==$||!J.discovery||!Array.isArray(J.discovery.builtinProviders)||!Array.isArray(J.discovery.customPool))return null;return{discovery:J.discovery,ageMs:Date.now()-J.savedAt}}catch(J){return H.warn("failed to read discovery cache:",J.message),null}}function e$($,j,J=b0){try{l(S0(J));let Z={savedAt:Date.now(),scope:j,discovery:$};Ej(J,JSON.stringify(Z),{encoding:"utf8",mode:384}),u(J)}catch(Z){H.warn("failed to write discovery cache:",Z.message)}}var D$="dm-cliproxy/0.3.5",Rj=5000;async function C0($,j){let J=new AbortController,Z=setTimeout(()=>J.abort(Error("timeout")),Rj);try{return await fetch($,{...j,signal:J.signal})}finally{clearTimeout(Z)}}function Nj($){return new URL("/.well-known/pi",new URL($).origin).toString()}async function Wj($){let j=Nj($.proxy.endpoint),J;try{J=await C0(j,{headers:{"User-Agent":D$,Accept:"application/json"}})}catch(Y){return H.warn("well-known fetch failed:",Y.message,"— falling back to /v1/models"),null}if(!J.ok)return H.warn(`well-known returned ${J.status} — falling back to /v1/models`),null;let Z;try{Z=await J.json()}catch{return H.warn("well-known returned non-JSON — falling back to /v1/models"),null}if(!Z||Z.schemaVersion!==1)return H.warn("well-known schemaVersion != 1 — falling back to /v1/models"),null;let X=[],z=Z.builtinProviders??{};for(let[Y,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??I$(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}}));X.push({name:Y,api:Q.api??"openai-responses",models:V})}let q=(Array.isArray(Z.customModelPool)?Z.customModelPool:[]).map((Y)=>({id:String(Y.id),name:typeof Y.name==="string"?Y.name:String(Y.id),reasoning:Boolean(Y.reasoning??I$(String(Y.id))),contextWindow:typeof Y.contextWindow==="number"?Y.contextWindow:128000,maxTokens:typeof Y.maxTokens==="number"?Y.maxTokens:16000,cost:Y.cost??{input:0,output:0,cacheRead:0,cacheWrite:0},api:Y.api??"openai-completions",suggestedProvider:L0(typeof Y.suggestedProviderName==="string"?Y.suggestedProviderName:"misc",$.proxy.providerPrefix),ownedBy:typeof Y.owned_by==="string"?Y.owned_by:""}));return{source:"well-known",upstreamVersion:typeof Z?.upstream?.upstreamVersion==="string"?Z.upstream.upstreamVersion:null,builtinProviders:X,customPool:q,serverDiscoveryExcludes:Array.isArray(Z.discoveryExcludes)?Z.discoveryExcludes.filter((Y)=>typeof Y==="string"):[],upstreamTotal:typeof Z?.counts?.upstreamTotal==="number"?Z.counts.upstreamTotal:0}}async function Hj($,j){let J=new URL("/v1/models",new URL($.proxy.endpoint).origin).toString(),Z=await C0(J,{headers:{Authorization:`Bearer ${j}`,Accept:"application/json","User-Agent":D$}});if(!Z.ok)throw Error(`/v1/models returned ${Z.status}`);let X=await Z.json();if(!X?.data||!Array.isArray(X.data))return[];return X.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 Oj($,j){let J=j.discoveryExcludes,Z=new Map,X=[],z=0;for(let q of $){if(z++,T0(q.id,J))continue;if(q.owned_by==="openai"){let M=E$(q.id);w0(Z,"openai","openai-responses",P0(M));continue}if(q.owned_by==="anthropic"){let M=E$(q.id);w0(Z,"anthropic","anthropic-messages",P0(M));continue}let{slug:Y,api:Q}=k0(q.owned_by,j.proxy.providerPrefix),V=E$(q.id);X.push({id:q.id,name:V.name??q.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:Y,ownedBy:q.owned_by})}return{source:"v1-models",upstreamVersion:null,builtinProviders:Array.from(Z.values()),customPool:X,serverDiscoveryExcludes:[],upstreamTotal:z}}function w0($,j,J,Z){let X=$.get(j);if(!X)X={name:j,api:J,models:[]},$.set(j,X);X.models.push(Z)}function P0($){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 t($,j){let J=x$($.proxy.endpoint,j),Z=await Wj($);if(Z)return H.info(`discovery via /.well-known/pi: ${Z.builtinProviders.length} builtin, ${Z.customPool.length} custom`),e$(Z,J),Z;if(!j)throw Error("well-known unavailable AND proxy apiKey is empty — cannot fall back to /v1/models. Set proxy.apiKey in config.");let X=await Hj($,j),z=Oj(X,$);return H.info(`discovery via /v1/models: ${z.builtinProviders.length} builtin, ${z.customPool.length} custom`),e$(z,J),z}function y0($){let j=new Set;for(let J of $.builtinProviders)for(let Z of J.models)j.add(Z.id);for(let J of $.customPool)j.add(J.id);return j}var n0=new WeakMap,$0=new WeakMap;function c($){let j=($0.get($)??0)+1;return $0.set($,j),j}function w$($,j){return j===void 0||j===($0.get($)??0)}function j0($,j,J){let Z=n0.get($)??new Set;for(let X of Z){if(j.has(X))continue;$.unregisterProvider(X),J.unregistered.push(X)}n0.set($,new Set(j))}function Gj($){let j={registered:[],skipped:[],unregistered:[]};return j0($,new Set,j),j.unregistered}function J0($){return c($),Gj($)}async function d($,j,J,Z){let X={registered:[],skipped:[],unregistered:[]};if(!w$($,Z))return X.skipped.push({provider:"*",reason:"stale refresh generation"}),X;let z=new Set,q=y0(J),Y=x(j.proxy.apiKey);if(!Y)return H.warn("proxy apiKey is empty — dm.registerProvider calls will be skipped"),j0($,z,X),X;let Q=new Map;for(let M of J.builtinProviders)Q.set(M.name,M.models.map((E)=>({id:E.id,name:E.name,reasoning:E.reasoning,contextWindow:E.contextWindow,maxTokens:E.maxTokens,cost:E.cost})));for(let[M,E]of Object.entries(j.builtinProviders)){if(!w$($,Z))return X;if(!E?.enabled){X.skipped.push({provider:M,reason:"disabled"});continue}if(!Array.isArray(E.models)||E.models.length===0){X.skipped.push({provider:M,reason:"empty whitelist"});continue}let k=[];try{k=Uj(M)}catch{}let _=new Map(k.map((A)=>[A.id,A])),U=new Map((Q.get(M)??[]).map((A)=>[A.id,A])),R=[];for(let A of E.models){if(!q.has(A))continue;let B=_.get(A),P=U.get(A);if(B){R.push({id:B.id,name:B.name,reasoning:B.reasoning,contextWindow:B.contextWindow,maxTokens:B.maxTokens,cost:B.cost,input:B.input,api:B.api,thinkingLevelMap:B.thinkingLevelMap});continue}if(!P)continue;let Q$=M==="anthropic"?"anthropic-messages":E.apiOverride??"openai-responses";R.push({id:P.id,name:P.name,reasoning:P.reasoning,contextWindow:P.contextWindow,maxTokens:P.maxTokens,cost:P.cost,input:["text"],api:Q$})}if(R.length===0){X.skipped.push({provider:M,reason:"no whitelisted models present on proxy"});continue}let O=E.apiOverride??R[0].api;if(!o$.has(O)){X.skipped.push({provider:M,reason:`api "${O}" not in allowlist`});continue}let I=R.map((A)=>{let B=j.overrides[A.id]??{},P={id:A.id,name:typeof B.name==="string"?B.name:A.name,api:O,reasoning:typeof B.reasoning==="boolean"?B.reasoning:A.reasoning,input:A.input,cost:B.cost??A.cost,contextWindow:typeof B.contextWindow==="number"?B.contextWindow:A.contextWindow,maxTokens:typeof B.maxTokens==="number"?B.maxTokens:A.maxTokens};if(A.thinkingLevelMap)P.thinkingLevelMap=A.thinkingLevelMap;return P}),n={name:M,baseUrl:d$(O,j.proxy.endpoint),apiKey:Y,authHeader:!0,api:O,models:I};$.registerProvider(M,n),z.add(M),X.registered.push({provider:M,modelCount:I.length,api:O})}let V=new Map(J.customPool.map((M)=>[M.id,M]));for(let[M,E]of Object.entries(j.customProviders)){if(!w$($,Z))return X;if(!o$.has(E.api)){X.skipped.push({provider:M,reason:`api "${E.api}" not in allowlist`});continue}let k=E.models.filter((R)=>q.has(R.id));if(k.length===0){X.skipped.push({provider:M,reason:"no configured models present on proxy"});continue}let _=k.map((R)=>{let O=V.get(R.id),I=E$(R.id),n=j.overrides[R.id]??{};return{id:R.id,name:R.name??O?.name??I.name??R.id,api:E.api,reasoning:Bj(R.reasoning,O?.reasoning,I.reasoning,n.reasoning)??!1,input:["text"],cost:R.cost??O?.cost??I.cost??{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:u0(R.contextWindow,O?.contextWindow,I.contextWindow,n.contextWindow)??128000,maxTokens:u0(R.maxTokens,O?.maxTokens,I.maxTokens,n.maxTokens)??16000}}),U={name:M,baseUrl:d$(E.api,j.proxy.endpoint),apiKey:Y,authHeader:!0,api:E.api,models:_};$.registerProvider(M,U),z.add(M),X.registered.push({provider:M,modelCount:_.length,api:E.api})}if(w$($,Z))j0($,z,X);return H.info(`applyAll: registered ${X.registered.length} providers, skipped ${X.skipped.length}, unregistered ${X.unregistered.length}`),X}function u0(...$){for(let j of $)if(typeof j==="number")return j;return}function Bj(...$){for(let j of $)if(typeof j==="boolean")return j;return}var _j=15000,G$=null;function R$(){G$=null}async function P$($,j,J={}){if(!J.force&&G$&&Date.now()-G$.fetchedAt<$.usageCacheTtlMs)return G$.doc;if(!j)throw Error("usage key not configured; set proxy.usageKey in config and rerun");let Z=new URL("/api/usage",new URL($.proxy.endpoint).origin).toString(),X=new AbortController,z=setTimeout(()=>X.abort(Error("timeout")),_j),q;try{q=await fetch(Z,{headers:{"X-Plugin-Key":j,Accept:"application/json","User-Agent":D$},signal:X.signal})}finally{clearTimeout(z)}if(!q.ok)throw Error(`/api/usage returned ${q.status}`);let Y=await q.json();if(!Y||Y.schemaVersion!==1||!Array.isArray(Y.accounts))throw Error("/api/usage returned unexpected payload shape");return G$={fetchedAt:Date.now(),doc:Y},H.debug("usage fetched, accounts:",Y.accounts.length),Y}import{getKeybindings as Y2,matchesKey as g}from"@duckmind/dm-tui";import{visibleWidth as X0}from"@duckmind/dm-tui";import{visibleWidth as v0}from"@duckmind/dm-tui";function F($,j){let J=v0($);if(J===j)return $;if(J<j)return $+" ".repeat(j-J);return Z0($,j)}function Z0($,j){if(j<=0)return"\x1B[0m";let J="",Z=0,X=0;while(X<$.length){let z=$[X];if(z==="\x1B"&&$[X+1]==="["){let Y=$.indexOf("m",X+2);if(Y>=0){J+=$.slice(X,Y+1),X=Y+1;continue}}let q=v0(z);if(Z+q>j)break;J+=z,Z+=q,X++}return`${J}\x1B[0m`}var Aj="│",Tj="╭",Lj="╮",kj="╰",Ij="╯",B$="─";function j$($,j){let J=Math.max(4,j.width);return[Kj($,j.title,j.titleColor??"accent",J),...j.lines.map((Z)=>Fj($,Z,J)),Sj($,j.footer,J)]}function Kj($,j,J,Z){let X=j??"",z=X0(X),q=Math.max(0,Z-3-z),Y=X?$.bold($.fg(J,X)):"",Q=`${Tj}${B$}${Y}${B$.repeat(q)}${Lj}`;return $.fg("borderAccent",Q)}function Fj($,j,J){let Z=Math.max(0,J-2),X=$.fg("borderAccent",Aj);return`${X}${F(j,Z)}${X}`}function Sj($,j,J){let Z=`${kj}${B$}`,X=`${Ij}`,z=3;if(!j||!j.hint&&!j.badge){let U=Math.max(0,J-3);return $.fg("borderAccent",`${Z}${B$.repeat(U)}${X}`)}let q=j.hint??"",Y=j.badge??"",Q=X0(q),V=X0(Y),M=Math.max(0,J-3-Q-V),E=$.fg("dim",q),k=Y?$.fg("muted",Y):"",_=B$.repeat(M);return`${$.fg("borderAccent",Z)}${E}${$.fg("borderAccent",_)}${k}${$.fg("borderAccent",X)}`}function C$($){return Math.max(0,$-2)}import{existsSync as f0}from"node:fs";import{homedir as bj}from"node:os";import{getKeybindings as xj,Input as z0,matchesKey as wj}from"@duckmind/dm-tui";var Pj=[{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 _$($,j=!1){let J=f(),Z={endpoint:J.proxy.endpoint??"",apiKey:J.proxy.apiKey??"",providerPrefix:J.proxy.providerPrefix??"",usageKey:J.proxy.usageKey??""},X=!1;for(let q of Pj){let Y=Z[q.label]??"",Q=q.secret?"":j?Z[q.label]??q.initialValue??"":Z[q.label]??"";if(!j&&Q)continue;let V=q.secret&&Y?{...q,required:!1}:q,M=await nj($,V,Q||q.initialValue||"");if(M===void 0){X=!0;break}let E=yj(q,Y,M);if(E===null){if(q.required){$.ui.notify(`${q.label} is required — aborted`,"warning"),X=!0;break}}Z[q.label]=E??""}if(X)return!1;let z={...J};if(z.proxy={...J.proxy,endpoint:Z.endpoint??"",apiKey:Z.apiKey??"",providerPrefix:Z.providerPrefix??""},Z.usageKey)z.proxy.usageKey=Z.usageKey;else delete z.proxy.usageKey;return b$(z),$.ui.notify(`saved to ${o}`,"info"),!0}function Cj($){if($.startsWith("!")||$.startsWith("$"))return $;if($.startsWith("~/")){let j=$.replace(/^~/,bj());return f0(j)?`!cat ${$}`:$}if($.startsWith("/"))return f0($)?`!cat ${$}`:$;return $}function yj($,j,J){let Z=J.trim();if(!Z){if($.secret&&j)return j;return $.required?null:""}if($.secret&&!$.required&&Z==="-")return"";return $.label==="providerPrefix"||$.label==="endpoint"?Z:Cj(Z)}async function nj($,j,J){return $.ui.custom((Z,X,z,q)=>uj(Z,X,j,J,q),{overlay:!0,overlayOptions:{width:100,maxHeight:"60%"}})}class g0{rawInput=new z0;displayInput=new z0;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 Z=$.codePointAt(J),X=String.fromCodePoint(Z);j+=Z<32||Z===127?X:"•",J+=X.length}return j}}function uj($,j,J,Z,X){let z=J.secret?new g0:new z0;z.setValue(Z),z.focused=!0;let q=null,Y=(Q)=>{if(!Q&&!J.required){X("");return}if(!Q&&J.required){q="required field",$.requestRender();return}if(J.validate){let V=Q.trim();if(V&&!V.startsWith("!")&&!V.startsWith("$")){let M=J.validate(V);if(M){q=M,$.requestRender();return}}}X(Q)};return z.onSubmit=Y,z.onEscape=()=>X(void 0),{render(Q){let V=C$(Q),M=z.render(V-4),E=["",` ${j.fg("dim",J.hint)}`,"",...M.map((k)=>` ${j.fg("accent",`❯ ${k}`)}`),"",q?` ${j.fg("error",`! ${q}`)}`:` ${j.fg("dim","enter = save · esc = cancel")}`];return j$(j,{width:Q,title:` setup: ${J.label} `,lines:E,footer:{hint:" enter = save · esc = cancel "}})},invalidate(){z.invalidate()},handleInput(Q){if(xj().matches(Q,"tui.select.cancel")||wj(Q,"escape")){X(void 0);return}q=null,z.handleInput(Q),$.requestRender()}}}import{visibleWidth as y$}from"@duckmind/dm-tui";function p0($,j,J,Z){let X=$.fg("borderAccent","│"),z=j.map((q,Y)=>{let Q=`${Y+1} ${q.label}`;return Y===J?$.bold($.fg("accent",` ${Q} `)):$.fg("dim",` ${Q} `)});return F(` ${z.join(X)}`,Z)}function h0($,j,J){let Z=j.join($.fg("dim"," "));return F(` ${Z}`,J)}function m0($,j){return $.fg("borderAccent","─".repeat(Math.max(0,j)))}function J$($,j,J){let Z=$.slice(j,j+J);while(Z.length<J)Z.push("");return Z}function n$($,j,J,Z,X,z){if(X<=Z)return 0;let q=Math.max(0,X-Z);if(j<z)return 0;let Y=Math.max(0,Math.min(J,q)),Q=Y+z;if($<Q)Y=Math.max(0,$-z);let V=Y+Z-1;if(j>V)Y=Math.min(q,j-(Z-1));return Y}function u$($,j,J){let Z=Math.max(0,J-j);return Math.max(0,Math.min($,Z))}import{matchesKey as Z$}from"@duckmind/dm-tui";import{existsSync as vj,readFileSync as fj}from"node:fs";import{homedir as c0}from"node:os";import{join as s0}from"node:path";var gj=s0(c0(),".dm","models.json"),pj=s0(c0(),".dm","auth.json");function l0($){if(!vj($))return null;try{return JSON.parse(fj($,"utf8"))}catch{return null}}function v$($){let j=[],J=new Set([...Object.keys($.builtinProviders),...Object.keys($.customProviders)]),Z=l0(gj);if(Z&&typeof Z==="object"){for(let z of Object.keys(Z))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 X=l0(pj);if(X&&typeof X==="object"){for(let z of Object.keys(X))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 i0($){let{theme:j,cfg:J}=$,Z=0,X=()=>{let Y=$.getDiscovery(),Q=(U)=>j.fg("success",U),V=(U)=>j.fg("error",U),M=(U)=>j.fg("dim",U),E=[];E.push(`${M("endpoint")} ${J.proxy.endpoint||V("(unset)")}`),E.push(`${M("apiKey")} ${x(J.proxy.apiKey)?Q("resolves"):V("empty after resolution")}`),E.push(`${M("usageKey")} ${J.proxy.usageKey?x(J.proxy.usageKey)?Q("resolves"):V("set but empty"):M("not configured")}`),E.push(`${M("user-agent")} ${D$}`),E.push(""),E.push(`${M("discovery")} source=${Y.source}`),E.push(`${M("upstream")} v=${Y.upstreamVersion??"(unknown)"} · ${Y.upstreamTotal} ids`);let k=Y.builtinProviders.map((U)=>`${U.name}=${U.models.length}`).join(", ")||M("(none)");E.push(`${M("built-in")} ${k}`),E.push(`${M("custom pool")} ${Y.customPool.length} models`);let _=v$(J);if(E.push(""),_.length===0)E.push(`${M("conflicts")} ${Q("none")}`);else{E.push(`${M("conflicts")}`);for(let U of _)E.push(` ${j.fg("warning",`[${U.kind}]`)} ${U.detail}`)}return E};return{id:"diagnostics",label:"Diagnostics",render:(Y,Q)=>{let V=X();return Z=u$(Z,Q,V.length),J$(V,Z,Q).map((M)=>F(` ${M}`,Y))},handleInput:(Y)=>{let Q=X().length;if(Z$(Y,"up")||Z$(Y,"k"))return Z=Math.max(0,Z-1),!0;if(Z$(Y,"down")||Z$(Y,"j"))return Z=Math.min(Math.max(0,Q-1),Z+1),!0;if(Z$(Y,"pageUp")||Z$(Y,"b"))return Z=Math.max(0,Z-10),!0;if(Z$(Y,"pageDown")||Z$(Y,"f"))return Z=Math.min(Math.max(0,Q-1),Z+10),!0;return!1},footerHint:()=>" ↑↓ scroll · r refresh discovery "}}import{matchesKey as L}from"@duckmind/dm-tui";function Y0($){let j=new Map,J=new Map;for(let X of $.builtinProviders){let z=[];for(let q of X.models)j.set(q.id,{id:q.id,name:q.name,suggestedApi:X.api,subtitle:q.name&&q.name!==q.id?q.name:void 0,ownedBy:X.name,reasoning:q.reasoning,contextWindow:q.contextWindow,maxTokens:q.maxTokens,cost:q.cost}),z.push(q.id);J.set(X.name,z)}let Z=[];for(let X of $.customPool){if(!j.has(X.id))j.set(X.id,{id:X.id,name:X.name,suggestedApi:X.api,subtitle:X.name&&X.name!==X.id?X.name:void 0,origin:X.suggestedProvider,ownedBy:X.ownedBy,reasoning:X.reasoning,contextWindow:X.contextWindow,maxTokens:X.maxTokens,cost:X.cost});Z.push(X.id)}return{byId:j,builtinModelIds:J,customPoolIds:Z}}function hj($){let j=new Map;for(let[J,Z]of Object.entries($.customProviders))for(let X of Z.models)j.set(X.id,J);return j}function q$($,j){if(j.kind==="builtin")return[...$.builtinProviders[j.name]?.models??[]];return $.customProviders[j.name]?.models.map((J)=>J.id)??[]}function o0($,j,J){if(j.kind==="builtin"){let z=J.builtinModelIds.get(j.name)??[],q=new Set(q$($,j));return z.filter((Y)=>!q.has(Y))}let Z=hj($),X=new Set(q$($,j));return J.customPoolIds.filter((z)=>{if(X.has(z))return!1;let q=Z.get(z);return q===void 0||q===j.name})}function mj($){return{id:$.id,name:$.name,contextWindow:$.contextWindow,maxTokens:$.maxTokens,reasoning:$.reasoning,cost:$.cost}}function d0($,j,J){if(j.kind==="builtin"){let X=$.builtinProviders[j.name]??{enabled:!0,models:[]},z=new Set(X.models);z.add(J.id),$.builtinProviders[j.name]={enabled:!0,apiOverride:X.apiOverride??null,models:Array.from(z).sort()};return}for(let[X,z]of Object.entries($.customProviders)){if(X===j.name)continue;let q=z.models.findIndex((Y)=>Y.id===J.id);if(q>=0)z.models.splice(q,1)}let Z=$.customProviders[j.name]??{api:j.api,models:[]};if(!Z.models.some((X)=>X.id===J.id))Z.models.push(mj(J));$.customProviders[j.name]=Z}function r0($,j,J){if(j.kind==="builtin"){let X=$.builtinProviders[j.name];if(!X)return;X.models=X.models.filter((z)=>z!==J),X.enabled=X.models.length>0;return}let Z=$.customProviders[j.name];if(!Z)return;Z.models=Z.models.filter((X)=>X.id!==J)}function q0($,j){if($===j)return!0;let J=["openai-completions","openai-responses"];if(J.includes($)&&J.includes(j))return!0;return!1}function t0($,j){let J=new Map;for(let Z of $){let X=j.byId.get(Z),z=X?.ownedBy||X?.origin||"misc",q=J.get(z)??[];q.push(Z),J.set(z,q)}return Array.from(J.entries()).sort((Z,X)=>Z[0].localeCompare(X[0])).map(([Z,X])=>({label:Z,ids:X}))}function a0($,j,J){let Z=J.trim().toLowerCase();if(!Z)return $;return $.filter((X)=>{if(X.toLowerCase().includes(Z))return!0;let z=j.byId.get(X)?.name;return z?z.toLowerCase().includes(Z):!1})}import{getModels as lj,getProviders as cj}from"@duckmind/dm-ai/compat";function Q0($,j){let J=[],Z=new Set(j.builtinModelIds.keys()),X=new Set(cj()),z=new Set([...Z,...X]);for(let q of Array.from(z).sort()){let Y=j.builtinModelIds.get(q);if(!Y||Y.length===0)continue;let Q;try{let M=lj(q).find((E)=>Y.includes(E.id));if(M)Q=M.api}catch{}if(!Q){let V=Y[0];Q=j.byId.get(V)?.suggestedApi??"openai-responses"}if(J.push({kind:"builtin",name:q,api:Q,subtitle:`built-in · ${Q}`}),!$.builtinProviders[q])$.builtinProviders[q]={enabled:!1,models:[]}}for(let q of Object.keys($.customProviders).sort()){let Y=$.customProviders[q];J.push({kind:"custom",name:q,api:Y.api,subtitle:`custom · ${Y.api}`})}return J}import{getKeybindings as sj,matchesKey as N$}from"@duckmind/dm-tui";async function e0($,j){return $.ui.custom((J,Z,X,z)=>ij(Z,`Remove custom group “${j}”?`,"All model assignments in this group will be discarded.",z),{overlay:!0,overlayOptions:{width:80,maxHeight:"40%"}})}function ij($,j,J,Z){return{render(X){return j$($,{width:X,title:" confirm ",titleColor:"error",lines:["",` ${$.bold(j)}`,` ${$.fg("dim",J)}`,""],footer:{hint:" y / enter = remove · n / esc = cancel "}})},invalidate(){},handleInput(X){if(sj().matches(X,"tui.select.cancel")||N$(X,"escape")||N$(X,"n")||N$(X,"q")){Z(!1);return}if(N$(X,"y")||N$(X,"enter")||N$(X,"return")){Z(!0);return}}}}import{getKeybindings as oj,Input as dj,matchesKey as rj}from"@duckmind/dm-tui";async function $1($,j){let J=k$(j,"group");return $.ui.custom((Z,X,z,q)=>tj(Z,X,J,q),{overlay:!0,overlayOptions:{width:80,maxHeight:"40%"}})}function tj($,j,J,Z){let X=new dj;if(J)X.setValue(J);X.focused=!0;let z=null;return X.onSubmit=(q)=>{let Y=q.trim();if(!/^[a-z0-9][a-z0-9._-]*$/i.test(Y)){z="letters / digits / dot / dash / underscore only",$.requestRender();return}Z(Y)},X.onEscape=()=>Z(null),{render(q){let Y=C$(q),Q=J?`name shown in /model picker, e.g. ${J}`:"letters / digits / dot / dash / underscore",V=X.render(Y-4),M=["",` ${j.fg("dim",Q)}`,"",...V.map((E)=>` ${j.fg("accent",`❯ ${E}`)}`),"",z?` ${j.fg("error",`! ${z}`)}`:""];return j$(j,{width:q,title:" new custom group ",lines:M,footer:{hint:" enter = create · esc = cancel "}})},invalidate(){X.invalidate()},handleInput(q){if(oj().matches(q,"tui.select.cancel")||rj(q,"escape")){Z(null);return}z=null,X.handleInput(q),$.requestRender()}}}import{visibleWidth as aj}from"@duckmind/dm-tui";function M0($,j,J){if(!j)return" ";if(J)return $.fg("accent","▶ ");return $.fg("muted","▸ ")}function j1($,j){let J=aj($);if(J===j)return $;if(J>j)return Z0($,j);return F($,j)}function J1($,j,J){let{theme:Z,width:X,isCursor:z,isFocused:q}=J,Y=M0(Z,z,q),Q=$.kind==="builtin"?j.builtinProviders[$.name]?.models.length??0:j.customProviders[$.name]?.models.length??0,V=$.kind==="builtin"?Z.fg("accent","B"):Z.fg("warning","C"),M=`${Z.fg("dim","[")}${V}${Z.fg("dim","]")}`,E=Q>0?Z.fg("success","●"):Z.fg("dim","○"),k=Q>0?Z.fg("success",String(Q).padStart(2)):Z.fg("dim"," 0"),_=z&&q?Z.bold(Z.fg("accent",$.name)):z?Z.bold($.name):$.name,U=Z.fg("dim",$.api),R=`${Y}${M} ${_} ${E}${k} ${U}`;return j1(R,X)}function Z1($,j,J,Z){let X=M0($,j,J),z=j&&J?$.bold($.fg("accent","+ new custom group…")):$.fg("accent","+ new custom group…");return F(`${X}${z}`,Z)}function V0($,j,J,Z,X){let{theme:z,width:q,isCursor:Y,isFocused:Q}=X,V=M0(z,Y,Q),M=J==="assigned"?z.fg("success","☑"):z.fg("dim","☐"),E=Z?` ${z.fg("warning","⚠")}`:"",k=Y&&Q?z.fg("accent",$):$,_=j?.reasoning?` ${z.fg("accent","✨")}`:"",U=j?z.fg("muted",` · ${j.suggestedApi}`):z.fg("error"," · not on proxy"),R=`${V}${M} ${k}${E}${_}${U}`;return j1(R,q)}function X1($,j,J){let Z=`${$.fg("borderAccent","──")} ${$.fg("warning",j)} ${$.fg("borderAccent","──")}`;return F(` ${Z}`,J)}function E0($,j,J){return F(` ${$.fg("dim",j)}`,J)}function z1($,j,J,Z){let X=Z?$.bold($.fg("accent","❚ ")):$.fg("dim"," ");return F(`${X}${j}`,J)}function Y1($){let{tui:j,theme:J,ctx:Z,cfg:X}=$,z=$.onChange??(()=>{}),q=Y0($.getDiscovery()),Y=Q0(X,q),Q="providers",V=0,M=0,E=0,k=0,_=0,U=0,R="",O=!1,I=()=>{if(Y.length===0)return null;let D=Math.max(0,Math.min(V,Y.length-1));return Y[D]??null},n=(D)=>{let G=a0(o0(X,D,q),q,R);return t0(G,q)},A=(D)=>n(D).flatMap((G)=>G.ids),B=()=>{Y=Q0(X,q);let D=Math.max(0,Y.length);if(V>D)V=D;let G=I();if(G){let w=q$(X,G).length,T=A(G).length;if(M>=w)M=Math.max(0,w-1);if(E>=T)E=Math.max(0,T-1)}},P=()=>{q=Y0($.getDiscovery()),B()},Q$=(D)=>{let G=["providers","assigned","pool"],w=G.indexOf(Q);Q=D?G[(w-1+G.length)%G.length]:G[(w+1)%G.length]},W=(D)=>{if(Q==="providers"){let T=Y.length+1;V=Math.max(0,Math.min(V+D,T-1));return}let G=I();if(!G)return;if(Q==="assigned"){let T=q$(X,G).length;if(T===0)return;M=Math.max(0,Math.min(M+D,T-1));return}let w=A(G).length;if(w===0)return;E=Math.max(0,Math.min(E+D,w-1))},b=async()=>{if(Q==="providers"){if(V===Y.length){let T=await $1(Z,X.proxy.providerPrefix);if(T&&!X.customProviders[T]){if(X.customProviders[T]={api:"openai-completions",models:[]},z(),B(),V=Y.findIndex((S)=>S.kind==="custom"&&S.name===T),V<0)V=Y.length-1;Q="pool"}j.requestRender();return}Q="pool";return}let D=I();if(!D)return;if(Q==="assigned"){let T=q$(X,D)[M];if(!T)return;r0(X,D,T),z(),B();return}let G=A(D)[E];if(!G)return;let w=q.byId.get(G);if(!w)return;d0(X,D,w),z(),B()},s=async()=>{if(Q!=="providers")return;let D=I();if(!D||D.kind!=="custom")return;if(!await e0(Z,D.name)){j.requestRender();return}if(delete X.customProviders[D.name],z(),B(),V>=Y.length)V=Math.max(0,Y.length-1);j.requestRender()},p=(D,G)=>i(D,G);function i(D,G){let w=Math.max(70,D),T=Math.min(56,Math.max(34,Math.floor(w*0.4))),S=w-T-1,a=Math.max(8,G),e=Math.max(5,Math.floor((a-1)/2)),R0=a-e,r=I(),W$=0,m$=0,l$=0,N0=0,c$=0,W0=0,X$=[];X$.push(M$(" providers ",T,Q==="providers"));for(let K=0;K<Y.length;K++){let h=Y[K],v=Q==="providers"&&K===V;if(v)W$=X$.length,m$=W$;X$.push(J1(h,X,{theme:J,width:T,isCursor:v,isFocused:Q==="providers"}))}{let K=Q==="providers"&&V===Y.length;if(K)W$=X$.length,m$=W$;X$.push(Z1(J,K,Q==="providers",T))}let z$=[],y1=r?`assigned to ${J.bold(r.name)} ${J.fg("dim",`· ${r.api}`)}`:J.fg("dim","no provider selected");if(z$.push(M$(" assigned ",S,Q==="assigned")),z$.push(z1(J,y1,S,Q==="assigned")),r){let K=q$(X,r);if(K.length===0)z$.push(E0(J,"(nothing assigned yet)",S));for(let h=0;h<K.length;h++){let v=K[h],m=q.byId.get(v),L$=Q==="assigned"&&h===M;if(L$)l$=z$.length,N0=l$;let V$=m?!q0(r.api,m.suggestedApi):!1;z$.push(V0(v,m,"assigned",V$,{theme:J,width:S,isCursor:L$,isFocused:Q==="assigned"}))}}let $$=[];if($$.push(C(S,Q==="pool")),r){let K=n(r);if(K.reduce((v,m)=>v+m.ids.length,0)===0)$$.push(E0(J,R?`(no matches for "${R}")`:"(no models available)",S));else{let v=0;for(let m of K){let L$=$$.length;$$.push(X1(J,m.label,S));for(let V$=0;V$<m.ids.length;V$++){let _0=m.ids[V$],i$=q.byId.get(_0),A0=Q==="pool"&&v===E;if(A0)c$=$$.length,W0=V$===0?L$:c$;let f1=i$?!q0(r.api,i$.suggestedApi):!1;$$.push(V0(_0,i$,"pool",f1,{theme:J,width:S,isCursor:A0,isFocused:Q==="pool"})),v++}}}}let n1=Math.max(1,R0-1),H0=n$(m$,W$,k,a,X$.length,1),O0=n$(Q==="assigned"?N0:0,Q==="assigned"?l$:0,_,e,z$.length,2),U0=n$(Q==="pool"?W0:0,Q==="pool"?c$:0,U,n1,$$.length,1);k=H0,_=O0,U=U0;let G0=J$(X$,H0,a),u1=J$(z$,O0,e),v1=J$($$,U0,R0),B0=J.fg("borderAccent","│"),s$=[];for(let K=0;K<a;K++){let h=F(G0[K]??"",T),v=K<e?u1[K]:v1[K-e],m=F(v,S);s$.push(`${h}${B0}${m}`)}let T$=e;if(T$>0&&T$<a){let K=F(G0[T$]??"",T),h=J.fg("borderAccent","─".repeat(S));s$[T$]=`${K}${B0}${h}`}return s$}function M$(D,G,w){let T=w?J.bold(J.fg("accent",D)):J.fg("muted",D),S=J.fg("borderAccent","─".repeat(Math.max(0,G-y$(D)-1)));return F(`${T}${S}`,G)}function C(D,G){let T=G?J.bold(J.fg("accent"," available pool ")):J.fg("muted"," available pool "),S="";if(O)S=`${J.fg("dim"," /")}${J.fg("accent",R)}${J.fg("accent","█")} `;else if(R)S=`${J.fg("dim"," /")}${J.fg("warning",R)} `;let a=y$(" available pool ")+y$(S),e=J.fg("borderAccent","─".repeat(Math.max(0,D-a-1)));return F(`${T}${S}${e}`,D)}function A$(D){if(O){if(L(D,"escape"))return R="",O=!1,E=0,!0;if(L(D,"enter")||L(D,"return"))return O=!1,!0;if(L(D,"backspace")||L(D,"delete"))return R=R.slice(0,-1),E=0,!0;if(D.length===1&&D>=" "&&D!=="")return R+=D,E=0,!0;return!0}if(L(D,"tab"))return Q$(!1),!0;if(L(D,"shift+tab"))return Q$(!0),!0;if(L(D,"/"))return Q="pool",O=!0,!0;if(L(D,"enter")||L(D,"return")||L(D,"space"))return b().then(()=>!0);if(Q==="providers"&&(L(D,"d")||L(D,"delete")||L(D,"backspace")))return s().then(()=>!0);if(L(D,"up")||L(D,"k"))return W(-1),!0;if(L(D,"down")||L(D,"j"))return W(1),!0;if(L(D,"pageUp")||L(D,"b"))return W(-8),!0;if(L(D,"pageDown")||L(D,"f"))return W(8),!0;if(L(D,"left")||L(D,"h"))return Q="providers",!0;if(L(D,"right")||L(D,"l")){if(Q==="providers")Q="assigned";else if(Q==="assigned")Q="pool";return!0}return!1}function C1(){if(O)return" type to filter · ↵ apply · esc clear ";return" tab ↔ panel · ↑↓ nav · ↵ move · / filter · d remove group "}return{id:"models",label:"Models",render:p,handleInput:A$,footerHint:C1,rebuild:P}}import{matchesKey as y}from"@duckmind/dm-tui";var N={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 q1($,j={}){let J=[],Z=new Map,X=0;for(let z of $.accounts){if(!j.showDisabled&&z.disabled){X++;continue}let q=Z.get(z.provider)??[];q.push(z),Z.set(z.provider,q)}if(J.push(`${N.dim}generated ${$.generatedAt}${N.reset}`),$.unsupportedProviders.length>0)J.push(`${N.dim}providers without quota lookup:${N.reset} ${$.unsupportedProviders.join(", ")}`);if(X>0)J.push(`${N.dim}hidden disabled accounts:${N.reset} ${X} ${N.dim2}(press d to show)${N.reset}`);for(let[z,q]of Array.from(Z.entries()).sort()){J.push(""),J.push(`${N.bold}${N.accent}▌ ${z}${N.reset}`);for(let Y of q){if(J.push($2(Y)),!Y.supported){J.push(` ${N.dim2}(provider not quota-aware)${N.reset}`);continue}if(Y.error){if(j.verbose)for(let V of ej(Y.error,88))J.push(` ${N.red}${V}${N.reset}`);continue}let Q=Y.groups??[];if(Q.length===0){J.push(` ${N.dim2}(no active quota windows)${N.reset}`);continue}for(let V of Q)J.push(J2(V))}}return J.push(""),J.push(`${N.dim}legend:${N.reset} ${Q1} ok ${M1} error/unavailable ${V1} disabled ${N.green}✓N${N.reset}/${N.red}✗N${N.reset} request counters ${N.dim}v = verbose, d = show disabled${N.reset}`),J}function ej($,j){if($.length<=j)return[$];let J=[],Z=$;while(Z.length>j){let X=Z.lastIndexOf(" ",j);if(X<j*0.6)X=j;J.push(Z.slice(0,X)),Z=Z.slice(X).replace(/^\s+/,"")}if(Z)J.push(Z);return J}function $2($){let j=j2($),J=`${N.green}✓${$.success}${N.reset} ${N.red}✗${$.failed}${N.reset}`,Z=R1($.label,36);return` ${j} ${N.bold}${Z}${N.reset} ${J}`}var Q1=`${N.green}●${N.reset}`,M1=`${N.yellow}⚠${N.reset}`,V1=`${N.dim2}⊘${N.reset}`;function j2($){if($.disabled)return V1;if($.unavailable||$.error||$.status&&$.status!=="active")return M1;return Q1}function J2($){let j=D1($.remainingFraction),J=Math.round(j*100),Z=Z2(j),X=$.resetTime?` ${N.dim}reset ${z2($.resetTime)}${N.reset}`:"",z=R1($.label,28).padEnd(28," ");return` ${Z} ${X2(J,j)} ${z}${X}`}function Z2($){let j=D1($),J=Math.round(j*18),Z=E1(j),X=N.dim2,z="█".repeat(J),q="░".repeat(18-J);return`${X}[${Z}${z}${X}${q}]${N.reset}`}function X2($,j){return`${E1(j)}${String($).padStart(3)}%${N.reset}`}function E1($){if($>=0.4)return N.green;if($>=0.15)return N.yellow;return N.red}function z2($){let j=Date.parse($);if(!Number.isFinite(j))return $;let J=j-Date.now();if(J<=0)return"now";let Z=Math.round(J/60000);if(Z<60)return`${Z}m`;let X=Math.round(Z/60);if(X<48)return`${X}h`;return`${Math.round(X/24)}d`}function D1($){return Math.max(0,Math.min(1,$))}function R1($,j){if($.length<=j)return $;return`${$.slice(0,j-1)}…`}function N1($){let{tui:j,theme:J,cfg:Z}=$,X="idle",z=null,q="",Y=0,Q=!1,V=!1,M=(R)=>{X="loading",j.requestRender();let O=x(Z.proxy.usageKey);P$(Z,O,{force:R}).then((I)=>{z=I,X="ready",Y=0,j.requestRender()}).catch((I)=>{q=I.message,X="error",j.requestRender()})},E=()=>{if(X==="idle"||X==="loading")return[J.fg("dim"," loading usage…")];if(X==="error")return[J.fg("error",` usage failed: ${q}`)];if(!z)return[J.fg("dim"," (no data)")];return q1(z,{showDisabled:Q,verbose:V})};return{id:"usage",label:"Usage",render:(R,O)=>{let I=E();return Y=u$(Y,O,I.length),J$(I,Y,O).map((n)=>F(` ${n}`,R))},handleInput:(R)=>{if(y(R,"d"))return Q=!Q,Y=0,!0;if(y(R,"v"))return V=!V,Y=0,!0;let O=E().length;if(y(R,"up")||y(R,"k"))return Y=Math.max(0,Y-1),!0;if(y(R,"down")||y(R,"j"))return Y=Math.min(Math.max(0,O-1),Y+1),!0;if(y(R,"pageUp")||y(R,"b"))return Y=Math.max(0,Y-10),!0;if(y(R,"pageDown")||y(R,"f"))return Y=Math.min(Math.max(0,O-1),Y+10),!0;if(y(R,"home")||y(R,"g"))return Y=0,!0;if(y(R,"end")||y(R,"shift+g"))return Y=Math.max(0,O-1),!0;return!1},footerHint:()=>{let R=Q?J.fg("success","[d disabled]"):"d disabled",O=V?J.fg("success","[v verbose]"):"v verbose";return` ↑↓ scroll · ${R} · ${O} `},onActivate:()=>{if(X==="idle")M(!1)},reload:()=>{if(R$(),X!=="idle")M(!0)}}}function W1($){let{dm:j,ctx:J,tui:Z,theme:X,cfg:z,done:q}=$,Y=$.discovery,Q=!1,V="",M=Y1({tui:Z,theme:X,ctx:J,cfg:z,getDiscovery:()=>Y,onChange:()=>{Q=!0,V=""}}),E=N1({tui:Z,theme:X,cfg:z}),k=i0({theme:X,cfg:z,getDiscovery:()=>Y}),_=[M,E,k],U=0,R=()=>_[U],O=(W)=>{if(W<0||W>=_.length||W===U)return;U=W,R().onActivate?.(),Z.requestRender()},I=()=>{V=X.fg("dim","saving…"),b$(z),Z.requestRender();let W=c(j);d(j,z,Y,W).then((b)=>{Q=!1,V=X.fg("success",`✓ settings saved · ${b.registered.length} registered, ${b.skipped.length} skipped`),Z.requestRender()}).catch((b)=>{V=X.fg("error",`save failed: ${b.message}`),Z.requestRender()})},n=async()=>{V=X.fg("dim","refreshing…"),Z.requestRender();try{let W=c(j),b=x(z.proxy.apiKey);Y=await t(z,b),R$(),M.rebuild(),E.reload();let s=await d(j,z,Y,W);V=X.fg("success",`✓ refreshed · ${s.registered.length} providers (${Y.source})`)}catch(W){V=X.fg("error",`refresh failed: ${W.message}`)}Z.requestRender()},A=async()=>{if(!await _$(J,!0)){Z.requestRender();return}let b=f();z.proxy={...z.proxy,...b.proxy},await n()},B=()=>{let W=z.proxy.endpoint||"(unset)",b=W.length>40?`…${W.slice(-39)}`:W,s=Boolean(x(z.proxy.apiKey)),p=0,i=0;for(let C of Object.values(z.builtinProviders)){if(C.enabled&&C.models.length>0)p++;i+=C.models.length}for(let C of Object.values(z.customProviders)){if(C.models.length>0)p++;i+=C.models.length}let M$=V?V:Q?X.fg("warning","● unsaved — press s to save"):X.fg("dim","✓ saved");return[`${X.fg("dim","endpoint")} ${b}`,`${X.fg("dim","key")} ${s?X.fg("success","✓"):X.fg("error","✗")}`,`${X.fg("dim","providers")} ${p}`,`${X.fg("dim","models")} ${i}`,M$]},P=(W)=>{let b=Z.rows??40,p=Math.max(16,Math.min(b-6,38))-2,i=Math.max(72,W-2),M$=Math.max(6,p-3),C=[];return C.push(h0(X,B(),i)),C.push(p0(X,_.map((A$)=>({id:A$.id,label:A$.label})),U,i)),C.push(m0(X,i)),C.push(...R().render(i,M$)),j$(X,{width:W,title:" /cliproxy ",lines:C,footer:{hint:R().footerHint(),badge:" [ ] tab · r refresh · e setup · s save · q close "}})},Q$=(W)=>{if(Y2().matches(W,"tui.select.cancel")||g(W,"q")||g(W,"escape"))return q(),!0;if(g(W,"]")||g(W,"tab"))return O((U+1)%_.length),!0;if(g(W,"[")||g(W,"shift+tab"))return O((U-1+_.length)%_.length),!0;if(g(W,"1"))return O(0),!0;if(g(W,"2"))return O(1),!0;if(g(W,"3"))return O(2),!0;if(g(W,"r"))return n().then(()=>!0);if(g(W,"e"))return A().then(()=>!0);if(g(W,"s"))return I(),!0;return!1};return{render:P,invalidate(){},handleInput(W){let b=R().handleInput(W);if(b instanceof Promise){V="",b.then((p)=>{if(p)Z.requestRender()});return}if(b){V="",Z.requestRender();return}let s=Q$(W);if(s instanceof Promise)s.then((p)=>{if(p)Z.requestRender()});else if(s)Z.requestRender()}}}async function H1($,j,J,Z){if(!j.hasUI){j.ui.notify("interactive UI required for /cliproxy","warning");return}let X=structuredClone(J);r$(!0);try{await j.ui.custom((z,q,Y,Q)=>W1({dm:$,ctx:j,tui:z,theme:q,cfg:X,discovery:Z,done:Q}),{overlay:!0,overlayOptions:{width:170,maxHeight:"94%"}})}finally{r$(!1)}}function O1($){$.registerCommand("cliproxy",{description:"Manage proxy models, usage, and diagnostics in one hub overlay",handler:q2.bind(null,$)}),$.registerCommand("cliproxy-setup",{description:"Set endpoint, API key, and (optional) usage key for the proxy",handler:Q2.bind(null,$)})}async function q2($,j,J){let Z=f();if(!Z.proxy.endpoint||!x(Z.proxy.apiKey)){if(J.ui.notify("endpoint or API key not set — launching setup first","info"),!await _$(J,!0))return}let X=f(),z=x(X.proxy.apiKey),q;try{q=await t(X,z)}catch(Y){J.ui.notify(`discovery failed: ${Y.message}`,"error");return}await H1($,J,X,q)}async function Q2($,j,J){if(!await _$(J,!0))return;let X=f();try{let z=c($),q=await t(X,x(X.proxy.apiKey)),Y=await d($,X,q,z);R$(),J.ui.notify(`setup ok · ${Y.registered.length} providers registered (source=${q.source})`,"info")}catch(z){J.ui.notify(`setup saved, but apply failed: ${z.message}`,"warning")}}import{createHash as M2}from"node:crypto";import{existsSync as U1,readFileSync as G1,statSync as V2,unlinkSync as B1,writeFileSync as _1}from"node:fs";import{dirname as f$,join as g$}from"node:path";var A1=g$(Y$,"usage-cache.json"),T1=g$(Y$,"usage-cache.lock"),E2=120000,D2=30000;function L1($,j,J=Y$){let Z=M2("sha256").update($.trim().replace(/\/+$/,"")).update("\x00").update(j).digest("hex").slice(0,24);return{cachePath:g$(J,`usage-cache-${Z}.json`),lockPath:g$(J,`usage-cache-${Z}.lock`)}}function k1($=A1){if(!U1($))return null;try{l(f$($)),u($);let j=JSON.parse(G1($,"utf8"));if(!j||typeof j.fetchedAt!=="number"||!j.doc||!Array.isArray(j.doc.accounts))return null;return{doc:j.doc,ageMs:Date.now()-j.fetchedAt}}catch(j){return H.warn("failed to read usage cache:",j.message),null}}function I1($){return $<E2}function K1($,j=A1){try{l(f$(j));let J={fetchedAt:Date.now(),doc:$};_1(j,JSON.stringify(J),{encoding:"utf8",mode:384}),u(j)}catch(J){H.warn("failed to write usage cache:",J.message)}}function F1($=T1){let j=`${process.pid}@${Date.now()}`;if(U1($))try{l(f$($)),u($);let J=V2($);if(Date.now()-J.mtimeMs>D2)H.debug("removing stale usage lock"),B1($);else return null}catch{return null}try{return l(f$($)),_1($,j,{flag:"wx",mode:384}),u($),j}catch{return null}}function S1($,j=T1){try{if(u(j),G1(j,"utf8").trim()===$)return B1(j),!0;return!1}catch{return!1}}var D0=["⡀","⠂","⣀","⣄","⣤","⣶","⣷","⣾"];function R2($){if($==="anthropic")return"claude";if($==="openai")return"codex";return null}function N2($){return!$.disabled&&!$.unavailable&&$.supported&&Array.isArray($.groups)&&$.groups.length>0}function W2($){let j=`${$.id} ${$.label??""}`.toLowerCase();return j.includes("5h")||j.includes("five-hour")||j.includes("five hour")}function H2($){let j=`${$.id} ${$.label??""}`.toLowerCase();return j.includes("7d")||j.includes("seven-day")||j.includes("seven day")}function b1($,j){let J=-1;for(let Z of $){if(!N2(Z))continue;let X=1/0;for(let z of Z.groups??[])if(j(z)){if(z.remainingFraction<X)X=z.remainingFraction}if(X!==1/0&&X>J)J=X}if(J<0)return null;return{fraction:O2(J)}}function O2($){return Math.max(0,Math.min(1,$))}function x1($){let j=Math.min(D0.length-1,Math.floor($*D0.length));return D0[j]}function p$($){if($>=0.7)return"success";if($>=0.3)return"warning";return"error"}function w1($){return Math.round($*100)}function P1($,j,J){let Z=R2(j);if(!Z)return null;let X=$.accounts.filter((Q)=>Q.provider===Z);if(X.length===0)return null;let z=b1(X,W2),q=b1(X,H2);if(!z&&!q)return null;let Y=[J.fg("dim","\uDB81\uDE27")];if(z)Y.push(`${J.fg("dim","5h")} ${J.fg(p$(z.fraction),x1(z.fraction))} ${J.fg(p$(z.fraction),String(w1(z.fraction)))}`);if(q)Y.push(`${J.fg("dim","7d")} ${J.fg(p$(q.fraction),x1(q.fraction))} ${J.fg(p$(q.fraction),String(w1(q.fraction)))}`);return Y.join(" ")}var h$="0quota",U2=5000;async function G2($,j,J={}){let{cachePath:Z,lockPath:X}=L1($.proxy.endpoint,j),z=k1(Z);if(z&&I1(z.ageMs))return z.doc;if(J.readOnly)return z?.doc??null;let q=F1(X);if(!q)return z?.doc??null;try{let Y=await P$($,j,{force:!0});return K1(Y,Z),Y}catch(Y){return H.debug("usage fetch failed in shared cache:",Y.message),z?.doc??null}finally{S1(q,X)}}async function B2($,j,J,Z,X={}){if(!Z){J.setStatus(h$,void 0);return}if(!j){J.setStatus(h$,void 0);return}let z=await G2($,j,X);if(!z){J.setStatus(h$,void 0);return}let q=P1(z,Z.provider,J.theme);J.setStatus(h$,q??void 0)}function _2($,j={},J={active:!0,quotaGeneration:0}){let Z={loadConfig:f,resolveConfigValue:x,refreshQuotaStatus:B2,now:Date.now,...j},X=0,z=async(q,Y=!1)=>{if(!q.hasUI||!J.active)return;let Q=++J.quotaGeneration,V=Z.loadConfig(),M=Z.resolveConfigValue(V.proxy.usageKey),E={theme:q.ui.theme,setStatus(k,_){if(J.active&&Q===J.quotaGeneration)q.ui.setStatus(k,_)}};await Z.refreshQuotaStatus(V,M,E,q.model,Y?{readOnly:!0}:{})};$.on("session_start",async(q,Y)=>{await z(Y)}),$.on("model_select",async(q,Y)=>{await z(Y,!0)}),$.on("turn_end",async(q,Y)=>{let Q=Z.now(),V=Q-X<U2;if(!V)X=Q;await z(Y,V)})}async function A2($){O1($);let j={active:!0,quotaGeneration:0};_2($,{},j);let J;$.on("session_shutdown",()=>{if(j.active=!1,j.quotaGeneration++,J!==void 0)clearInterval(J);J0($)});let Z=f(),X=x(Z.proxy.apiKey);if(!X){H.debug("apiKey is empty after resolution — skipping initial apply. Run /cliproxy-setup to configure."),J0($);return}let z=v$(Z);for(let q of z)H.warn(`conflict (${q.kind}): ${q.detail}`);try{let q=c($),Y=x0(x$(Z.proxy.endpoint,X));if(Y)H.info(`discovery from cache (age ${Math.round(Y.ageMs/1000)}s): ${Y.discovery.builtinProviders.length} builtin, ${Y.discovery.customPool.length} custom`),await d($,Z,Y.discovery,q),(async()=>{let Q=c($);try{let V=await t(Z,X);if(!j.active)return;await d($,Z,V,Q),H.debug("discovery revalidated from network")}catch(V){H.warn("background discovery revalidate failed:",V.message)}})();else{let Q=c($),V=await t(Z,X);if(!j.active)return;await d($,Z,V,Q)}}catch(q){H.error("initial apply failed:",q.message)}if(Z.refreshIntervalMinutes>0){let q=Z.refreshIntervalMinutes*60000;J=setInterval(()=>{(async()=>{let Y=c($);try{if(!j.active)return;let Q=f(),V=x(Q.proxy.apiKey);if(!V)return;let M=await t(Q,V);if(!j.active)return;await d($,Q,M,Y),H.debug("background refresh ok")}catch(Q){H.warn("background refresh failed:",Q.message)}})()},q),H.info(`background refresh every ${Z.refreshIntervalMinutes}m`)}}export{_2 as registerQuotaHooks,A2 as default};
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "dm-cliproxy",
3
+ "version": "0.3.5",
4
+ "type": "module",
5
+ "description": "DM extension for managing model providers through a single CliProxyAPI endpoint",
6
+ "license": "MIT",
7
+ "dm": {
8
+ "extensions": [
9
+ "./index.js"
10
+ ]
11
+ },
12
+ "keywords": [
13
+ "duckmind",
14
+ "dm",
15
+ "dm-extension",
16
+ "cliproxy",
17
+ "cliproxyapi",
18
+ "proxy"
19
+ ]
20
+ }
@@ -0,0 +1,8 @@
1
+ import J from"node:assert/strict";import{chmodSync as n,existsSync as T,mkdtempSync as y,mkdirSync as f,readFileSync as E,rmSync as g,statSync as L,writeFileSync as B}from"node:fs";import{tmpdir as l}from"node:os";import{dirname as Q,join as u}from"node:path";import{randomUUID as G}from"node:crypto";import{chmodSync as H,closeSync as P,constants as x,copyFileSync as A,existsSync as V,fsyncSync as h,linkSync as C,mkdirSync as I,openSync as t,readFileSync as _,renameSync as r,rmSync as O,writeFileSync as e}from"node:fs";import{homedir as R}from"node:os";import{dirname as S,join as k}from"node:path";import{fileURLToPath as v}from"node:url";var Y=!1;function w(q){Y=q}var M={info(...q){if(!Y)console.log("[dm-cliproxy]",...q)},warn(...q){if(!Y)console.warn("[dm-cliproxy]",...q)},error(...q){if(!Y)console.error("[dm-cliproxy]",...q)},debug(...q){if(!Y&&(process.env.DM_CLIPROXY_DEBUG||process.env.PI_CLIPROXYAPI_DEBUG))console.log("[dm-cliproxy]","[debug]",...q)}};var D=k(R(),".dm","agent","dm-cliproxy"),m=k(D,"config.json"),F=[k(R(),".pi","agent","pi-cliproxyapi","config.json"),k(R(),".config","pi-cliproxyapi","config.json")];function s(q){I(q,{recursive:!0,mode:448}),H(q,448)}function N(q){if(V(q))H(q,384)}function p(q){let K;try{K=JSON.parse(_(q,"utf8"))}catch{return}let Z=K&&typeof K==="object"?K.proxy:void 0;for(let j of[Z?.apiKey,Z?.usageKey]){if(typeof j!=="string")continue;let W=/^!cat\s+((?:~\/|\/)[^\s;&|`]+)$/.exec(j.trim());if(!W)continue;let $=W[1].replace(/^~/,R());N($)}}function d(){return V(k(S(v(import.meta.url)),"..",".git"))}function U(q=F,K=m,Z=d()){if(V(K))return;let W=(typeof q==="string"?[q]:[...q]).find((b)=>V(b));if(!W)return;let $;try{N(W),p(W),s(S(K)),$=`${K}.${process.pid}.${G()}.tmp`,A(W,$,x.COPYFILE_EXCL),H($,384),C($,K),O($),$=void 0,M.info("legacy config copied to",K)}catch(b){if($)try{O($,{force:!0})}catch(X){M.warn("failed to clean temporary config:",X)}M.warn("failed to migrate legacy config:",b)}}w(!0);var z=y(u(l(),"dm-cliproxy-migration-"));try{for(let Z of[!0,!1]){let j=u(z,String(Z),"legacy","config.json"),W=u(z,String(Z),"missing","config.json"),$=u(z,String(Z),"current","config.json"),b=Buffer.from(JSON.stringify({proxy:{apiKey:`!cat ${u(Q(j),"key")}`,usageKey:`!cat ${u(Q(j),"usage-key")}`}},null,2)+`
2
+ `);f(Q(j),{recursive:!0}),B(j,b),n(j,416);for(let X of["key","usage-key"])B(u(Q(j),X),`${X}
3
+ `);U([W,j],$,Z),J.deepEqual(E($),b),J.equal(L($).mode&511,384),J.equal(L(Q($)).mode&511,448),J.equal(T(j),!0),J.equal(L(j).mode&511,384);for(let X of["key","usage-key"])J.equal(E(u(Q(j),X),"utf8"),`${X}
4
+ `),J.equal(L(u(Q(j),X)).mode&511,384),J.equal(T(u(Q($),X)),!1)}let q=u(z,"no-overwrite","legacy","config.json"),K=u(z,"no-overwrite","current","config.json");f(Q(q),{recursive:!0}),f(Q(K),{recursive:!0}),B(q,`legacy
5
+ `),B(K,`current
6
+ `),U(q,K,!1),J.equal(E(K,"utf8"),`current
7
+ `),J.equal(E(q,"utf8"),`legacy
8
+ `),console.log("dm-cliproxy config migration check: ok")}finally{g(z,{recursive:!0,force:!0})}
@@ -0,0 +1 @@
1
+ import{getModels as t}from"@duckmind/dm-ai/compat";var w=new Set(["openai-completions","openai-responses","anthropic-messages"]);function C(J,Y){let X=Y.replace(/\/+$/,"");if(J==="anthropic-messages")return X.replace(/\/v1$/,"");return X}var f=128000,g=16000,l={input:0,output:0,cacheRead:0,cacheWrite:0},p=[/.*-thinking$/,/^gpt-5(\.\d+)?(-.*)?$/,/^gemini-3(\.\d+)?(-.*)?$/];function b(J){return p.some((Y)=>Y.test(J))}function n(J){return J.replace(/[/:]/g," ").split(/[-_]/).filter(Boolean).map((Y)=>Y[0].toUpperCase()+Y.slice(1)).join(" ")}function N(J){return{id:J,name:n(J),contextWindow:f,maxTokens:g,reasoning:b(J),cost:{...l}}}import{execSync as c}from"node:child_process";import{homedir as _}from"node:os";import{dirname as Y0,join as D}from"node:path";var k=!1;var K={info(...J){if(!k)console.log("[dm-cliproxy]",...J)},warn(...J){if(!k)console.warn("[dm-cliproxy]",...J)},error(...J){if(!k)console.error("[dm-cliproxy]",...J)},debug(...J){if(!k&&(process.env.DM_CLIPROXY_DEBUG||process.env.PI_CLIPROXYAPI_DEBUG))console.log("[dm-cliproxy]","[debug]",...J)}};var F=D(_(),".dm","agent","dm-cliproxy"),$0=D(F,"config.json"),Q0=[D(_(),".pi","agent","pi-cliproxyapi","config.json"),D(_(),".config","pi-cliproxyapi","config.json")];function x(J){if(!J)return"";let Y=J.trim();if(Y.startsWith("!"))try{return c(Y.slice(1),{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).trim()}catch(X){let q=X?.status,Z=typeof q==="number"?` (exit ${q})`:"";return K.warn(`failed to resolve "!" config value${Z}`),""}if(Y.startsWith("$"))return process.env[Y.slice(1)]??"";return Y}import{dirname as M0,join as s}from"node:path";var W0=s(F,"discovery-cache.json");function v(J){let Y=new Set;for(let X of J.builtinProviders)for(let q of X.models)Y.add(q.id);for(let X of J.customPool)Y.add(X.id);return Y}var u=new WeakMap,I=new WeakMap;function d(J){let Y=(I.get(J)??0)+1;return I.set(J,Y),Y}function B(J,Y){return Y===void 0||Y===(I.get(J)??0)}function T(J,Y,X){let q=u.get(J)??new Set;for(let Z of q){if(Y.has(Z))continue;J.unregisterProvider(Z),X.unregistered.push(Z)}u.set(J,new Set(Y))}function i(J){let Y={registered:[],skipped:[],unregistered:[]};return T(J,new Set,Y),Y.unregistered}function I0(J){return d(J),i(J)}async function T0(J,Y,X,q){let Z={registered:[],skipped:[],unregistered:[]};if(!B(J,q))return Z.skipped.push({provider:"*",reason:"stale refresh generation"}),Z;let E=new Set,G=v(X),O=x(Y.proxy.apiKey);if(!O)return K.warn("proxy apiKey is empty — dm.registerProvider calls will be skipped"),T(J,E,Z),Z;let S=new Map;for(let $ of X.builtinProviders)S.set($.name,$.models.map((Q)=>({id:Q.id,name:Q.name,reasoning:Q.reasoning,contextWindow:Q.contextWindow,maxTokens:Q.maxTokens,cost:Q.cost})));for(let[$,Q]of Object.entries(Y.builtinProviders)){if(!B(J,q))return Z;if(!Q?.enabled){Z.skipped.push({provider:$,reason:"disabled"});continue}if(!Array.isArray(Q.models)||Q.models.length===0){Z.skipped.push({provider:$,reason:"empty whitelist"});continue}let R=[];try{R=t($)}catch{}let L=new Map(R.map((z)=>[z.id,z])),U=new Map((S.get($)??[]).map((z)=>[z.id,z])),j=[];for(let z of Q.models){if(!G.has(z))continue;let V=L.get(z),H=U.get(z);if(V){j.push({id:V.id,name:V.name,reasoning:V.reasoning,contextWindow:V.contextWindow,maxTokens:V.maxTokens,cost:V.cost,input:V.input,api:V.api,thinkingLevelMap:V.thinkingLevelMap});continue}if(!H)continue;let P=$==="anthropic"?"anthropic-messages":Q.apiOverride??"openai-responses";j.push({id:H.id,name:H.name,reasoning:H.reasoning,contextWindow:H.contextWindow,maxTokens:H.maxTokens,cost:H.cost,input:["text"],api:P})}if(j.length===0){Z.skipped.push({provider:$,reason:"no whitelisted models present on proxy"});continue}let M=Q.apiOverride??j[0].api;if(!w.has(M)){Z.skipped.push({provider:$,reason:`api "${M}" not in allowlist`});continue}let W=j.map((z)=>{let V=Y.overrides[z.id]??{},H={id:z.id,name:typeof V.name==="string"?V.name:z.name,api:M,reasoning:typeof V.reasoning==="boolean"?V.reasoning:z.reasoning,input:z.input,cost:V.cost??z.cost,contextWindow:typeof V.contextWindow==="number"?V.contextWindow:z.contextWindow,maxTokens:typeof V.maxTokens==="number"?V.maxTokens:z.maxTokens};if(z.thinkingLevelMap)H.thinkingLevelMap=z.thinkingLevelMap;return H}),A={name:$,baseUrl:C(M,Y.proxy.endpoint),apiKey:O,authHeader:!0,api:M,models:W};J.registerProvider($,A),E.add($),Z.registered.push({provider:$,modelCount:W.length,api:M})}let y=new Map(X.customPool.map(($)=>[$.id,$]));for(let[$,Q]of Object.entries(Y.customProviders)){if(!B(J,q))return Z;if(!w.has(Q.api)){Z.skipped.push({provider:$,reason:`api "${Q.api}" not in allowlist`});continue}let R=Q.models.filter((j)=>G.has(j.id));if(R.length===0){Z.skipped.push({provider:$,reason:"no configured models present on proxy"});continue}let L=R.map((j)=>{let M=y.get(j.id),W=N(j.id),A=Y.overrides[j.id]??{};return{id:j.id,name:j.name??M?.name??W.name??j.id,api:Q.api,reasoning:a(j.reasoning,M?.reasoning,W.reasoning,A.reasoning)??!1,input:["text"],cost:j.cost??M?.cost??W.cost??{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:h(j.contextWindow,M?.contextWindow,W.contextWindow,A.contextWindow)??128000,maxTokens:h(j.maxTokens,M?.maxTokens,W.maxTokens,A.maxTokens)??16000}}),U={name:$,baseUrl:C(Q.api,Y.proxy.endpoint),apiKey:O,authHeader:!0,api:Q.api,models:L};J.registerProvider($,U),E.add($),Z.registered.push({provider:$,modelCount:L.length,api:Q.api})}if(B(J,q))T(J,E,Z);return K.info(`applyAll: registered ${Z.registered.length} providers, skipped ${Z.skipped.length}, unregistered ${Z.unregistered.length}`),Z}function h(...J){for(let Y of J)if(typeof Y==="number")return Y;return}function a(...J){for(let Y of J)if(typeof Y==="boolean")return Y;return}export{i as unregisterOwnedProviders,I0 as invalidateProviderLifecycle,d as beginProviderRefresh,T0 as applyAll};
@@ -0,0 +1 @@
1
+ import{createHash as V}from"node:crypto";import{existsSync as j,readFileSync as R,writeFileSync as q}from"node:fs";import{dirname as Y,join as A}from"node:path";import{chmodSync as X,closeSync as C,constants as k,copyFileSync as L,existsSync as $,fsyncSync as B,linkSync as U,mkdirSync as z,openSync as u,readFileSync as O,renameSync as x,rmSync as N,writeFileSync as T}from"node:fs";import{homedir as D}from"node:os";import{dirname as I,join as W}from"node:path";var J=!1;var M={info(...v){if(!J)console.log("[dm-cliproxy]",...v)},warn(...v){if(!J)console.warn("[dm-cliproxy]",...v)},error(...v){if(!J)console.error("[dm-cliproxy]",...v)},debug(...v){if(!J&&(process.env.DM_CLIPROXY_DEBUG||process.env.PI_CLIPROXYAPI_DEBUG))console.log("[dm-cliproxy]","[debug]",...v)}};var E=W(D(),".dm","agent","dm-cliproxy"),S=W(E,"config.json"),f=[W(D(),".pi","agent","pi-cliproxyapi","config.json"),W(D(),".config","pi-cliproxyapi","config.json")];function K(v){z(v,{recursive:!0,mode:448}),X(v,448)}function Q(v){if($(v))X(v,384)}var Z=A(E,"discovery-cache.json");function t(v,b){return V("sha256").update(v.trim().replace(/\/+$/,"")).update("\x00").update(b).digest("hex")}function e(v,b=Z){if(!j(b))return null;try{K(Y(b)),Q(b);let s=JSON.parse(R(b,"utf8"));if(!s||typeof s.savedAt!=="number"||s.scope!==v||!s.discovery||!Array.isArray(s.discovery.builtinProviders)||!Array.isArray(s.discovery.customPool))return null;return{discovery:s.discovery,ageMs:Date.now()-s.savedAt}}catch(s){return M.warn("failed to read discovery cache:",s.message),null}}function l(v,b,s=Z){try{K(Y(s));let w={savedAt:Date.now(),scope:b,discovery:v};q(s,JSON.stringify(w),{encoding:"utf8",mode:384}),Q(s)}catch(w){M.warn("failed to write discovery cache:",w.message)}}export{l as writeDiscoveryCache,e as readDiscoveryCache,t as discoveryCacheScope,Z as DISCOVERY_CACHE_PATH};
@@ -0,0 +1,2 @@
1
+ import{getModels as sj}from"@duckmind/dm-ai/compat";var f$=new Set(["openai-completions","openai-responses","anthropic-messages"]);function h$($,j){let J=j.replace(/\/+$/,"");if($==="anthropic-messages")return J.replace(/\/v1$/,"");return J}function D0($,j){if(!$)return!0;for(let J of j)if(new RegExp("^"+J.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*")+"$").test($))return!0;return!1}var Rj=128000,_j=16000,Aj={input:0,output:0,cacheRead:0,cacheWrite:0},Oj=[/.*-thinking$/,/^gpt-5(\.\d+)?(-.*)?$/,/^gemini-3(\.\d+)?(-.*)?$/];function L$($){return Oj.some((j)=>j.test($))}var Hj=[[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 B$($,j){let J=($??"").trim();return J?`${J}-${j}`:j}function R0($,j){let J=(j??"").trim(),Z=$.match(/^([a-z0-9]+-)(.*)$/);if(Z)return J?`${J}-${Z[1]}`:Z[1];return $}function _0($,j){for(let[J,Z,Y]of Hj)if(J.has($))return{slug:B$(j,Z),api:Y};return{slug:B$(j,"misc"),api:"openai-completions"}}function Gj($){return $.replace(/[/:]/g," ").split(/[-_]/).filter(Boolean).map((j)=>j[0].toUpperCase()+j.slice(1)).join(" ")}function X$($){return{id:$,name:Gj($),contextWindow:Rj,maxTokens:_j,reasoning:L$($),cost:{...Aj}}}import{execSync as Nj}from"node:child_process";import{randomUUID as O0}from"node:crypto";import{chmodSync as l$,closeSync as A0,constants as Wj,copyFileSync as Tj,existsSync as V$,fsyncSync as kj,linkSync as Bj,mkdirSync as Lj,openSync as Fj,readFileSync as H0,renameSync as Kj,rmSync as c$,writeFileSync as Sj}from"node:fs";import{homedir as F$}from"node:os";import{dirname as S$,join as D$}from"node:path";import{fileURLToPath as Ij}from"node:url";var U$=!1;function p$($){U$=$}var F={info(...$){if(!U$)console.log("[dm-cliproxy]",...$)},warn(...$){if(!U$)console.warn("[dm-cliproxy]",...$)},error(...$){if(!U$)console.error("[dm-cliproxy]",...$)},debug(...$){if(!U$&&(process.env.DM_CLIPROXY_DEBUG||process.env.PI_CLIPROXYAPI_DEBUG))console.log("[dm-cliproxy]","[debug]",...$)}};var m$=D$(F$(),".dm","agent","dm-cliproxy"),l=D$(m$,"config.json"),bj=[D$(F$(),".pi","agent","pi-cliproxyapi","config.json"),D$(F$(),".config","pi-cliproxyapi","config.json")];function R$($){Lj($,{recursive:!0,mode:448}),l$($,448)}function Q$($){if(V$($))l$($,384)}function Pj($){let j;try{j=JSON.parse(H0($,"utf8"))}catch{return}let J=j&&typeof j==="object"?j.proxy:void 0;for(let Z of[J?.apiKey,J?.usageKey]){if(typeof Z!=="string")continue;let Y=/^!cat\s+((?:~\/|\/)[^\s;&|`]+)$/.exec(Z.trim());if(!Y)continue;let X=Y[1].replace(/^~/,F$());Q$(X)}}function xj(){return V$(D$(S$(Ij(import.meta.url)),"..",".git"))}function nj($=bj,j=l,J=xj()){if(V$(j))return;let Y=(typeof $==="string"?[$]:[...$]).find((z)=>V$(z));if(!Y)return;let X;try{Q$(Y),Pj(Y),R$(S$(j)),X=`${j}.${process.pid}.${O0()}.tmp`,Tj(Y,X,Wj.COPYFILE_EXCL),l$(X,384),Bj(X,j),c$(X),X=void 0,F.info("legacy config copied to",j)}catch(z){if(X)try{c$(X,{force:!0})}catch(Q){F.warn("failed to clean temporary config:",Q)}F.warn("failed to migrate legacy config:",z)}}var K$={proxy:{endpoint:"",apiKey:""},builtinProviders:{},customProviders:{},discoveryExcludes:["*:*"],overrides:{},refreshIntervalMinutes:0,usageCacheTtlMs:30000};function r(){if(nj(),!V$(l))return F.debug("config not found, using defaults at",l),structuredClone(K$);try{R$(S$(l)),Q$(l);let $=JSON.parse(H0(l,"utf8"));return wj($)}catch($){return F.error("failed to read config:",$,"— using defaults"),structuredClone(K$)}}function yj($,j=l){R$(S$(j));let J=`${j}.${process.pid}.${O0()}.tmp`,Z;try{Z=Fj(J,"wx",384),Sj(Z,JSON.stringify($,null,2)+`
2
+ `,{encoding:"utf8"}),kj(Z),A0(Z),Z=void 0,Kj(J,j),Q$(j)}finally{if(Z!==void 0)A0(Z);c$(J,{force:!0})}}function I$($){yj($),F.info("config saved to",l)}function wj($){if(!$||typeof $!=="object")return structuredClone(K$);let j=$,J=structuredClone(K$),Z=j.proxy??{};if(J.proxy.endpoint=typeof Z.endpoint==="string"?Z.endpoint:J.proxy.endpoint,J.proxy.apiKey=typeof Z.apiKey==="string"?Z.apiKey:"",typeof Z.usageKey==="string")J.proxy.usageKey=Z.usageKey;if(typeof Z.providerPrefix==="string"&&Z.providerPrefix.trim())J.proxy.providerPrefix=Z.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 x($){if(!$)return"";let j=$.trim();if(j.startsWith("!"))try{return Nj(j.slice(1),{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).trim()}catch(J){let Z=J?.status,Y=typeof Z==="number"?` (exit ${Z})`:"";return F.warn(`failed to resolve "!" config value${Y}`),""}if(j.startsWith("$"))return process.env[j.slice(1)]??"";return j}import{createHash as Cj}from"node:crypto";import{existsSync as i1,readFileSync as r1,writeFileSync as vj}from"node:fs";import{dirname as uj,join as gj}from"node:path";var fj=gj(m$,"discovery-cache.json");function G0($,j){return Cj("sha256").update($.trim().replace(/\/+$/,"")).update("\x00").update(j).digest("hex")}function s$($,j,J=fj){try{R$(uj(J));let Z={savedAt:Date.now(),scope:j,discovery:$};vj(J,JSON.stringify(Z),{encoding:"utf8",mode:384}),Q$(J)}catch(Z){F.warn("failed to write discovery cache:",Z.message)}}var z$="dm-cliproxy/0.3.5",hj=5000;async function T0($,j){let J=new AbortController,Z=setTimeout(()=>J.abort(Error("timeout")),hj);try{return await fetch($,{...j,signal:J.signal})}finally{clearTimeout(Z)}}function pj($){return new URL("/.well-known/pi",new URL($).origin).toString()}async function cj($){let j=pj($.proxy.endpoint),J;try{J=await T0(j,{headers:{"User-Agent":z$,Accept:"application/json"}})}catch(Q){return F.warn("well-known fetch failed:",Q.message,"— falling back to /v1/models"),null}if(!J.ok)return F.warn(`well-known returned ${J.status} — falling back to /v1/models`),null;let Z;try{Z=await J.json()}catch{return F.warn("well-known returned non-JSON — falling back to /v1/models"),null}if(!Z||Z.schemaVersion!==1)return F.warn("well-known schemaVersion != 1 — falling back to /v1/models"),null;let Y=[],X=Z.builtinProviders??{};for(let[Q,q]of Object.entries(X)){if(!q||!Array.isArray(q.models))continue;let E=q.models.map((M)=>({id:String(M.id),name:typeof M.name==="string"?M.name:String(M.id),reasoning:Boolean(M.reasoning??L$(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:Q,api:q.api??"openai-responses",models:E})}let z=(Array.isArray(Z.customModelPool)?Z.customModelPool:[]).map((Q)=>({id:String(Q.id),name:typeof Q.name==="string"?Q.name:String(Q.id),reasoning:Boolean(Q.reasoning??L$(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:R0(typeof Q.suggestedProviderName==="string"?Q.suggestedProviderName:"misc",$.proxy.providerPrefix),ownedBy:typeof Q.owned_by==="string"?Q.owned_by:""}));return{source:"well-known",upstreamVersion:typeof Z?.upstream?.upstreamVersion==="string"?Z.upstream.upstreamVersion:null,builtinProviders:Y,customPool:z,serverDiscoveryExcludes:Array.isArray(Z.discoveryExcludes)?Z.discoveryExcludes.filter((Q)=>typeof Q==="string"):[],upstreamTotal:typeof Z?.counts?.upstreamTotal==="number"?Z.counts.upstreamTotal:0}}async function lj($,j){let J=new URL("/v1/models",new URL($.proxy.endpoint).origin).toString(),Z=await T0(J,{headers:{Authorization:`Bearer ${j}`,Accept:"application/json","User-Agent":z$}});if(!Z.ok)throw Error(`/v1/models returned ${Z.status}`);let Y=await Z.json();if(!Y?.data||!Array.isArray(Y.data))return[];return Y.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 mj($,j){let J=j.discoveryExcludes,Z=new Map,Y=[],X=0;for(let z of $){if(X++,D0(z.id,J))continue;if(z.owned_by==="openai"){let M=X$(z.id);N0(Z,"openai","openai-responses",W0(M));continue}if(z.owned_by==="anthropic"){let M=X$(z.id);N0(Z,"anthropic","anthropic-messages",W0(M));continue}let{slug:Q,api:q}=_0(z.owned_by,j.proxy.providerPrefix),E=X$(z.id);Y.push({id:z.id,name:E.name??z.id,reasoning:E.reasoning??!1,contextWindow:E.contextWindow??128000,maxTokens:E.maxTokens??16000,cost:E.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(Z.values()),customPool:Y,serverDiscoveryExcludes:[],upstreamTotal:X}}function N0($,j,J,Z){let Y=$.get(j);if(!Y)Y={name:j,api:J,models:[]},$.set(j,Y);Y.models.push(Z)}function W0($){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 _$($,j){let J=G0($.proxy.endpoint,j),Z=await cj($);if(Z)return F.info(`discovery via /.well-known/pi: ${Z.builtinProviders.length} builtin, ${Z.customPool.length} custom`),s$(Z,J),Z;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 lj($,j),X=mj(Y,$);return F.info(`discovery via /v1/models: ${X.builtinProviders.length} builtin, ${X.customPool.length} custom`),s$(X,J),X}function k0($){let j=new Set;for(let J of $.builtinProviders)for(let Z of J.models)j.add(Z.id);for(let J of $.customPool)j.add(J.id);return j}var B0=new WeakMap,o$=new WeakMap;function A$($){let j=(o$.get($)??0)+1;return o$.set($,j),j}function b$($,j){return j===void 0||j===(o$.get($)??0)}function L0($,j,J){let Z=B0.get($)??new Set;for(let Y of Z){if(j.has(Y))continue;$.unregisterProvider(Y),J.unregistered.push(Y)}B0.set($,new Set(j))}async function O$($,j,J,Z){let Y={registered:[],skipped:[],unregistered:[]};if(!b$($,Z))return Y.skipped.push({provider:"*",reason:"stale refresh generation"}),Y;let X=new Set,z=k0(J),Q=x(j.proxy.apiKey);if(!Q)return F.warn("proxy apiKey is empty — dm.registerProvider calls will be skipped"),L0($,X,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(!b$($,Z))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 K=[];try{K=sj(M)}catch{}let k=new Map(K.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=k.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){Y.skipped.push({provider:M,reason:"no whitelisted models present on proxy"});continue}let A=U.apiOverride??D[0].api;if(!f$.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:h$(A,j.proxy.endpoint),apiKey:Q,authHeader:!0,api:A,models:B};$.registerProvider(M,C),X.add(M),Y.registered.push({provider:M,modelCount:B.length,api:A})}let E=new Map(J.customPool.map((M)=>[M.id,M]));for(let[M,U]of Object.entries(j.customProviders)){if(!b$($,Z))return Y;if(!f$.has(U.api)){Y.skipped.push({provider:M,reason:`api "${U.api}" not in allowlist`});continue}let K=U.models.filter((D)=>z.has(D.id));if(K.length===0){Y.skipped.push({provider:M,reason:"no configured models present on proxy"});continue}let k=K.map((D)=>{let A=E.get(D.id),B=X$(D.id),C=j.overrides[D.id]??{};return{id:D.id,name:D.name??A?.name??B.name??D.id,api:U.api,reasoning:oj(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:F0(D.contextWindow,A?.contextWindow,B.contextWindow,C.contextWindow)??128000,maxTokens:F0(D.maxTokens,A?.maxTokens,B.maxTokens,C.maxTokens)??16000}}),O={name:M,baseUrl:h$(U.api,j.proxy.endpoint),apiKey:Q,authHeader:!0,api:U.api,models:k};$.registerProvider(M,O),X.add(M),Y.registered.push({provider:M,modelCount:k.length,api:U.api})}if(b$($,Z))L0($,X,Y);return F.info(`applyAll: registered ${Y.registered.length} providers, skipped ${Y.skipped.length}, unregistered ${Y.unregistered.length}`),Y}function F0(...$){for(let j of $)if(typeof j==="number")return j;return}function oj(...$){for(let j of $)if(typeof j==="boolean")return j;return}var ij=15000,H$=null;function q$(){H$=null}async function K0($,j,J={}){if(!J.force&&H$&&Date.now()-H$.fetchedAt<$.usageCacheTtlMs)return H$.doc;if(!j)throw Error("usage key not configured; set proxy.usageKey in config and rerun");let Z=new URL("/api/usage",new URL($.proxy.endpoint).origin).toString(),Y=new AbortController,X=setTimeout(()=>Y.abort(Error("timeout")),ij),z;try{z=await fetch(Z,{headers:{"X-Plugin-Key":j,Accept:"application/json","User-Agent":z$},signal:Y.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 H$={fetchedAt:Date.now(),doc:Q},F.debug("usage fetched, accounts:",Q.accounts.length),Q}import{getKeybindings as n1,matchesKey as u}from"@duckmind/dm-tui";import{visibleWidth as r$}from"@duckmind/dm-tui";import{visibleWidth as S0}from"@duckmind/dm-tui";function S($,j){let J=S0($);if(J===j)return $;if(J<j)return $+" ".repeat(j-J);return i$($,j)}function i$($,j){if(j<=0)return"\x1B[0m";let J="",Z=0,Y=0;while(Y<$.length){let X=$[Y];if(X==="\x1B"&&$[Y+1]==="["){let Q=$.indexOf("m",Y+2);if(Q>=0){J+=$.slice(Y,Q+1),Y=Q+1;continue}}let z=S0(X);if(Z+z>j)break;J+=X,Z+=z,Y++}return`${J}\x1B[0m`}var rj="│",dj="╭",tj="╮",aj="╰",ej="╯",G$="─";function d($,j){let J=Math.max(4,j.width);return[$1($,j.title,j.titleColor??"accent",J),...j.lines.map((Z)=>j1($,Z,J)),J1($,j.footer,J)]}function $1($,j,J,Z){let Y=j??"",X=r$(Y),z=Math.max(0,Z-3-X),Q=Y?$.bold($.fg(J,Y)):"",q=`${dj}${G$}${Q}${G$.repeat(z)}${tj}`;return $.fg("borderAccent",q)}function j1($,j,J){let Z=Math.max(0,J-2),Y=$.fg("borderAccent",rj);return`${Y}${S(j,Z)}${Y}`}function J1($,j,J){let Z=`${aj}${G$}`,Y=`${ej}`,X=3;if(!j||!j.hint&&!j.badge){let O=Math.max(0,J-3);return $.fg("borderAccent",`${Z}${G$.repeat(O)}${Y}`)}let z=j.hint??"",Q=j.badge??"",q=r$(z),E=r$(Q),M=Math.max(0,J-3-q-E),U=$.fg("dim",z),K=Q?$.fg("muted",Q):"",k=G$.repeat(M);return`${$.fg("borderAccent",Z)}${U}${$.fg("borderAccent",k)}${K}${$.fg("borderAccent",Y)}`}function P$($){return Math.max(0,$-2)}import{existsSync as I0}from"node:fs";import{homedir as Y1}from"node:os";import{getKeybindings as Z1,Input as d$,matchesKey as X1}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 N$($,j=!1){let J=r(),Z={endpoint:J.proxy.endpoint??"",apiKey:J.proxy.apiKey??"",providerPrefix:J.proxy.providerPrefix??"",usageKey:J.proxy.usageKey??""},Y=!1;for(let z of Q1){let Q=Z[z.label]??"",q=z.secret?"":j?Z[z.label]??z.initialValue??"":Z[z.label]??"";if(!j&&q)continue;let E=z.secret&&Q?{...z,required:!1}:z,M=await M1($,E,q||z.initialValue||"");if(M===void 0){Y=!0;break}let U=q1(z,Q,M);if(U===null){if(z.required){$.ui.notify(`${z.label} is required — aborted`,"warning"),Y=!0;break}}Z[z.label]=U??""}if(Y)return!1;let X={...J};if(X.proxy={...J.proxy,endpoint:Z.endpoint??"",apiKey:Z.apiKey??"",providerPrefix:Z.providerPrefix??""},Z.usageKey)X.proxy.usageKey=Z.usageKey;else delete X.proxy.usageKey;return I$(X),$.ui.notify(`saved to ${l}`,"info"),!0}function z1($){if($.startsWith("!")||$.startsWith("$"))return $;if($.startsWith("~/")){let j=$.replace(/^~/,Y1());return I0(j)?`!cat ${$}`:$}if($.startsWith("/"))return I0($)?`!cat ${$}`:$;return $}function q1($,j,J){let Z=J.trim();if(!Z){if($.secret&&j)return j;return $.required?null:""}if($.secret&&!$.required&&Z==="-")return"";return $.label==="providerPrefix"||$.label==="endpoint"?Z:z1(Z)}async function M1($,j,J){return $.ui.custom((Z,Y,X,z)=>E1(Z,Y,j,J,z),{overlay:!0,overlayOptions:{width:100,maxHeight:"60%"}})}class b0{rawInput=new d$;displayInput=new d$;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 Z=$.codePointAt(J),Y=String.fromCodePoint(Z);j+=Z<32||Z===127?Y:"•",J+=Y.length}return j}}function E1($,j,J,Z,Y){let X=J.secret?new b0:new d$;X.setValue(Z),X.focused=!0;let z=null,Q=(q)=>{if(!q&&!J.required){Y("");return}if(!q&&J.required){z="required field",$.requestRender();return}if(J.validate){let E=q.trim();if(E&&!E.startsWith("!")&&!E.startsWith("$")){let M=J.validate(E);if(M){z=M,$.requestRender();return}}}Y(q)};return X.onSubmit=Q,X.onEscape=()=>Y(void 0),{render(q){let E=P$(q),M=X.render(E-4),U=["",` ${j.fg("dim",J.hint)}`,"",...M.map((K)=>` ${j.fg("accent",`❯ ${K}`)}`),"",z?` ${j.fg("error",`! ${z}`)}`:` ${j.fg("dim","enter = save · esc = cancel")}`];return d(j,{width:q,title:` setup: ${J.label} `,lines:U,footer:{hint:" enter = save · esc = cancel "}})},invalidate(){X.invalidate()},handleInput(q){if(Z1().matches(q,"tui.select.cancel")||X1(q,"escape")){Y(void 0);return}z=null,X.handleInput(q),$.requestRender()}}}import{visibleWidth as x$}from"@duckmind/dm-tui";function P0($,j,J,Z){let Y=$.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(Y)}`,Z)}function x0($,j,J){let Z=j.join($.fg("dim"," "));return S(` ${Z}`,J)}function n0($,j){return $.fg("borderAccent","─".repeat(Math.max(0,j)))}function t($,j,J){let Z=$.slice(j,j+J);while(Z.length<J)Z.push("");return Z}function n$($,j,J,Z,Y,X){if(Y<=Z)return 0;let z=Math.max(0,Y-Z);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 E=Q+Z-1;if(j>E)Q=Math.min(z,j-(Z-1));return Q}function y$($,j,J){let Z=Math.max(0,J-j);return Math.max(0,Math.min($,Z))}import{matchesKey as a}from"@duckmind/dm-tui";import{existsSync as U1,readFileSync as V1}from"node:fs";import{homedir as w0}from"node:os";import{join as C0}from"node:path";var D1=C0(w0(),".dm","models.json"),R1=C0(w0(),".dm","auth.json");function y0($){if(!U1($))return null;try{return JSON.parse(V1($,"utf8"))}catch{return null}}function v0($){let j=[],J=new Set([...Object.keys($.builtinProviders),...Object.keys($.customProviders)]),Z=y0(D1);if(Z&&typeof Z==="object"){for(let X of Object.keys(Z))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 Y=y0(R1);if(Y&&typeof Y==="object"){for(let X of Object.keys(Y))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 u0($){let{theme:j,cfg:J}=$,Z=0,Y=()=>{let Q=$.getDiscovery(),q=(O)=>j.fg("success",O),E=(O)=>j.fg("error",O),M=(O)=>j.fg("dim",O),U=[];U.push(`${M("endpoint")} ${J.proxy.endpoint||E("(unset)")}`),U.push(`${M("apiKey")} ${x(J.proxy.apiKey)?q("resolves"):E("empty after resolution")}`),U.push(`${M("usageKey")} ${J.proxy.usageKey?x(J.proxy.usageKey)?q("resolves"):E("set but empty"):M("not configured")}`),U.push(`${M("user-agent")} ${z$}`),U.push(""),U.push(`${M("discovery")} source=${Q.source}`),U.push(`${M("upstream")} v=${Q.upstreamVersion??"(unknown)"} · ${Q.upstreamTotal} ids`);let K=Q.builtinProviders.map((O)=>`${O.name}=${O.models.length}`).join(", ")||M("(none)");U.push(`${M("built-in")} ${K}`),U.push(`${M("custom pool")} ${Q.customPool.length} models`);let k=v0(J);if(U.push(""),k.length===0)U.push(`${M("conflicts")} ${q("none")}`);else{U.push(`${M("conflicts")}`);for(let O of k)U.push(` ${j.fg("warning",`[${O.kind}]`)} ${O.detail}`)}return U};return{id:"diagnostics",label:"Diagnostics",render:(Q,q)=>{let E=Y();return Z=y$(Z,q,E.length),t(E,Z,q).map((M)=>S(` ${M}`,Q))},handleInput:(Q)=>{let q=Y().length;if(a(Q,"up")||a(Q,"k"))return Z=Math.max(0,Z-1),!0;if(a(Q,"down")||a(Q,"j"))return Z=Math.min(Math.max(0,q-1),Z+1),!0;if(a(Q,"pageUp")||a(Q,"b"))return Z=Math.max(0,Z-10),!0;if(a(Q,"pageDown")||a(Q,"f"))return Z=Math.min(Math.max(0,q-1),Z+10),!0;return!1},footerHint:()=>" ↑↓ scroll · r refresh discovery "}}import{matchesKey as T}from"@duckmind/dm-tui";function t$($){let j=new Map,J=new Map;for(let Y of $.builtinProviders){let X=[];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}),X.push(z.id);J.set(Y.name,X)}let Z=[];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});Z.push(Y.id)}return{byId:j,builtinModelIds:J,customPoolIds:Z}}function _1($){let j=new Map;for(let[J,Z]of Object.entries($.customProviders))for(let Y of Z.models)j.set(Y.id,J);return j}function j$($,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$($,j));return X.filter((Q)=>!z.has(Q))}let Z=_1($),Y=new Set(j$($,j));return J.customPoolIds.filter((X)=>{if(Y.has(X))return!1;let z=Z.get(X);return z===void 0||z===j.name})}function A1($){return{id:$.id,name:$.name,contextWindow:$.contextWindow,maxTokens:$.maxTokens,reasoning:$.reasoning,cost:$.cost}}function f0($,j,J){if(j.kind==="builtin"){let Y=$.builtinProviders[j.name]??{enabled:!0,models:[]},X=new Set(Y.models);X.add(J.id),$.builtinProviders[j.name]={enabled:!0,apiOverride:Y.apiOverride??null,models:Array.from(X).sort()};return}for(let[Y,X]of Object.entries($.customProviders)){if(Y===j.name)continue;let z=X.models.findIndex((Q)=>Q.id===J.id);if(z>=0)X.models.splice(z,1)}let Z=$.customProviders[j.name]??{api:j.api,models:[]};if(!Z.models.some((Y)=>Y.id===J.id))Z.models.push(A1(J));$.customProviders[j.name]=Z}function h0($,j,J){if(j.kind==="builtin"){let Y=$.builtinProviders[j.name];if(!Y)return;Y.models=Y.models.filter((X)=>X!==J),Y.enabled=Y.models.length>0;return}let Z=$.customProviders[j.name];if(!Z)return;Z.models=Z.models.filter((Y)=>Y.id!==J)}function a$($,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 Z of $){let Y=j.byId.get(Z),X=Y?.ownedBy||Y?.origin||"misc",z=J.get(X)??[];z.push(Z),J.set(X,z)}return Array.from(J.entries()).sort((Z,Y)=>Z[0].localeCompare(Y[0])).map(([Z,Y])=>({label:Z,ids:Y}))}function c0($,j,J){let Z=J.trim().toLowerCase();if(!Z)return $;return $.filter((Y)=>{if(Y.toLowerCase().includes(Z))return!0;let X=j.byId.get(Y)?.name;return X?X.toLowerCase().includes(Z):!1})}import{getModels as O1,getProviders as H1}from"@duckmind/dm-ai/compat";function e$($,j){let J=[],Z=new Set(j.builtinModelIds.keys()),Y=new Set(H1()),X=new Set([...Z,...Y]);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=O1(z).find((U)=>Q.includes(U.id));if(M)q=M.api}catch{}if(!q){let E=Q[0];q=j.byId.get(E)?.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 G1,matchesKey as M$}from"@duckmind/dm-tui";async function l0($,j){return $.ui.custom((J,Z,Y,X)=>N1(Z,`Remove custom group “${j}”?`,"All model assignments in this group will be discarded.",X),{overlay:!0,overlayOptions:{width:80,maxHeight:"40%"}})}function N1($,j,J,Z){return{render(Y){return d($,{width:Y,title:" confirm ",titleColor:"error",lines:["",` ${$.bold(j)}`,` ${$.fg("dim",J)}`,""],footer:{hint:" y / enter = remove · n / esc = cancel "}})},invalidate(){},handleInput(Y){if(G1().matches(Y,"tui.select.cancel")||M$(Y,"escape")||M$(Y,"n")||M$(Y,"q")){Z(!1);return}if(M$(Y,"y")||M$(Y,"enter")||M$(Y,"return")){Z(!0);return}}}}import{getKeybindings as W1,Input as T1,matchesKey as k1}from"@duckmind/dm-tui";async function m0($,j){let J=B$(j,"group");return $.ui.custom((Z,Y,X,z)=>B1(Z,Y,J,z),{overlay:!0,overlayOptions:{width:80,maxHeight:"40%"}})}function B1($,j,J,Z){let Y=new T1;if(J)Y.setValue(J);Y.focused=!0;let X=null;return Y.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}Z(Q)},Y.onEscape=()=>Z(null),{render(z){let Q=P$(z),q=J?`name shown in /model picker, e.g. ${J}`:"letters / digits / dot / dash / underscore",E=Y.render(Q-4),M=["",` ${j.fg("dim",q)}`,"",...E.map((U)=>` ${j.fg("accent",`❯ ${U}`)}`),"",X?` ${j.fg("error",`! ${X}`)}`:""];return d(j,{width:z,title:" new custom group ",lines:M,footer:{hint:" enter = create · esc = cancel "}})},invalidate(){Y.invalidate()},handleInput(z){if(W1().matches(z,"tui.select.cancel")||k1(z,"escape")){Z(null);return}X=null,Y.handleInput(z),$.requestRender()}}}import{visibleWidth as L1}from"@duckmind/dm-tui";function $0($,j,J){if(!j)return" ";if(J)return $.fg("accent","▶ ");return $.fg("muted","▸ ")}function s0($,j){let J=L1($);if(J===j)return $;if(J>j)return i$($,j);return S($,j)}function o0($,j,J){let{theme:Z,width:Y,isCursor:X,isFocused:z}=J,Q=$0(Z,X,z),q=$.kind==="builtin"?j.builtinProviders[$.name]?.models.length??0:j.customProviders[$.name]?.models.length??0,E=$.kind==="builtin"?Z.fg("accent","B"):Z.fg("warning","C"),M=`${Z.fg("dim","[")}${E}${Z.fg("dim","]")}`,U=q>0?Z.fg("success","●"):Z.fg("dim","○"),K=q>0?Z.fg("success",String(q).padStart(2)):Z.fg("dim"," 0"),k=X&&z?Z.bold(Z.fg("accent",$.name)):X?Z.bold($.name):$.name,O=Z.fg("dim",$.api),D=`${Q}${M} ${k} ${U}${K} ${O}`;return s0(D,Y)}function i0($,j,J,Z){let Y=$0($,j,J),X=j&&J?$.bold($.fg("accent","+ new custom group…")):$.fg("accent","+ new custom group…");return S(`${Y}${X}`,Z)}function j0($,j,J,Z,Y){let{theme:X,width:z,isCursor:Q,isFocused:q}=Y,E=$0(X,Q,q),M=J==="assigned"?X.fg("success","☑"):X.fg("dim","☐"),U=Z?` ${X.fg("warning","⚠")}`:"",K=Q&&q?X.fg("accent",$):$,k=j?.reasoning?` ${X.fg("accent","✨")}`:"",O=j?X.fg("muted",` · ${j.suggestedApi}`):X.fg("error"," · not on proxy"),D=`${E}${M} ${K}${U}${k}${O}`;return s0(D,z)}function r0($,j,J){let Z=`${$.fg("borderAccent","──")} ${$.fg("warning",j)} ${$.fg("borderAccent","──")}`;return S(` ${Z}`,J)}function J0($,j,J){return S(` ${$.fg("dim",j)}`,J)}function d0($,j,J,Z){let Y=Z?$.bold($.fg("accent","❚ ")):$.fg("dim"," ");return S(`${Y}${j}`,J)}function t0($){let{tui:j,theme:J,ctx:Z,cfg:Y}=$,X=$.onChange??(()=>{}),z=t$($.getDiscovery()),Q=e$(Y,z),q="providers",E=0,M=0,U=0,K=0,k=0,O=0,D="",A=!1,B=()=>{if(Q.length===0)return null;let V=Math.max(0,Math.min(E,Q.length-1));return Q[V]??null},C=(V)=>{let H=c0(g0(Y,V,z),z,D);return p0(H,z)},N=(V)=>C(V).flatMap((H)=>H.ids),G=()=>{Q=e$(Y,z);let V=Math.max(0,Q.length);if(E>V)E=V;let H=B();if(H){let P=j$(Y,H).length,W=N(H).length;if(M>=P)M=Math.max(0,P-1);if(U>=W)U=Math.max(0,W-1)}},n=()=>{z=t$($.getDiscovery()),G()},J$=(V)=>{let H=["providers","assigned","pool"],P=H.indexOf(q);q=V?H[(P-1+H.length)%H.length]:H[(P+1)%H.length]},_=(V)=>{if(q==="providers"){let W=Q.length+1;E=Math.max(0,Math.min(E+V,W-1));return}let H=B();if(!H)return;if(q==="assigned"){let W=j$(Y,H).length;if(W===0)return;M=Math.max(0,Math.min(M+V,W-1));return}let P=N(H).length;if(P===0)return;U=Math.max(0,Math.min(U+V,P-1))},b=async()=>{if(q==="providers"){if(E===Q.length){let W=await m0(Z,Y.proxy.providerPrefix);if(W&&!Y.customProviders[W]){if(Y.customProviders[W]={api:"openai-completions",models:[]},X(),G(),E=Q.findIndex((I)=>I.kind==="custom"&&I.name===W),E<0)E=Q.length-1;q="pool"}j.requestRender();return}q="pool";return}let V=B();if(!V)return;if(q==="assigned"){let W=j$(Y,V)[M];if(!W)return;h0(Y,V,W),X(),G();return}let H=N(V)[U];if(!H)return;let P=z.byId.get(H);if(!P)return;f0(Y,V,P),X(),G()},p=async()=>{if(q!=="providers")return;let V=B();if(!V||V.kind!=="custom")return;if(!await l0(Z,V.name)){j.requestRender();return}if(delete Y.customProviders[V.name],X(),G(),E>=Q.length)E=Math.max(0,Q.length-1);j.requestRender()},g=(V,H)=>c(V,H);function c(V,H){let P=Math.max(70,V),W=Math.min(56,Math.max(34,Math.floor(P*0.4))),I=P-W-1,s=Math.max(8,H),o=Math.max(5,Math.floor((s-1)/2)),Y0=s-o,m=B(),E$=0,w$=0,C$=0,Z0=0,v$=0,X0=0,e=[];e.push(Y$(" providers ",W,q==="providers"));for(let L=0;L<Q.length;L++){let f=Q[L],v=q==="providers"&&L===E;if(v)E$=e.length,w$=E$;e.push(o0(f,Y,{theme:J,width:W,isCursor:v,isFocused:q==="providers"}))}{let L=q==="providers"&&E===Q.length;if(L)E$=e.length,w$=E$;e.push(i0(J,L,q==="providers",W))}let $$=[],Mj=m?`assigned to ${J.bold(m.name)} ${J.fg("dim",`· ${m.api}`)}`:J.fg("dim","no provider selected");if($$.push(Y$(" assigned ",I,q==="assigned")),$$.push(d0(J,Mj,I,q==="assigned")),m){let L=j$(Y,m);if(L.length===0)$$.push(J0(J,"(nothing assigned yet)",I));for(let f=0;f<L.length;f++){let v=L[f],h=z.byId.get(v),k$=q==="assigned"&&f===M;if(k$)C$=$$.length,Z0=C$;let Z$=h?!a$(m.api,h.suggestedApi):!1;$$.push(j0(v,h,"assigned",Z$,{theme:J,width:I,isCursor:k$,isFocused:q==="assigned"}))}}let i=[];if(i.push(y(I,q==="pool")),m){let L=C(m);if(L.reduce((v,h)=>v+h.ids.length,0)===0)i.push(J0(J,D?`(no matches for "${D}")`:"(no models available)",I));else{let v=0;for(let h of L){let k$=i.length;i.push(r0(J,h.label,I));for(let Z$=0;Z$<h.ids.length;Z$++){let U0=h.ids[Z$],g$=z.byId.get(U0),V0=q==="pool"&&v===U;if(V0)v$=i.length,X0=Z$===0?k$:v$;let Dj=g$?!a$(m.api,g$.suggestedApi):!1;i.push(j0(U0,g$,"pool",Dj,{theme:J,width:I,isCursor:V0,isFocused:q==="pool"})),v++}}}}let Ej=Math.max(1,Y0-1),Q0=n$(w$,E$,K,s,e.length,1),z0=n$(q==="assigned"?Z0:0,q==="assigned"?C$:0,k,o,$$.length,2),q0=n$(q==="pool"?X0:0,q==="pool"?v$:0,O,Ej,i.length,1);K=Q0,k=z0,O=q0;let M0=t(e,Q0,s),Uj=t($$,z0,o),Vj=t(i,q0,Y0),E0=J.fg("borderAccent","│"),u$=[];for(let L=0;L<s;L++){let f=S(M0[L]??"",W),v=L<o?Uj[L]:Vj[L-o],h=S(v,I);u$.push(`${f}${E0}${h}`)}let T$=o;if(T$>0&&T$<s){let L=S(M0[T$]??"",W),f=J.fg("borderAccent","─".repeat(I));u$[T$]=`${L}${E0}${f}`}return u$}function Y$(V,H,P){let W=P?J.bold(J.fg("accent",V)):J.fg("muted",V),I=J.fg("borderAccent","─".repeat(Math.max(0,H-x$(V)-1)));return S(`${W}${I}`,H)}function y(V,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=x$(" available pool ")+x$(I),o=J.fg("borderAccent","─".repeat(Math.max(0,V-s-1)));return S(`${W}${I}${o}`,V)}function W$(V){if(A){if(T(V,"escape"))return D="",A=!1,U=0,!0;if(T(V,"enter")||T(V,"return"))return A=!1,!0;if(T(V,"backspace")||T(V,"delete"))return D=D.slice(0,-1),U=0,!0;if(V.length===1&&V>=" "&&V!=="")return D+=V,U=0,!0;return!0}if(T(V,"tab"))return J$(!1),!0;if(T(V,"shift+tab"))return J$(!0),!0;if(T(V,"/"))return q="pool",A=!0,!0;if(T(V,"enter")||T(V,"return")||T(V,"space"))return b().then(()=>!0);if(q==="providers"&&(T(V,"d")||T(V,"delete")||T(V,"backspace")))return p().then(()=>!0);if(T(V,"up")||T(V,"k"))return _(-1),!0;if(T(V,"down")||T(V,"j"))return _(1),!0;if(T(V,"pageUp")||T(V,"b"))return _(-8),!0;if(T(V,"pageDown")||T(V,"f"))return _(8),!0;if(T(V,"left")||T(V,"h"))return q="providers",!0;if(T(V,"right")||T(V,"l")){if(q==="providers")q="assigned";else if(q==="assigned")q="pool";return!0}return!1}function qj(){if(A)return" type to filter · ↵ apply · esc clear ";return" tab ↔ panel · ↑↓ nav · ↵ move · / filter · d remove group "}return{id:"models",label:"Models",render:g,handleInput:W$,footerHint:qj,rebuild:n}}import{matchesKey as w}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=[],Z=new Map,Y=0;for(let X of $.accounts){if(!j.showDisabled&&X.disabled){Y++;continue}let z=Z.get(X.provider)??[];z.push(X),Z.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(Y>0)J.push(`${R.dim}hidden disabled accounts:${R.reset} ${Y} ${R.dim2}(press d to show)${R.reset}`);for(let[X,z]of Array.from(Z.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 E of F1(Q.error,88))J.push(` ${R.red}${E}${R.reset}`);continue}let q=Q.groups??[];if(q.length===0){J.push(` ${R.dim2}(no active quota windows)${R.reset}`);continue}for(let E of q)J.push(I1(E))}}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 F1($,j){if($.length<=j)return[$];let J=[],Z=$;while(Z.length>j){let Y=Z.lastIndexOf(" ",j);if(Y<j*0.6)Y=j;J.push(Z.slice(0,Y)),Z=Z.slice(Y).replace(/^\s+/,"")}if(Z)J.push(Z);return J}function K1($){let j=S1($),J=`${R.green}✓${$.success}${R.reset} ${R.red}✗${$.failed}${R.reset}`,Z=Zj($.label,36);return` ${j} ${R.bold}${Z}${R.reset} ${J}`}var e0=`${R.green}●${R.reset}`,$j=`${R.yellow}⚠${R.reset}`,jj=`${R.dim2}⊘${R.reset}`;function S1($){if($.disabled)return jj;if($.unavailable||$.error||$.status&&$.status!=="active")return $j;return e0}function I1($){let j=Yj($.remainingFraction),J=Math.round(j*100),Z=b1(j),Y=$.resetTime?` ${R.dim}reset ${x1($.resetTime)}${R.reset}`:"",X=Zj($.label,28).padEnd(28," ");return` ${Z} ${P1(J,j)} ${X}${Y}`}function b1($){let j=Yj($),J=Math.round(j*18),Z=Jj(j),Y=R.dim2,X="█".repeat(J),z="░".repeat(18-J);return`${Y}[${Z}${X}${Y}${z}]${R.reset}`}function P1($,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 Z=Math.round(J/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 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:Z}=$,Y="idle",X=null,z="",Q=0,q=!1,E=!1,M=(D)=>{Y="loading",j.requestRender();let A=x(Z.proxy.usageKey);K0(Z,A,{force:D}).then((B)=>{X=B,Y="ready",Q=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(!X)return[J.fg("dim"," (no data)")];return a0(X,{showDisabled:q,verbose:E})};return{id:"usage",label:"Usage",render:(D,A)=>{let B=U();return Q=y$(Q,A,B.length),t(B,Q,A).map((C)=>S(` ${C}`,D))},handleInput:(D)=>{if(w(D,"d"))return q=!q,Q=0,!0;if(w(D,"v"))return E=!E,Q=0,!0;let A=U().length;if(w(D,"up")||w(D,"k"))return Q=Math.max(0,Q-1),!0;if(w(D,"down")||w(D,"j"))return Q=Math.min(Math.max(0,A-1),Q+1),!0;if(w(D,"pageUp")||w(D,"b"))return Q=Math.max(0,Q-10),!0;if(w(D,"pageDown")||w(D,"f"))return Q=Math.min(Math.max(0,A-1),Q+10),!0;if(w(D,"home")||w(D,"g"))return Q=0,!0;if(w(D,"end")||w(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=E?J.fg("success","[v verbose]"):"v verbose";return` ↑↓ scroll · ${D} · ${A} `},onActivate:()=>{if(Y==="idle")M(!1)},reload:()=>{if(q$(),Y!=="idle")M(!0)}}}function Qj($){let{dm:j,ctx:J,tui:Z,theme:Y,cfg:X,done:z}=$,Q=$.discovery,q=!1,E="",M=t0({tui:Z,theme:Y,ctx:J,cfg:X,getDiscovery:()=>Q,onChange:()=>{q=!0,E=""}}),U=Xj({tui:Z,theme:Y,cfg:X}),K=u0({theme:Y,cfg:X,getDiscovery:()=>Q}),k=[M,U,K],O=0,D=()=>k[O],A=(_)=>{if(_<0||_>=k.length||_===O)return;O=_,D().onActivate?.(),Z.requestRender()},B=()=>{E=Y.fg("dim","saving…"),I$(X),Z.requestRender();let _=A$(j);O$(j,X,Q,_).then((b)=>{q=!1,E=Y.fg("success",`✓ settings saved · ${b.registered.length} registered, ${b.skipped.length} skipped`),Z.requestRender()}).catch((b)=>{E=Y.fg("error",`save failed: ${b.message}`),Z.requestRender()})},C=async()=>{E=Y.fg("dim","refreshing…"),Z.requestRender();try{let _=A$(j),b=x(X.proxy.apiKey);Q=await _$(X,b),q$(),M.rebuild(),U.reload();let p=await O$(j,X,Q,_);E=Y.fg("success",`✓ refreshed · ${p.registered.length} providers (${Q.source})`)}catch(_){E=Y.fg("error",`refresh failed: ${_.message}`)}Z.requestRender()},N=async()=>{if(!await N$(J,!0)){Z.requestRender();return}let b=r();X.proxy={...X.proxy,...b.proxy},await C()},G=()=>{let _=X.proxy.endpoint||"(unset)",b=_.length>40?`…${_.slice(-39)}`:_,p=Boolean(x(X.proxy.apiKey)),g=0,c=0;for(let y of Object.values(X.builtinProviders)){if(y.enabled&&y.models.length>0)g++;c+=y.models.length}for(let y of Object.values(X.customProviders)){if(y.models.length>0)g++;c+=y.models.length}let Y$=E?E:q?Y.fg("warning","● unsaved — press s to save"):Y.fg("dim","✓ saved");return[`${Y.fg("dim","endpoint")} ${b}`,`${Y.fg("dim","key")} ${p?Y.fg("success","✓"):Y.fg("error","✗")}`,`${Y.fg("dim","providers")} ${g}`,`${Y.fg("dim","models")} ${c}`,Y$]},n=(_)=>{let b=Z.rows??40,g=Math.max(16,Math.min(b-6,38))-2,c=Math.max(72,_-2),Y$=Math.max(6,g-3),y=[];return y.push(x0(Y,G(),c)),y.push(P0(Y,k.map((W$)=>({id:W$.id,label:W$.label})),O,c)),y.push(n0(Y,c)),y.push(...D().render(c,Y$)),d(Y,{width:_,title:" /cliproxy ",lines:y,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)%k.length),!0;if(u(_,"[")||u(_,"shift+tab"))return A((O-1+k.length)%k.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){E="",b.then((g)=>{if(g)Z.requestRender()});return}if(b){E="",Z.requestRender();return}let p=J$(_);if(p instanceof Promise)p.then((g)=>{if(g)Z.requestRender()});else if(p)Z.requestRender()}}}async function zj($,j,J,Z){if(!j.hasUI){j.ui.notify("interactive UI required for /cliproxy","warning");return}let Y=structuredClone(J);p$(!0);try{await j.ui.custom((X,z,Q,q)=>Qj({dm:$,ctx:j,tui:X,theme:z,cfg:Y,discovery:Z,done:q}),{overlay:!0,overlayOptions:{width:170,maxHeight:"94%"}})}finally{p$(!1)}}function vJ($){$.registerCommand("cliproxy",{description:"Manage proxy models, usage, and diagnostics in one hub overlay",handler:y1.bind(null,$)}),$.registerCommand("cliproxy-setup",{description:"Set endpoint, API key, and (optional) usage key for the proxy",handler:w1.bind(null,$)})}async function y1($,j,J){let Z=r();if(!Z.proxy.endpoint||!x(Z.proxy.apiKey)){if(J.ui.notify("endpoint or API key not set — launching setup first","info"),!await N$(J,!0))return}let Y=r(),X=x(Y.proxy.apiKey),z;try{z=await _$(Y,X)}catch(Q){J.ui.notify(`discovery failed: ${Q.message}`,"error");return}await zj($,J,Y,z)}async function w1($,j,J){if(!await N$(J,!0))return;let Y=r();try{let X=A$($),z=await _$(Y,x(Y.proxy.apiKey)),Q=await O$($,Y,z,X);q$(),J.ui.notify(`setup ok · ${Q.registered.length} providers registered (source=${z.source})`,"info")}catch(X){J.ui.notify(`setup saved, but apply failed: ${X.message}`,"warning")}}export{vJ as registerCommands};
@@ -0,0 +1 @@
1
+ var K=new Set(["openai-completions","openai-responses","anthropic-messages"]);function h(b,c){let j=c.replace(/\/+$/,"");if(b==="anthropic-messages")return j.replace(/\/v1$/,"");return j}function M(b,c){if(!b)return!0;for(let j of c)if(new RegExp("^"+j.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*")+"$").test(b))return!0;return!1}var H=128000,J=16000,Q={input:0,output:0,cacheRead:0,cacheWrite:0},V=[/.*-thinking$/,/^gpt-5(\.\d+)?(-.*)?$/,/^gemini-3(\.\d+)?(-.*)?$/];function Y(b){return V.some((c)=>c.test(b))}var Z=[[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 q(b,c){let j=(b??"").trim();return j?`${j}-${c}`:c}function W(b,c){let j=(c??"").trim(),k=b.match(/^([a-z0-9]+-)(.*)$/);if(k)return j?`${j}-${k[1]}`:k[1];return b}function l(b,c){for(let[j,k,z]of Z)if(j.has(b))return{slug:q(c,k),api:z};return{slug:q(c,"misc"),api:"openai-completions"}}function $(b){return b.replace(/[/:]/g," ").split(/[-_]/).filter(Boolean).map((c)=>c[0].toUpperCase()+c.slice(1)).join(" ")}function y(b){return{id:b,name:$(b),contextWindow:H,maxTokens:J,reasoning:Y(b),cost:{...Q}}}export{q as withProviderPrefix,Y as reasoningFromId,$ as prettifyName,W as normalizeSuggestedProvider,y as modelDefaults,M as isExcluded,l as classifyCustom,h as baseUrlFor,J as DEFAULT_MAX_TOKENS,Q as DEFAULT_COST,H as DEFAULT_CONTEXT_WINDOW,K as ALLOWED_APIS};
@@ -0,0 +1,2 @@
1
+ import{execSync as G}from"node:child_process";import{randomUUID as k}from"node:crypto";import{chmodSync as B,closeSync as U,constants as N,copyFileSync as w,existsSync as Y,fsyncSync as A,linkSync as I,mkdirSync as _,openSync as D,readFileSync as O,renameSync as C,rmSync as L,writeFileSync as x}from"node:fs";import{homedir as V}from"node:os";import{dirname as q,join as $}from"node:path";import{fileURLToPath as v}from"node:url";var M=!1;var b={info(...K){if(!M)console.log("[dm-cliproxy]",...K)},warn(...K){if(!M)console.warn("[dm-cliproxy]",...K)},error(...K){if(!M)console.error("[dm-cliproxy]",...K)},debug(...K){if(!M&&(process.env.DM_CLIPROXY_DEBUG||process.env.PI_CLIPROXYAPI_DEBUG))console.log("[dm-cliproxy]","[debug]",...K)}};var S=$(V(),".dm","agent","dm-cliproxy"),z=$(S,"config.json"),F=[$(V(),".pi","agent","pi-cliproxyapi","config.json"),$(V(),".config","pi-cliproxyapi","config.json")];function H(K){_(K,{recursive:!0,mode:448}),B(K,448)}function R(K){if(Y(K))B(K,384)}function u(K){let J;try{J=JSON.parse(O(K,"utf8"))}catch{return}let W=J&&typeof J==="object"?J.proxy:void 0;for(let Q of[W?.apiKey,W?.usageKey]){if(typeof Q!=="string")continue;let X=/^!cat\s+((?:~\/|\/)[^\s;&|`]+)$/.exec(Q.trim());if(!X)continue;let Z=X[1].replace(/^~/,V());R(Z)}}function f(){return Y($(q(v(import.meta.url)),"..",".git"))}function p(K=F,J=z,W=f()){if(Y(J))return;let X=(typeof K==="string"?[K]:[...K]).find((E)=>Y(E));if(!X)return;let Z;try{R(X),u(X),H(q(J)),Z=`${J}.${process.pid}.${k()}.tmp`,w(X,Z,N.COPYFILE_EXCL),B(Z,384),I(Z,J),L(Z),Z=void 0,b.info("legacy config copied to",J)}catch(E){if(Z)try{L(Z,{force:!0})}catch(T){b.warn("failed to clean temporary config:",T)}b.warn("failed to migrate legacy config:",E)}}var j={proxy:{endpoint:"",apiKey:""},builtinProviders:{},customProviders:{},discoveryExcludes:["*:*"],overrides:{},refreshIntervalMinutes:0,usageCacheTtlMs:30000};function c(){if(p(),!Y(z))return b.debug("config not found, using defaults at",z),structuredClone(j);try{H(q(z)),R(z);let K=JSON.parse(O(z,"utf8"));return m(K)}catch(K){return b.error("failed to read config:",K,"— using defaults"),structuredClone(j)}}function d(K,J=z){H(q(J));let W=`${J}.${process.pid}.${k()}.tmp`,Q;try{Q=D(W,"wx",384),x(Q,JSON.stringify(K,null,2)+`
2
+ `,{encoding:"utf8"}),A(Q),U(Q),Q=void 0,C(W,J),R(J)}finally{if(Q!==void 0)U(Q);L(W,{force:!0})}}function o(K){d(K),b.info("config saved to",z)}function m(K){if(!K||typeof K!=="object")return structuredClone(j);let J=K,W=structuredClone(j),Q=J.proxy??{};if(W.proxy.endpoint=typeof Q.endpoint==="string"?Q.endpoint:W.proxy.endpoint,W.proxy.apiKey=typeof Q.apiKey==="string"?Q.apiKey:"",typeof Q.usageKey==="string")W.proxy.usageKey=Q.usageKey;if(typeof Q.providerPrefix==="string"&&Q.providerPrefix.trim())W.proxy.providerPrefix=Q.providerPrefix.trim();if(J.builtinProviders&&typeof J.builtinProviders==="object")W.builtinProviders=J.builtinProviders;if(J.customProviders&&typeof J.customProviders==="object")W.customProviders=J.customProviders;if(Array.isArray(J.discoveryExcludes))W.discoveryExcludes=J.discoveryExcludes.filter((X)=>typeof X==="string");if(J.overrides&&typeof J.overrides==="object")W.overrides=J.overrides;if(typeof J.refreshIntervalMinutes==="number")W.refreshIntervalMinutes=J.refreshIntervalMinutes;if(typeof J.usageCacheTtlMs==="number")W.usageCacheTtlMs=J.usageCacheTtlMs;return W}function t(K){if(!K)return"";let J=K.trim();if(J.startsWith("!"))try{return G(J.slice(1),{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).trim()}catch(W){let Q=W?.status,X=typeof Q==="number"?` (exit ${Q})`:"";return b.warn(`failed to resolve "!" config value${X}`),""}if(J.startsWith("$"))return process.env[J.slice(1)]??"";return J}export{d as saveConfigAtPath,o as saveConfig,t as resolveConfigValue,p as migrateLegacyConfig,c as loadConfig,f as isLocalCheckout,R as ensurePrivateFile,H as ensurePrivateDirectory,F as LEGACY_CONFIG_PATHS,z as CONFIG_PATH,S as CONFIG_DIR};
@@ -0,0 +1 @@
1
+ import{existsSync as c,readFileSync as f}from"node:fs";import{homedir as d}from"node:os";import{join as a}from"node:path";var m=a(d(),".dm","models.json"),u=a(d(),".dm","auth.json");function s(o){if(!c(o))return null;try{return JSON.parse(f(o,"utf8"))}catch{return null}}function g(o){let n=[],i=new Set([...Object.keys(o.builtinProviders),...Object.keys(o.customProviders)]),r=s(m);if(r&&typeof r==="object"){for(let e of Object.keys(r))if(i.has(e))n.push({kind:"models.json",provider:e,detail:`provider "${e}" has user overrides in ~/.dm/models.json which DM merges on top of our registration`})}let t=s(u);if(t&&typeof t==="object"){for(let e of Object.keys(t))if(i.has(e))n.push({kind:"auth.json",provider:e,detail:`provider "${e}" has user-set credentials in ~/.dm/auth.json which take priority over our apiKey`})}return n}export{g as detectConflicts};
@@ -0,0 +1 @@
1
+ function C(J,Z){if(!J)return!0;for(let $ of Z)if(new RegExp("^"+$.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*")+"$").test(J))return!0;return!1}var T=128000,x=16000,S={input:0,output:0,cacheRead:0,cacheWrite:0},b=[/.*-thinking$/,/^gpt-5(\.\d+)?(-.*)?$/,/^gemini-3(\.\d+)?(-.*)?$/];function H(J){return b.some((Z)=>Z.test(J))}var u=[[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 L(J,Z){let $=(J??"").trim();return $?`${$}-${Z}`:Z}function E(J,Z){let $=(Z??"").trim(),Y=J.match(/^([a-z0-9]+-)(.*)$/);if(Y)return $?`${$}-${Y[1]}`:Y[1];return J}function B(J,Z){for(let[$,Y,V]of u)if($.has(J))return{slug:L(Z,Y),api:V};return{slug:L(Z,"misc"),api:"openai-completions"}}function h(J){return J.replace(/[/:]/g," ").split(/[-_]/).filter(Boolean).map((Z)=>Z[0].toUpperCase()+Z.slice(1)).join(" ")}function v(J){return{id:J,name:h(J),contextWindow:T,maxTokens:x,reasoning:H(J),cost:{...S}}}import{createHash as n}from"node:crypto";import{existsSync as k0,readFileSync as A0,writeFileSync as p}from"node:fs";import{dirname as P,join as s}from"node:path";import{chmodSync as O,closeSync as a,constants as e,copyFileSync as J0,existsSync as f,fsyncSync as Y0,linkSync as Z0,mkdirSync as y,openSync as $0,readFileSync as Q0,renameSync as V0,rmSync as z0,writeFileSync as j0}from"node:fs";import{homedir as D}from"node:os";import{dirname as W0,join as R}from"node:path";var K=!1;var X={info(...J){if(!K)console.log("[dm-cliproxy]",...J)},warn(...J){if(!K)console.warn("[dm-cliproxy]",...J)},error(...J){if(!K)console.error("[dm-cliproxy]",...J)},debug(...J){if(!K&&(process.env.DM_CLIPROXY_DEBUG||process.env.PI_CLIPROXYAPI_DEBUG))console.log("[dm-cliproxy]","[debug]",...J)}};var k=R(D(),".dm","agent","dm-cliproxy"),H0=R(k,"config.json"),v0=[R(D(),".pi","agent","pi-cliproxyapi","config.json"),R(D(),".config","pi-cliproxyapi","config.json")];function w(J){y(J,{recursive:!0,mode:448}),O(J,448)}function U(J){if(f(J))O(J,384)}var g=s(k,"discovery-cache.json");function G(J,Z){return n("sha256").update(J.trim().replace(/\/+$/,"")).update("\x00").update(Z).digest("hex")}function A(J,Z,$=g){try{w(P($));let Y={savedAt:Date.now(),scope:Z,discovery:J};p($,JSON.stringify(Y),{encoding:"utf8",mode:384}),U($)}catch(Y){X.warn("failed to write discovery cache:",Y.message)}}var _="dm-cliproxy/0.3.5",d=5000;async function F(J,Z){let $=new AbortController,Y=setTimeout(()=>$.abort(Error("timeout")),d);try{return await fetch(J,{...Z,signal:$.signal})}finally{clearTimeout(Y)}}function l(J){return new URL("/.well-known/pi",new URL(J).origin).toString()}async function c(J){let Z=l(J.proxy.endpoint),$;try{$=await F(Z,{headers:{"User-Agent":_,Accept:"application/json"}})}catch(Q){return X.warn("well-known fetch failed:",Q.message,"— falling back to /v1/models"),null}if(!$.ok)return X.warn(`well-known returned ${$.status} — falling back to /v1/models`),null;let Y;try{Y=await $.json()}catch{return X.warn("well-known returned non-JSON — falling back to /v1/models"),null}if(!Y||Y.schemaVersion!==1)return X.warn("well-known schemaVersion != 1 — falling back to /v1/models"),null;let V=[],z=Y.builtinProviders??{};for(let[Q,q]of Object.entries(z)){if(!q||!Array.isArray(q.models))continue;let W=q.models.map((j)=>({id:String(j.id),name:typeof j.name==="string"?j.name:String(j.id),reasoning:Boolean(j.reasoning??H(String(j.id))),contextWindow:typeof j.contextWindow==="number"?j.contextWindow:200000,maxTokens:typeof j.maxTokens==="number"?j.maxTokens:16000,cost:j.cost??{input:0,output:0,cacheRead:0,cacheWrite:0}}));V.push({name:Q,api:q.api??"openai-responses",models:W})}let M=(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??H(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:E(typeof Q.suggestedProviderName==="string"?Q.suggestedProviderName:"misc",J.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:V,customPool:M,serverDiscoveryExcludes:Array.isArray(Y.discoveryExcludes)?Y.discoveryExcludes.filter((Q)=>typeof Q==="string"):[],upstreamTotal:typeof Y?.counts?.upstreamTotal==="number"?Y.counts.upstreamTotal:0}}async function t(J,Z){let $=new URL("/v1/models",new URL(J.proxy.endpoint).origin).toString(),Y=await F($,{headers:{Authorization:`Bearer ${Z}`,Accept:"application/json","User-Agent":_}});if(!Y.ok)throw Error(`/v1/models returned ${Y.status}`);let V=await Y.json();if(!V?.data||!Array.isArray(V.data))return[];return V.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 i(J,Z){let $=Z.discoveryExcludes,Y=new Map,V=[],z=0;for(let M of J){if(z++,C(M.id,$))continue;if(M.owned_by==="openai"){let j=v(M.id);I(Y,"openai","openai-responses",N(j));continue}if(M.owned_by==="anthropic"){let j=v(M.id);I(Y,"anthropic","anthropic-messages",N(j));continue}let{slug:Q,api:q}=B(M.owned_by,Z.proxy.providerPrefix),W=v(M.id);V.push({id:M.id,name:W.name??M.id,reasoning:W.reasoning??!1,contextWindow:W.contextWindow??128000,maxTokens:W.maxTokens??16000,cost:W.cost??{input:0,output:0,cacheRead:0,cacheWrite:0},api:q,suggestedProvider:Q,ownedBy:M.owned_by})}return{source:"v1-models",upstreamVersion:null,builtinProviders:Array.from(Y.values()),customPool:V,serverDiscoveryExcludes:[],upstreamTotal:z}}function I(J,Z,$,Y){let V=J.get(Z);if(!V)V={name:Z,api:$,models:[]},J.set(Z,V);V.models.push(Y)}function N(J){return{id:J.id,name:J.name??J.id,reasoning:J.reasoning??!1,contextWindow:J.contextWindow??128000,maxTokens:J.maxTokens??16000,cost:J.cost??{input:0,output:0,cacheRead:0,cacheWrite:0}}}async function G0(J,Z){let $=G(J.proxy.endpoint,Z),Y=await c(J);if(Y)return X.info(`discovery via /.well-known/pi: ${Y.builtinProviders.length} builtin, ${Y.customPool.length} custom`),A(Y,$),Y;if(!Z)throw Error("well-known unavailable AND proxy apiKey is empty — cannot fall back to /v1/models. Set proxy.apiKey in config.");let V=await t(J,Z),z=i(V,J);return X.info(`discovery via /v1/models: ${z.builtinProviders.length} builtin, ${z.customPool.length} custom`),A(z,$),z}function I0(J){let Z=new Set;for(let $ of J.builtinProviders)for(let Y of $.models)Z.add(Y.id);for(let $ of J.customPool)Z.add($.id);return Z}export{G0 as fetchDiscovery,I0 as discoveryToIdSet,_ as PLUGIN_USER_AGENT};
@@ -0,0 +1 @@
1
+ import{dirname as O,join as z}from"node:path";import{homedir as A}from"node:os";import{dirname as U,join as $}from"node:path";var V=!1;var s={info(...n){if(!V)console.log("[dm-cliproxy]",...n)},warn(...n){if(!V)console.warn("[dm-cliproxy]",...n)},error(...n){if(!V)console.error("[dm-cliproxy]",...n)},debug(...n){if(!V&&(process.env.DM_CLIPROXY_DEBUG||process.env.PI_CLIPROXYAPI_DEBUG))console.log("[dm-cliproxy]","[debug]",...n)}};var M=$(A(),".dm","agent","dm-cliproxy"),H=$(M,"config.json"),C=[$(A(),".pi","agent","pi-cliproxyapi","config.json"),$(A(),".config","pi-cliproxyapi","config.json")];var I=z(M,"discovery-cache.json");var Z="dm-cliproxy/0.3.5";var R=15000,u=null;function l(){u=null}async function y(n,Q,j={}){if(!j.force&&u&&Date.now()-u.fetchedAt<n.usageCacheTtlMs)return u.doc;if(!Q)throw Error("usage key not configured; set proxy.usageKey in config and rerun");let X=new URL("/api/usage",new URL(n.proxy.endpoint).origin).toString(),Y=new AbortController,w=setTimeout(()=>Y.abort(Error("timeout")),R),J;try{J=await fetch(X,{headers:{"X-Plugin-Key":Q,Accept:"application/json","User-Agent":Z},signal:Y.signal})}finally{clearTimeout(w)}if(!J.ok)throw Error(`/api/usage returned ${J.status}`);let t=await J.json();if(!t||t.schemaVersion!==1||!Array.isArray(t.accounts))throw Error("/api/usage returned unexpected payload shape");return u={fetchedAt:Date.now(),doc:t},s.debug("usage fetched, accounts:",t.accounts.length),t}export{y as fetchUsage,l as clearUsageCache};
@@ -0,0 +1 @@
1
+ var f=!1;function h(b){f=b}var j={info(...b){if(!f)console.log("[dm-cliproxy]",...b)},warn(...b){if(!f)console.warn("[dm-cliproxy]",...b)},error(...b){if(!f)console.error("[dm-cliproxy]",...b)},debug(...b){if(!f&&(process.env.DM_CLIPROXY_DEBUG||process.env.PI_CLIPROXYAPI_DEBUG))console.log("[dm-cliproxy]","[debug]",...b)}};export{h as setLogQuiet,j as log};
@@ -0,0 +1 @@
1
+ var O=["⡀","⠂","⣀","⣄","⣤","⣶","⣷","⣾"];function Y(j){if(j==="anthropic")return"claude";if(j==="openai")return"codex";return null}function Z(j){return!j.disabled&&!j.unavailable&&j.supported&&Array.isArray(j.groups)&&j.groups.length>0}function _(j){let k=`${j.id} ${j.label??""}`.toLowerCase();return k.includes("5h")||k.includes("five-hour")||k.includes("five hour")}function $(j){let k=`${j.id} ${j.label??""}`.toLowerCase();return k.includes("7d")||k.includes("seven-day")||k.includes("seven day")}function Q(j,k){let q=-1;for(let H of j){if(!Z(H))continue;let C=1/0;for(let z of H.groups??[])if(k(z)){if(z.remainingFraction<C)C=z.remainingFraction}if(C!==1/0&&C>q)q=C}if(q<0)return null;return{fraction:N(q)}}function N(j){return Math.max(0,Math.min(1,j))}function S(j){let k=Math.min(O.length-1,Math.floor(j*O.length));return O[k]}function J(j){if(j>=0.7)return"success";if(j>=0.3)return"warning";return"error"}function V(j){return Math.round(j*100)}function T(j,k,q){let H=Y(k);if(!H)return null;let C=j.accounts.filter((X)=>X.provider===H);if(C.length===0)return null;let z=Q(C,_),D=Q(C,$);if(!z&&!D)return null;let M=[q.fg("dim","\uDB81\uDE27")];if(z)M.push(`${q.fg("dim","5h")} ${q.fg(J(z.fraction),S(z.fraction))} ${q.fg(J(z.fraction),String(V(z.fraction)))}`);if(D)M.push(`${q.fg("dim","7d")} ${q.fg(J(D.fraction),S(D.fraction))} ${q.fg(J(D.fraction),String(V(D.fraction)))}`);return M.join(" ")}export{T as renderQuotaSegment,Y as providerToUsageKey};
@@ -0,0 +1 @@
1
+ import{visibleWidth as X}from"@duckmind/dm-tui";import{visibleWidth as Y}from"@duckmind/dm-tui";function Z(j,q){let z=Y(j);if(z===q)return j;if(z<q)return j+" ".repeat(q-z);return N(j,q)}function N(j,q){if(q<=0)return"\x1B[0m";let z="",J=0,F=0;while(F<j.length){let O=j[F];if(O==="\x1B"&&j[F+1]==="["){let K=j.indexOf("m",F+2);if(K>=0){z+=j.slice(F,K+1),F=K+1;continue}}let M=Y(O);if(J+M>q)break;z+=O,J+=M,F++}return`${z}\x1B[0m`}var U="│",A="╭",I="╮",L="╰",C="╯",P="─";function W(j,q){let z=Math.max(4,q.width);return[S(j,q.title,q.titleColor??"accent",z),...q.lines.map((J)=>T(j,J,z)),V(j,q.footer,z)]}function S(j,q,z,J){let F=q??"",O=X(F),M=Math.max(0,J-3-O),K=F?j.bold(j.fg(z,F)):"",Q=`${A}${P}${K}${P.repeat(M)}${I}`;return j.fg("borderAccent",Q)}function T(j,q,z){let J=Math.max(0,z-2),F=j.fg("borderAccent",U);return`${F}${Z(q,J)}${F}`}function V(j,q,z){let J=`${L}${P}`,F=`${C}`,O=3;if(!q||!q.hint&&!q.badge){let G=Math.max(0,z-3);return j.fg("borderAccent",`${J}${P.repeat(G)}${F}`)}let M=q.hint??"",K=q.badge??"",Q=X(M),_=X(K),$=Math.max(0,z-3-Q-_),x=j.fg("dim",M),D=K?j.fg("muted",K):"",E=P.repeat($);return`${j.fg("borderAccent",J)}${x}${j.fg("borderAccent",E)}${D}${j.fg("borderAccent",F)}`}function R(j){return Math.max(0,j-2)}export{R as frameInner,W as frame};