@eddyskywalker/dsh-chatgpt-subscription 0.32.0 → 0.33.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 (79) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +49 -1
  3. package/lib/client.js +3535 -1191
  4. package/lib/client.js.map +1 -1
  5. package/lib/index.js +7225 -2833
  6. package/lib/types/client/hub/brand-icons.d.ts +17 -1
  7. package/lib/types/client/hub/brand-icons.d.ts.map +1 -1
  8. package/lib/types/client/hub/hub-styles.d.ts.map +1 -1
  9. package/lib/types/client/hub/providers.d.ts.map +1 -1
  10. package/lib/types/client/index.d.ts +2 -0
  11. package/lib/types/client/index.d.ts.map +1 -1
  12. package/lib/types/client/minimax-code/VideoFormDialog.d.ts +46 -50
  13. package/lib/types/client/minimax-code/VideoFormDialog.d.ts.map +1 -1
  14. package/lib/types/client/minimax-code/locales.d.ts +80 -20
  15. package/lib/types/client/minimax-code/locales.d.ts.map +1 -1
  16. package/lib/types/client/minimax-code/styles.d.ts.map +1 -1
  17. package/lib/types/client/minimax-code/video-command-host.d.ts +17 -11
  18. package/lib/types/client/minimax-code/video-command-host.d.ts.map +1 -1
  19. package/lib/types/client/minimax-code/video-command-icon.d.ts +38 -0
  20. package/lib/types/client/minimax-code/video-command-icon.d.ts.map +1 -0
  21. package/lib/types/client/minimax-code/video-command.d.ts +53 -59
  22. package/lib/types/client/minimax-code/video-command.d.ts.map +1 -1
  23. package/lib/types/client/minimax-code/video-media-dropzone.d.ts +57 -0
  24. package/lib/types/client/minimax-code/video-media-dropzone.d.ts.map +1 -0
  25. package/lib/types/client/minimax-code/video-media-input.d.ts +173 -0
  26. package/lib/types/client/minimax-code/video-media-input.d.ts.map +1 -0
  27. package/lib/types/client/minimax-code/video-presets.d.ts +67 -0
  28. package/lib/types/client/minimax-code/video-presets.d.ts.map +1 -0
  29. package/lib/types/client/minimax-code/video-workspace.d.ts +41 -0
  30. package/lib/types/client/minimax-code/video-workspace.d.ts.map +1 -0
  31. package/lib/types/client/qoder/QoderComposerQuota.d.ts +41 -0
  32. package/lib/types/client/qoder/QoderComposerQuota.d.ts.map +1 -0
  33. package/lib/types/client/qoder/QoderSection.d.ts +26 -0
  34. package/lib/types/client/qoder/QoderSection.d.ts.map +1 -0
  35. package/lib/types/client/qoder/api.d.ts +4 -0
  36. package/lib/types/client/qoder/api.d.ts.map +1 -0
  37. package/lib/types/client/qoder/locales.d.ts +310 -0
  38. package/lib/types/client/qoder/locales.d.ts.map +1 -0
  39. package/lib/types/client/qoder/styles.d.ts +16 -0
  40. package/lib/types/client/qoder/styles.d.ts.map +1 -0
  41. package/lib/types/client/qoder/useQoderSection.d.ts +97 -0
  42. package/lib/types/client/qoder/useQoderSection.d.ts.map +1 -0
  43. package/lib/types/host/common/model-request-control.d.ts +1 -1
  44. package/lib/types/host/common/model-request-control.d.ts.map +1 -1
  45. package/lib/types/host/common/request-diagnostics.d.ts +1 -1
  46. package/lib/types/host/common/request-diagnostics.d.ts.map +1 -1
  47. package/lib/types/host/kimi-code/adapter.d.ts +3 -1
  48. package/lib/types/host/kimi-code/adapter.d.ts.map +1 -1
  49. package/lib/types/host/kimi-code/mapper.d.ts.map +1 -1
  50. package/lib/types/host/qoder/account-pool.d.ts +137 -0
  51. package/lib/types/host/qoder/account-pool.d.ts.map +1 -0
  52. package/lib/types/host/qoder/adapter.d.ts +134 -0
  53. package/lib/types/host/qoder/adapter.d.ts.map +1 -0
  54. package/lib/types/host/qoder/adopt.d.ts +146 -0
  55. package/lib/types/host/qoder/adopt.d.ts.map +1 -0
  56. package/lib/types/host/qoder/client.d.ts +189 -0
  57. package/lib/types/host/qoder/client.d.ts.map +1 -0
  58. package/lib/types/host/qoder/cosy.d.ts +173 -0
  59. package/lib/types/host/qoder/cosy.d.ts.map +1 -0
  60. package/lib/types/host/qoder/mapper.d.ts +235 -0
  61. package/lib/types/host/qoder/mapper.d.ts.map +1 -0
  62. package/lib/types/host/qoder/model-catalog.d.ts +185 -0
  63. package/lib/types/host/qoder/model-catalog.d.ts.map +1 -0
  64. package/lib/types/host/qoder/oauth.d.ts +134 -0
  65. package/lib/types/host/qoder/oauth.d.ts.map +1 -0
  66. package/lib/types/host/qoder/routes.d.ts +96 -0
  67. package/lib/types/host/qoder/routes.d.ts.map +1 -0
  68. package/lib/types/host/qoder/token-store.d.ts +231 -0
  69. package/lib/types/host/qoder/token-store.d.ts.map +1 -0
  70. package/lib/types/host/qoder/types.d.ts +257 -0
  71. package/lib/types/host/qoder/types.d.ts.map +1 -0
  72. package/lib/types/host/workbuddy/adapter.d.ts.map +1 -1
  73. package/lib/types/host/workbuddy/mapper.d.ts +1 -0
  74. package/lib/types/host/workbuddy/mapper.d.ts.map +1 -1
  75. package/lib/types/index.d.ts +5 -0
  76. package/lib/types/index.d.ts.map +1 -1
  77. package/lib/types/shared/qoder-contracts.d.ts +293 -0
  78. package/lib/types/shared/qoder-contracts.d.ts.map +1 -0
  79. package/package.json +1 -1
