dsh-llm-codebuddy-power 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +66 -0
  3. package/README.zh.md +66 -0
  4. package/cordis.patch.yml +32 -0
  5. package/lib/cli-login.js +2099 -0
  6. package/lib/client.js +2814 -0
  7. package/lib/index.js +3957 -0
  8. package/lib/types/adapter.d.ts +58 -0
  9. package/lib/types/atomic-file.d.ts +43 -0
  10. package/lib/types/auth-service.d.ts +195 -0
  11. package/lib/types/cli/login.d.ts +23 -0
  12. package/lib/types/client/AccountSwitcher.d.ts +53 -0
  13. package/lib/types/client/CodeBuddySection.d.ts +62 -0
  14. package/lib/types/client/ComposerControls.d.ts +29 -0
  15. package/lib/types/client/DrawToolCard.d.ts +24 -0
  16. package/lib/types/client/ModelPanel.d.ts +77 -0
  17. package/lib/types/client/TurnCreditPill.d.ts +33 -0
  18. package/lib/types/client/UsageIndicator.d.ts +21 -0
  19. package/lib/types/client/icons.d.ts +24 -0
  20. package/lib/types/client/index.d.ts +34 -0
  21. package/lib/types/client/locales.d.ts +90 -0
  22. package/lib/types/client/poll.d.ts +19 -0
  23. package/lib/types/client/store.d.ts +59 -0
  24. package/lib/types/client/wire.d.ts +147 -0
  25. package/lib/types/codebuddy.d.ts +187 -0
  26. package/lib/types/constants.d.ts +67 -0
  27. package/lib/types/credit-store.d.ts +25 -0
  28. package/lib/types/image-tool.d.ts +34 -0
  29. package/lib/types/index.d.ts +79 -0
  30. package/lib/types/login.d.ts +43 -0
  31. package/lib/types/model-enrich.d.ts +125 -0
  32. package/lib/types/prefs.d.ts +43 -0
  33. package/lib/types/rpc-route.d.ts +25 -0
  34. package/lib/types/selection.d.ts +35 -0
  35. package/lib/types/serialize.d.ts +37 -0
  36. package/lib/types/session-store.d.ts +63 -0
  37. package/lib/types/session.d.ts +415 -0
  38. package/lib/types/settings.d.ts +18 -0
  39. package/lib/types/sse.d.ts +22 -0
  40. package/lib/types/storage.d.ts +118 -0
  41. package/lib/types/translate.d.ts +61 -0
  42. package/lib/types/types.d.ts +345 -0
  43. package/lib/types/usage.d.ts +109 -0
  44. package/package.json +119 -0
