@ckyueix/glm-usage 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,128 @@
1
+ # CKYUEIX Software License
2
+
3
+ **Free Use — Restricted Redistribution**
4
+
5
+ Version 1.0
6
+
7
+ Copyright © 2026 ckyueix. All rights reserved.
8
+
9
+ ### 1. Scope and Acceptance
10
+
11
+ This license applies to software packages or distributions expressly provided with this license by their copyright holder (the "Licensor"), collectively referred to as the "Software".
12
+
13
+ A software package is covered only when the Licensor expressly includes this license with that package. Other products from the same developer are not automatically covered.
14
+
15
+ By exercising the permissions granted under this license, you agree to its terms. If you do not agree, you may not exercise those permissions.
16
+
17
+ Nothing in this license restricts rights that applicable law grants independently of this license.
18
+
19
+ ### 2. License Grant
20
+
21
+ Subject to compliance with this license, the Licensor grants you a worldwide, non-exclusive, royalty-free, perpetual license, subject to termination under Section 8, to:
22
+
23
+ a. Download, install, run, and use the Software for personal, educational, research, and commercial purposes.
24
+
25
+ b. Deploy the Software on multiple devices or systems within your organization.
26
+
27
+ c. Make copies reasonably necessary for internal deployment, backup, recovery, testing, and maintenance.
28
+
29
+ d. Privately modify the Software for your own or your organization's internal use.
30
+
31
+ e. Allow employees and contractors acting on your behalf to use or maintain the Software for authorized purposes.
32
+
33
+ f. Use the Software to operate commercial services, including hosted services, without transferring copies of the Software to customers except as permitted under Section 3.
34
+
35
+ No license fee is required for these activities.
36
+
37
+ ### 3. Professional Services and Customer Deployment
38
+
39
+ You may charge for consulting, installation, configuration, maintenance, hosting, and other professional services involving the Software.
40
+
41
+ A service provider may install or configure the Software on a customer's infrastructure when:
42
+
43
+ a. The customer independently receives the right to use the Software under this license.
44
+
45
+ b. The Software is obtained through the official distribution channel or a permitted package mirror or cache.
46
+
47
+ c. The service provider acts on the customer's behalf and does not independently sell, sublicense, or market copies of the Software.
48
+
49
+ Transfers strictly necessary for an authorized customer installation are permitted.
50
+
51
+ Fees for professional services do not constitute prohibited resale merely because the services involve the Software.
52
+
53
+ Providing customers with access to services powered by the Software, without transferring copies, is permitted.
54
+
55
+ ### 4. Redistribution Restrictions
56
+
57
+ Unless expressly permitted by this license or separately authorized in writing by the Licensor, you may not:
58
+
59
+ a. Redistribute, republish, upload, host, sell, rent, sublicense, or otherwise make copies of the Software available to third parties, whether free of charge or for payment.
60
+
61
+ b. Publicly distribute or publish modified versions of the Software.
62
+
63
+ c. Bundle or incorporate copies of the Software into products, installers, or software distributions supplied to third parties.
64
+
65
+ d. Misrepresent the Software's authorship, ownership, or official distribution status.
66
+
67
+ **Permitted Distribution Infrastructure**
68
+
69
+ The restrictions above do not prohibit:
70
+
71
+ - Distribution through the official package registry or other channels authorized by the Licensor.
72
+ - Automated mirroring, caching, and proxying of unmodified official package artifacts through ordinary package-management infrastructure for acquisition, installation, updates, or recovery.
73
+ - Internal package repositories, organizational caching, and authorized internal deployment.
74
+ - Technical transfers necessary for customer installations permitted under Section 3.
75
+
76
+ Applicable copyright and license notices must be preserved.
77
+
78
+ Charging for package-management infrastructure or professional services is permitted. These exceptions do not authorize independently marketing, reselling, or publishing modified copies of the Software as a separate product.
79
+
80
+ ### 5. Ownership and Third-Party Rights
81
+
82
+ The Licensor and other applicable rights holders retain ownership of their respective intellectual property.
83
+
84
+ This license does not grant ownership of the Software, access to private source code repositories, or rights to the Licensor's trademarks, logos, or endorsements.
85
+
86
+ You must preserve applicable copyright and license notices.
87
+
88
+ Third-party components remain subject to their respective licenses.
89
+
90
+ ### 6. Disclaimer of Warranties
91
+
92
+ TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE SOFTWARE IS PROVIDED "AS IS" AND "AS AVAILABLE", WITHOUT WARRANTIES OF ANY KIND, EXPRESS, IMPLIED, OR STATUTORY.
93
+
94
+ THE LICENSOR DISCLAIMS ALL WARRANTIES, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND UNINTERRUPTED OR ERROR-FREE OPERATION.
95
+
96
+ THE LICENSOR HAS NO OBLIGATION TO PROVIDE SUPPORT, MAINTENANCE, OR UPDATES UNLESS SEPARATELY AGREED IN WRITING.
97
+
98
+ ### 7. Limitation of Liability
99
+
100
+ TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSOR SHALL NOT BE LIABLE FOR ANY DAMAGES ARISING OUT OF OR RELATING TO THE SOFTWARE, ITS USE, OR INABILITY TO USE, WHETHER DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, EXEMPLARY, OR PUNITIVE, UNDER ANY LEGAL THEORY, INCLUDING CONTRACT, TORT, OR NEGLIGENCE.
101
+
102
+ THIS INCLUDES, WITHOUT LIMITATION, LOSS OF DATA, PROFITS, BUSINESS, OR SERVICE AVAILABILITY.
103
+
104
+ NOTHING IN THIS LICENSE EXCLUDES OR LIMITS LIABILITY THAT CANNOT LAWFULLY BE EXCLUDED OR LIMITED.
105
+
106
+ ### 8. Termination
107
+
108
+ If you materially violate this license, the Licensor may terminate your rights if you fail to remedy the violation within 30 calendar days after receiving written notice.
109
+
110
+ Conduct expressly prohibited by this license is not authorized during any cure period.
111
+
112
+ Upon effective termination, you must cease unauthorized use and distribution and remove copies under your control, except those required to be retained by applicable law. Legally retained copies may not be used unless independently authorized.
113
+
114
+ Termination of your rights does not automatically terminate licenses independently obtained by other users.
115
+
116
+ Ownership, warranty disclaimers, liability limitations, and provisions intended by their nature to survive termination remain effective.
117
+
118
+ ### 9. Additional Permissions and General Terms
119
+
120
+ Activities not authorized by this license require the Licensor's prior affirmative written permission.
121
+
122
+ Requests for additional permissions may be directed through the licensing contact identified in the official package metadata or an official release page designated by the Licensor.
123
+
124
+ Silence or failure to respond does not constitute authorization.
125
+
126
+ If any provision is held invalid or unenforceable, the remaining provisions continue in effect to the maximum extent permitted by applicable law.
127
+
128
+ All rights not expressly granted are reserved by the Licensor.
package/README.md CHANGED
@@ -1,3 +1,72 @@
1
- # Temporary Holding Version
1
+ # @ckyueix/glm-usage — GLM Usage (GLM 用量)
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ A DeepSeek Harness (DSH) plugin that adds a compact **GLM Coding Plan usage pill**
4
+ to the native conversation composer dock (`conversation.composer.dock`, new row
5
+ id `ckyueix-glm-quota`, order 2 — the shipped `activity` / `usage` rows are never
6
+ replaced). Collapsed it shows the weekly-limit percentage of the GLM Coding
7
+ Plan account bound to the session's current provider; clicking expands the
8
+ 5-hour / weekly windows, remaining / total quota, reset times and the data
9
+ timestamp in your local timezone.
10
+
11
+ ## License
12
+
13
+ Free to use, including commercial use. Redistribution, resale, and publishing
14
+ modified versions are restricted; see [LICENSE](./LICENSE) for the exact terms.
15
+
16
+ For requests for additional permissions, including redistribution authorization,
17
+ contact **ckyueix@gmail.com**. This is the public licensing contact for this
18
+ package.
19
+
20
+ ## Requirements
21
+
22
+ - DeepSeek Harness **0.2.1-rc.2** (`engines.dsh` is enforced; other host
23
+ versions are untested).
24
+ - A configured GLM Coding Plan provider (Zhipu `open.bigmodel.cn` coding-plan
25
+ routes, e.g. the built-in `zai-coding-cn` China route or explicit
26
+ `openai-completions` profiles).
27
+
28
+ Non-GLM providers render nothing; no request is made for them. Credentials are
29
+ resolved only inside the DSH host process and never reach the browser client.
30
+
31
+ ## Install
32
+
33
+ Install through DSH's plugin management (Plugins → Add plugin, or a plugin
34
+ market index that lists this package). After installing, open or reload a
35
+ conversation: the pill appears beside the native activity / usage stats.
36
+
37
+ ## Refresh interval
38
+
39
+ Default **60 seconds**. Configure under Plugins →
40
+ `@ckyueix/glm-usage` → refresh interval (seconds), allowed range
41
+ 60–86400. The value controls the host cache and the client's refresh
42
+ scheduling.
43
+
44
+ ## Optional configuration (profile patch)
45
+
46
+ ```yaml
47
+ - id: glm-usage
48
+ name: '@ckyueix/glm-usage'
49
+ config:
50
+ providers: # explicit providerId -> credential-ref binding
51
+ my-glm-account: MY_GLM_API_KEY_ENV
52
+ autoDiscover: true # exact official HTTPS routes only
53
+ ttlMs: 60000 # 60000–86400000
54
+ minIntervalMs: 60000
55
+ timeoutMs: 10000
56
+ ```
57
+
58
+ ## Security boundary
59
+
60
+ - The quota endpoint is fixed (`https://open.bigmodel.cn/api/monitor/usage/quota/limit`,
61
+ GET); URLs supplied by callers are never fetched.
62
+ - The browser client only ever receives whitelisted fields (percentages,
63
+ totals, reset timestamps); raw upstream responses, messages, credentials and
64
+ stack traces never cross the remote boundary.
65
+ - Provider admission is fail-closed: only exact official HTTPS hostnames, the
66
+ catalog-verified built-in `zai-coding-cn` default route, or explicit
67
+ ref-matched bindings are queried.
68
+
69
+ ## Source
70
+
71
+ The source of this plugin is maintained in a private repository; this package
72
+ is the built release artifact.
@@ -0,0 +1,7 @@
1
+ # Loader patch for @ckyueix/glm-usage.
2
+ # Mounts the host half as the Cordis service entry `glm-usage`; the package's
3
+ # `dsh.client` declaration additionally serves `lib/client.js` to the Web UI,
4
+ # where it registers the `ckyueix-glm-quota` row of `conversation.composer.dock`.
5
+ - insert:
6
+ - id: glm-usage
7
+ name: '@ckyueix/glm-usage'
package/dist/client.js ADDED
@@ -0,0 +1,13 @@
1
+ window.__ModuleLoader__.load({id:"@ckyueix/glm-usage",factory:require=>{var module={exports:{}},exports=module.exports;let react=require("react"),zodModule=require("zod");const zod=zodModule.z??zodModule,createElement=react.createElement,useSyncExternalStore=react.useSyncExternalStore,useEffect=react.useEffect;let dialogRuntime;function createTypertRemoteInfo(spec,zod2){return new RemoteInfo(spec,zod2)}var RemoteInfo=class{spec;zod;index;constructor(spec,zod2){this.spec=spec,this.zod=zod2}get package(){return this.spec.package}get descriptors(){return this.resolve().descriptors}get methods(){return this.resolve().methods}resolve(){if(this.index!==void 0)return this.index;const zod2=this.zod,descriptors=[],methods=Object.create(null);for(const[endpoint,definition]of Object.entries(this.spec.methods)){const separator=endpoint.indexOf("/"),namespace=endpoint.slice(0,separator),method=endpoint.slice(separator+1),parameters=definition.parameters.map(parameter=>({...parameter,wire:parameter.wire??parameter.name})),descriptor={...definition,id:`${this.spec.package}#${endpoint}`,namespace,method,parameters,result:definition.result.description===void 0?definition.result:new ResultValue(definition.result)};if(definition.invocation.kind==="direct"){const inputs=[];methods[endpoint]=Object.assign(descriptor,{input(options){const strict=options?.strict===!0;return inputs[strict?1:0]??=new NamedInput(parameters,strict,zod2)},invoke(remote,input,signal){const named=input,values=parameters.map(parameter=>named[parameter.wire]);definition.cancellation!==void 0&&values.push(signal);const receiver=Reflect.get(remote,namespace);return Reflect.get(receiver,method).apply(receiver,values)}})}descriptors.push(descriptor)}return this.index={descriptors,methods}}};function optional(parameter){return parameter.source==="json"&&parameter.acceptsUndefined===!0}var NamedInput=class{parameters;strict;zod;schema;projection;constructor(parameters,strict,zod2){this.parameters=parameters,this.strict=strict,this.zod=zod2}codec(parameter){return this.strict?parameter.strictCodec:parameter.codec}create=()=>this.schema??=this.zod.strictObject(Object.fromEntries(this.parameters.map(parameter=>{const value=this.codec(parameter).create();return[parameter.wire,optional(parameter)?value.optional():value.nonoptional()]})));get jsonSchema(){return this.project().jsonSchema}get jsonSchemaError(){return this.project().jsonSchemaError}project(){if(this.projection!==void 0)return this.projection;const unavailable=this.parameters.find(parameter=>this.codec(parameter).jsonSchema===void 0);return unavailable!==void 0?this.projection={jsonSchemaError:this.codec(unavailable).jsonSchemaError??`No JSON Schema for parameter ${unavailable.wire}`}:this.projection={jsonSchema:{type:"object",properties:Object.fromEntries(this.parameters.map(parameter=>[parameter.wire,{...this.codec(parameter).jsonSchema,...parameter.description===void 0?{}:{description:parameter.description}}])),required:this.parameters.filter(parameter=>!optional(parameter)).map(parameter=>parameter.wire),additionalProperties:!1}}}},ResultValue=class{spec;projection;constructor(spec){this.spec=spec}get mode(){return this.spec.mode}get typeSymbol(){return this.spec.typeSymbol}get create(){return this.spec.create}get decode(){return this.spec.decode}get encode(){return this.spec.encode}get description(){return this.spec.description}get jsonSchemaError(){return this.spec.jsonSchemaError}get jsonSchema(){if(this.projection===void 0){const schema=this.spec.jsonSchema;this.projection={value:schema===void 0?void 0:{...schema,description:this.spec.description}}}return this.projection.value}};const TYPERT_REMOTE_SPEC=Object.freeze({package:"@ckyueix/glm-usage",methods:Object.freeze({"glmQuota/get":Object.freeze({service:"glmQuota",description:"Read the GLM Coding Plan quota whitelist snapshot for the session-selected provider.",invocation:Object.freeze({kind:"direct"}),parameters:Object.freeze([Object.freeze({name:"providerId",description:"session-selected provider id (never a model name).",source:"json",codec:Object.freeze({mode:"strict",typeSymbol:"@ckyueix/glm-usage/types#GlmProviderId",create:()=>zod.string().min(1).max(200),jsonSchema:Object.freeze({type:"string",minLength:1,maxLength:200})}),strictCodec:Object.freeze({mode:"strict",typeSymbol:"@ckyueix/glm-usage/types#GlmProviderId",create:()=>zod.string().min(1).max(200),jsonSchema:Object.freeze({type:"string",minLength:1,maxLength:200})})}),Object.freeze({name:"options",description:"optional read options; force bypasses cache/cooldown once.",source:"json",acceptsUndefined:!0,codec:Object.freeze({mode:"strict",typeSymbol:"@ckyueix/glm-usage/types#GlmReadOptions",create:()=>zod.strictObject({force:zod.boolean().optional()}).optional(),jsonSchema:Object.freeze({type:"object",properties:Object.freeze({force:Object.freeze({type:"boolean"})}),additionalProperties:!1})}),strictCodec:Object.freeze({mode:"strict",typeSymbol:"@ckyueix/glm-usage/types#GlmReadOptions",create:()=>zod.strictObject({force:zod.boolean().optional()}).optional(),jsonSchema:Object.freeze({type:"object",properties:Object.freeze({force:Object.freeze({type:"boolean"})}),additionalProperties:!1})})})]),result:Object.freeze({mode:"strict",typeSymbol:"@ckyueix/glm-usage/types#GlmQuotaPayload",create:()=>zod.looseObject({status:zod.string(),provider:zod.string()}),description:"whitelist payload; never carries credentials, upstream messages, or raw bodies.",jsonSchema:Object.freeze({type:"object",properties:Object.freeze({status:Object.freeze({type:"string"}),provider:Object.freeze({type:"string"})}),required:Object.freeze(["status","provider"])})})})})}),TYPERT_REMOTE=createTypertRemoteInfo(TYPERT_REMOTE_SPEC,zod),NS="glmQuota",DICT=Object.freeze({zh:Object.freeze({"pill.fiveHour":"5\u65F6","pill.weekly":"\u5468","pill.used":"\u5DF2\u7528","pill.inactive":"\u672A\u6FC0\u6D3B","pill.loading":"\u67E5\u8BE2\u4E2D\u2026","pill.error":"\u914D\u989D\u4E0D\u53EF\u7528","pill.staleAt":"\u6570\u636E\u65F6\u95F4","pill.stale":"\u65E7\u6570\u636E","pill.weeklyLimit":"\u5468\u9650","pill.details":"GLM \u7528\u91CF","pill.expand":"GLM \u7528\u91CF\u8BE6\u60C5","pill.account":"\u8D26\u53F7","pill.fiveHourUsed":"5 \u5C0F\u65F6\u5DF2\u7528","pill.weeklyUsed":"\u5468\u9650\u5DF2\u7528","pill.fiveHourBudget":"5 \u5C0F\u65F6\u5269\u4F59 / \u603B\u989D","pill.weeklyBudget":"\u5468\u9650\u5269\u4F59 / \u603B\u989D","pill.fiveHourReset":"5 \u5C0F\u65F6\u91CD\u7F6E","pill.weeklyReset":"\u5468\u9650\u91CD\u7F6E","config.interval":"\u5237\u65B0\u95F4\u9694\uFF08\u79D2\uFF09","config.hint":"\u9ED8\u8BA4 60 \u79D2\uFF0C\u6700\u77ED 60 \u79D2\uFF0C\u6700\u957F 86400 \u79D2\u3002\u540C\u6B65\u63A7\u5236 Host \u7F13\u5B58\u4E0E\u53EF\u89C1\u9875\u9762\u5237\u65B0\uFF1B\u9690\u85CF\u9875\u9762\u6682\u505C\u5237\u65B0\u3002\u7559\u7A7A\u53EF\u6062\u590D\u9ED8\u8BA4\u3002","config.invalid":"\u8BF7\u8F93\u5165 60\u201386400 \u4E4B\u95F4\u7684\u6574\u6570\u79D2\u6570\u3002","config.overridden":"\u5DF2\u81EA\u5B9A\u4E49","config.reset":"\u6062\u590D\u9ED8\u8BA4","config.save":"\u4FDD\u5B58","config.saving":"\u4FDD\u5B58\u4E2D\u2026","config.unavailable":"\u5F53\u524D Host \u65E0\u6CD5\u63D0\u4F9B\u6B64\u63D2\u4EF6\u914D\u7F6E\u3002","config.readOnly":"\u5F53\u524D\u914D\u7F6E\u53EA\u8BFB\u3002","config.saveFailed":"\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002"}),en:Object.freeze({"pill.fiveHour":"5h","pill.weekly":"wk","pill.used":"used","pill.inactive":"inactive","pill.loading":"loading\u2026","pill.error":"quota unavailable","pill.staleAt":"as of","pill.stale":"stale","pill.weeklyLimit":"Week","pill.details":"GLM usage","pill.expand":"GLM usage details","pill.account":"Account","pill.fiveHourUsed":"5-hour used","pill.weeklyUsed":"Weekly used","pill.fiveHourBudget":"5-hour left / total","pill.weeklyBudget":"Weekly left / total","pill.fiveHourReset":"5-hour reset","pill.weeklyReset":"Weekly reset","config.interval":"Refresh interval (seconds)","config.hint":"Default/minimum 60 seconds; maximum 86400. Controls Host caching and visible-page refresh together. Hidden pages pause refresh. Clear to restore the default.","config.invalid":"Enter a whole number of seconds from 60 to 86400.","config.overridden":"Customized","config.reset":"Restore default","config.save":"Save","config.saving":"Saving\u2026","config.unavailable":"Plugin configuration is unavailable on this Host.","config.readOnly":"Configuration is read-only.","config.saveFailed":"Save failed. Please try again."})});function formatClock(ms){const dt=new Date(ms),pad=n=>String(n).padStart(2,"0");return dt.getFullYear()+"-"+pad(dt.getMonth()+1)+"-"+pad(dt.getDate())+" "+pad(dt.getHours())+":"+pad(dt.getMinutes())}const SNAPSHOT_TTL_MS=6e4,REFRESH_RETRY_MS=6e4,pageVisible=()=>typeof document<"u"&&document.visibilityState==="visible",validTtl=value=>Number.isInteger(value)&&value>=6e4&&value<=864e5,snapshotExpired=(snapshot,ttlMs)=>typeof snapshot.fetchedAt!="number"||!Number.isFinite(snapshot.fetchedAt)||Date.now()-snapshot.fetchedAt>=ttlMs;function registerConfiguration(ctx,controller,t){const scope=ctx.configForms.get("glm-usage"),unbind=controller.bindConfig(scope);let form;try{let RefreshSettings2=function(){const snapshot=useSyncExternalStore(state.subscribe,state.getSnapshot),id=react.useId();return createElement(SettingsForm,{state:snapshot,labels:Object.fromEntries(["unavailable","readOnly","saveFailed","save","saving"].map(key=>[key,t("config."+key)])),onSave:actions.save,onDiscard:actions.discard},createElement(SettingsValueField,{id,label:t("config.interval"),hint:t("config.hint"),numeric:!0,...snapshot.interval,overriddenLabel:t("config.overridden"),resetLabel:t("config.reset"),invalidLabel:t("config.invalid"),disabled:!snapshot.writable||snapshot.saving,onEdit:text=>actions.edit("ttlMs",text),onReset:()=>actions.resetField("ttlMs")}))};var RefreshSettings=RefreshSettings2;const{SettingsFormModel,SettingsForm,SettingsValueField}=require("@deepseek-ai/dsh-client-ui-primitives");if(![SettingsFormModel,SettingsForm,SettingsValueField].every(value=>typeof value=="function"))throw new Error("native settings runtime unavailable");form=new SettingsFormModel(scope,[{field:"ttlMs",format:value=>String((value??SNAPSHOT_TTL_MS)/1e3),parse:text=>{if(text.trim()==="")return{kind:"clear"};const seconds=Number(text);return Number.isInteger(seconds)&&validTtl(seconds*1e3)?{kind:"set",value:seconds*1e3}:void 0}}]);const state=form.bind(()=>({...form.shell(),interval:form.field("ttlMs")})),actions=form.actions();ctx.slots.inject("plugins.bundle.config",()=>ctx.slots.register({name:"plugins.bundle.config",key:"@ckyueix/glm-usage",locale:NS},RefreshSettings2))}catch{form?.dispose(),form=void 0,console.error("ckyueix-glm-quota: native settings editor unavailable; quota display retained")}return()=>{form?.dispose(),unbind()}}class QuotaController{constructor(ctx){this.remote=ctx.remote,this.listeners=new Set,this.snapshots=new Map,this.pending=new Map,this.generations=new Map,this.retryAt=new Map,this.watchers=new Set,this.ttlMs=SNAPSHOT_TTL_MS,this.configReady=!1,this.disposed=!1}setTtl(value){this.disposed||!validTtl(value)||this.ttlMs===value||(this.ttlMs=value,this.#notify())}bindConfig(scope){const accept=()=>{const snapshot=scope.getSnapshot();snapshot.status!=="ready"||!validTtl(snapshot.value?.ttlMs)||(this.configReady=!0,this.setTtl(snapshot.value.ttlMs))},unsubscribe=scope.subscribe(accept);return accept(),unsubscribe}dispose(){this.disposed=!0;for(const cleanup of[...this.watchers])cleanup();this.listeners.clear(),this.snapshots.clear(),this.pending.clear(),this.retryAt.clear()}subscribe(listener){return this.listeners.add(listener),()=>this.listeners.delete(listener)}#notify(){for(const listener of[...this.listeners])listener()}snapshotOf(providerId){const existing=this.snapshots.get(providerId);if(existing!==void 0)return existing;const fresh={phase:"loading",provider:providerId};return this.snapshots.set(providerId,fresh),fresh}watch(providerId){if(this.disposed||providerId===null)return()=>{};let active=!0,timer,focusListening=!1,reconciling=!1,unsubscribe=()=>{};const clearTimer=()=>{clearTimeout(timer),timer=void 0},listenForFocus=enabled=>{enabled!==focusListening&&(focusListening=enabled,enabled?window.addEventListener("focus",reconcile):window.removeEventListener("focus",reconcile))},cleanup=()=>{active&&(active=!1,clearTimer(),listenForFocus(!1),document.removeEventListener("visibilitychange",reconcile),unsubscribe(),this.watchers.delete(cleanup))},reconcile=()=>{if(!(!active||reconciling)){reconciling=!0;try{if(clearTimer(),this.disposed||this.snapshotOf(providerId).phase==="hidden"){cleanup();return}const visible=pageVisible();if(listenForFocus(visible),!visible||(this.ensureFresh(providerId),this.pending.has(providerId)))return;const current=this.snapshotOf(providerId),due=current.phase==="ok"&&!current.stale&&!snapshotExpired(current,this.ttlMs)?current.fetchedAt+this.ttlMs:this.retryAt.get(providerId)??Date.now()+REFRESH_RETRY_MS;timer=setTimeout(reconcile,Math.max(1,due-Date.now()))}finally{reconciling=!1}}};return this.watchers.add(cleanup),unsubscribe=this.subscribe(reconcile),document.addEventListener("visibilitychange",reconcile),reconcile(),cleanup}ensureFresh(providerId){if(this.disposed||providerId===null||!pageVisible())return;const current=this.snapshotOf(providerId);if(current.phase==="hidden")return;const aged=current.phase==="ok"&&!current.stale&&snapshotExpired(current,this.ttlMs);if(aged&&this.snapshots.set(providerId,{...current,stale:!0}),current.phase==="ok"&&!current.stale&&!aged)return;if(this.pending.has(providerId)||Date.now()<(this.retryAt.get(providerId)??0)){aged&&this.#notify();return}this.retryAt.set(providerId,Date.now()+REFRESH_RETRY_MS);const generation=(this.generations.get(providerId)??0)+1;this.generations.set(providerId,generation);let dispatched=!1;const promise=Promise.resolve().then(()=>{if(!(this.disposed||!pageVisible()))return dispatched=!0,this.remote.glmQuota.get(providerId,void 0)}).then(result=>{if(!dispatched||this.disposed||this.generations.get(providerId)!==generation)return;const payload=result!==null&&typeof result=="object"&&result.ok===!0?result.value:null;payload===null||typeof payload!="object"||payload.provider!==providerId?this.snapshots.set(providerId,{phase:"error",provider:providerId,at:Date.now()}):(this.configReady||this.setTtl(payload.ttlMs),this.snapshots.set(providerId,this.#project(payload))),this.#notify()}).catch(()=>{this.disposed||this.generations.get(providerId)!==generation||(this.snapshots.set(providerId,{phase:"error",provider:providerId,at:Date.now()}),this.#notify())}).finally(()=>{this.disposed||this.generations.get(providerId)!==generation||(this.pending.delete(providerId),dispatched?this.retryAt.set(providerId,Date.now()+REFRESH_RETRY_MS):this.retryAt.delete(providerId),this.#notify())});this.pending.set(providerId,promise),aged&&this.#notify()}#project(payload){return payload===null||typeof payload!="object"?{phase:"error",provider:"",at:Date.now()}:payload.status==="ok"?{phase:"ok",provider:payload.provider,fetchedAt:payload.fetchedAt,stale:payload.stale===!0||snapshotExpired(payload,this.ttlMs),windows:{fiveHour:payload.windows?.fiveHour??null,weekly:payload.windows?.weekly??null}}:payload.status==="not_glm"?{phase:"hidden",provider:payload.provider}:{phase:"error",provider:payload.provider,at:Date.now()}}}function QuotaPill(props){const controller=props.controller,useProjection=props.useProjection;if(controller===void 0||useProjection===void 0)return null;const selection=useProjection("modelSelection",face=>face==null?null:face.next??face.lastUsed??null),providerId=selection===null?null:selection.provider,snapshot=useSyncExternalStore(listener=>controller.subscribe(listener),()=>providerId===null?HIDDEN_EMPTY:controller.snapshotOf(providerId));return useEffect(()=>controller.watch(providerId),[controller,providerId]),providerId===null?null:createElement(PillView,{snapshot,t:props.t,onOpen:()=>controller.ensureFresh(providerId)})}const NATIVE_DOCK_STYLE=Object.freeze({fontSize:"12px",lineHeight:"20px",color:"var(--dsw-alias-label-tertiary, var(--dsh-boot-label-tertiary))"}),DIALOG_CSS=`
2
+ .ckyueix-glm-quota{display:inline-flex;min-width:0}
3
+ .ckyueix-glm-quota-button{box-sizing:border-box;border-radius:var(--dsw-radius-sm);max-width:100%;color:inherit;font:inherit;font-variant-numeric:tabular-nums;line-height:inherit;white-space:nowrap;background:transparent;border:0;align-items:center;gap:6px;padding:1px 8px;display:inline-flex;cursor:pointer}
4
+ .ckyueix-glm-quota-icon{width:14px;height:14px;flex-shrink:0}
5
+ .ckyueix-glm-quota-button:hover,.ckyueix-glm-quota-button[aria-expanded=true]{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}
6
+ .ckyueix-glm-quota-panel{z-index:1100;box-sizing:border-box;border-radius:var(--dsw-radius-lg);background:var(--dsw-specific-menu);width:max-content;min-width:min(300px,100vw - 24px);max-width:min(440px,100vw - 24px);max-height:calc(100dvh - 24px);overflow:auto;backdrop-filter:var(--dsw-menu-backdrop-filter);--dsw-elevation-stroke-color:var(--dsw-alias-border-l1);box-shadow:var(--dsw-elevation-prominent);color:var(--dsw-alias-label-secondary);cursor:default;border:0;padding:16px;font-size:12px;line-height:18px;position:fixed}
7
+ .ckyueix-glm-quota-title{color:var(--dsw-alias-label-primary);margin-bottom:8px;font-weight:500}
8
+ .ckyueix-glm-quota-rule{border-top:.5px solid var(--dsw-alias-border-l2);margin-bottom:10px}
9
+ .ckyueix-glm-quota-details{color:var(--dsw-alias-label-tertiary);grid-template-columns:minmax(76px,auto) minmax(0,1fr);gap:6px 16px;margin:0;display:grid}
10
+ .ckyueix-glm-quota-details dt,.ckyueix-glm-quota-details dd{min-width:0;margin:0}
11
+ .ckyueix-glm-quota-details dd{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;text-align:right;overflow-wrap:anywhere}
12
+ .ckyueix-glm-quota-stale{color:var(--dsw-alias-label-tertiary);margin-bottom:10px}
13
+ `;function installDialogStyles(){if(typeof document>"u"||document.head===void 0)return()=>{};const tag=document.createElement("style");return tag.dataset.pluginCss="@ckyueix/glm-usage/dialog",tag.textContent=DIALOG_CSS,document.head.appendChild(tag),()=>tag.remove()}function useQuotaDialog(provider,enabled){const[expandedProvider,setExpandedProvider]=react.useState(null),rootRef=react.useRef(null),panelRef=react.useRef(null),panelId=react.useId(),open=enabled&&expandedProvider===provider,setOpen=react.useCallback(next=>{setExpandedProvider(previous=>(typeof next=="function"?next(previous===provider):next)?provider:null)},[provider]),pos=dialogRuntime.useAnchoredPosition({open,anchorRef:rootRef,panelRef,side:"top",gap:8,margin:12});return dialogRuntime.useDismissOnOutsidePointer(rootRef,open,setOpen,panelRef),useEffect(()=>{setExpandedProvider(null)},[provider,enabled]),useEffect(()=>{if(!open||typeof document>"u")return;const onKeyDown=event=>{event.key==="Escape"&&(setOpen(!1),rootRef.current?.querySelector("button")?.focus())},onClick=event=>{typeof Node<"u"&&event.target instanceof Node&&rootRef.current?.contains(event.target)!==!0&&panelRef.current?.contains(event.target)!==!0&&setOpen(!1)};return document.addEventListener("keydown",onKeyDown),document.addEventListener("click",onClick,!0),()=>{document.removeEventListener("keydown",onKeyDown),document.removeEventListener("click",onClick,!0)}},[open,setOpen]),{open,setOpen,rootRef,panelRef,panelId,pos}}function percentText(window2){return typeof window2?.usedPercent=="number"&&Number.isFinite(window2.usedPercent)&&window2.usedPercent>=0&&window2.usedPercent<=100?window2.usedPercent+"%":"\u2014"}function quotaIcon(){return createElement("svg",{className:"ckyueix-glm-quota-icon",width:14,height:14,viewBox:"0 0 16 16",fill:"none",stroke:"currentColor",strokeWidth:1.25,strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":!0,focusable:"false"},createElement("path",{d:"M8 1.75V8h6.25A6.25 6.25 0 0 0 8 1.75Z"}),createElement("path",{d:"M5.5 2.27A6.25 6.25 0 1 0 13.73 10.5"}))}function quotaDetails(snapshot,t){const rows=[],row=(key,label,value)=>{rows.push(createElement("dt",{key:key+"-label"},label),createElement("dd",{key,"data-ckyueix-quota-detail":key},value))};row("account",t("pill.account"),snapshot.provider);for(const[key,used,budget,reset]of[["fiveHour","pill.fiveHourUsed","pill.fiveHourBudget","pill.fiveHourReset"],["weekly","pill.weeklyUsed","pill.weeklyBudget","pill.weeklyReset"]]){const window2=snapshot.windows?.[key];row(key+"-used",t(used),percentText(window2));const validAmount=value=>typeof value=="number"&&Number.isFinite(value)&&value>=0;if(validAmount(window2?.remaining)||validAmount(window2?.total)){const amount=value=>validAmount(value)?value.toLocaleString("en-US"):"\u2014";row(key+"-budget",t(budget),amount(window2.remaining)+" / "+amount(window2.total)+(window2.type==="CREDIT_LIMIT"?" Credit":" Token"))}row(key+"-reset",t(reset),window2?.active===!1?t("pill.inactive"):typeof window2?.resetMs=="number"&&Number.isFinite(window2.resetMs)?formatClock(window2.resetMs):"\u2014")}return row("fetchedAt",t("pill.staleAt"),typeof snapshot.fetchedAt=="number"&&Number.isFinite(snapshot.fetchedAt)?formatClock(snapshot.fetchedAt):"\u2014"),createElement("dl",{className:"ckyueix-glm-quota-details"},...rows)}function PillView({snapshot,t,onOpen}){const dialog=useQuotaDialog(snapshot?.provider??null,snapshot?.phase==="ok");if(snapshot==null||snapshot.phase==="hidden")return null;if(snapshot.phase==="loading")return createElement("span",{"data-ckyueix-glm-quota":"loading",className:"ckyueix-glm-quota",style:NATIVE_DOCK_STYLE},t("pill.loading"));if(snapshot.phase==="error"){const title=t("pill.error")+(snapshot.at!==void 0?" \xB7 "+t("pill.staleAt")+" "+formatClock(snapshot.at):"");return createElement("span",{"data-ckyueix-glm-quota":"error",className:"ckyueix-glm-quota",style:NATIVE_DOCK_STYLE,title},"\u26A0 "+t("pill.error"))}const label=t("pill.weeklyLimit")+" "+percentText(snapshot.windows?.weekly);return createElement("span",{ref:dialog.rootRef,"data-ckyueix-glm-quota":snapshot.stale===!0?"stale":"ok",className:"ckyueix-glm-quota",style:NATIVE_DOCK_STYLE,title:(snapshot.stale?t("pill.stale")+" \xB7 ":"")+t("pill.staleAt")+" "+formatClock(snapshot.fetchedAt)},createElement("button",{type:"button",className:"ckyueix-glm-quota-button","aria-haspopup":"dialog","aria-expanded":dialog.open,"aria-controls":dialog.panelId,"aria-label":t("pill.expand"),onClick:()=>{const next=!dialog.open;dialog.setOpen(next),next&&onOpen?.()}},quotaIcon(),createElement("span",null,(snapshot.stale===!0?"\u26A0 ":"")+label)),dialog.open?dialogRuntime.createPortal(createElement("div",{ref:dialog.panelRef,id:dialog.panelId,className:"ckyueix-glm-quota-panel",role:"dialog","aria-label":t("pill.details"),style:dialog.pos??{visibility:"hidden",left:0,top:0}},createElement("div",{className:"ckyueix-glm-quota-title"},t("pill.details")),createElement("div",{className:"ckyueix-glm-quota-rule","aria-hidden":!0}),snapshot.stale===!0?createElement("div",{className:"ckyueix-glm-quota-stale"},"\u26A0 "+t("pill.stale")):null,quotaDetails(snapshot,t)),document.body):null)}const HIDDEN_EMPTY=Object.freeze({phase:"hidden",provider:""}),inject=["remote","slots","locale"];async function apply(ctx){try{const primitives=require("@deepseek-ai/dsh-client-ui-primitives"),dom=require("react-dom");if(typeof primitives.useAnchoredPosition!="function"||typeof primitives.useDismissOnOutsidePointer!="function"||typeof dom.createPortal!="function")throw new Error("dialog runtime unavailable");dialogRuntime={useAnchoredPosition:primitives.useAnchoredPosition,useDismissOnOutsidePointer:primitives.useDismissOnOutsidePointer,createPortal:dom.createPortal}}catch{return console.error("ckyueix-glm-quota: native dialog runtime unavailable; dock entry disabled"),()=>{}}ctx.effect(installDialogStyles,"glm-quota: dialog styles"),ctx.effect(()=>ctx.locale.register(NS,DICT),"glm-quota: dictionaries");let unmountRemote;try{unmountRemote=await ctx.remote.$mount(TYPERT_REMOTE)}catch(error){return console.error("ckyueix-glm-quota: remote namespace mount failed; dock entry disabled",error),()=>{}}let disposed=!1;const disposeSelf=async()=>{if(!disposed){disposed=!0;try{await unmountRemote()}catch(error){console.error("ckyueix-glm-quota: remote namespace unmount failed",error)}}};let ui;try{if(ctx.get("remote.glmQuota")===void 0)throw new Error("namespace remote.glmQuota missing after $mount");ui=ctx.inject(["remote","remote.glmQuota","slots","locale"],registerUi),await ui}catch(error){console.error("ckyueix-glm-quota: dock registration failed; feature disabled",error);try{await ui?.dispose?.()}catch{}return await disposeSelf(),()=>{}}return async()=>{try{await ui.dispose()}finally{await disposeSelf()}}}function registerUi(ctx){const controller=new QuotaController(ctx),t=ctx.locale.bind(NS),configuration=ctx.inject(["configForms","slots"],child=>registerConfiguration(child,controller,t));return Promise.resolve(configuration).catch(()=>console.error("ckyueix-glm-quota: native configuration mirror unavailable")),ctx.slots.inject("conversation.composer.dock",function*(){yield ctx.slots.register({name:"conversation.composer.dock",id:"ckyueix-glm-quota",order:2,locale:NS,inject:()=>({controller,t})},QuotaPill)}),async()=>{try{await configuration.dispose()}finally{controller.dispose()}}}return exports.apply=apply,exports.inject=inject,exports.remoteSpec=TYPERT_REMOTE_SPEC,module.exports}});
package/dist/index.js ADDED
@@ -0,0 +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};
package/package.json CHANGED
@@ -1,6 +1,37 @@
1
1
  {
2
2
  "name": "@ckyueix/glm-usage",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "GLM Coding Plan usage pill for the DeepSeek Harness composer dock (dual-half: host quota reader + web client entry)",
5
+ "type": "module",
6
+ "license": "SEE LICENSE IN LICENSE",
7
+ "main": "./dist/index.js",
8
+ "exports": {
9
+ ".": "./dist/index.js",
10
+ "./client": "./dist/client.js",
11
+ "./package.json": "./package.json"
12
+ },
13
+ "files": [
14
+ "dist",
15
+ "cordis.patch.yml",
16
+ "README.md",
17
+ "LICENSE"
18
+ ],
19
+ "engines": {
20
+ "dsh": "0.2.1-rc.2"
21
+ },
22
+ "peerDependencies": {
23
+ "@deepseek-ai/dsh": "0.2.1-rc.2"
24
+ },
25
+ "dependencies": {
26
+ "@deepseek-ai/dsh-typert-protocol": "0.2.1-rc.2",
27
+ "@deepseek-ai/schemastery": "~3.18.5"
28
+ },
29
+ "dsh": {
30
+ "bundle": {
31
+ "patch": "./cordis.patch.yml"
32
+ },
33
+ "client": {
34
+ "platform": "web"
35
+ }
36
+ }
37
+ }