@@ -1,57 +1,43 @@
1
1
  /**
2
- * `/video` 命令:让用户**看见**视频工具有哪些参数,再把选好的参数填进输入框。
2
+ * `/video` 命令:一个入口,直接打开参数面板。
3
3
  *
4
- * ## 形态:popupSelect 作为入口,自建弹窗作为表单
4
+ * ## 形态:action,而不是 popupSelect
5
5
  *
6
- * 视频工具(`minimax_generate_video` / `minimax_understand_video`)是**模型自主
7
- * 调用**的,用户唯一的入口是自然语言。这带来两个问题:用户不知道有哪些参数,
8
- * 而且这些参数有联动规则(首帧→比例被强制成 `adaptive`、纯文本→`adaptive` 不
9
- * 可用)。
6
+ * 这里曾经是两级——popupSelect 列几条预设档,选中后把一段模板写进输入框,
7
+ * 「自定义…」那一行才打开面板。两个问题:
10
8
  *
11
- * 宿主给了两种命令 UI(`packages/client/ui-commands/src/client/contract.ts`):
9
+ * 1. **模板会占用输入框**。用户点了「H3 · 4 秒 · 768P」,输入框里立刻出现一整段
10
+ * `用 minimax_generate_video 生成视频:prompt=(在这里写画面描述)…`,他还得
11
+ * 回到那段话里找哪一处该改。命令的职责是**帮他配参数**,不是替他起草消息。
12
+ * 2. **档位在面板里本来就有**。面板顶部现在就是一排档位胶囊,先弹一次列表等于
13
+ * 让同一件事发生两遍。
12
14
  *
13
- * - `PopupSelectSpec`(`:64-75`):只有 `options()` + `onSelect()`,**单选**;
14
- * - `ActionSpec`(`:82-89`):`run(session)`,契约明写它「不提交任何东西」。
15
+ * 所以现在只有一个动作:打开面板。面板自己负责档位、参数与描述,用户点「填入
16
+ * 输入框」之后才产生文本——而且那段文本是把描述与参数压成一条请求的**成品**,
17
+ * 不是留了占位符的模板。
15
18
  *
16
- * 单选的 popupSelect 装不下「提示词 + 模型 + 比例 + 时长 + 分辨率 + 四类参考
17
- * 文件 + 水印」,所以这里是**两级**:popupSelect 列出几条预设档,「自定义…」那
18
- * 一行打开 `VideoFormDialog`。预设档没有覆盖的定制组合因此仍然可达,而最常见
19
- * 的几种是一键的。
19
+ * ## 为什么不是「/video 后面直接写描述」
20
20
  *
21
- * ## 填进输入框,而不是直接发送
22
- *
23
- * `ActionSpec` 不能提交,这是宿主的限制;但即使能提交,**直接发起一次计费生成
24
- * 也仍然是错的**:用户看不到自己填的参数被联动规则改写成了什么。所以走
25
- * `SessionInput.setDraft`,把参数拼成一句话放进输入框,用户看一眼再发送。
21
+ * 宿主的命令解析只在**裸命令**时把一行交给客户端贡献:`/video 描述…` 这一行
22
+ * 已经带了参数,`ui-commands` 会把它当成普通消息(`service.ts` 的
23
+ * `matchEnter`:`if (!bare) return undefined`)。所以「像 skill 一样接续输入」
24
+ * 在这个宿主版本里做不到;面板把这件事补上:**输入框里已有的文字会被当成画面
25
+ * 描述带进来**,效果接近「先写一句话,再叫面板」。
26
26
  *
27
27
  * ## `available` 怎么判「这条会话在 minimax-code 上」
28
28
  *
29
- * `ClientSessionContext` 只有 `sessionId`(`ui-input-trigger/src/types.ts:29`),
30
- * 没有 provider。路由要从 `ctx.sessions` 上按 id 取:
31
- *
32
- * ```ts
33
- * ctx.sessions.binding(id)?.session.projections.faceOf('modelSelection').getSnapshot()
34
- * ```
35
- *
36
- * 这是宿主自己读当前模型的方式(`ui-conversation/src/client/input/hub.ts:104-113`
37
- * 的 `submissionState`),投影值形如 `{ next?, lastUsed? }`,每项带
38
- * `{ provider, model, reasoningEffort? }`。
39
- *
40
- * **任何一步拿不到就返回 false,绝不抛错**:`available` 在每次打开斜杠菜单时都
41
- * 会被调用,它抛一次就会让整个菜单塌掉;而一个刚建好的会话、或宿主还没回落
42
- * 投影时,这些读取本来就会是空的。
29
+ * `ClientSessionContext` 只有 `sessionId`,没有 provider。路由要从 `ctx.sessions`
30
+ * 上按 id 取投影。**任何一步拿不到就返回 false,绝不抛错**:`available` 在每次
31
+ * 打开斜杠菜单时都会被调用,它抛一次就会让整个菜单塌掉。
43
32
  *
44
33
  * @module @eddyskywalker/dsh-chatgpt-subscription/client/minimax-code/video-command
45
34
  */
46
35
  import type { Context as ClientContext } from '@deepseek-ai/cordis';
47
36
  import type { CommandContribution } from './commands-contract.ts';
48
37
  import { type VideoDefaults } from './video-form-rules.ts';
49
- import { type VideoPreset } from './VideoFormDialog.tsx';
50
38
  import { type MinimaxCodeLocaleKey } from './locales.ts';
51
39
  /** 本线路的 provider id(宿主 `PROVIDER_ID` 的同值副本)。 */
52
40
  export declare const MINIMAX_CODE_PROVIDER = "minimax-code";
53
- /** `/video` 里「自定义…」那一行的 id。 */
54
- export declare const CUSTOM_OPTION_ID = "custom";
55
41
  /** 本模块登记的命令名。 */
56
42
  export declare const VIDEO_COMMAND_NAME = "video";
57
43
  /** 翻译函数座位。 */
