dsh-keys-manager 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 +21 -0
- package/README.md +163 -2
- package/README.zh-CN.md +114 -0
- package/bundle/cordis.patch.yml +5 -0
- package/icon.svg +12 -0
- package/lib/client/format.d.ts +8 -0
- package/lib/client/index.d.ts +3 -0
- package/lib/client/locales.d.ts +4 -0
- package/lib/client/runtime.d.ts +21 -0
- package/lib/client/store.d.ts +4 -0
- package/lib/client/styles.d.ts +2 -0
- package/lib/client/types.d.ts +87 -0
- package/lib/client/ui.d.ts +18 -0
- package/lib/client.js +1594 -0
- package/lib/core.d.ts +71 -0
- package/lib/core.js +238 -0
- package/lib/core.js.map +1 -0
- package/lib/domain.d.ts +171 -0
- package/lib/domain.js +9 -0
- package/lib/domain.js.map +1 -0
- package/lib/host-types.d.ts +178 -0
- package/lib/host-types.js +2 -0
- package/lib/host-types.js.map +1 -0
- package/lib/index.d.ts +181 -0
- package/lib/index.js +1782 -0
- package/lib/index.js.map +1 -0
- package/lib/providers.d.ts +28 -0
- package/lib/providers.js +1308 -0
- package/lib/providers.js.map +1 -0
- package/lib/store.d.ts +62 -0
- package/lib/store.js +398 -0
- package/lib/store.js.map +1 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +90 -4
- package/scripts/build-client.mjs +53 -0
- package/scripts/prepare-release.mjs +243 -0
- package/scripts/verify-dist.mjs +30 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 BT.Wood(Tang Bo Hao)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,164 @@
|
|
|
1
|
-
#
|
|
1
|
+
# DSH Keys Manager
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/dsh-keys-manager)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[](https://www.npmjs.com/package/dsh-keys-manager)
|
|
6
|
+
[](https://www.npmjs.com/package/@deepseek-ai/dsh-llm)
|
|
7
|
+
|
|
8
|
+
**English** | [简体中文](README.zh-CN.md)
|
|
9
|
+
|
|
10
|
+
Docs: [Development](docs/development.md) · [Release](docs/release.md) · [Known limits](docs/known-limits.md) — Documentation in Chinese: [开发](docs/development.zh-CN.md) · [发布](docs/release.zh-CN.md) · [已知限制](docs/known-limits.zh-CN.md)
|
|
11
|
+
|
|
12
|
+
A DeepSeek Harness plugin that turns one provider API key into a managed pool.
|
|
13
|
+
It extends the Models page rather than replacing it: providers, models, and the
|
|
14
|
+
model picker stay where they are; only the API-key source moves behind the
|
|
15
|
+
manager.
|
|
16
|
+
|
|
17
|
+
## Features
|
|
18
|
+
|
|
19
|
+
- Several keys per provider, each with an alias and health state.
|
|
20
|
+
- One key pinned to a session, with round-robin selection for new sessions.
|
|
21
|
+
- Bounded retry on the same key, then automatic failover to another key.
|
|
22
|
+
- Exponential cooldown recovery, capped at seven days.
|
|
23
|
+
- A search-driven Keys Manager page on the plugin's own detail page.
|
|
24
|
+
- A "managed by Keys Manager" badge inside the existing Models provider cards.
|
|
25
|
+
- Extra built-in providers installed as ordinary `llm-pi-ai` routes.
|
|
26
|
+
|
|
27
|
+
### Extra providers
|
|
28
|
+
|
|
29
|
+
`src/providers.ts` contains a curated catalog of 34 extra providers (21 from
|
|
30
|
+
the original catalog plus 13 added in this release, for example SiliconFlow,
|
|
31
|
+
Zhipu coding plan, Cline Pass, Ollama Cloud, and Alibaba Token Plan (CN)),
|
|
32
|
+
derived from
|
|
33
|
+
[oh-my-pi](https://github.com/can1357/oh-my-pi)'s provider catalog (MIT).
|
|
34
|
+
An extra id is added only when the shipped DSH catalog does not already
|
|
35
|
+
declare that route id (for example, `meta` and `typesafe` are not
|
|
36
|
+
duplicated); same-endpoint providers with distinct credential identities
|
|
37
|
+
are kept by design.
|
|
38
|
+
|
|
39
|
+
## Quick start
|
|
40
|
+
|
|
41
|
+
### Install — published package
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
dsh plugin --profile web add dsh-keys-manager
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Install — local checkout
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
git clone https://github.com/btspoony/dsh-keys-manager
|
|
51
|
+
cd dsh-keys-manager
|
|
52
|
+
pnpm i
|
|
53
|
+
dsh plugin --profile web link .
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Refresh the Web page after installing so the browser half is fetched.
|
|
57
|
+
|
|
58
|
+
## Usage
|
|
59
|
+
|
|
60
|
+
Open **Plugins → Keys Manager → View** (rendered as
|
|
61
|
+
`Plugins → 密钥管理 → 查看` in the Chinese locale). The manager renders on the
|
|
62
|
+
plugin's detail page, between its description and its included rows, matching
|
|
63
|
+
the shipped plugin configuration cards.
|
|
64
|
+
|
|
65
|
+
1. Search for a provider. Existing DSH providers appear first; the plugin also
|
|
66
|
+
ships the curated extra catalog described above.
|
|
67
|
+
2. Adopt a provider. For an existing provider the manager imports the
|
|
68
|
+
currently resolved credential, writes a broker reference into the provider
|
|
69
|
+
profile, and leaves the original key in the credential store so release can
|
|
70
|
+
restore it.
|
|
71
|
+
3. Add more keys with an alias. Every key is stored in the Harness credential
|
|
72
|
+
store under its own reference; the manager state document never contains a
|
|
73
|
+
key literal.
|
|
74
|
+
4. Manage a key from the three-dot menu: rename, pause/resume, delete. A key
|
|
75
|
+
row shows status, last use, and the recovery time while cooling.
|
|
76
|
+
5. Tune retry count (1–3), base cooldown, and recovery grace in the settings
|
|
77
|
+
card.
|
|
78
|
+
|
|
79
|
+
### Selection and failure policy
|
|
80
|
+
|
|
81
|
+
- **Sticky session**: the first request of a session selects a key and binds
|
|
82
|
+
it for that session/provider pair. Later requests reuse it.
|
|
83
|
+
- **Round robin**: a new session advances the provider cursor and takes the
|
|
84
|
+
next healthy key.
|
|
85
|
+
- **Retry**: a failing request is retried on the same key `retryCount` times.
|
|
86
|
+
- **Switch**: after the retry budget is spent, the failing key is marked
|
|
87
|
+
cooling, and the session is rebound to another healthy key.
|
|
88
|
+
- **Cooldown**: the first failure cools a key for `baseCooldownMs`. A failure
|
|
89
|
+
while cooling, or within `recoveryGraceMs` after recovery, doubles the
|
|
90
|
+
next cooldown. A long healthy gap resets the escalation. The hard cap is
|
|
91
|
+
seven days.
|
|
92
|
+
- **Recovery**: the key is automatically selectable again when its cooldown
|
|
93
|
+
expires; no manual reset is required.
|
|
94
|
+
- **Delegation**: request-shaped failures such as
|
|
95
|
+
`CONTEXT_WINDOW_EXCEEDED` and cancellation never cool a key. When no
|
|
96
|
+
alternate key exists, the manager delegates to the composition's normal
|
|
97
|
+
retry/fallback policy.
|
|
98
|
+
|
|
99
|
+
## Configuration & data
|
|
100
|
+
|
|
101
|
+
Manager metadata lives at:
|
|
102
|
+
|
|
103
|
+
```text
|
|
104
|
+
$DSH_HOME/keys-manager/state.json
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
with owner-only permissions. It contains aliases, credential references,
|
|
108
|
+
health counters, session bindings, and provider adoption facts. API key
|
|
109
|
+
literals live only in the Harness credential store. The file is written
|
|
110
|
+
atomically through a temporary file and a rename.
|
|
111
|
+
|
|
112
|
+
Each managed provider profile points its `apiKeyEnv` at a broker reference
|
|
113
|
+
such as `KEYSMGR_ZAI_CODING_CN_3FA2C1`. The Host credential layer answers that
|
|
114
|
+
reference per request with the session's selected key. The Models page sees
|
|
115
|
+
the profile as configured; writing directly to the broker reference is
|
|
116
|
+
refused with a pointer to the manager.
|
|
117
|
+
|
|
118
|
+
### OAuth2 extension point
|
|
119
|
+
|
|
120
|
+
The state shape already distinguishes `kind: "api-key"` from `kind: "oauth"`
|
|
121
|
+
and keeps a nullable `oauth` object beside the credential reference. A future
|
|
122
|
+
account flow can add records under `keys-manager/<provider>/<key>` without
|
|
123
|
+
rewriting existing rows. Providers whose only authentication is OAuth are
|
|
124
|
+
reported as unsupported in this version rather than being treated as API-key
|
|
125
|
+
providers.
|
|
126
|
+
|
|
127
|
+
## Provider classification
|
|
128
|
+
|
|
129
|
+
Every provider card carries its origin:
|
|
130
|
+
|
|
131
|
+
- **DSH built-in** (`DSH 内置`) — a route from the shipped DSH pi-ai catalog.
|
|
132
|
+
- **Plugin built-in** (`插件内置`) — a route from this plugin's extra catalog
|
|
133
|
+
in `src/providers.ts`.
|
|
134
|
+
- **Custom** (`自定义`) — a hand-declared route in the active profile.
|
|
135
|
+
|
|
136
|
+
The following DSH built-ins are explicitly outside single-key pool management:
|
|
137
|
+
|
|
138
|
+
| Provider | Why |
|
|
139
|
+
|---|---|
|
|
140
|
+
| `amazon-bedrock` | AWS credential chain (profile, IAM keys, ECS/IRSA/EC2), not one API key |
|
|
141
|
+
| `cloudflare-ai-gateway` | API key plus a Cloudflare account ID and gateway ID |
|
|
142
|
+
| `cloudflare-workers-ai` | API key plus a Cloudflare account ID |
|
|
143
|
+
| `openai-codex` | ChatGPT OAuth sign-in only; no API-key credential |
|
|
144
|
+
|
|
145
|
+
All other DSH catalog routes expose an API-key credential. Providers that also
|
|
146
|
+
support OAuth (Anthropic, GitHub Copilot, Kimi, OpenRouter, xAI, Radius) remain
|
|
147
|
+
manageable through their API-key path; OAuth accounts are tracked separately
|
|
148
|
+
in the roadmap issue.
|
|
149
|
+
|
|
150
|
+
## Documentation
|
|
151
|
+
|
|
152
|
+
| Doc | Content |
|
|
153
|
+
|---|---|
|
|
154
|
+
| [Development](docs/development.md) | build and dev workflow, repository layout |
|
|
155
|
+
| [Release](docs/release.md) | CI checks and the npm release flow |
|
|
156
|
+
| [Known limits](docs/known-limits.md) | current design boundaries, including deferred providers |
|
|
157
|
+
|
|
158
|
+
Chinese versions: [README.zh-CN.md](README.zh-CN.md) and the `*.zh-CN.md`
|
|
159
|
+
files in `docs/`. Current design boundaries at a glance:
|
|
160
|
+
[Known limits](docs/known-limits.md).
|
|
161
|
+
|
|
162
|
+
## License
|
|
163
|
+
|
|
164
|
+
Released under the [MIT License](LICENSE).
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# DSH Keys Manager
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/dsh-keys-manager)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[](https://www.npmjs.com/package/dsh-keys-manager)
|
|
6
|
+
[](https://www.npmjs.com/package/@deepseek-ai/dsh-llm)
|
|
7
|
+
|
|
8
|
+
[English](README.md) | **简体中文**
|
|
9
|
+
|
|
10
|
+
文档:[开发](docs/development.zh-CN.md) · [发布](docs/release.zh-CN.md) · [已知限制](docs/known-limits.zh-CN.md) — English docs: [Development](docs/development.md) · [Release](docs/release.md) · [Known limits](docs/known-limits.md)
|
|
11
|
+
|
|
12
|
+
DSH Keys Manager 是一个 DeepSeek Harness 插件,把一个提供商 API key 变成托管密钥池。它扩展而非替换 Models 页面:提供商、模型和模型选择器都在原处,只有 API key 来源移到管理器之后。
|
|
13
|
+
|
|
14
|
+
## 特性
|
|
15
|
+
|
|
16
|
+
- 每个提供商可配多把 key,每把有别名和健康状态。
|
|
17
|
+
- 一把 key 粘滞绑定到会话,新会话按轮询选择。
|
|
18
|
+
- 同一把 key 上有界重试,预算耗尽后自动切换到另一把 key。
|
|
19
|
+
- 指数升级的冷却恢复,上限七天。
|
|
20
|
+
- 插件详情页上提供可搜索的 Keys Manager 页面。
|
|
21
|
+
- 既有 Models 提供商卡片内出现"由 Keys Manager 托管"徽标。
|
|
22
|
+
- 额外内置提供商以普通 `llm-pi-ai` 路由安装。
|
|
23
|
+
|
|
24
|
+
### 额外提供商
|
|
25
|
+
|
|
26
|
+
`src/providers.ts` 收录 34 个精选提供商(原有 21 个加本次发布新增 13 个,例如 SiliconFlow、智谱编码套餐、Cline Pass、Ollama Cloud、Alibaba Token Plan (CN)),目录源自 [oh-my-pi](https://github.com/can1357/oh-my-pi)(MIT)。只有当随附 DSH 目录尚未声明该 route id 时才会新增条目(例如 `meta`、`typesafe` 不会重复提供);与既有端点共享 base URL、但凭据身份不同的提供商会按设计保留。
|
|
27
|
+
|
|
28
|
+
## 快速开始
|
|
29
|
+
|
|
30
|
+
### 安装 —— 已发布包
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
dsh plugin --profile web add dsh-keys-manager
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### 安装 —— 本地检出
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
git clone https://github.com/btspoony/dsh-keys-manager
|
|
40
|
+
cd dsh-keys-manager
|
|
41
|
+
pnpm i
|
|
42
|
+
dsh plugin --profile web link .
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
安装完成后刷新 Web 页面,让浏览器侧代码被取到。
|
|
46
|
+
|
|
47
|
+
## 使用
|
|
48
|
+
|
|
49
|
+
打开 **Plugins → 密钥管理 → 查看**(英文 locale 下显示为 `Plugins → Keys Manager → View`)。管理器渲染在插件详情页上,位于描述与包含行之间,与随附的插件配置卡片一致。
|
|
50
|
+
|
|
51
|
+
1. 搜索提供商。既有 DSH 提供商排在前面;插件同时附带上述精选扩展目录。
|
|
52
|
+
2. 接管提供商。对既有提供商,管理器导入当前解析出的凭据、把 broker 引用写进提供商档案,并把原 key 留在凭据存储里,以便停止接管时还原。
|
|
53
|
+
3. 用别名添加更多 key。每把 key 都以自己的引用存进 Harness 凭据存储;管理器状态文档从不包含 key 字面量。
|
|
54
|
+
4. 在三点菜单中管理 key:重命名、暂停/恢复、删除。key 行显示状态、最近使用,以及冷却中的恢复时间。
|
|
55
|
+
5. 在设置卡片中调整重试次数(1–3)、基础冷却与恢复宽限。
|
|
56
|
+
|
|
57
|
+
### 选择与故障策略
|
|
58
|
+
|
|
59
|
+
- **会话粘滞**:会话的首次请求选出一把 key 并为该会话/提供商对绑定,后续请求复用。
|
|
60
|
+
- **轮询**:新会话推进提供商游标,取下一把健康 key。
|
|
61
|
+
- **重试**:失败请求在同一把 key 上重试 `retryCount` 次。
|
|
62
|
+
- **切换**:重试预算耗尽后,失败 key 标记为冷却,会话重新绑定到另一把健康 key。
|
|
63
|
+
- **冷却**:首次失败使 key 冷却 `baseCooldownMs`。冷却中再次失败,或恢复后 `recoveryGraceMs` 内失败,下一次冷却翻倍;长时间健康运行会重置升级。硬上限七天。
|
|
64
|
+
- **恢复**:冷却到期后 key 自动恢复可选,无需手动重置。
|
|
65
|
+
- **委托**:请求形态的失败(如 `CONTEXT_WINDOW_EXCEEDED`)与取消从不冷却 key。没有备用 key 时,管理器委托给组合层常规的重试/回退策略。
|
|
66
|
+
|
|
67
|
+
## 配置与数据
|
|
68
|
+
|
|
69
|
+
管理器元数据位于:
|
|
70
|
+
|
|
71
|
+
```text
|
|
72
|
+
$DSH_HOME/keys-manager/state.json
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
权限为仅属主可读写。内容包含别名、凭据引用、健康计数、会话绑定和提供商接管事实。API key 字面量只存在于 Harness 凭据存储。文件通过临时文件加重命名原子写入。
|
|
76
|
+
|
|
77
|
+
每个受管提供商档案的 `apiKeyEnv` 指向 broker 引用,例如 `KEYSMGR_ZAI_CODING_CN_3FA2C1`。Host 凭据层按请求用该会话选中的 key 应答这个引用。Models 页面视该档案为已配置;直接写 broker 引用会被拒绝并指向管理器。
|
|
78
|
+
|
|
79
|
+
### OAuth2 扩展点
|
|
80
|
+
|
|
81
|
+
状态结构已区分 `kind: "api-key"` 与 `kind: "oauth"`,并在凭据引用旁保留可空的 `oauth` 对象。未来的账号流程可以在 `keys-manager/<provider>/<key>` 下追加记录而不改写既有行。本版本中,只有 OAuth 认证的提供商会按不支持上报,而不会被当作 API key 提供商处理。
|
|
82
|
+
|
|
83
|
+
## 提供商分类
|
|
84
|
+
|
|
85
|
+
每个提供商卡片标注来源:
|
|
86
|
+
|
|
87
|
+
- **DSH 内置**(英文界面显示 `DSH built-in`)——随附 DSH pi-ai 目录的路由。
|
|
88
|
+
- **插件内置**(`Plugin built-in`)——来自本插件 `src/providers.ts` 扩展目录的路由。
|
|
89
|
+
- **自定义**(`Custom`)——当前档案中手工声明的路由。
|
|
90
|
+
|
|
91
|
+
以下 DSH 内置提供商明确不在单 key 池管理范围内:
|
|
92
|
+
|
|
93
|
+
| 提供商 | 原因 |
|
|
94
|
+
|---|---|
|
|
95
|
+
| `amazon-bedrock` | AWS 凭据链(profile、IAM 密钥、ECS/IRSA/EC2),不是单一 API key |
|
|
96
|
+
| `cloudflare-ai-gateway` | API key 之外还需 Cloudflare 账号 ID 与网关 ID |
|
|
97
|
+
| `cloudflare-workers-ai` | API key 之外还需 Cloudflare 账号 ID |
|
|
98
|
+
| `openai-codex` | 仅支持 ChatGPT OAuth 登录,无 API key 凭据 |
|
|
99
|
+
|
|
100
|
+
其余 DSH 目录路由都提供 API key 凭据。同时支持 OAuth 的提供商(Anthropic、GitHub Copilot、Kimi、OpenRouter、xAI、Radius)仍可经其 API key 路径管理;OAuth 账号在路线图 issue 中单独跟踪。
|
|
101
|
+
|
|
102
|
+
## 文档
|
|
103
|
+
|
|
104
|
+
| 文档 | 内容 |
|
|
105
|
+
|---|---|
|
|
106
|
+
| [开发](docs/development.zh-CN.md) | 构建与开发工作流、仓库布局 |
|
|
107
|
+
| [发布](docs/release.zh-CN.md) | CI 检查与 npm 发布流程 |
|
|
108
|
+
| [已知限制](docs/known-limits.zh-CN.md) | 当前设计边界,含延后提供商 |
|
|
109
|
+
|
|
110
|
+
英文版本:[README.md](README.md) 及 `docs/` 下的 `*.md`。当前设计边界速览:[已知限制](docs/known-limits.zh-CN.md)。
|
|
111
|
+
|
|
112
|
+
## 许可证
|
|
113
|
+
|
|
114
|
+
基于 [MIT 许可证](LICENSE) 发布。
|
package/icon.svg
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="dsh-keys-manager-icon-bg" x1="6" y1="4" x2="30" y2="33" gradientUnits="userSpaceOnUse">
|
|
4
|
+
<stop stop-color="#5B9BFF"/>
|
|
5
|
+
<stop offset="1" stop-color="#315BE6"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
</defs>
|
|
8
|
+
<rect x="2.5" y="2.5" width="31" height="31" rx="9" fill="url(#dsh-keys-manager-icon-bg)"/>
|
|
9
|
+
<circle cx="18" cy="13.1" r="4.1" stroke="#F9FAFB" stroke-width="2.2"/>
|
|
10
|
+
<path d="M18 17.2V26.6" stroke="#F9FAFB" stroke-width="2.2" stroke-linecap="round"/>
|
|
11
|
+
<path d="M18 21.8H22.2M18 24.7H21.2" stroke="#F9FAFB" stroke-width="2.2" stroke-linecap="round"/>
|
|
12
|
+
</svg>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Exact millisecond/minute conversions used by the policy form. */
|
|
2
|
+
export declare function cooldownMinutes(ms: number): number;
|
|
3
|
+
/** Convert a user-entered base cooldown to milliseconds without rounding. */
|
|
4
|
+
export declare function cooldownMs(minutes: number): number;
|
|
5
|
+
/** Convert a user-entered recovery grace to minutes. */
|
|
6
|
+
export declare function graceMinutes(ms: number): number;
|
|
7
|
+
/** Convert a user-entered recovery grace to milliseconds without rounding. */
|
|
8
|
+
export declare function graceMs(minutes: number): number;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** React runtime context and hooks shared by the Client plugin body. */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import type { ClientContext, ClientSnapshot, Runtime } from './types';
|
|
4
|
+
/** Context installed by every wrapped slot entry. */
|
|
5
|
+
export declare const RuntimeContext: React.Context<Runtime | null>;
|
|
6
|
+
/** Read the plugin runtime; a component outside the wrapper is a wiring bug. */
|
|
7
|
+
export declare function useRuntime(): Runtime;
|
|
8
|
+
/** Translate through the plugin locale namespace, re-rendering on locale changes. */
|
|
9
|
+
export declare function useT(): (key: string, params?: Record<string, string | number>) => string;
|
|
10
|
+
/** Active locale id, used by date/time formatting. */
|
|
11
|
+
export declare function useLocaleId(): string;
|
|
12
|
+
/** Subscribe to the shared manager store. */
|
|
13
|
+
export declare function useStore(): ClientSnapshot;
|
|
14
|
+
/** Current wall clock from the store's 30-second tick. */
|
|
15
|
+
export declare function useNow(): number;
|
|
16
|
+
/** Install the plugin stylesheet once per mounted surface. */
|
|
17
|
+
export declare function useStyles(): void;
|
|
18
|
+
/** Wrap a slot component with the runtime provider and the stylesheet. */
|
|
19
|
+
export declare function wrapComponent(Component: React.ComponentType<any>, runtime: Runtime): React.ComponentType<any>;
|
|
20
|
+
/** Re-export for callers that want the raw context value. */
|
|
21
|
+
export type { ClientContext, Runtime };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/** Stylesheet owned by the Keys Manager client surface. */
|
|
2
|
+
export declare const CSS = "\n.km-page{max-width:920px;margin:0 auto;padding:0 0 8px;color:var(--dsw-alias-label-primary);font-size:13.5px;line-height:1.5}\n.km-embedded-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;margin:0 0 16px}\n.km-summary{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin:0 0 16px;flex:1;min-width:0}\n.km-embedded-head .km-summary{margin:0}\n.km-embedded-actions{display:flex;gap:8px;flex-shrink:0;padding-top:2px}\n.km-summary-line{color:var(--dsw-alias-label-secondary);font-size:12.5px;line-height:1.5}\n.km-stat{display:flex;flex-direction:column;gap:2px;padding:11px 14px;border:1px solid var(--dsw-alias-border-l1);border-radius:10px;background:var(--dsw-alias-bg-layer-1)}\n.km-stat strong{font-size:19px;line-height:1.15;font-weight:650;font-variant-numeric:tabular-nums}\n.km-stat span{color:var(--dsw-alias-label-secondary);font-size:12px}\n.km-search{position:relative;display:flex;align-items:center;margin:0 0 20px}\n.km-search-icon{position:absolute;left:12px;color:var(--dsw-alias-label-secondary);pointer-events:none}\n.km-search-input{width:100%;box-sizing:border-box;padding:10px 38px 10px 36px;border:1px solid var(--dsw-alias-border-l1);border-radius:10px;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font:inherit;outline:none}\n.km-search-input:focus{border-color:var(--dsw-alias-state-business-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--dsw-alias-state-business-primary) 20%,transparent)}\n.km-search-clear{position:absolute;right:8px;display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;border:0;border-radius:6px;background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer}\n.km-search-clear:hover{background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary)}\n.km-section{margin:0 0 22px}\n.km-section-head{display:flex;align-items:baseline;gap:8px;margin:0 0 9px}\n.km-section-title{font-size:14px;font-weight:650;margin:0;letter-spacing:.01em}\n.km-section-count{font-size:12px;color:var(--dsw-alias-label-secondary)}\n.km-provider-list{display:flex;flex-direction:column;gap:8px}\n.km-show-more{display:flex;justify-content:center;padding:8px 0 0}\n.km-card{border:1px solid var(--dsw-alias-border-l1);border-radius:12px;background:var(--dsw-alias-bg-layer-1);overflow:hidden}\n.km-provider-managed{border-color:color-mix(in srgb,var(--dsw-alias-brand-primary) 26%,var(--dsw-alias-border-l1))}\n.km-provider-open{overflow:visible}\n.km-provider-head{display:flex;align-items:center;gap:12px;width:100%;padding:12px 14px;border:0;background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer}\n.km-provider-head:hover{background:color-mix(in srgb,var(--dsw-alias-label-primary) 3%,transparent)}\n.km-avatar{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;flex:0 0 32px;border-radius:9px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);font-weight:650;font-size:13px;color:var(--dsw-alias-label-secondary)}\n.km-provider-main{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1}\n.km-provider-title-line{display:flex;align-items:center;gap:6px;flex-wrap:wrap;min-width:0}\n.km-provider-name{font-weight:650;font-size:13.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:360px}\n.km-provider-meta{display:flex;align-items:center;gap:7px;flex-wrap:wrap;color:var(--dsw-alias-label-secondary);font-size:11.5px;min-width:0}\n.km-provider-side{display:flex;align-items:center;gap:9px;flex-shrink:0}\n.km-count{font-size:11.5px;color:var(--dsw-alias-label-secondary);white-space:nowrap}\n.km-chevron{color:var(--dsw-alias-label-secondary);transition:transform .16s ease}\n.km-chevron-open{transform:rotate(180deg)}\n.km-provider-body{border-top:1px solid var(--dsw-alias-border-l1);padding:13px 14px 14px;background:color-mix(in srgb,var(--dsw-alias-bg-layer-2) 40%,transparent)}\n.km-adopt{display:flex;flex-direction:column;gap:12px}\n.km-adopt-copy{display:flex;flex-direction:column;gap:5px;color:var(--dsw-alias-label-secondary);font-size:12.5px}\n.km-adopt-title{color:var(--dsw-alias-label-primary);font-size:12.5px}\n.km-adopt-actions{display:flex;gap:8px;align-items:center}\n.km-meta-line{display:flex;gap:6px;align-items:baseline;flex-wrap:wrap;font-size:11.5px}\n.km-managed-body{display:flex;flex-direction:column;gap:10px}\n.km-managed-toolbar{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;flex-wrap:wrap}\n.km-managed-summary{display:flex;flex-direction:column;gap:2px;min-width:0;font-size:11.5px}\n.km-managed-actions{display:flex;gap:6px;align-items:center;flex-shrink:0}\n.km-keys{display:flex;flex-direction:column;border:1px solid var(--dsw-alias-border-l1);border-radius:9px;background:var(--dsw-alias-bg-layer-1);overflow:visible}\n.km-key-row{position:relative;display:grid;grid-template-columns:minmax(0,1.35fr) minmax(150px,.8fr) minmax(150px,.9fr) 32px;gap:10px;align-items:center;padding:10px 11px;border-top:1px solid var(--dsw-alias-border-l1)}\n.km-key-row:first-child{border-top:0}\n.km-key-identity{min-width:0;display:flex;flex-direction:column;gap:2px}\n.km-key-alias-line{display:flex;align-items:center;gap:6px;min-width:0}\n.km-key-alias{font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:220px}\n.km-key-sub{display:flex;align-items:center;gap:8px;font-size:11px;color:var(--dsw-alias-label-secondary);flex-wrap:wrap}\n.km-key-status{display:flex;flex-direction:column;gap:2px;align-items:flex-start}\n.km-key-last{display:flex;flex-direction:column;gap:2px;min-width:0}\n.km-key-time{font-size:11.5px;color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums}\n.km-key-time.km-warn{color:var(--dsw-alias-state-warn-primary)}\n.km-key-actions{position:relative;display:flex;justify-content:flex-end}\n.km-status{display:inline-flex;align-items:center;gap:5px;padding:2px 7px;border-radius:999px;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);font-size:11px;white-space:nowrap;color:var(--dsw-alias-label-secondary)}\n.km-status-success{color:var(--dsw-alias-state-success-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-success-primary) 26%,var(--dsw-alias-border-l1));background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 8%,transparent)}\n.km-status-warn{color:var(--dsw-alias-state-warn-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 30%,var(--dsw-alias-border-l1));background:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 8%,transparent)}\n.km-status-error{color:var(--dsw-alias-state-error-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 30%,var(--dsw-alias-border-l1));background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 8%,transparent)}\n.km-status-idle{color:var(--dsw-alias-state-idle-primary)}\n.km-dot{display:inline-block;width:6px;height:6px;border-radius:50%;flex:0 0 6px;background:var(--dsw-alias-state-idle-primary)}\n.km-dot-success{background:var(--dsw-alias-state-success-primary)}\n.km-dot-warn{background:var(--dsw-alias-state-warn-primary)}\n.km-dot-error{background:var(--dsw-alias-state-error-primary)}\n.km-dot-idle{background:var(--dsw-alias-state-idle-primary)}\n.km-dot-sep{color:var(--dsw-alias-label-secondary)}\n.km-tag{display:inline-flex;align-items:center;padding:1px 6px;border-radius:5px;font-size:10.5px;line-height:1.45;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);white-space:nowrap}\n.km-tag-accent{color:var(--dsw-alias-state-business-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-business-primary) 34%,var(--dsw-alias-border-l1));background:var(--dsw-alias-state-business-tertiary)}\n.km-tag-warn{color:var(--dsw-alias-state-warn-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 30%,var(--dsw-alias-border-l1));background:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 8%,transparent)}\n.km-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:1px solid transparent;border-radius:7px;background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer;flex:0 0 auto}\n.km-icon-btn:hover{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary)}\n.km-icon-btn:disabled{opacity:.5;cursor:default}\n.km-menu{position:absolute;top:32px;right:0;z-index:20;min-width:138px;padding:4px;border:1px solid var(--dsw-alias-border-l2);border-radius:9px;background:var(--dsw-alias-bg-overlay);box-shadow:0 7px 22px color-mix(in srgb,var(--dsw-alias-label-primary) 14%,transparent)}\n.km-menu-item{display:flex;align-items:center;gap:8px;width:100%;padding:7px 9px;border:0;border-radius:6px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:12.5px;text-align:left;cursor:pointer}\n.km-menu-item:hover{background:var(--dsw-alias-bg-layer-2)}\n.km-menu-item:disabled{opacity:.5;cursor:default}\n.km-menu-danger{color:var(--dsw-alias-state-error-primary)}\n.km-menu-sep{height:1px;margin:4px 2px;background:var(--dsw-alias-border-l1)}\n.km-btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;padding:7px 11px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font:inherit;font-size:12.5px;font-weight:550;line-height:1.2;cursor:pointer;white-space:nowrap;transition:opacity .15s ease,background .15s ease}\n.km-btn:hover{background:var(--dsw-alias-bg-layer-2)}\n.km-btn:disabled{opacity:.5;cursor:default}\n.km-btn-primary{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-base);border-color:transparent}\n.km-btn-primary:hover{opacity:.9;background:var(--dsw-alias-label-primary)}\n.km-btn-ghost{background:transparent;border-color:transparent;color:var(--dsw-alias-label-secondary)}\n.km-btn-ghost:hover{background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary)}\n.km-btn-danger{background:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-bg-base);border-color:transparent}\n.km-btn-danger:hover{opacity:.9;background:var(--dsw-alias-state-error-primary)}\n.km-btn-small{padding:5px 8px;font-size:12px;border-radius:7px}\n.km-input{width:100%;box-sizing:border-box;padding:8px 10px;border:1px solid var(--dsw-alias-border-l1);border-radius:8px;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;outline:none}\n.km-input:focus{border-color:var(--dsw-alias-state-business-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--dsw-alias-state-business-primary) 18%,transparent)}\n.km-input:disabled{opacity:.6}\nselect.km-input{appearance:auto}\n.km-form{display:flex;flex-direction:column;gap:10px;padding:12px;border:1px solid var(--dsw-alias-border-l1);border-radius:9px;background:var(--dsw-alias-bg-layer-1)}\n.km-form-lead{display:flex;flex-direction:column;gap:2px}\n.km-form-title{font-weight:650;font-size:12.5px}\n.km-form-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.4fr);gap:10px}\n.km-field{display:flex;flex-direction:column;gap:5px;min-width:0}\n.km-field-wide{min-width:0}\n.km-field-label{font-size:11.5px;font-weight:550;color:var(--dsw-alias-label-secondary)}\n.km-field-hint{font-size:11px;color:var(--dsw-alias-label-secondary);line-height:1.45}\n.km-secret{position:relative;display:flex;align-items:center}\n.km-secret-input{padding-right:38px}\n.km-secret-toggle{position:absolute;right:4px;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:0;border-radius:6px;background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer}\n.km-secret-toggle:hover{background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary)}\n.km-form-actions{display:flex;justify-content:flex-end;gap:8px}\n.km-rename{display:flex;align-items:center;gap:4px;min-width:0;flex:1 1 auto;max-width:100%}\n.km-rename-input{flex:1 1 auto;width:auto;min-width:60px;padding:4px 7px;font-size:12.5px}\n.km-inline-error{padding:7px 9px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-error-primary) 35%,var(--dsw-alias-border-l1));border-radius:7px;background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 8%,transparent);color:var(--dsw-alias-state-error-primary);font-size:12px;word-break:break-word}\n.km-key-error{grid-column:1/-1;margin-top:-2px}\n.km-notice{display:flex;align-items:flex-start;gap:8px;padding:9px 10px;border:1px solid var(--dsw-alias-border-l1);border-radius:8px;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);font-size:12px}\n.km-notice-icon{flex:0 0 auto;margin-top:1px}\n.km-notice-warn{border-color:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 32%,var(--dsw-alias-border-l1));background:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 7%,transparent)}\n.km-notice-error{border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 32%,var(--dsw-alias-border-l1));background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 7%,transparent)}\n.km-notice-body{display:flex;flex-direction:column;gap:2px;min-width:0}\n.km-notice-title{color:var(--dsw-alias-label-primary);font-weight:600;font-size:12px}\n.km-notice-text{line-height:1.5}\n.km-notice-action{flex:0 0 auto}\n.km-empty-keys{padding:12px;border:1px dashed var(--dsw-alias-border-l2);border-radius:8px;color:var(--dsw-alias-label-secondary);font-size:12px}\n.km-empty{display:flex;align-items:center;gap:8px;padding:14px;border:1px dashed var(--dsw-alias-border-l2);border-radius:10px;color:var(--dsw-alias-label-secondary);font-size:12.5px}\n.km-provider-foot{display:flex;justify-content:space-between;gap:10px;align-items:center;margin-top:10px;padding-top:9px;border-top:1px dashed var(--dsw-alias-border-l1);font-size:11px;min-height:15px}\n.km-settings{padding:14px}\n.km-settings-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:12px}\n.km-settings-title{font-size:14px;font-weight:650;margin:0 0 3px}\n.km-settings-intro{margin:0;color:var(--dsw-alias-label-secondary);font-size:12px}\n.km-settings-icon{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:9px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-brand-primary);border:1px solid var(--dsw-alias-border-l1)}\n.km-settings-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr) minmax(0,1fr);gap:12px;align-items:start}\n.km-field-note{grid-column:1/-1}\n.km-policy-note{padding:9px 10px;border:1px solid var(--dsw-alias-border-l1);border-radius:8px;background:var(--dsw-alias-bg-layer-2)}\n.km-policy-title{display:flex;align-items:center;gap:6px;font-size:11.5px;font-weight:600;color:var(--dsw-alias-label-primary);margin-bottom:2px}\n.km-policy-note p{margin:0;font-size:11.5px;line-height:1.5}\n.km-settings-actions{display:flex;align-items:center;justify-content:flex-end;gap:10px;margin-top:12px}\n.km-saved{display:inline-flex;align-items:center;gap:4px;color:var(--dsw-alias-state-success-primary);font-size:11.5px}\n.km-banner{display:flex;align-items:flex-start;gap:8px;padding:9px 10px;border-radius:8px;margin:0 0 12px;font-size:12px;line-height:1.5;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1)}\n.km-banner-error{border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 32%,var(--dsw-alias-border-l1));background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 7%,transparent)}\n.km-banner-warn{border-color:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 32%,var(--dsw-alias-border-l1));background:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 7%,transparent)}\n.km-banner-text{flex:1;min-width:0;word-break:break-word}\n.km-banner-close{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border:0;border-radius:5px;background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer}\n.km-banner-close:hover{background:var(--dsw-alias-bg-layer-2)}\n.km-loading{display:flex;align-items:center;gap:8px;padding:20px 0;color:var(--dsw-alias-label-secondary);font-size:12.5px}\n.km-load-failure{display:flex;flex-direction:column;gap:10px;align-items:flex-start;padding:18px;border:1px dashed var(--dsw-alias-border-l2);border-radius:10px;color:var(--dsw-alias-label-secondary);font-size:12.5px}\n.km-empty-title{font-weight:600;color:var(--dsw-alias-label-primary)}\n.km-footer{display:flex;align-items:flex-start;gap:6px;padding-top:4px;color:var(--dsw-alias-label-secondary);font-size:11px;line-height:1.5}\n.km-muted{color:var(--dsw-alias-label-secondary)}\n.km-warn{color:var(--dsw-alias-state-warn-primary)}\n.km-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px}\n.km-truncate{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.km-spin{animation:km-spin 1s linear infinite}\n.km-models-note{display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin:8px 0 0;padding:7px 9px;border:1px solid color-mix(in srgb,var(--dsw-alias-brand-primary) 24%,var(--dsw-alias-border-l1));border-radius:7px;background:color-mix(in srgb,var(--dsw-alias-brand-primary) 6%,transparent);font-size:11.5px;color:var(--dsw-alias-label-primary)}\n.km-models-note-warn{border-color:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 30%,var(--dsw-alias-border-l1));background:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 7%,transparent)}\n.km-models-note-text{font-weight:600}\n.km-models-note-hint{color:var(--dsw-alias-label-secondary);font-weight:400}\n.km-modal-backdrop{position:fixed;inset:0;z-index:80;display:flex;align-items:center;justify-content:center;padding:24px;background:color-mix(in srgb,var(--dsw-alias-label-primary) 26%,transparent)}\n.km-modal{width:min(440px,100%);border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-bg-overlay);padding:16px;box-shadow:0 18px 48px color-mix(in srgb,var(--dsw-alias-label-primary) 20%,transparent)}\n.km-modal-title{font-weight:650;font-size:14px;margin-bottom:7px}\n.km-modal-body{color:var(--dsw-alias-label-secondary);font-size:12.5px}\n.km-modal-copy{margin:0;line-height:1.55}\n.km-modal-footer{display:flex;justify-content:flex-end;gap:8px;margin-top:16px}\n@keyframes km-spin{to{transform:rotate(360deg)}}\n@media(max-width:720px){\n .km-summary{grid-template-columns:repeat(2,minmax(0,1fr))}\n .km-key-row{grid-template-columns:minmax(0,1fr) 32px;gap:6px}\n .km-key-status,.km-key-last{grid-column:1;padding-left:0}\n .km-key-actions{grid-column:2;grid-row:1}\n .km-settings-grid{grid-template-columns:1fr}\n .km-form-grid{grid-template-columns:1fr}\n .km-provider-side .km-status{display:none}\n .km-embedded-head{flex-direction:column;gap:10px}\n .km-embedded-actions{padding-top:0}\n}\n";
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/** Browser-half domain and service contracts for the Keys Manager. */
|
|
2
|
+
import type * as React from 'react';
|
|
3
|
+
import type { KeyStatus, KeyView, ManagerSettings, ProviderStatus, ProviderView, StateView } from '../domain';
|
|
4
|
+
export type { KeyStatus, KeyView, ManagerSettings, ProviderStatus, ProviderView, StateView };
|
|
5
|
+
/** Locale dictionaries registered under the plugin namespace. */
|
|
6
|
+
export interface LocaleDicts {
|
|
7
|
+
zh: Record<string, string>;
|
|
8
|
+
en: Record<string, string>;
|
|
9
|
+
}
|
|
10
|
+
/** Successful or failed `keysManager/*` Remote answer. */
|
|
11
|
+
export type RpcResult = {
|
|
12
|
+
ok: true;
|
|
13
|
+
value: StateView;
|
|
14
|
+
} | {
|
|
15
|
+
ok: false;
|
|
16
|
+
error: {
|
|
17
|
+
message: string;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
/** One unary result surfaced by the client store. */
|
|
21
|
+
export type ActionOutcome = {
|
|
22
|
+
ok: true;
|
|
23
|
+
value: StateView;
|
|
24
|
+
} | {
|
|
25
|
+
ok: false;
|
|
26
|
+
error: string;
|
|
27
|
+
};
|
|
28
|
+
/** Immutable UI snapshot. */
|
|
29
|
+
export interface ClientSnapshot {
|
|
30
|
+
status: 'idle' | 'loading' | 'ready' | 'error';
|
|
31
|
+
state: StateView | null;
|
|
32
|
+
error: string | null;
|
|
33
|
+
busy: string | null;
|
|
34
|
+
now: number;
|
|
35
|
+
}
|
|
36
|
+
/** Store shared by the plugin-detail card and the Models badges. */
|
|
37
|
+
export interface ClientStore {
|
|
38
|
+
getSnapshot(): ClientSnapshot;
|
|
39
|
+
subscribe(listener: () => void): () => void;
|
|
40
|
+
load(options?: {
|
|
41
|
+
keepError?: boolean;
|
|
42
|
+
}): Promise<void>;
|
|
43
|
+
call(method: string, args: Record<string, unknown>): Promise<ActionOutcome>;
|
|
44
|
+
tick(): void;
|
|
45
|
+
dismissError(): void;
|
|
46
|
+
}
|
|
47
|
+
/** Locale snapshot exposed by the Client locale service. */
|
|
48
|
+
export interface LocaleSnapshot {
|
|
49
|
+
active: string;
|
|
50
|
+
locales: readonly unknown[];
|
|
51
|
+
revision: number;
|
|
52
|
+
}
|
|
53
|
+
/** Slot registration options, narrowed to the fields this plugin uses. */
|
|
54
|
+
export interface SlotRegistrationOptions {
|
|
55
|
+
name: string;
|
|
56
|
+
key?: string;
|
|
57
|
+
id?: string;
|
|
58
|
+
order?: number;
|
|
59
|
+
label?: () => string;
|
|
60
|
+
}
|
|
61
|
+
/** Services required by the browser half. */
|
|
62
|
+
export interface ClientContext {
|
|
63
|
+
connection: {
|
|
64
|
+
rpc: {
|
|
65
|
+
call(channel: string, endpoint: string, payload: {
|
|
66
|
+
args: Record<string, unknown>;
|
|
67
|
+
}): Promise<RpcResult>;
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
locale: {
|
|
71
|
+
register(ns: string, dicts: LocaleDicts): () => void;
|
|
72
|
+
bind(ns: string): (key: string, params?: Record<string, string | number>) => string;
|
|
73
|
+
subscribe(listener: () => void): () => void;
|
|
74
|
+
getSnapshot(): LocaleSnapshot;
|
|
75
|
+
};
|
|
76
|
+
slots: {
|
|
77
|
+
inject(key: string, callback: () => undefined | (() => void)): () => void;
|
|
78
|
+
register(options: SlotRegistrationOptions, component: React.ComponentType<any>): () => void;
|
|
79
|
+
};
|
|
80
|
+
on(name: string, listener: (...args: any[]) => void): () => void;
|
|
81
|
+
effect(effect: () => undefined | (() => void), label?: string): () => void;
|
|
82
|
+
}
|
|
83
|
+
/** Runtime value threaded through the generated React context. */
|
|
84
|
+
export interface Runtime {
|
|
85
|
+
ctx: ClientContext;
|
|
86
|
+
store: ClientStore;
|
|
87
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Keys Manager browser components, rendered from the plugin-detail card and
|
|
2
|
+
* the Models provider-card extension slot. */
|
|
3
|
+
import React from 'react';
|
|
4
|
+
declare function KeysManagerBody(): React.ReactElement;
|
|
5
|
+
interface KeysManagerCardProps {
|
|
6
|
+
view?: 'summary' | 'page';
|
|
7
|
+
form?: unknown;
|
|
8
|
+
}
|
|
9
|
+
declare function KeysManagerCard({ view }: KeysManagerCardProps): React.ReactElement | null;
|
|
10
|
+
interface ManagedProviderBadgeProps {
|
|
11
|
+
provider?: {
|
|
12
|
+
provider?: string;
|
|
13
|
+
};
|
|
14
|
+
view?: 'summary' | 'page';
|
|
15
|
+
}
|
|
16
|
+
declare function ManagedProviderBadge(props: ManagedProviderBadgeProps): React.ReactElement | null;
|
|
17
|
+
export { KeysManagerCard, ManagedProviderBadge, KeysManagerBody };
|
|
18
|
+
export type { KeysManagerCardProps, ManagedProviderBadgeProps };
|