@@ -0,0 +1,58 @@
1
+ /**
2
+ * `CodeBuddyAdapter`:针对 CodeBuddy 的 OpenAI 兼容聊天路由使用 fetch + SSE,
3
+ * 身份与模型目录则从 OAuth 会话解析。
4
+ *
5
+ * 这一区分很重要:聊天面兼容 OpenAI,而目录面并不兼容,因此模型信息取自 CodeBuddy
6
+ * 自己的 `/v3/config` 响应——每个模型的工具调用、推理、图像与尺寸事实都出自那里。
7
+ * 本类中不存在任何 API key;每个请求都由会话刷新的、浏览器签发的 bearer token 授权。
8
+ *
9
+ * @module dsh-llm-codebuddy-power/adapter
10
+ */
11
+ import { LlmAdapter } from '@deepseek-ai/dsh-llm';
12
+ import type { GenerateOptions, LlmModelInfo, LlmProviderInfo, LlmResolvedModelInfo, StreamChunk } from '@deepseek-ai/dsh-llm';
13
+ import type { AttachmentStore } from '@deepseek-ai/dsh-attachment';
14
+ import { DEFAULT_CONTEXT_WINDOW, DEFAULT_MAX_TOKENS } from './constants.ts';
15
+ import type { CodeBuddySession } from './session.ts';
16
+ import type { WireError } from './types.ts';
17
+ import type { ModelOverrides } from './model-enrich.ts';
18
+ /** 由注册插件解析、适配器直接采信的连接事实。 */
19
+ export interface CodeBuddyConnectionOptions {
20
+ /** 聊天 endpoint 的基地址;其后会追加 `/chat/completions`。 */
21
+ baseURL: string;
22
+ /** 目录未给出模型容量时使用的上下文容量。 */
23
+ defaultContextWindow: number;
24
+ /** 目录未给出模型上限时使用的单请求输出上限。 */
25
+ defaultMaxTokens: number;
26
+ /** 单次流读取尚未返回时,provider 允许的最大空闲时间。 */
27
+ streamIdleTimeoutMs: number;
28
+ }
29
+ /** 构造参数:会话,以及每次操作调用的连接 thunk。 */
30
+ export interface CodeBuddyAdapterOptions {
31
+ session: CodeBuddySession;
32
+ options: () => CodeBuddyConnectionOptions;
33
+ /** 解析持久化附件服务;缺失时拒绝图像输入。 */
34
+ resolveAttachments: () => AttachmentStore | undefined;
35
+ /** 已设置时,解析用户为单个模型设置的上限(上下文窗口 / 最大输出)。 */
36
+ resolveOverrides?: (modelId: string) => Promise<ModelOverrides | undefined>;
37
+ }
38
+ /**
39
+ * 把 HTTP 状态码映射为稳定的 harness 错误码。
40
+ * @param status - 非 2xx 的状态码。
41
+ * @param error - 可读取时,已解析的 provider 错误体。
42
+ * @returns 归一化后的错误码。
43
+ */
44
+ export declare function httpErrorCode(status: number, error?: WireError['error']): string;
45
+ /**
46
+ * CodeBuddy 适配器。单个实例服务于唯一的 `codebuddy` 路由,
47
+ * 以及该路由目录报告的全部模型。
48
+ */
49
+ export declare class CodeBuddyAdapter extends LlmAdapter {
50
+ private readonly config;
51
+ constructor(config: CodeBuddyAdapterOptions);
52
+ providerInfo(provider: string): LlmProviderInfo;
53
+ listModels(provider: string): Promise<readonly LlmModelInfo[]>;
54
+ resolveModel(provider: string, model: string, signal?: AbortSignal): Promise<LlmResolvedModelInfo>;
55
+ stream(options: GenerateOptions): AsyncIterable<StreamChunk>;
56
+ }
57
+ export { DEFAULT_CONTEXT_WINDOW, DEFAULT_MAX_TOKENS };
58
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1,43 @@
1
+ /**
2
+ * 插件自有 JSON 文件的写入底座:原子替换 + 按路径串行化。
3
+ *
4
+ * 三个存储(账号、会话选择、每轮积分)都是读-改-写的文件。原子替换让
5
+ * 残缺内容永远不会留在磁盘上被当成一份读不出的记录;按路径排队让并发写入
6
+ * 串行执行 —— 后一次读得到前一次的结果,而不是各自基于同一份旧内容覆盖对方。
7
+ * 集中在这里,使三个存储不会各自实现一遍,也不会各自漏掉队列。
8
+ *
9
+ * @module dsh-llm-codebuddy-power/atomic-file
10
+ */
11
+ /**
12
+ * 排队一次针对某文件的写:前一次写完成后才开始执行。
13
+ *
14
+ * 队尾保存的是已消化失败的 promise —— 它的拒绝无人 await,留着会变成未处理的
15
+ * rejection;调用方从返回的 promise 收到同一个失败。
16
+ * @param path - 被写的文件。
17
+ * @param write - 实际写入;在同一路径的写之间串行执行。
18
+ * @returns 本次写入的结果;失败时以该失败拒绝。
19
+ */
20
+ export declare function queueWrite(path: string, write: () => Promise<void>): Promise<void>;
21
+ /**
22
+ * 以原子替换写入一个文件,并在支持的文件系统上收紧为仅属主可读。
23
+ *
24
+ * 先写同目录下的临时文件再改名:改名在同一文件系统内是原子的,因此读到的
25
+ * 要么是旧内容要么是新内容,不会是写了一半的内容。
26
+ *
27
+ * 内容是调用方给的字符串而不是由本函数序列化:`JSON.stringify` 的默认输出是一个
28
+ * 字节的重复都没有的紧凑格式,可读性全靠调用方自己插入的换行 —— 需要控制"哪里换行"
29
+ * 的存储因此各自决定格式(见 `session-store.ts` 的逐轮一行)。
30
+ * @param path - 目标文件。
31
+ * @param content - 要写入的完整内容。
32
+ */
33
+ export declare function writeFileAtomic(path: string, content: string): Promise<void>;
34
+ /**
35
+ * 以原子替换写入一个 JSON 文件,缩进两格。
36
+ *
37
+ * 缩进是给需要肉眼排查的凭据文件用的(`storage.ts` 的 refresh token 与过期时间),
38
+ * 不是通用默认值:批量记录类文件改用 {@link writeFileAtomic} 自己排版。
39
+ * @param path - 目标文件。
40
+ * @param value - 要序列化的值。
41
+ */
42
+ export declare function writeJsonAtomic(path: string, value: unknown): Promise<void>;
43
+ //# sourceMappingURL=atomic-file.d.ts.map
@@ -0,0 +1,195 @@
1
+ /**
2
+ * 通过私有 RPC 通道暴露给 Web 客户端的宿主侧 OAuth 服务。
3
+ *
4
+ * 浏览器登录是长时操作(要等待用户完成登录),因此拆成两个 RPC endpoint:
5
+ * `startLogin` 生成握手并返回用户必须打开的 URL,`pollLogin` 检查该握手是否已完成;
6
+ * 一次完成的登录会**追加**一个账号,而不是取代已有的。`accounts`、`activate`、
7
+ * `setDefault`、`logout` 是设置页与会话账号按钮其余时间驱动的读写组合。
8
+ *
9
+ * @module dsh-llm-codebuddy-power/auth-service
10
+ */
11
+ import type { Context } from '@deepseek-ai/cordis';
12
+ import type { CodeBuddySession } from './session.ts';
13
+ import type { CodeBuddyAccountInfo } from './session.ts';
14
+ import type { EnrichedModelRow } from './model-enrich.ts';
15
+ /** 客户端调用认证服务所用的 RPC 通道。 */
16
+ export declare const CODEBUDDY_AUTH_CHANNEL = "/codebuddy";
17
+ /** `accounts` 返回给客户端的结构。 */
18
+ export interface CodeBuddyAccountsResult {
19
+ /** 已存账号,顺序与磁盘一致。 */
20
+ accounts: CodeBuddyAccountInfo[];
21
+ /** 用户显式指定的默认账号;未指定或缺省时缺省。 */
22
+ defaultUid?: string;
23
+ }
24
+ /** `startLogin` 返回给客户端的结构。 */
25
+ export interface CodeBuddyLoginStart {
26
+ /** 用户必须打开以完成登录的 URL。 */
27
+ authUrl: string;
28
+ /** 握手 id;客户端会把它回传给 `pollLogin`。 */
29
+ state: string;
30
+ }
31
+ /** `pollLogin` 返回给客户端的结构。 */
32
+ export interface CodeBuddyLoginPoll {
33
+ /** 握手是否已完成,且账号已持久化。 */
34
+ done: boolean;
35
+ /** 登录刚刚完成时的显示名称。 */
36
+ nickname?: string;
37
+ }
38
+ /** `sessionAccount` 返回给客户端的结构。 */
39
+ export interface CodeBuddySessionAccount {
40
+ /** 该会话此刻生效的账号 uid;一个账号也没有时缺省。 */
41
+ uid?: string;
42
+ }
43
+ /**
44
+ * 发给客户端的一个计量窗口,是 {@link UsageWindow} 的纯数据投影,
45
+ * 其中的可选字段可以安全省略。
46
+ */
47
+ export interface CodeBuddyUsageWindow {
48
+ name: string;
49
+ used?: number;
50
+ limit?: number;
51
+ resetsAt?: string;
52
+ }
53
+ /** 发给客户端的一个聚合额度池。 */
54
+ export interface CodeBuddyUsagePool {
55
+ used: number;
56
+ limit: number;
57
+ }
58
+ /** 赠送额度的汇总,以及其提示中最近到期的明细。 */
59
+ export interface CodeBuddyUsageGift extends CodeBuddyUsagePool {
60
+ /** 生效中的赠送窗口,按最早到期在前排序,最多 5 个。 */
61
+ soonest: CodeBuddyUsageWindow[];
62
+ }
63
+ /** `usage` 返回给客户端的结构。 */
64
+ export interface CodeBuddyUsageResult {
65
+ /** 该会话是否有可用账号;为 false 表示没有用量可显示。 */
66
+ loggedIn: boolean;
67
+ /**
68
+ * 首个计量窗口的重置时刻,与主池的数值显示在同一行提示里;平面未报告窗口
69
+ * 或该窗口未披露重置时刻时为 `undefined`。
70
+ */
71
+ primaryResetsAt?: string;
72
+ /** 可刷新的主额度池。 */
73
+ main?: CodeBuddyUsagePool;
74
+ /** 一次性的赠送额度池及其最近到期明细。 */
75
+ gift?: CodeBuddyUsageGift;
76
+ }
77
+ /** `creditOf` 返回给客户端的一条轮次记录。 */
78
+ export interface CodeBuddyTurnCreditResult {
79
+ credit: number;
80
+ /** 本轮扣分用过的账号,按首次使用排序;一轮里切换过账号时会有多个。 */
81
+ accounts: CodeBuddyTurnCreditAccount[];
82
+ }
83
+ /** `creditOf` 返回给客户端的一个账号。 */
84
+ export interface CodeBuddyTurnCreditAccount {
85
+ nickname: string;
86
+ /** uid 的显示前段;提示框只用于区分同名账号,不必给全量。 */
87
+ uidPrefix: string;
88
+ }
89
+ /**
90
+ * CodeBuddy 认证 RPC 服务。
91
+ *
92
+ * 握手由 `startLogin` 发起,由 `pollLogin` 轮询至完成,其账号由适配器的
93
+ * `CodeBuddySession` 在下一个请求中取用 → 因此通过 UI 完成的登录无需重启
94
+ * 即可到达运行中的 harness。`logout` 移除指定账号并使会话缓存失效。
95
+ */
96
+ export declare class CodeBuddyAuthService {
97
+ private readonly session?;
98
+ /** 按 state id 索引的进行中握手。 */
99
+ private readonly pending;
100
+ constructor(ctx: Context, session?: CodeBuddySession | undefined);
101
+ /** 把一次 RPC endpoint 调用路由到对应的处理器。 */
102
+ private dispatch;
103
+ /**
104
+ * 读取已存账号及其默认账号,不要求必须存在。
105
+ * @returns 账号集合;未存任何内容时为空列表。
106
+ */
107
+ accounts(): Promise<CodeBuddyAccountsResult>;
108
+ /**
109
+ * 发起一次浏览器登录握手。
110
+ * @returns 用户必须打开的 URL。
111
+ */
112
+ startLogin(): Promise<CodeBuddyLoginStart>;
113
+ /**
114
+ * 检查已发起的握手是否完成。
115
+ * @param state - 来自 `startLogin` 的握手 id。
116
+ * @returns 登录是否完成、账号是否已持久化。
117
+ */
118
+ pollLogin(state: string): Promise<CodeBuddyLoginPoll>;
119
+ /**
120
+ * 某会话此刻生效的账号。
121
+ * @param sessionId - dsh 会话身份;为空时按未选定处理。
122
+ * @returns 该会话的账号 uid;没有账号时缺省。
123
+ */
124
+ sessionAccount(sessionId: string): Promise<CodeBuddySessionAccount>;
125
+ /**
126
+ * 把某会话的账号切换为指定账号。
127
+ * @param sessionId - dsh 会话身份。
128
+ * @param uid - 目标账号 uid。
129
+ * @returns 该账号已存时为 true。
130
+ */
131
+ activate(sessionId: string, uid: string): Promise<boolean>;
132
+ /**
133
+ * 放弃一次进行中的登录握手。
134
+ *
135
+ * 中止底层的令牌轮询并丢弃该握手:用户点了取消之后,客户端不再轮询,而宿主也不该
136
+ * 继续占着一个十分钟的轮询循环。未知或已完成的 state 视作已经结束,返回 true ——
137
+ * 取消是幂等的收尾动作,没有"已经取消过"这种失败。
138
+ * @param state - 来自 `startLogin` 的握手 id。
139
+ * @returns 该握手是否已被放弃(未知 state 同样是 true)。
140
+ */
141
+ cancelLogin(state: string): boolean;
142
+ /**
143
+ * 指定或取消默认账号。
144
+ * @param uid - 默认账号 uid;`undefined` 表示取消默认账号。
145
+ * @returns 指定时该账号已存、或取消成功时为 true。
146
+ */
147
+ setDefault(uid: string | undefined): Promise<boolean>;
148
+ /**
149
+ * 移除若干账号。
150
+ * @param uids - 要移除的账号 uid。
151
+ */
152
+ logout(uids: readonly string[]): Promise<void>;
153
+ /**
154
+ * 按给定顺序重排账号。
155
+ *
156
+ * 顺序即展示顺序,也是没有默认账号、也没有手动切换记录时的兜底账号,因此这里真的
157
+ * 改变"用谁"。重排会让输入区控件组读到的账号集合顺序变化,故同样使会话缓存失效。
158
+ * @param uids - 目标顺序上的账号 uid。
159
+ */
160
+ reorder(uids: readonly string[]): Promise<void>;
161
+ /**
162
+ * 为界面读取某会话账号的 CodeBuddy 用量快照。
163
+ *
164
+ * 委托给会话完成:会话会在读取计量前解析刷新后的身份,且计量服务不可用时不会抛错。
165
+ * 没有账号时按 `loggedIn: false` 上报,让客户端隐藏该呈现,
166
+ * 而不是渲染出坏掉的进度条。
167
+ * @param sessionId - dsh 会话身份。
168
+ * @returns 用量投影;没有账号时返回未登录结构。
169
+ */
170
+ usage(sessionId: string): Promise<CodeBuddyUsageResult>;
171
+ /**
172
+ * 把一次握手推进到持久化的账号。
173
+ *
174
+ * 复用 `buildAccount`,使落盘结构与 CLI 登录完全一致。
175
+ * 任何失败都返回 `undefined`,让客户端的轮询得到 `done: false`,
176
+ * 从而可以从 `startLogin` 重试。
177
+ */
178
+ private runLogin;
179
+ /**
180
+ * 供客户端面板使用的增强版 CodeBuddy 目录:应用了促销/等级展示信息与覆盖配置的模型。
181
+ * @param sessionId - 用哪个会话的账号读目录;为空时用默认账号。
182
+ * @returns 增强结果;会话不可用或该账号没有目录时为空行。
183
+ */
184
+ enrichedModels(sessionId: string): Promise<{
185
+ models: EnrichedModelRow[];
186
+ }>;
187
+ /**
188
+ * 插入或更新(或清除)单个模型的用户覆盖配置,并持久化整张表。
189
+ * @param modelId - 模型 id。
190
+ * @param payload - `{ contextWindow?, maxOutputTokens? }`;显式缺省或非正数的字段
191
+ * 会清除对应的上限。
192
+ */
193
+ setOverride(modelId: string, payload: unknown): Promise<void>;
194
+ }
195
+ //# sourceMappingURL=auth-service.d.ts.map
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * `codebuddy-power`:通过浏览器登录 CodeBuddy,把账号追加到插件读取的账号列表,
4
+ * 并管理那份列表。
5
+ *
6
+ * 刻意作为独立入口而非 harness 内的提示:该流程需要浏览器和
7
+ * 人工,而运行中的 agent 不应为等待它而阻塞模型调用。已在运行
8
+ * 的 harness 会在下一次请求时取用该账号,无需重启。
9
+ *
10
+ * 用法:
11
+ * codebuddy-power 登录并追加账号
12
+ * codebuddy-power --status 列出全部账号与默认账号
13
+ * codebuddy-power --default <账号> 把某个账号设为默认
14
+ * codebuddy-power --logout <账号> 退出一个账号
15
+ * codebuddy-power --logout --all 退出全部账号
16
+ * codebuddy-power --no-open 只打印 URL,不打开浏览器
17
+ *
18
+ * `<账号>` 可以是 `--status` 列出的序号、账号 uid 或昵称。
19
+ *
20
+ * @module dsh-llm-codebuddy-power/cli/login
21
+ */
22
+ export {};
23
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1,53 @@
1
+ /**
2
+ * 对话框输入区里的 CodeBuddy 账号控件:一个额度圆环加一个账号切换按钮。
3
+ *
4
+ * 它注册在 `conversation.input.right`,与 CodeBuddy 模型按钮同处一个插槽元素、
5
+ * 排在其左侧。两者都按**当前会话**取数:圆环显示该会话此刻生效账号的用量
6
+ * (主额度与赠送额度合并成一个圆环,百分比按两者之和算),按钮显示该账号昵称的
7
+ * 缩写,点开在账号之间切换 —— 每个会话各选各的,不影响别的会话。
8
+ *
9
+ * **不挂 store**:本插槽是会话作用域,而设置页是 root 作用域,一个 store handle
10
+ * 只能绑一个作用域(挂两处会在加载时抛 "one handle, one scope")。账号集合因此在
11
+ * 这里由注入面按轮询间隔自取。
12
+ *
13
+ * 偏好不是自取的:它经注入面的 `hooks` 隔舱与设置页共享同一个活来源(用户设置
14
+ * 文档里的命名空间),因此「显示额度余量」开关翻动的那一帧圆环就跟着出现或消失,
15
+ * 不经过轮询。
16
+ *
17
+ * @module dsh-llm-codebuddy-power/client/AccountSwitcher
18
+ */
19
+ import type { ReactElement } from 'react';
20
+ import type { HostObservable, InjectFace, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
21
+ import type { CodeBuddyPrefs } from '../prefs.ts';
22
+ import type { CodeBuddyKey } from './locales.ts';
23
+ import type { CodeBuddyAccountView, CodeBuddyUsageResult } from './wire.ts';
24
+ /** 本控件按会话取数的注入面。 */
25
+ export interface AccountSwitcherInjected {
26
+ hooks: {
27
+ /** 三个界面偏好的当前值,与设置页同源。 */
28
+ prefs: HostObservable<CodeBuddyPrefs>;
29
+ };
30
+ /** 读取账号集合与默认账号。 */
31
+ fetchAccounts: () => Promise<{
32
+ accounts: CodeBuddyAccountView[];
33
+ defaultUid: string | null;
34
+ } | null>;
35
+ /** 读取该会话此刻生效的账号 uid;没有账号时为 null。 */
36
+ fetchSessionAccount: () => Promise<string | null>;
37
+ /** 把该会话切换到指定账号;该账号已存时解析为 true。 */
38
+ activate: (uid: string) => Promise<boolean>;
39
+ /** 读取该会话生效账号的用量;没有账号或计量不可用时为 null。 */
40
+ fetchUsage: () => Promise<CodeBuddyUsageResult | null>;
41
+ }
42
+ /** 插槽 runtime 份额 + locale + 注入 face。 */
43
+ export type AccountSwitcherProps = PropsRuntime<'conversation.input.right'> & {
44
+ t: (key: CodeBuddyKey, params?: Record<string, unknown>) => string;
45
+ } & InjectFace<AccountSwitcherInjected>;
46
+ /**
47
+ * 会话账号控件:额度圆环(可选)+ 账号切换按钮。
48
+ * @param props - 带注入 face 的插槽 props。
49
+ * @returns 控件元素;一个账号都没有时为 null。
50
+ */
51
+ export declare function AccountSwitcher(props: AccountSwitcherProps): ReactElement | null;
52
+ export type { AccountSwitcherProps as CodeBuddyAccountSwitcherProps };
53
+ //# sourceMappingURL=AccountSwitcher.d.ts.map
@@ -0,0 +1,62 @@
1
+ /**
2
+ * CodeBuddy 设置分区:多账号登录页。
3
+ *
4
+ * 展示全部已登录账号(每个账号一个徽章),在此发起浏览器登录以**追加**账号、
5
+ * 退出单个或选中的多个账号、指定或取消默认账号;下方是两种登录状态下都渲染的
6
+ * 界面偏好行。退出是破坏性操作(会删除磁盘上的凭据),因此单个与批量都先弹确认框。
7
+ * 弹窗可见性由 shell 拥有,故此处不需要关闭控件。
8
+ */
9
+ import type { ReactElement } from 'react';
10
+ import type { HostObservable, InjectFace, PropsLocale, PropsRuntime, PropsStore } from '@deepseek-ai/dsh-client-ui-slots';
11
+ import { createCodeBuddyStore } from './store.ts';
12
+ import type { CodeBuddyPrefs } from '../prefs.ts';
13
+ /**
14
+ * 设置分区与对话内账号控件共享的、经 RPC 支撑的业务面。每个回调都经 store action
15
+ * 写入;组件自身不接触 wire。
16
+ *
17
+ * 界面偏好走 `hooks` 隔舱:它与对话输入区的控件组是同一份活来源(用户设置文档里
18
+ * 的命名空间),写入经 `setPref`。
19
+ */
20
+ export interface CodeBuddySectionInjected {
21
+ hooks: {
22
+ /** 三个界面偏好的当前值,与对话输入区的控件组同源。 */
23
+ prefs: HostObservable<CodeBuddyPrefs>;
24
+ };
25
+ /** 重新读取账号集合与默认账号,并离开加载阶段。 */
26
+ refreshAccounts: () => Promise<void>;
27
+ /** 发起浏览器登录握手(在新标签页打开鉴权 URL);完成后账号被追加到列表。 */
28
+ startLogin: () => Promise<void>;
29
+ /**
30
+ * 发起一次登录握手并把鉴权 URL 复制到剪贴板(不打开浏览器),用于在别的浏览器或
31
+ * 机器上完成登录。失败时会发布一条页面级错误。
32
+ * @returns 链接是否已复制到剪贴板。
33
+ */
34
+ copyLoginLink: () => Promise<boolean>;
35
+ /**
36
+ * 放弃一次进行中的登录握手,并把界面从“登录中”收回到可再次发起的状态。
37
+ * @returns 是否确已放弃;未知或已完成的握手同样返回 true(取消是幂等的)。
38
+ */
39
+ cancelLogin: (state: string) => Promise<boolean>;
40
+ /** 按 state id 轮询一次握手;账号持久化后解析为 true。 */
41
+ pollLogin: (state: string) => Promise<boolean>;
42
+ /** 退出若干账号。 */
43
+ logoutAccounts: (uids: string[]) => Promise<void>;
44
+ /**
45
+ * 按给定顺序重排账号。顺序即展示顺序,并决定没有默认账号时用谁。
46
+ * @param uids - 目标顺序上的全部账号 uid。
47
+ */
48
+ reorderAccounts: (uids: string[]) => Promise<void>;
49
+ /** 指定默认账号;`null` 表示取消默认账号。 */
50
+ setDefault: (uid: string | null) => Promise<void>;
51
+ /** 写入一个界面偏好字段;该写入持久化到用户设置文档。 */
52
+ setPref: (field: keyof CodeBuddyPrefs, value: boolean | number) => void;
53
+ }
54
+ /** 完整组件 props:runtime 份额 + store 份额 + locale seat + inject face。 */
55
+ export type CodeBuddySectionProps = PropsRuntime<'settings.section'> & PropsStore<ReturnType<typeof createCodeBuddyStore>> & PropsLocale<'settings.codebuddy'> & InjectFace<CodeBuddySectionInjected>;
56
+ /**
57
+ * CodeBuddy 设置分区。
58
+ * @param props - 组合后的 slot props。
59
+ * @returns 分区的元素树。
60
+ */
61
+ export declare function CodeBuddySection(props: CodeBuddySectionProps): ReactElement;
62
+ //# sourceMappingURL=CodeBuddySection.d.ts.map
@@ -0,0 +1,29 @@
1
+ /**
2
+ * 对话框输入区里的 CodeBuddy 控件组:额度圆环、账号切换按钮与模型面板的 logo 按钮。
3
+ *
4
+ * 三者注册为 `conversation.input.right` 的**同一个条目**,因此处在同一个容器元素里。
5
+ * 分成两个条目时它们只是插槽 owner 容器下的两个兄弟元素,各自带自己的根元素,中间
6
+ * 还隔着该容器的间距 —— 读起来像两组互不相干的控件,而它们其实是同桌的三个按钮。
7
+ *
8
+ * @module dsh-llm-codebuddy-power/client/ComposerControls
9
+ */
10
+ import type { ReactElement } from 'react';
11
+ import type { InjectFace, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
12
+ import type { AccountSwitcherInjected } from './AccountSwitcher.tsx';
13
+ import type { ModelPanelInjected } from './ModelPanel.tsx';
14
+ import type { CodeBuddyKey } from './locales.ts';
15
+ /** 插槽 runtime 份额 + locale + 两个子控件的注入面。 */
16
+ export type ComposerControlsProps = PropsRuntime<'conversation.input.right'> & {
17
+ t: (key: CodeBuddyKey, params?: Record<string, unknown>) => string;
18
+ } & InjectFace<AccountSwitcherInjected & ModelPanelInjected>;
19
+ /**
20
+ * 把额度圆环、账号切换按钮与模型面板拼进同一个容器。
21
+ *
22
+ * 两个子控件各自接受 runtime 份额与自己的注入成员,因此整份 props 原样透传即可:
23
+ * 它们看到的正是自己声明的那部分。
24
+ * @param props - 组合后的 slot props。
25
+ * @returns 控件组元素。
26
+ */
27
+ export declare function ComposerControls(props: ComposerControlsProps): ReactElement;
28
+ export type { ComposerControlsProps as CodeBuddyComposerControlsProps };
29
+ //# sourceMappingURL=ComposerControls.d.ts.map
@@ -0,0 +1,24 @@
1
+ /**
2
+ * codebuddy-draw 工具的浏览器卡片:按已结算工具结果 content 里的标准
3
+ * ImageBlock,经系统附件通道(loadImage → uiConversation.imageUrl →
4
+ * session.readAttachment)读取图片并在对话中内联展示,图下方标注提示词
5
+ * 与实际扣分。重启后图片仍可读(附件持久化于磁盘,读经 host 鉴权通道)。
6
+ *
7
+ * @module dsh-llm-codebuddy-power/client/DrawToolCard
8
+ */
9
+ import { type ReactElement } from 'react';
10
+ import type { ImageAttachmentRef } from '@deepseek-ai/dsh-attachment';
11
+ import type { PropsLocale } from '@deepseek-ai/dsh-client-ui-slots';
12
+ import type { ToolCallViewProps } from '@deepseek-ai/dsh-client-ui-tool/client';
13
+ /** 组件 props:标准 toolview 份额 + locale seat + 注册时 inject face 注入的 loadImage。 */
14
+ type DrawToolCardProps = ToolCallViewProps & PropsLocale<'settings.codebuddy'> & {
15
+ loadImage: ((attachment: ImageAttachmentRef) => Promise<string>) | undefined;
16
+ };
17
+ /**
18
+ * codebuddy-draw 的 keyed toolview 组件。运行中的调用显示占位;已结算
19
+ * 结果按 content 里的标准 ImageBlock 经 loadImage 渲染图片,meta 缺失时
20
+ * (如无卡片客户端回放)返回空。
21
+ */
22
+ export declare function DrawToolCard(props: DrawToolCardProps): ReactElement | null;
23
+ export {};
24
+ //# sourceMappingURL=DrawToolCard.d.ts.map
@@ -0,0 +1,77 @@
1
+ /**
2
+ * CodeBuddy 模型能力面板:官方模型选择器(conversation.input.right)旁边的
3
+ * 一个按钮,点击后打开仅包含 CodeBuddy 模型的列表,其中的模型带有促销/档位
4
+ * 信息。悬停某一行会显示提示框,内含模型信息,以及就地覆盖上下文窗口和最大
5
+ * 输出 token 数的输入项;两者都通过宿主覆盖存储按模型持久化,并传给
6
+ * resolveModel,由 dsh 依据它们管理上下文与输出上限。
7
+ *
8
+ * 与上游项目不同,本面板不会遮蔽官方的 conversation.input.model 座位——
9
+ * 选择仍然流经共享的 ModelDirectory,因此官方座位、/model 弹窗和本面板保持
10
+ * 同步。
11
+ *
12
+ * @module dsh-llm-codebuddy-power/client/ModelPanel
13
+ */
14
+ import type { ReactElement } from 'react';
15
+ import type { HostObservable, InjectFace, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
16
+ import type { CodeBuddyKey } from './locales.ts';
17
+ import type { CodeBuddyModelRow, CodeBuddyModelOverrides } from './wire.ts';
18
+ /** 本面板读取的共享模型目录快照的最小投影。 */
19
+ export interface CodeBuddyDirectoryState {
20
+ current: {
21
+ provider: string;
22
+ model: string;
23
+ reasoningEffort?: string;
24
+ } | null;
25
+ groups: readonly {
26
+ id: string;
27
+ name: string;
28
+ models: readonly {
29
+ id: string;
30
+ name: string;
31
+ /**
32
+ * 该模型公布的思考等级。来自共享目录而非本插件的富化 RPC:harness 组装目录
33
+ * 时会对每个模型额外调一次 `resolveModelInfo` 取推理元数据,那份数据只存在
34
+ * 于目录快照里,富化行没有它。
35
+ */
36
+ reasoning?: {
37
+ efforts: readonly {
38
+ id: string;
39
+ name: string;
40
+ }[];
41
+ defaultEffort?: string;
42
+ };
43
+ }[];
44
+ }[];
45
+ status: 'idle' | 'loading' | 'selecting' | 'ready' | 'error';
46
+ }
47
+ /** 注入侧:共享模型目录 + 本插件的富化 RPC。 */
48
+ export interface ModelPanelInjected {
49
+ hooks: {
50
+ /** 会话共享的模型目录快照(与官方座位是同一个存储)。 */
51
+ directory: HostObservable<CodeBuddyDirectoryState>;
52
+ };
53
+ /** 确保共享目录已加载。 */
54
+ load: () => void;
55
+ /** 提交一次 provider/model 选择(写回共享目录)。 */
56
+ select: (selection: {
57
+ provider: string;
58
+ model: string;
59
+ reasoningEffort?: string;
60
+ }) => Promise<boolean>;
61
+ /** 获取富化后的 CodeBuddy 模型行。 */
62
+ fetchModels: () => Promise<CodeBuddyModelRow[]>;
63
+ /** 持久化某个模型的覆盖值。 */
64
+ saveOverrides: (modelId: string, overrides: CodeBuddyModelOverrides) => Promise<void>;
65
+ }
66
+ /** 插槽 owner props + locale + 注入 face。 */
67
+ export type ModelPanelProps = PropsRuntime<'conversation.input.right'> & {
68
+ t: (key: CodeBuddyKey, params?: Record<string, unknown>) => string;
69
+ } & InjectFace<ModelPanelInjected>;
70
+ /**
71
+ * CodeBuddy 模型面板的触发按钮 + 弹出层。
72
+ * @param props - 带注入 face 的插槽 props。
73
+ * @returns 触发按钮、打开时的面板,以及行的提示框。
74
+ */
75
+ export declare function ModelPanel(props: ModelPanelProps): ReactElement | null;
76
+ export type { ModelPanelProps as CodeBuddyModelPanelProps };
77
+ //# sourceMappingURL=ModelPanel.d.ts.map
@@ -0,0 +1,33 @@
1
+ /**
2
+ * codebuddy 每轮积分的按钮 pill,插在官方用量/耗时 pill 同一行的
3
+ * `conversation.chat.assistant-actions` seat(copy/branch 之间)。
4
+ *
5
+ * owner 只给 durable `messageId`,轮号由 `useChat` 快照里匹配的 assistant
6
+ * 节点反查(`AssistantMessageNode.turn`);再经注入的 RPC 查该轮积分,有记录
7
+ * 则渲染,无记录(非 CodeBuddy 轮)渲染为空。与官方 `TurnUsagePanel` 同构:
8
+ * 图标 + 文字标签,点击无详情面板(仅展示一条合计)。
9
+ *
10
+ * 悬停提示附上本轮用过的账号:账号在扣分那一刻随记录写入(见 host 的
11
+ * `recordCredit`),不是悬停时现查 —— 一轮里用户可以切换账号,现查会把整轮
12
+ * 说成最后那个账号。
13
+ *
14
+ * @module dsh-llm-codebuddy-power/client/TurnCreditPill
15
+ */
16
+ import type { ReactElement } from 'react';
17
+ import type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
18
+ import type { AssistantActionOwnerProps } from '@deepseek-ai/dsh-client-ui-chat/client';
19
+ import type { CodeBuddyTurnCreditRecord } from './wire.ts';
20
+ /** 注册侧提供的 credit 查询 face。 */
21
+ export interface TurnCreditInjected {
22
+ /** 查询某会话某一轮的积分记录(无则 undefined)。 */
23
+ creditOf: (sessionId: string, turn: number) => Promise<CodeBuddyTurnCreditRecord | undefined>;
24
+ }
25
+ /** 组件 props:assistant-actions owner 的 messageId + 标准 session 份额 + locale + inject face。 */
26
+ export type TurnCreditPillProps = Pick<AssistantActionOwnerProps, 'messageId'> & PropsRuntime<'conversation.chat.assistant-actions'> & PropsLocale<'settings.codebuddy'> & TurnCreditInjected;
27
+ /**
28
+ * 每轮积分 pill。messageId 反查轮号后查该轮记录;无记录渲染为空(未用
29
+ * CodeBuddy 模型即一轮 0 分也渲染,有记录即证明用了 CodeBuddy)。只显示
30
+ * 积分,模型由 dsh 用量自带;悬停给出本轮用过的账号。
31
+ */
32
+ export declare function TurnCreditPill(props: TurnCreditPillProps): ReactElement | null;
33
+ //# sourceMappingURL=TurnCreditPill.d.ts.map
@@ -0,0 +1,21 @@
1
+ /**
2
+ * 渲染在侧边栏底部 Settings 触发项上方的用量指示器。
3
+ *
4
+ * 宽列在赠送剩余额度的纯文本行上方显示主池的进度条(可续期额度 —— 自定义配额
5
+ * 上限与危险阈值仅作用于该进度条);赠送行的 tooltip 列出五个最早过期的有效赠送
6
+ * 窗口及其剩余/总量数值。未登录的账号、计量服务故障或空池都不渲染任何内容 ——
7
+ * 该提示纯属附加。窄栏列为主池保留单个圆环,其下是赠送剩余的裸数值。
8
+ */
9
+ import type { ReactElement } from 'react';
10
+ import type { PropsLocale, PropsRuntime, PropsStore } from '@deepseek-ai/dsh-client-ui-slots';
11
+ import { createCodeBuddyStore } from './store.ts';
12
+ import type { CodeBuddySectionInjected } from './CodeBuddySection.tsx';
13
+ /** 完整组件 props:footer-action 运行时份额 + store + locale + 注入 face。 */
14
+ export type CodeBuddyUsageIndicatorProps = PropsRuntime<'sidebar.footer.action'> & PropsStore<ReturnType<typeof createCodeBuddyStore>> & PropsLocale<'settings.codebuddy'> & CodeBuddySectionInjected;
15
+ /**
16
+ * 两条用量进度条(宽列)或主池圆环(窄栏),仅在存在可用池时渲染。
17
+ * @param props - 组合后的 slot props。
18
+ * @returns 指示器元素;无内容显示时为 null。
19
+ */
20
+ export declare function UsageIndicator(props: CodeBuddyUsageIndicatorProps): ReactElement | null;
21
+ //# sourceMappingURL=UsageIndicator.d.ts.map
@@ -0,0 +1,24 @@
1
+ /**
2
+ * 以行内图标组件形式给出的 CodeBuddy 品牌 logo。
3
+ *
4
+ * dsh 客户端栈把图标按代码渲染(ui-primitives 的图标是行内 SVG)而非图片资源,
5
+ * 故插件 logo 在此内联。源图形是 40×40 的品牌标识(紫色圆角方块 + 白色字形);
6
+ * 组件经标准 IconProps 的 size 缩放它。
7
+ *
8
+ * @module dsh-llm-codebuddy-power/client/icons
9
+ */
10
+ import type { ReactElement } from 'react';
11
+ /** 行内图标的通用尺寸。 */
12
+ export interface IconProps {
13
+ /** 边长,单位 px;默认 16。 */
14
+ size?: number;
15
+ /** 可选地拼接到 svg 上的 class(无默认值)。 */
16
+ className?: string;
17
+ }
18
+ /**
19
+ * CodeBuddy 徽标图形。
20
+ * @param props - 尺寸与 class。
21
+ * @returns 行内 SVG。
22
+ */
23
+ export declare function CodeBuddyLogo({ size, className }: IconProps): ReactElement;
24
+ //# sourceMappingURL=icons.d.ts.map