@ckyueix/glm-usage 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,6 +8,13 @@ Plan account bound to the session's current provider; clicking expands the
8
8
  5-hour / weekly windows, remaining / total quota, reset times and the data
9
9
  timestamp in your local timezone.
10
10
 
11
+ ## 0.1.1
12
+
13
+ Preserves the Host method parameter names required by DSH's Remote Gateway.
14
+ This fixes the packaged 0.1.0 build's `gateway/arguments-invalid` error. The
15
+ packed Host and Client are regression-tested together through the real Gateway
16
+ with synthetic quota responses; no account credentials are included.
17
+
11
18
  ## License
12
19
 
13
20
  Free to use, including commercial use. Redistribution, resale, and publishing
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{TypertRemoteService as v}from"@deepseek-ai/dsh-typert-protocol";import h from"@deepseek-ai/schemastery";var w="https://open.bigmodel.cn/api/monitor/usage/quota/limit",d=Object.freeze({BAD_JSON:"bad_json",API_REJECTED:"api_rejected",NO_DATA:"no_data",NO_WINDOWS:"no_windows"}),E=Object.freeze({hours:3,week:6});function _(r){return typeof r=="number"&&Number.isFinite(r)?r:typeof r=="string"&&r.trim()!==""&&Number.isFinite(Number(r))?Number(r):null}function T(r){let e=_(r);return e===null||e<0||e>100?null:Math.round(e)}function D(r){if(typeof r!="object"||r===null||r.type!=="TOKENS_LIMIT"&&r.type!=="CREDIT_LIMIT")return null;let e=T(r.percentage);if(e===null)return null;let n=_(r.usage),o=_(r.remaining),t=_(r.nextResetTime),l=t!==null&&t>0?Math.round(t):null,s=e>0||l!==null;return Object.freeze({type:r.type,usedPercent:e,...n!==null?{total:n}:{},...o!==null?{remaining:o}:{},...l!==null?{resetMs:l}:{},active:s})}function O(r){let e=r.find(o=>o.type==="TOKENS_LIMIT");return e!==void 0?e:r.find(o=>o.type==="CREDIT_LIMIT")??null}function A(r){let e;try{let i=typeof r=="string"?r:new TextDecoder().decode(r);e=JSON.parse(i)}catch{return{ok:!1,error:d.BAD_JSON}}if(typeof e!="object"||e===null)return{ok:!1,error:d.BAD_JSON};if(e.success!==!0)return{ok:!1,error:d.API_REJECTED};let n=e.data;if(typeof n!="object"||n===null||Array.isArray(n))return{ok:!1,error:d.NO_DATA};let t=(Array.isArray(n.limits)?n.limits:[]).map(i=>[i,D(i)]).filter(([,i])=>i!==null),l=[],s=[];for(let[i,g]of t){let p=_(i.unit),b=_(i.number);p===E.hours&&b===5?l.push(g):p===E.week&&s.push(g)}let a=O(l),c=O(s);return a===null&&c===null?{ok:!1,error:d.NO_WINDOWS}:{ok:!0,level:typeof n.level=="string"&&n.level.length>0?n.level:null,windows:{fiveHour:a,weekly:c}}}function N(r,e,n,{stale:o=!1}={}){let t={status:"ok",provider:r,fetchedAt:n,stale:o,windows:{fiveHour:e.windows.fiveHour,weekly:e.windows.weekly}};return e.level!==null&&(t.level=e.level),t}var M="@deepseek-ai/dsh-typert-protocol/remote-methods",u=Object.freeze({OK:"ok",NOT_GLM:"not_glm",NO_CREDENTIAL:"no_credential",INVALID_PROVIDER:"invalid_provider",CONFIG_MISMATCH:"config_mismatch",CONFIG_UNVERIFIED:"config_unverified",FETCH_FAILED:"fetch_failed",BAD_RESPONSE:"bad_response"}),C=new Set(["open.bigmodel.cn"]),I="zai-coding-cn",R="https://open.bigmodel.cn/api/coding/paas/v4";function k(r){if(r===void 0||r==="")return"unknown";let e;try{e=new URL(r)}catch{return"no"}return e.protocol!=="https:"?"no":C.has(e.hostname)?"yes":"no"}var y=r=>r!==null&&typeof r=="object"&&typeof r.get=="function"?r.get():r,L=new Set(["zai","openai-completions"]),m=class extends v{static inject=[];static Config=h.object({providers:h.dict(h.string().pattern(/^[A-Z_][A-Z0-9_]*$/u)).default({}).volatile(),autoDiscover:h.boolean().default(!0).volatile(),ttlMs:h.natural().min(6e4).max(864e5).default(6e4).description("\u914D\u989D\u5237\u65B0\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09\uFF1A\u9ED8\u8BA4 60000\uFF1B\u6700\u5C0F 1 \u5206\u949F\uFF0C\u6700\u5927 24 \u5C0F\u65F6\u3002\u540C\u6B65\u63A7\u5236 Host \u7F13\u5B58\u548C\u53EF\u89C1\u9875\u9762\u5237\u65B0\u3002").volatile(),minIntervalMs:h.natural().min(1e3).default(6e4).volatile(),timeoutMs:h.natural().min(1e3).max(12e4).default(1e4).volatile()});cache=new Map;inFlight=new Map;lastAttempt=new Map;fetchImpl=globalThis.fetch;constructor(e,n){super(e,"glmQuota"),this.config=n,e.effect(()=>async()=>{for(let o of this.inFlight.values())o.abort(new Error("glm-quota: disposed"));this.inFlight.clear(),this.cache.clear()})}async get(e,n){return{...await this._get(e,n),ttlMs:this.config.ttlMs.get()}}async _get(e,n){if(typeof e!="string"||e.length===0||e.length>200)return{status:u.INVALID_PROVIDER,provider:typeof e=="string"?e:"",reason:"invalid_provider"};let o=n!==null&&typeof n=="object"&&n.force===!0,t=this.cache.get(e),l=Date.now();if(!o&&t!==void 0&&l-t.at<this.config.ttlMs.get())return{...t.payload,stale:!1};let s=this.inFlight.get(e);if(s!==void 0)return s.promise.then(i=>({...i}));let a=this.lastAttempt.get(e);if(!o&&a!==void 0&&l-a<this.config.minIntervalMs.get())return t!==void 0?{...t.payload,stale:!0}:{status:u.FETCH_FAILED,provider:e,reason:"cooldown"};let c=new AbortController,f={controller:c,promise:null};return this.inFlight.set(e,f),this.lastAttempt.set(e,l),f.promise=this._query(e,c.signal,t).then(i=>(i.status===u.OK&&this.cache.set(e,{at:i.fetchedAt,payload:i}),i)).finally(()=>{this.inFlight.delete(e);try{this.ctx.emit("glm-quota/changed",{provider:e})}catch{}}),f.promise}async _query(e,n,o){let t=this._providerGate(e);if(!t.allowed)return{status:t.status,provider:e};let l=await this._resolveCredential(t.ref);if(l===null)return{status:u.NO_CREDENTIAL,provider:e,reason:t.ref};try{let s=AbortSignal.timeout(this.config.timeoutMs.get()),a=n.aborted?n:AbortSignal.any([n,s]),f=await(await this.fetchImpl(w,{method:"GET",headers:{Authorization:l,Accept:"application/json","Accept-Language":"zh-CN,zh"},signal:a})).text(),i=A(f);return i.ok?N(e,i,Date.now()):this._withStale({status:i.error===d.API_REJECTED?u.BAD_RESPONSE:u.FETCH_FAILED,provider:e,reason:i.error},o)}catch(s){let a=n.aborted?"cancelled":s instanceof Error&&s.name==="TimeoutError"?"timeout":"network";return this._withStale({status:u.FETCH_FAILED,provider:e,reason:a},o)}}_withStale(e,n){return n!==void 0?{...n.payload,stale:!0,supersedes:e}:e}_providerGate(e){let n=this.config.providers.get(),o=Object.prototype.hasOwnProperty.call(n,e)?n[e]:void 0,t=null;try{t=this._piAiProfile(e)}catch{t=null}return o!==void 0?t===null?{allowed:!1,status:u.CONFIG_UNVERIFIED}:(typeof t.apiKeyEnv=="string"&&t.apiKeyEnv.length>0?t.apiKeyEnv:void 0)!==o?{allowed:!1,status:u.CONFIG_MISMATCH}:!t.kindOk||t.urlEvidence==="no"?{allowed:!1,status:u.NOT_GLM}:{allowed:!0,ref:o}:this.config.autoDiscover.get()?t===null?{allowed:!1,status:u.NOT_GLM}:typeof t.apiKeyEnv!="string"||t.apiKeyEnv.length===0?{allowed:!1,status:u.NOT_GLM}:!t.kindOk||t.urlEvidence!=="yes"?{allowed:!1,status:u.NOT_GLM}:{allowed:!0,ref:t.apiKeyEnv}:{allowed:!1,status:u.NOT_GLM}}_piAiProfile(e){let n=this.ctx.get("llm"),o=this.ctx.get("loader");if(n===void 0||o===void 0||!n.listProviders().some(p=>p.id===e))return null;let t=n.listConfigurableProviders().find(p=>p.provider===e);if(t===void 0)return null;let l=[...o.entries()].find(p=>p.options.id===t.settingsNs);if(l?.fiber?.state!==2)return null;let s=l.fiber.config?.providers?.get?.();if(s===null||typeof s!="object"||Array.isArray(s)||!Object.prototype.hasOwnProperty.call(s,e))return null;let a=s[e];if(a===null||typeof a!="object"||Array.isArray(a))return null;let c=y(a.apiKeyEnv),f=y(a.api),i=y(a.baseURL),g=e===I&&i===void 0&&t.declared===!1&&t.error===void 0&&t.defaultBaseURL===R;return{apiKeyEnv:typeof c=="string"&&c.length>0?c:void 0,kindOk:f===void 0||L.has(f),urlEvidence:g?"yes":typeof i=="string"?k(i):"unknown"}}async _resolveCredential(e){let n=this.ctx.get("credentials");if(n!==void 0){let t=await n.resolve(e);return t!==void 0&&typeof t.value=="string"&&t.value.length>0?t.value:null}let o=process.env[e];return typeof o=="string"&&o.length>0?o:null}};Object.defineProperty(m.prototype,M,{configurable:!0,value:Object.freeze({version:1,methods:Object.freeze([Object.freeze({method:"get",invocation:Object.freeze({kind:"direct"})})])})});export{u as Status,m as default};
1
+ import{TypertRemoteService}from"@deepseek-ai/dsh-typert-protocol";import z from"@deepseek-ai/schemastery";var QUOTA_ENDPOINT="https://open.bigmodel.cn/api/monitor/usage/quota/limit",QuotaError=Object.freeze({BAD_JSON:"bad_json",API_REJECTED:"api_rejected",NO_DATA:"no_data",NO_WINDOWS:"no_windows"}),WINDOW_UNITS=Object.freeze({hours:3,week:6});function amountOf(value){return typeof value=="number"&&Number.isFinite(value)?value:typeof value=="string"&&value.trim()!==""&&Number.isFinite(Number(value))?Number(value):null}function usedPercentOf(value){let n=amountOf(value);return n===null||n<0||n>100?null:Math.round(n)}function projectLimit(item){if(typeof item!="object"||item===null||item.type!=="TOKENS_LIMIT"&&item.type!=="CREDIT_LIMIT")return null;let usedPercent=usedPercentOf(item.percentage);if(usedPercent===null)return null;let total=amountOf(item.usage),remaining=amountOf(item.remaining),resetRaw=amountOf(item.nextResetTime),resetMs=resetRaw!==null&&resetRaw>0?Math.round(resetRaw):null,active=usedPercent>0||resetMs!==null;return Object.freeze({type:item.type,usedPercent,...total!==null?{total}:{},...remaining!==null?{remaining}:{},...resetMs!==null?{resetMs}:{},active})}function pickWindow(items){let token=items.find(w=>w.type==="TOKENS_LIMIT");return token!==void 0?token:items.find(w=>w.type==="CREDIT_LIMIT")??null}function parseQuotaResponse(body){let parsed;try{let text=typeof body=="string"?body:new TextDecoder().decode(body);parsed=JSON.parse(text)}catch{return{ok:!1,error:QuotaError.BAD_JSON}}if(typeof parsed!="object"||parsed===null)return{ok:!1,error:QuotaError.BAD_JSON};if(parsed.success!==!0)return{ok:!1,error:QuotaError.API_REJECTED};let data=parsed.data;if(typeof data!="object"||data===null||Array.isArray(data))return{ok:!1,error:QuotaError.NO_DATA};let pairs=(Array.isArray(data.limits)?data.limits:[]).map(item=>[item,projectLimit(item)]).filter(([,window])=>window!==null),fiveHourRaw=[],weeklyRaw=[];for(let[item,window]of pairs){let unit=amountOf(item.unit),number_=amountOf(item.number);unit===WINDOW_UNITS.hours&&number_===5?fiveHourRaw.push(window):unit===WINDOW_UNITS.week&&weeklyRaw.push(window)}let fiveHour=pickWindow(fiveHourRaw),weekly=pickWindow(weeklyRaw);return fiveHour===null&&weekly===null?{ok:!1,error:QuotaError.NO_WINDOWS}:{ok:!0,level:typeof data.level=="string"&&data.level.length>0?data.level:null,windows:{fiveHour,weekly}}}function buildPayload(providerId,parsed,fetchedAt,{stale=!1}={}){let payload={status:"ok",provider:providerId,fetchedAt,stale,windows:{fiveHour:parsed.windows.fiveHour,weekly:parsed.windows.weekly}};return parsed.level!==null&&(payload.level=parsed.level),payload}var REMOTE_METHOD_DESCRIPTOR="@deepseek-ai/dsh-typert-protocol/remote-methods",Status=Object.freeze({OK:"ok",NOT_GLM:"not_glm",NO_CREDENTIAL:"no_credential",INVALID_PROVIDER:"invalid_provider",CONFIG_MISMATCH:"config_mismatch",CONFIG_UNVERIFIED:"config_unverified",FETCH_FAILED:"fetch_failed",BAD_RESPONSE:"bad_response"}),GLM_OFFICIAL_HOSTS=new Set(["open.bigmodel.cn"]),CHINA_CODING_PROVIDER="zai-coding-cn",CHINA_CODING_BASE_URL="https://open.bigmodel.cn/api/coding/paas/v4";function glmUrlEvidence(baseURL){if(baseURL===void 0||baseURL==="")return"unknown";let url;try{url=new URL(baseURL)}catch{return"no"}return url.protocol!=="https:"?"no":GLM_OFFICIAL_HOSTS.has(url.hostname)?"yes":"no"}var plain=value=>value!==null&&typeof value=="object"&&typeof value.get=="function"?value.get():value,GLM_API_KINDS=new Set(["zai","openai-completions"]),GlmQuotaService=class extends TypertRemoteService{static inject=[];static Config=z.object({providers:z.dict(z.string().pattern(/^[A-Z_][A-Z0-9_]*$/u)).default({}).volatile(),autoDiscover:z.boolean().default(!0).volatile(),ttlMs:z.natural().min(6e4).max(864e5).default(6e4).description("\u914D\u989D\u5237\u65B0\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09\uFF1A\u9ED8\u8BA4 60000\uFF1B\u6700\u5C0F 1 \u5206\u949F\uFF0C\u6700\u5927 24 \u5C0F\u65F6\u3002\u540C\u6B65\u63A7\u5236 Host \u7F13\u5B58\u548C\u53EF\u89C1\u9875\u9762\u5237\u65B0\u3002").volatile(),minIntervalMs:z.natural().min(1e3).default(6e4).volatile(),timeoutMs:z.natural().min(1e3).max(12e4).default(1e4).volatile()});cache=new Map;inFlight=new Map;lastAttempt=new Map;fetchImpl=globalThis.fetch;constructor(ctx,config){super(ctx,"glmQuota"),this.config=config,ctx.effect(()=>async()=>{for(let controller of this.inFlight.values())controller.abort(new Error("glm-quota: disposed"));this.inFlight.clear(),this.cache.clear()})}async get(providerId,options){return{...await this._get(providerId,options),ttlMs:this.config.ttlMs.get()}}async _get(providerId,options){if(typeof providerId!="string"||providerId.length===0||providerId.length>200)return{status:Status.INVALID_PROVIDER,provider:typeof providerId=="string"?providerId:"",reason:"invalid_provider"};let force=options!==null&&typeof options=="object"&&options.force===!0,cached=this.cache.get(providerId),now=Date.now();if(!force&&cached!==void 0&&now-cached.at<this.config.ttlMs.get())return{...cached.payload,stale:!1};let running=this.inFlight.get(providerId);if(running!==void 0)return running.promise.then(payload=>({...payload}));let attempt=this.lastAttempt.get(providerId);if(!force&&attempt!==void 0&&now-attempt<this.config.minIntervalMs.get())return cached!==void 0?{...cached.payload,stale:!0}:{status:Status.FETCH_FAILED,provider:providerId,reason:"cooldown"};let controller=new AbortController,entry={controller,promise:null};return this.inFlight.set(providerId,entry),this.lastAttempt.set(providerId,now),entry.promise=this._query(providerId,controller.signal,cached).then(payload=>(payload.status===Status.OK&&this.cache.set(providerId,{at:payload.fetchedAt,payload}),payload)).finally(()=>{this.inFlight.delete(providerId);try{this.ctx.emit("glm-quota/changed",{provider:providerId})}catch{}}),entry.promise}async _query(providerId,signal,cached){let gate=this._providerGate(providerId);if(!gate.allowed)return{status:gate.status,provider:providerId};let token=await this._resolveCredential(gate.ref);if(token===null)return{status:Status.NO_CREDENTIAL,provider:providerId,reason:gate.ref};try{let timeout=AbortSignal.timeout(this.config.timeoutMs.get()),combined=signal.aborted?signal:AbortSignal.any([signal,timeout]),body=await(await this.fetchImpl(QUOTA_ENDPOINT,{method:"GET",headers:{Authorization:token,Accept:"application/json","Accept-Language":"zh-CN,zh"},signal:combined})).text(),parsed=parseQuotaResponse(body);return parsed.ok?buildPayload(providerId,parsed,Date.now()):this._withStale({status:parsed.error===QuotaError.API_REJECTED?Status.BAD_RESPONSE:Status.FETCH_FAILED,provider:providerId,reason:parsed.error},cached)}catch(error){let reason=signal.aborted?"cancelled":error instanceof Error&&error.name==="TimeoutError"?"timeout":"network";return this._withStale({status:Status.FETCH_FAILED,provider:providerId,reason},cached)}}_withStale(payload,cached){return cached!==void 0?{...cached.payload,stale:!0,supersedes:payload}:payload}_providerGate(providerId){let configured=this.config.providers.get(),explicit=Object.prototype.hasOwnProperty.call(configured,providerId)?configured[providerId]:void 0,profile=null;try{profile=this._piAiProfile(providerId)}catch{profile=null}return explicit!==void 0?profile===null?{allowed:!1,status:Status.CONFIG_UNVERIFIED}:(typeof profile.apiKeyEnv=="string"&&profile.apiKeyEnv.length>0?profile.apiKeyEnv:void 0)!==explicit?{allowed:!1,status:Status.CONFIG_MISMATCH}:!profile.kindOk||profile.urlEvidence==="no"?{allowed:!1,status:Status.NOT_GLM}:{allowed:!0,ref:explicit}:this.config.autoDiscover.get()?profile===null?{allowed:!1,status:Status.NOT_GLM}:typeof profile.apiKeyEnv!="string"||profile.apiKeyEnv.length===0?{allowed:!1,status:Status.NOT_GLM}:!profile.kindOk||profile.urlEvidence!=="yes"?{allowed:!1,status:Status.NOT_GLM}:{allowed:!0,ref:profile.apiKeyEnv}:{allowed:!1,status:Status.NOT_GLM}}_piAiProfile(providerId){let llm=this.ctx.get("llm"),loader=this.ctx.get("loader");if(llm===void 0||loader===void 0||!llm.listProviders().some(row=>row.id===providerId))return null;let directory=llm.listConfigurableProviders().find(row=>row.provider===providerId);if(directory===void 0)return null;let entry=[...loader.entries()].find(row=>row.options.id===directory.settingsNs);if(entry?.fiber?.state!==2)return null;let profiles=entry.fiber.config?.providers?.get?.();if(profiles===null||typeof profiles!="object"||Array.isArray(profiles)||!Object.prototype.hasOwnProperty.call(profiles,providerId))return null;let profile=profiles[providerId];if(profile===null||typeof profile!="object"||Array.isArray(profile))return null;let apiKeyEnv=plain(profile.apiKeyEnv),api=plain(profile.api),baseURL=plain(profile.baseURL),nativeChinaDefault=providerId===CHINA_CODING_PROVIDER&&baseURL===void 0&&directory.declared===!1&&directory.error===void 0&&directory.defaultBaseURL===CHINA_CODING_BASE_URL;return{apiKeyEnv:typeof apiKeyEnv=="string"&&apiKeyEnv.length>0?apiKeyEnv:void 0,kindOk:api===void 0||GLM_API_KINDS.has(api),urlEvidence:nativeChinaDefault?"yes":typeof baseURL=="string"?glmUrlEvidence(baseURL):"unknown"}}async _resolveCredential(ref){let credentials=this.ctx.get("credentials");if(credentials!==void 0){let hit=await credentials.resolve(ref);return hit!==void 0&&typeof hit.value=="string"&&hit.value.length>0?hit.value:null}let ambient=process.env[ref];return typeof ambient=="string"&&ambient.length>0?ambient:null}};Object.defineProperty(GlmQuotaService.prototype,REMOTE_METHOD_DESCRIPTOR,{configurable:!0,value:Object.freeze({version:1,methods:Object.freeze([Object.freeze({method:"get",invocation:Object.freeze({kind:"direct"})})])})});export{Status,GlmQuotaService as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckyueix/glm-usage",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "GLM Coding Plan usage pill for the DeepSeek Harness composer dock (dual-half: host quota reader + web client entry)",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",