@@ -73,13 +59,35 @@ export interface SessionRoute {
73
59
  * @returns 形如 `{ provider, model }` 的路由,或 undefined。
74
60
  */
75
61
  export declare function sessionRouteOf(ctx: ClientContext, sessionId: string): SessionRoute | undefined;
62
+ /**
63
+ * 去掉输入框文字开头那一截命令 token。
64
+ *
65
+ * 从菜单里点命令时,token 由宿主消费,输入框里通常已经干净;但用户也可能是
66
+ * 先把 `/video` 打出来、再从菜单里点一次,此时草稿里还留着那个 token。把
67
+ * `/video` 当成画面描述带进面板显然不对,所以在这里剥掉**开头任意一截**命令
68
+ * token——只剥开头,正文里的斜杠是用户自己的内容。
69
+ *
70
+ * @param draft - 输入框里的文字。
71
+ * @returns 去掉前导命令 token 与首尾空白后的文字。
72
+ */
73
+ export declare function stripLeadingCommandToken(draft: string): string;
74
+ /**
75
+ * 这条会话输入框里**已经有的文字**。
76
+ *
77
+ * 走宿主的 `SessionInput.state`(`ui-conversation/src/client/contract/input.ts`
78
+ * 的 `InputState.draft`):那是编辑器内容的投影,不是一次发送。读不到就返回空串
79
+ * ——面板会以空描述打开,而不是报错。
80
+ *
81
+ * @param ctx - 浏览器根上下文。
82
+ * @param sessionId - 目标会话。
83
+ * @returns 输入框里的文字。
84
+ */
85
+ export declare function composerDraftOf(ctx: ClientContext, sessionId: string): string;
76
86
  /**
77
87
  * 把一段文本写进该会话的输入框。
78
88
  *
79
- * 走宿主的 `SessionInput.setDraft`(`ui-conversation/src/client/contract/input.ts:186`),
80
- * 不是 `prompt`:后者会绕过输入框直接把一条用户消息发出去,用户就看不见自己填了
81
- * 什么。`for(actx)` 要求一个**会话作用域的 Context**,正是
82
- * `ctx.sessions.binding(id).ctx`(见 `session-controller/src/client/sessions/service.ts:101-108`)。
89
+ * 走宿主的 `SessionInput.setDraft`,不是 `prompt`:后者会绕过输入框直接把一条
90
+ * 用户消息发出去,用户就看不见自己填了什么。
83
91
  *
84
92
  * @param ctx - 浏览器根上下文。
85
93
  * @param sessionId - 目标会话。
@@ -87,31 +95,17 @@ export declare function sessionRouteOf(ctx: ClientContext, sessionId: string): S
87
95
  * @returns 是否真的填进去了。
88
96
  */
89
97
  export declare function fillComposer(ctx: ClientContext, sessionId: string, text: string): boolean;
90
- /** `/video` 命令需要外部给的两件事。 */
98
+ /** `/video` 命令需要外部给的东西。 */
91
99
  export interface VideoCommandOptions {
92
- /** 打开参数弹窗。「自定义…」这一行调它。 */
100
+ /** 打开参数面板。 */
93
101
  readonly openForm: (sessionId: string, defaults: VideoDefaults) => void;
94
- /**
95
- * 预设档直接填输入框时用的通道。
96
- *
97
- * 缺省是 `fillComposer`,测试注入一个假的来断言「填进去的那段话是什么」。
98
- */
99
- readonly fill?: (sessionId: string, text: string) => boolean;
100
- /** 设置页里的默认参数。每次打开菜单时现取。 */
102
+ /** 设置页里的默认参数。每次打开时现取。 */
101
103
  readonly defaults?: () => VideoDefaults;
102
104
  /** 翻译;缺省走本线路的中文兜底。 */
103
105
  readonly translate?: VideoCommandTranslate;
104
106
  }
105
- /**
106
- * 把一条预设档拼成填进输入框的那段话。
107
- *
108
- * 提示词留一条**待填的占位**,而不是随便编一句:用户选了「H3 · 4秒 · 768P」之后,
109
- * 真正缺的只有画面描述,那一条应当由他来写。
110
- *
111
- * @param preset - 选中的预设档。
112
- * @returns 填进输入框的文本。
113
- */
114
- export declare function presetDraftText(preset: VideoPreset): string;
107
+ /** 兜底翻译:只在没有 locale 服务时用到(测试、以及菜单渲染早于字典注册)。 */
108
+ export declare function fallbackTranslate(key: MinimaxCodeLocaleKey, params?: Record<string, string | number>): string;
115
109
  /**
116
110
  * 构造 `/video` 的 `CommandContribution`。
117
111
  *
@@ -119,7 +113,7 @@ export declare function presetDraftText(preset: VideoPreset): string;
119
113
  * `ui-message-feedback` 的 `/feedback` 装饰同一种接线方式。
120
114
  *
121
115
  * @param ctx - 浏览器根上下文。
122
- * @param options - 打开弹窗与填输入框的通道。
116
+ * @param options - 打开面板的通道。
123
117
  * @returns 一份可直接交给 `commandUi.register` 的贡献。
124
118
  */
125
119
  export declare function createVideoCommand(ctx: ClientContext, options: VideoCommandOptions): CommandContribution;
@@ -1 +1 @@
1
- {"version":3,"file":"video-command.d.ts","sourceRoot":"","sources":["../../../../src/client/minimax-code/video-command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH,OAAO,KAAK,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAInE,OAAO,KAAK,EAAE,mBAAmB,EAAgB,MAAM,wBAAwB,CAAA;AAE/E,OAAO,EAGL,KAAK,aAAa,EAEnB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACtE,OAAO,EAAM,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAE5D,gDAAgD;AAChD,eAAO,MAAM,qBAAqB,iBAAiB,CAAA;AAEnD,+BAA+B;AAC/B,eAAO,MAAM,gBAAgB,WAAW,CAAA;AAExC,iBAAiB;AACjB,eAAO,MAAM,kBAAkB,UAAU,CAAA;AAEzC,cAAc;AACd,MAAM,MAAM,qBAAqB,GAAG,CAAC,GAAG,EAAE,oBAAoB,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,KAAK,MAAM,CAAA;AAEnH,cAAc;AACd,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAuB9F;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAkBzF;AAED,4BAA4B;AAC5B,MAAM,WAAW,mBAAmB;IAClC,0BAA0B;IAC1B,QAAQ,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAA;IACvE;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAA;IAC5D,2BAA2B;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,aAAa,CAAA;IACvC,sBAAsB;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,qBAAqB,CAAA;CAC3C;AASD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAU3D;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,mBAAmB,GAAG,mBAAmB,CAwCxG"}
1
+ {"version":3,"file":"video-command.d.ts","sourceRoot":"","sources":["../../../../src/client/minimax-code/video-command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,KAAK,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAInE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAEjE,OAAO,EAA0B,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAElF,OAAO,EAAM,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAE5D,gDAAgD;AAChD,eAAO,MAAM,qBAAqB,iBAAiB,CAAA;AAEnD,iBAAiB;AACjB,eAAO,MAAM,kBAAkB,UAAU,CAAA;AAEzC,cAAc;AACd,MAAM,MAAM,qBAAqB,GAAG,CAAC,GAAG,EAAE,oBAAoB,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,KAAK,MAAM,CAAA;AAEnH,cAAc;AACd,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAuB9F;AAyBD;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAS7E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CASzF;AAED,2BAA2B;AAC3B,MAAM,WAAW,mBAAmB;IAClC,cAAc;IACd,QAAQ,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAA;IACvE,yBAAyB;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,aAAa,CAAA;IACvC,sBAAsB;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,qBAAqB,CAAA;CAC3C;AAED,+CAA+C;AAC/C,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,oBAAoB,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG,MAAM,CAI7G;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,mBAAmB,GAAG,mBAAmB,CAoBxG"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * 参考媒体的**输入区**:浏览、拖拽、粘贴三个入口共用一个落脚点。
3
+ *
4
+ * ## 为什么是一个自建组件而不是三个输入框
5
+ *
6
+ * 参数面板里四类参考媒体(首帧、末帧、参考图/视频/音频)此前是四排纯文本框,
7
+ * 用户要自己去资源管理器里复制路径。现在每一类都变成一块「媒体块」:一条条已收下
8
+ * 的路径显示成可移除的标签,右上角是「浏览…」,整块可以拖入文件,也可以直接
9
+ * 粘贴路径或链接。
10
+ *
11
+ * ## 「浏览」为什么用 `<input type="file">`
12
+ *
13
+ * 桌面端没有向网页暴露「选文件」的原生对话框 IPC(只有目录选择器)。而浏览器
14
+ * 自带的 `<input type="file">` 在桌面端同样能拿到文件对象——本机路径由宿主桥
15
+ * `__DSH_HOST_PATHS__.pathFor` 还原。网页端拿不到路径时如实提示,而不是让用户
16
+ * 以为已经加上了。
17
+ *
18
+ * @module @eddyskywalker/dsh-chatgpt-subscription/client/minimax-code/video-media-dropzone
19
+ */
20
+ import type { WorkspaceLister } from './video-workspace.ts';
21
+ import type { MinimaxCodeLocaleKey } from './locales.ts';
22
+ /** 翻译座位(与 VideoFormDialog 同一形状)。 */
23
+ type Translate = (key: MinimaxCodeLocaleKey, params?: Record<string, string | number>) => string;
24
+ /** 媒体块的入参。 */
25
+ export interface MediaDropZoneProps {
26
+ /** 区块标题。 */
27
+ readonly label: string;
28
+ /** 已收下的路径,按顺序。 */
29
+ readonly paths: readonly string[];
30
+ /** 路径整组变化(拖入、粘贴、浏览、移除都走这里)。 */
31
+ readonly onChange: (paths: readonly string[]) => void;
32
+ /** 浏览按钮接受的类型,如 `image/*`。 */
33
+ readonly accept: string;
34
+ /** 输入元素的 id,用于标签关联。 */
35
+ readonly id: string;
36
+ /** 翻译。 */
37
+ readonly t: Translate;
38
+ /** 额外的一行说明(可选)。 */
39
+ readonly hint?: string;
40
+ /** 是否允许多选;首帧/末帧只有一格,所以那里传 false。 */
41
+ readonly multiple?: boolean;
42
+ /**
43
+ * 列出某个工作区目录的子项,供 `@` 补全。
44
+ *
45
+ * 缺席(宿主没装 remote、或还没挂载)时就只是没有候选列表:输入照样能填路径。
46
+ */
47
+ readonly listWorkspace?: WorkspaceLister | undefined;
48
+ }
49
+ /**
50
+ * 一块媒体输入:已收下的条目 + 浏览按钮 + 拖拽与粘贴。
51
+ *
52
+ * @param props - 标题、当前路径、变更回调、接受的类型。
53
+ * @returns 媒体块。
54
+ */
55
+ export declare function MediaDropZone({ label, paths, onChange, accept, id, t, hint, multiple, listWorkspace, }: MediaDropZoneProps): React.JSX.Element;
56
+ export {};
57
+ //# sourceMappingURL=video-media-dropzone.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-media-dropzone.d.ts","sourceRoot":"","sources":["../../../../src/client/minimax-code/video-media-dropzone.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAWH,OAAO,KAAK,EAAkB,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAE3E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAExD,oCAAoC;AACpC,KAAK,SAAS,GAAG,CAAC,GAAG,EAAE,oBAAoB,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,KAAK,MAAM,CAAA;AAEhG,cAAc;AACd,MAAM,WAAW,kBAAkB;IACjC,YAAY;IACZ,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,kBAAkB;IAClB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,+BAA+B;IAC/B,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,KAAK,IAAI,CAAA;IACrD,6BAA6B;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,uBAAuB;IACvB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,UAAU;IACV,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAA;IACrB,mBAAmB;IACnB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,eAAe,GAAG,SAAS,CAAA;CACrD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,QAAe,EAAE,aAAa,GAC5E,EAAE,kBAAkB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAyOxC"}
@@ -0,0 +1,173 @@
1
+ /**
2
+ * 参考媒体的**入口归一化**:把「拖进来的文件」「粘贴板里的文字」「浏览选中的文件」
3
+ * 变成一张路径列表。
4
+ *
5
+ * ## 为什么需要一个纯函数模块
6
+ *
7
+ * 这三种入口最终都要回答同一个问题:**这一条是不是服务端认识的本机路径**。宿主
8
+ * 的 `minimax_generate_video` 只接受本机文件(`video-tool.ts` 里逐条校验),
9
+ * 网页链接和 `data:` 内联串在服务端一律被拒。如果这里放行,用户会看到「填好了」
10
+ * 然后被计费前的校验打回来——那正是这个入口要避免的体验。
11
+ *
12
+ * 所以判定写在纯函数里,事件绑定留在组件里:判定能被测试钉死,DOM 细节不必。
13
+ *
14
+ * ## 「真实路径」是怎么来的
15
+ *
16
+ * 浏览器的 `File` 对象**没有**路径字段(安全模型如此)。DSH 桌面端额外暴露出
17
+ * `window.__DSH_HOST_PATHS__.pathFor(file)`(Electron `webUtils.getPathForFile`),
18
+ * 本插件按鸭子类型取用:拿得到就是绝对路径,拿不到就如实返回空串,由界面提示
19
+ * 用户改用粘贴——**绝不编一条看起来像路径的字符串**。
20
+ *
21
+ * @module @eddyskywalker/dsh-chatgpt-subscription/client/minimax-code/video-media-input
22
+ */
23
+ /** 一次归一化的结果。 */
24
+ export interface MediaIntake {
25
+ /** 可以直接写进表单的路径,按输入顺序、已去重。 */
26
+ readonly paths: readonly string[];
27
+ /** 被拒绝的网页链接(不是本机路径)。 */
28
+ readonly rejectedUrls: readonly string[];
29
+ /** 拿不到本机路径的文件个数(浏览器里拖进来的网页图片、内联字节等)。 */
30
+ readonly withoutPath: number;
31
+ }
32
+ /** 空结果,供调用方省一次判断。 */
33
+ export declare const EMPTY_INTAKE: MediaIntake;
34
+ /** 桌面端宿主路径桥的形状(`apps/desktop/src/preload-app.ts` 暴露的那一个)。 */
35
+ interface HostPathBridge {
36
+ readonly pathFor?: (file: File) => string;
37
+ }
38
+ /**
39
+ * 取一个 `File` 的本机绝对路径。
40
+ *
41
+ * 桌面端由宿主桥给出;网页端、或宿主那一版没有这个桥时返回空串。**任何异常都
42
+ * 吞掉**:拖进一个文件不该把面板带崩。
43
+ *
44
+ * @param file - 拖入或浏览选中的文件。
45
+ * @param bridge - 取值来源;缺省读 `globalThis`,测试注入一个假的。
46
+ * @returns 绝对路径,或空串。
47
+ */
48
+ export declare function hostPathForFile(file: File, bridge?: HostPathBridge | undefined): string;
49
+ /**
50
+ * 服务端唯一会被读的 URL 主机(宿主 `MINIMAX_CDN_HOST`,实测结论)。
51
+ *
52
+ * 其他公网地址在服务端会被拒——`video-tool.ts` 的 `prepareMediaInput` 里
53
+ * `assertMinimaxCdnUrl` 先拦一道,第三方链接根本到不了模型。所以这一条不是
54
+ * 保守,而是把事实写进入口。
55
+ */
56
+ export declare const MINIMAX_CDN_HOST = "cdn.hailuoai.com";
57
+ /**
58
+ * 这条 URL 是不是 MiniMax 自己的 CDN 地址。
59
+ *
60
+ * @param text - 一条 URL。
61
+ * @returns 主机名匹配时为 true。
62
+ */
63
+ export declare function isMinimaxCdnUrl(text: string): boolean;
64
+ /**
65
+ * 一条文本是不是「有协议头的 URL」。
66
+ *
67
+ * 只看形如 `scheme://…` 与 `scheme:…` 的写法;Windows 盘符(`C:\…`)只有一个
68
+ * 字母,会被这条规则误伤,所以单字母 scheme 除外。
69
+ *
70
+ * @param text - 一行文本。
71
+ * @returns 命中的协议名(小写),没有则 undefined。
72
+ */
73
+ export declare function urlSchemeOf(text: string): string | undefined;
74
+ /**
75
+ * 把 `file://` 地址还原成本机路径。
76
+ *
77
+ * 只处理最常见的两种写法:`file:///C:/x/y.png`(Windows)与
78
+ * `file:///home/u/a.png`(POSIX)。解不出来就原样返回,让调用方按 URL 拒绝。
79
+ *
80
+ * @param url - 一条 `file:` 地址。
81
+ * @returns 本机路径,或空串。
82
+ */
83
+ export declare function pathFromFileUrl(url: string): string;
84
+ /**
85
+ * 把一行文本归一化成一条本机路径。
86
+ *
87
+ * 空行、`file:` 地址、普通路径都接受;其余带协议的(`http:`、`data:`、
88
+ * `blob:`…)一律判为「网页链接」,由调用方提示用户先下载。
89
+ *
90
+ * @param line - 一行原始文本。
91
+ * @returns 判定结果。
92
+ */
93
+ export declare function normalizeMediaLine(line: string): {
94
+ path: string;
95
+ } | {
96
+ rejectedUrl: string;
97
+ } | undefined;
98
+ /**
99
+ * 去掉输入框里引用工作区文件的那一个 `@`。
100
+ *
101
+ * `@docs/a.png` 是**对话框**里引用文件的写法,而工具参数收的是普通路径。用户
102
+ * 从对话里原样复制一行过来时,这个前缀跟着一起来,所以在这里去掉——只去一个,
103
+ * 且只在它后面还有内容时去(`@` 本身不是路径)。
104
+ *
105
+ * @param text - 一行原始文本。
106
+ * @returns 去掉前导 `@` 的文本。
107
+ */
108
+ export declare function stripReferencePrefix(text: string): string;
109
+ /**
110
+ * 把粘贴板里的一段文字归一化成路径。
111
+ *
112
+ * 支持多行、去重;`text/uri-list` 的注释行(以 `#` 开头)按规范忽略。
113
+ *
114
+ * @param text - 粘贴板文字。
115
+ * @returns 归一化结果。
116
+ */
117
+ export declare function intakeFromText(text: string): MediaIntake;
118
+ /**
119
+ * 把一批 `File` 归一化成路径。
120
+ *
121
+ * 拿不到路径的文件计入 `withoutPath`,**不进** `paths`:界面据此说一句实话,而
122
+ * 不是塞一条空路径进表单。
123
+ *
124
+ * @param files - 拖入或选中的文件。
125
+ * @param bridge - 路径来源,缺省读宿主桥。
126
+ * @returns 归一化结果。
127
+ */
128
+ export declare function intakeFromFiles(files: readonly File[], bridge?: HostPathBridge | undefined): MediaIntake;
129
+ /**
130
+ * 合并两份归一化结果。
131
+ *
132
+ * @param left - 先到的。
133
+ * @param right - 后到的。
134
+ * @returns 合并结果(去重顺序保持)。
135
+ */
136
+ export declare function mergeIntake(left: MediaIntake, right: MediaIntake): MediaIntake;
137
+ /** 媒体类别:决定一条路径进哪一栏。 */
138
+ export type MediaKind = 'image' | 'video' | 'audio' | 'unknown';
139
+ /**
140
+ * 按后缀判断一条路径属于哪一栏。
141
+ *
142
+ * 只看后缀名:浏览器里没有文件系统,问不了 MIME;而服务端本来就按路径读盘,
143
+ * 后缀是它唯一能用的线索。
144
+ *
145
+ * @param path - 一条路径。
146
+ * @returns 类别;认不出时是 `unknown`。
147
+ */
148
+ export declare function mediaKindOf(path: string): MediaKind;
149
+ /** 一条已经收下的参考媒体:路径 + 它在界面上显示的名字。 */
150
+ export interface MediaEntry {
151
+ readonly path: string;
152
+ readonly name: string;
153
+ }
154
+ /**
155
+ * 从一条路径取出显示名(最后一段,兼容两种分隔符)。
156
+ *
157
+ * @param path - 一条路径。
158
+ * @returns 用于界面上的名字。
159
+ */
160
+ /**
161
+ * 一条路径是不是「需要单独给时长」的远端视频。
162
+ *
163
+ * 本机文件由宿主从容器里读时长;CDN 上的链接读不到(宿主不下拉去量),所以
164
+ * 那一条必须在旁边写一个秒数,否则提交会被 `MINIMAX_VIDEO_REFERENCE_DURATION_REQUIRED`
165
+ * 拒掉。
166
+ *
167
+ * @param path - 一条路径或 URL。
168
+ * @returns 需要用户手填时长时为 true。
169
+ */
170
+ export declare function needsDuration(path: string): boolean;
171
+ export declare function mediaNameOf(path: string): string;
172
+ export {};
173
+ //# sourceMappingURL=video-media-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-media-input.d.ts","sourceRoot":"","sources":["../../../../src/client/minimax-code/video-media-input.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,gBAAgB;AAChB,MAAM,WAAW,WAAW;IAC1B,6BAA6B;IAC7B,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,wBAAwB;IACxB,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAA;IACxC,wCAAwC;IACxC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAC7B;AAED,qBAAqB;AACrB,eAAO,MAAM,YAAY,EAAE,WAA6D,CAAA;AAExF,6DAA6D;AAC7D,UAAU,cAAc;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAA;CAC1C;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,cAAc,GAAG,SAAS,GAAG,MAAM,CAQvF;AAED;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,qBAAqB,CAAA;AAElD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOrD;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG5D;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAUnD;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAavG;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAcxD;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,EAAE,MAAM,CAAC,EAAE,cAAc,GAAG,SAAS,GAAG,WAAW,CASxG;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,GAAG,WAAW,CAM9E;AAED,uBAAuB;AACvB,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAAA;AAM/D;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAQnD;AAED,mCAAmC;AACnC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED;;;;;GAKG;AACH;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGhD"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * 预设档:一张**实测合法**的「模型 × 比例 × 时长 × 分辨率」表。
3
+ *
4
+ * ## 为什么从 VideoFormDialog 里搬出来
5
+ *
6
+ * 这张表有两个消费者:`/video` 命令(决定默认档位)和参数面板(顶部那一排档位
7
+ * 胶囊)。它曾经和面板组件写在同一个文件里,于是命令层为了读一张常量表去 import
8
+ * 一个 `.tsx`——那条依赖除了把组件拖进命令模块的闭包,没有任何好处。搬成纯模块
9
+ * 之后,两边都只是读表。
10
+ *
11
+ * ## 每一档都必须是真能发出去的组合
12
+ *
13
+ * - H3:4-15 秒、768P/2K;H3-Max:5-15 秒、480P/768P;Hailuo:6 或 10 秒、768P/1080P;
14
+ * - 比例是纯文本分支,所以 `adaptive` 一律不出现(那是首帧/参考媒体的分支才会有的值)。
15
+ *
16
+ * 时长都取各模型的下界,理由与 `defaultDuration` 相同:第一档应当是最便宜的
17
+ * 一次生成。更细的组合在面板的「更多参数」里调。
18
+ *
19
+ * @module @eddyskywalker/dsh-chatgpt-subscription/client/minimax-code/video-presets
20
+ */
21
+ import { type MinimaxVideoModel, type MinimaxVideoRatio, type MinimaxVideoResolution } from './video-form-rules.ts';
22
+ /** 预设档。 */
23
+ export interface VideoPreset {
24
+ readonly id: string;
25
+ readonly model: MinimaxVideoModel;
26
+ readonly ratio: MinimaxVideoRatio | undefined;
27
+ readonly durationSeconds: number;
28
+ readonly resolution: MinimaxVideoResolution;
29
+ }
30
+ /** 翻译函数的最小形状:档位标签要拼「秒」。 */
31
+ type Translate = (key: 'videoDurationUnit') => string;
32
+ /**
33
+ * 预设档表。
34
+ *
35
+ * ## 标签为什么分成两截
36
+ *
37
+ * `label` 是**胶囊上**那行字:只留区分三档所需的最少信息(模型 + 时长),因为
38
+ * 三个全名并排放在 600px 宽的面板里必然换行,换行后胶囊高低不齐,比省掉几个字
39
+ * 难看得多。`title` 是完整参数,挂在 `title` 与 `aria-label` 上——想确认分辨率
40
+ * 与比例的人仍然看得到。
41
+ *
42
+ * @param t - 翻译函数(只需要时长单位)。
43
+ * @returns 每一档、它的短标签与完整说明。
44
+ */
45
+ export declare function videoPresets(t: Translate): readonly {
46
+ readonly preset: VideoPreset;
47
+ readonly label: string;
48
+ readonly title: string;
49
+ }[];
50
+ /** 默认的一档:H3 的合法下界,也就是 `DEFAULT_MINIMAX_VIDEO_MODEL` 自己的默认值。 */
51
+ export declare function defaultPreset(): VideoPreset | undefined;
52
+ /**
53
+ * 当前这组参数落在哪一档上;没有一档完全吻合时返回 undefined。
54
+ *
55
+ * 面板据此高亮胶囊:用户改过时长之后,那一档就不再是「当前档」了——继续高亮会
56
+ * 让胶囊和它下面的选择器互相矛盾。
57
+ *
58
+ * @param values - 当前模型、时长、分辨率。
59
+ * @returns 命中的档位 id,或 undefined。
60
+ */
61
+ export declare function presetIdOf(values: {
62
+ readonly model: MinimaxVideoModel;
63
+ readonly durationSeconds?: number | undefined;
64
+ readonly resolution?: MinimaxVideoResolution | undefined;
65
+ }): string | undefined;
66
+ export {};
67
+ //# sourceMappingURL=video-presets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-presets.d.ts","sourceRoot":"","sources":["../../../../src/client/minimax-code/video-presets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAML,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC5B,MAAM,uBAAuB,CAAA;AAE9B,WAAW;AACX,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAA;IACjC,QAAQ,CAAC,KAAK,EAAE,iBAAiB,GAAG,SAAS,CAAA;IAC7C,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,QAAQ,CAAC,UAAU,EAAE,sBAAsB,CAAA;CAC5C;AAED,2BAA2B;AAC3B,KAAK,SAAS,GAAG,CAAC,GAAG,EAAE,mBAAmB,KAAK,MAAM,CAAA;AAErD;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,SAAS,GAAG,SAAS;IACnD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB,EAAE,CAkBF;AAED,+DAA+D;AAC/D,wBAAgB,aAAa,IAAI,WAAW,GAAG,SAAS,CAYvD;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE;IACjC,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAA;IACjC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7C,QAAQ,CAAC,UAAU,CAAC,EAAE,sBAAsB,GAAG,SAAS,CAAA;CACzD,GAAG,MAAM,GAAG,SAAS,CAOrB"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * 工作区目录列表:给媒体块里的 `@` 补全用。
3
+ *
4
+ * ## 为什么这里能列目录
5
+ *
6
+ * 宿主的 `remote.workspaceFiles` 除了 `readBytes` 还有一个 `list(sessionId, path, signal)`
7
+ * (`api/workspace-files/src/index.ts:304`,生成的客户端声明在
8
+ * `lib/typert.remote-client.d.ts:15`),返回该目录的直接子项与**工作区相对路径**。
9
+ * 那正是对话框里 `@` 引用文件时用的那套坐标,所以拿去补全不用做任何换算。
10
+ *
11
+ * 与取字节一样,这个服务按需解析、**可选**:宿主没装、或 remote 尚未挂载时返回
12
+ * `undefined`,媒体块会退化成「只能手填路径」,而不是报错。
13
+ *
14
+ * @module @eddyskywalker/dsh-chatgpt-subscription/client/minimax-code/video-workspace
15
+ */
16
+ import type { Context as ClientContext } from '@deepseek-ai/cordis';
17
+ /** 目录里的一项(`WorkspaceDirectoryEntry` 的窄化副本)。 */
18
+ export interface WorkspaceEntry {
19
+ /** 文件名或目录名。 */
20
+ readonly name: string;
21
+ /** 相对工作区根的路径;拼在已列出的目录后面。 */
22
+ readonly path: string;
23
+ /** 是否目录;目录在补全里带一个尾斜杠,便于继续下钻。 */
24
+ readonly directory: boolean;
25
+ }
26
+ /** 列一个目录的直接子项;路径相对工作区根,空串是工作区根。 */
27
+ export type WorkspaceLister = (path: string) => Promise<readonly WorkspaceEntry[]>;
28
+ /**
29
+ * 为一条会话准备目录列表器。
30
+ *
31
+ * 返回的列表器**不抛异常**:远端失败、服务缺席、目录不存在都收敛成空数组——补全
32
+ * 少几行是可接受的,让一次按键变成一条控制台异常不是。
33
+ *
34
+ * @param ctx - 浏览器根上下文。
35
+ * @param sessionId - 决定工作区根的会话 id。
36
+ * @returns 列表器;宿主没有这个能力时为 undefined。
37
+ */
38
+ export declare function workspaceListerFor(ctx: ClientContext, sessionId: string): WorkspaceLister | undefined;
39
+ /** 在一条已命中的路径后面拼一个子项,处理根目录那一档。 */
40
+ export declare function joinWorkspacePath(base: string, name: string): string;
41
+ //# sourceMappingURL=video-workspace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-workspace.d.ts","sourceRoot":"","sources":["../../../../src/client/minimax-code/video-workspace.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAGnE,+CAA+C;AAC/C,MAAM,WAAW,cAAc;IAC7B,eAAe;IACf,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,4BAA4B;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,gCAAgC;IAChC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAC5B;AAED,mCAAmC;AACnC,MAAM,MAAM,eAAe,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC,CAAA;AAqClF;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAkBrG;AAED,iCAAiC;AACjC,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpE"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Qoder(订阅)在输入框右侧的额度胶囊。
3
+ *
4
+ * 与兄弟线路的胶囊同款:胶囊是唯一一眼能看到数字的地方,所以点一下要走强制刷新;
5
+ * 而「显示哪一个数字」是每条线路唯一值得自己写的部分,因此单独导出一个纯函数
6
+ * selectBadgeFacts 供测试直接调用。
7
+ *
8
+ * 挑选口径:**只按有总额的桶选已用比例最高的那只**(个人 / 加购 / 组织包),
9
+ * 显示它的剩余百分比。桶是绝对量,而百分比需要 total 这个分母——没有 total 或
10
+ * total 为 0 的桶不参与选择(「上游没报」与「一点都不剩」必须长得不一样);
11
+ * 一只可计量的桶都没有时返回 null,即**不渲染胶囊**:装一个占位数字比不显示更像坏了。
12
+ */
13
+ import type { ModelDirectoryState } from '@deepseek-ai/dsh-client-ui-model-selection/client';
14
+ import type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
15
+ import { type QoderStatusDto } from '../../shared/qoder-contracts.ts';
16
+ import { type ComposerQuotaFacts } from '../common/ComposerQuotaBadge.tsx';
17
+ import type { SnapshotStore } from '../store.ts';
18
+ import { NS_QODER, type QoderLocaleKey } from './locales.ts';
19
+ type Props = PropsRuntime<'conversation.input.right'> & PropsLocale<typeof NS_QODER> & {
20
+ directory: SnapshotStore<ModelDirectoryState>;
21
+ loadModelDirectory: () => void;
22
+ };
23
+ /**
24
+ * 胶囊显示「最紧的那只桶」的剩余百分比。
25
+ *
26
+ * 多只桶互相独立地消耗,用户当下真正被卡住的是**已用比例最高**的那一只:
27
+ * 另外那只可能还剩一大半。所以这里不平均、不取最小剩余,而是取最大已用比例。
28
+ * 没有快照、没有桶、或全部桶都没有总额时返回 null(见文件头)。
29
+ */
30
+ export declare function selectBadgeFacts(status: QoderStatusDto | null, lookup?: (key: QoderLocaleKey) => string): ComposerQuotaFacts | null;
31
+ /**
32
+ * 输入框右侧的额度胶囊本体。
33
+ *
34
+ * **槽位号由波次 4 注册,本文件不注册任何槽位**:conversation.input.right 现有
35
+ * 35–44(codex → … → step-code → cline-pass),本线路取下一个号 45,id 沿用命名习惯
36
+ * 'qoder-quota',locale 为 NS_QODER。顺延而不是插号:给新线路重排既有号会让
37
+ * 已上线线路的槽位位置无谓地变一次。
38
+ */
39
+ export declare function QoderComposerQuota({ directory, loadModelDirectory, t }: Props): React.JSX.Element | null;
40
+ export {};
41
+ //# sourceMappingURL=QoderComposerQuota.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QoderComposerQuota.d.ts","sourceRoot":"","sources":["../../../../src/client/qoder/QoderComposerQuota.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mDAAmD,CAAA;AAC5F,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AACjF,OAAO,EAEL,KAAK,cAAc,EACpB,MAAM,iCAAiC,CAAA;AACxC,OAAO,EAAkC,KAAK,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AAC1G,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEhD,OAAO,EAAE,QAAQ,EAAuB,KAAK,cAAc,EAAE,MAAM,cAAc,CAAA;AAEjF,KAAK,KAAK,GAAG,YAAY,CAAC,0BAA0B,CAAC,GAAG,WAAW,CAAC,OAAO,QAAQ,CAAC,GAAG;IACrF,SAAS,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAA;IAC7C,kBAAkB,EAAE,MAAM,IAAI,CAAA;CAC/B,CAAA;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,cAAc,GAAG,IAAI,EAC7B,MAAM,GAAE,CAAC,GAAG,EAAE,cAAc,KAAK,MAAyB,GACzD,kBAAkB,GAAG,IAAI,CAqB3B;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC,EAAE,EAAE,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,GAAG,IAAI,CAYxG"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Qoder(订阅)设置卡片。
3
+ *
4
+ * 纯渲染:状态、副作用与请求都在 'useQoderSection.ts',两者之间只通过一个具名结构
5
+ * 交接(GLM / WorkBuddy / Step Code 同款分工)。
6
+ *
7
+ * 本文件没有新建任何 UI 组件:进入入口(hub 卡片)在 hub/providers.tsx,账号池与它的
8
+ * 配额条在 AccountPoolSection,模型勾选在 ModelChecklist,上下文窗口在
9
+ * ContextWindowEditor,输入框胶囊在 QoderComposerQuota.tsx。
10
+ *
11
+ * 两条它自己负责的渲染规则:
12
+ *
13
+ * 1. **能力只画契约里的字段**:图片输入、思考档位、上下文窗口全部来自 host 生成的
14
+ * hint,客户端不按模型名推断任何一项;同一事实只呈现一次;
15
+ * 2. **额度画绝对量,缓存画 token 维度**:额度是三只桶的总量/已用/剩余(上游自述的
16
+ * 单位),缺桶不画;缓存只有读入/写入/样本,没数据就是占位符;单价未公开,
17
+ * 整页不出现任何金额。
18
+ *
19
+ * 版面纪律(全卡适用):**每个分组标题下最多留一行说明**,其余原句收进 .dshq-details
20
+ * 折叠区(moreNotes 辅助函数),阅读顺序因此固定为「标题 → 一句话 → 控件 → 折叠的补充
21
+ * 说明」。
22
+ */
23
+ import React from 'react';
24
+ import { type QoderSectionProps } from './useQoderSection.ts';
25
+ export declare function QoderSection({ onModelChange }?: QoderSectionProps): React.JSX.Element;
26
+ //# sourceMappingURL=QoderSection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QoderSection.d.ts","sourceRoot":"","sources":["../../../../src/client/qoder/QoderSection.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,MAAM,OAAO,CAAA;AAoBzB,OAAO,EAAmB,KAAK,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AA4D9E,wBAAgB,YAAY,CAAC,EAAE,aAAa,EAAE,GAAE,iBAAsB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAudzF"}
@@ -0,0 +1,4 @@
1
+ export declare const get: <T>(path: string) => Promise<T>;
2
+ export declare const post: <T>(path: string, body?: object) => Promise<T>;
3
+ export declare function messageOf(cause: unknown): string;
4
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../src/client/qoder/api.ts"],"names":[],"mappings":"AA8BA,eAAO,MAAM,GAAG,iCAAU,CAAA;AAC1B,eAAO,MAAM,IAAI,gDAAW,CAAA;AAE5B,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEhD"}