@krischoichoi/channel-harness 0.6.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 (202) hide show
  1. package/README.md +110 -0
  2. package/lib/access/controller.d.ts +37 -0
  3. package/lib/access/controller.d.ts.map +1 -0
  4. package/lib/access/controller.js +51 -0
  5. package/lib/access/controller.js.map +1 -0
  6. package/lib/access/decision.d.ts +18 -0
  7. package/lib/access/decision.d.ts.map +1 -0
  8. package/lib/access/decision.js +2 -0
  9. package/lib/access/decision.js.map +1 -0
  10. package/lib/access/resolver.d.ts +41 -0
  11. package/lib/access/resolver.d.ts.map +1 -0
  12. package/lib/access/resolver.js +31 -0
  13. package/lib/access/resolver.js.map +1 -0
  14. package/lib/agent-manager.d.ts +314 -0
  15. package/lib/agent-manager.d.ts.map +1 -0
  16. package/lib/agent-manager.js +603 -0
  17. package/lib/agent-manager.js.map +1 -0
  18. package/lib/agent-router.d.ts +37 -0
  19. package/lib/agent-router.d.ts.map +1 -0
  20. package/lib/agent-router.js +33 -0
  21. package/lib/agent-router.js.map +1 -0
  22. package/lib/bind-support.d.ts +23 -0
  23. package/lib/bind-support.d.ts.map +1 -0
  24. package/lib/bind-support.js +63 -0
  25. package/lib/bind-support.js.map +1 -0
  26. package/lib/binding-store.d.ts +104 -0
  27. package/lib/binding-store.d.ts.map +1 -0
  28. package/lib/binding-store.js +354 -0
  29. package/lib/binding-store.js.map +1 -0
  30. package/lib/bridge.d.ts +248 -0
  31. package/lib/bridge.d.ts.map +1 -0
  32. package/lib/bridge.js +961 -0
  33. package/lib/bridge.js.map +1 -0
  34. package/lib/channel-label.d.ts +46 -0
  35. package/lib/channel-label.d.ts.map +1 -0
  36. package/lib/channel-label.js +89 -0
  37. package/lib/channel-label.js.map +1 -0
  38. package/lib/channel-session-factory.d.ts +76 -0
  39. package/lib/channel-session-factory.d.ts.map +1 -0
  40. package/lib/channel-session-factory.js +187 -0
  41. package/lib/channel-session-factory.js.map +1 -0
  42. package/lib/commands/bind.d.ts +21 -0
  43. package/lib/commands/bind.d.ts.map +1 -0
  44. package/lib/commands/bind.js +91 -0
  45. package/lib/commands/bind.js.map +1 -0
  46. package/lib/commands/help.d.ts +15 -0
  47. package/lib/commands/help.d.ts.map +1 -0
  48. package/lib/commands/help.js +89 -0
  49. package/lib/commands/help.js.map +1 -0
  50. package/lib/commands/index.d.ts +122 -0
  51. package/lib/commands/index.d.ts.map +1 -0
  52. package/lib/commands/index.js +63 -0
  53. package/lib/commands/index.js.map +1 -0
  54. package/lib/commands/locale.d.ts +9 -0
  55. package/lib/commands/locale.d.ts.map +1 -0
  56. package/lib/commands/locale.js +27 -0
  57. package/lib/commands/locale.js.map +1 -0
  58. package/lib/commands/mirror.d.ts +14 -0
  59. package/lib/commands/mirror.d.ts.map +1 -0
  60. package/lib/commands/mirror.js +44 -0
  61. package/lib/commands/mirror.js.map +1 -0
  62. package/lib/commands/model.d.ts +20 -0
  63. package/lib/commands/model.d.ts.map +1 -0
  64. package/lib/commands/model.js +106 -0
  65. package/lib/commands/model.js.map +1 -0
  66. package/lib/commands/models.d.ts +14 -0
  67. package/lib/commands/models.d.ts.map +1 -0
  68. package/lib/commands/models.js +67 -0
  69. package/lib/commands/models.js.map +1 -0
  70. package/lib/commands/new.d.ts +14 -0
  71. package/lib/commands/new.d.ts.map +1 -0
  72. package/lib/commands/new.js +37 -0
  73. package/lib/commands/new.js.map +1 -0
  74. package/lib/commands/status.d.ts +12 -0
  75. package/lib/commands/status.d.ts.map +1 -0
  76. package/lib/commands/status.js +30 -0
  77. package/lib/commands/status.js.map +1 -0
  78. package/lib/commands/stop.d.ts +16 -0
  79. package/lib/commands/stop.d.ts.map +1 -0
  80. package/lib/commands/stop.js +27 -0
  81. package/lib/commands/stop.js.map +1 -0
  82. package/lib/commands/version.d.ts +25 -0
  83. package/lib/commands/version.d.ts.map +1 -0
  84. package/lib/commands/version.js +57 -0
  85. package/lib/commands/version.js.map +1 -0
  86. package/lib/config.d.ts +119 -0
  87. package/lib/config.d.ts.map +1 -0
  88. package/lib/config.js +60 -0
  89. package/lib/config.js.map +1 -0
  90. package/lib/debug-logger.d.ts +8 -0
  91. package/lib/debug-logger.d.ts.map +1 -0
  92. package/lib/debug-logger.js +32 -0
  93. package/lib/debug-logger.js.map +1 -0
  94. package/lib/dsh-home.d.ts +12 -0
  95. package/lib/dsh-home.d.ts.map +1 -0
  96. package/lib/dsh-home.js +31 -0
  97. package/lib/dsh-home.js.map +1 -0
  98. package/lib/failure-display.d.ts +10 -0
  99. package/lib/failure-display.d.ts.map +1 -0
  100. package/lib/failure-display.js +42 -0
  101. package/lib/failure-display.js.map +1 -0
  102. package/lib/file-provider.d.ts +96 -0
  103. package/lib/file-provider.d.ts.map +1 -0
  104. package/lib/file-provider.js +44 -0
  105. package/lib/file-provider.js.map +1 -0
  106. package/lib/index.d.ts +31 -0
  107. package/lib/index.d.ts.map +1 -0
  108. package/lib/index.js +31 -0
  109. package/lib/index.js.map +1 -0
  110. package/lib/interactions/index.d.ts +13 -0
  111. package/lib/interactions/index.d.ts.map +1 -0
  112. package/lib/interactions/index.js +13 -0
  113. package/lib/interactions/index.js.map +1 -0
  114. package/lib/interactions/question-backend.d.ts +133 -0
  115. package/lib/interactions/question-backend.d.ts.map +1 -0
  116. package/lib/interactions/question-backend.js +37 -0
  117. package/lib/interactions/question-backend.js.map +1 -0
  118. package/lib/interactions/question-presenter.d.ts +68 -0
  119. package/lib/interactions/question-presenter.d.ts.map +1 -0
  120. package/lib/interactions/question-presenter.js +425 -0
  121. package/lib/interactions/question-presenter.js.map +1 -0
  122. package/lib/interactions/question-renderer.d.ts +37 -0
  123. package/lib/interactions/question-renderer.d.ts.map +1 -0
  124. package/lib/interactions/question-renderer.js +79 -0
  125. package/lib/interactions/question-renderer.js.map +1 -0
  126. package/lib/interactions/question-state.d.ts +106 -0
  127. package/lib/interactions/question-state.d.ts.map +1 -0
  128. package/lib/interactions/question-state.js +99 -0
  129. package/lib/interactions/question-state.js.map +1 -0
  130. package/lib/interactions/question-text-answer.d.ts +37 -0
  131. package/lib/interactions/question-text-answer.d.ts.map +1 -0
  132. package/lib/interactions/question-text-answer.js +70 -0
  133. package/lib/interactions/question-text-answer.js.map +1 -0
  134. package/lib/interactions/question-waterfall-backend.d.ts +42 -0
  135. package/lib/interactions/question-waterfall-backend.d.ts.map +1 -0
  136. package/lib/interactions/question-waterfall-backend.js +162 -0
  137. package/lib/interactions/question-waterfall-backend.js.map +1 -0
  138. package/lib/lifecycle.d.ts +36 -0
  139. package/lib/lifecycle.d.ts.map +1 -0
  140. package/lib/lifecycle.js +303 -0
  141. package/lib/lifecycle.js.map +1 -0
  142. package/lib/loggable-error.d.ts +10 -0
  143. package/lib/loggable-error.d.ts.map +1 -0
  144. package/lib/loggable-error.js +32 -0
  145. package/lib/loggable-error.js.map +1 -0
  146. package/lib/message-converter.d.ts +64 -0
  147. package/lib/message-converter.d.ts.map +1 -0
  148. package/lib/message-converter.js +191 -0
  149. package/lib/message-converter.js.map +1 -0
  150. package/lib/model-selection.d.ts +54 -0
  151. package/lib/model-selection.d.ts.map +1 -0
  152. package/lib/model-selection.js +116 -0
  153. package/lib/model-selection.js.map +1 -0
  154. package/lib/outbox/binding-resolver.d.ts +23 -0
  155. package/lib/outbox/binding-resolver.d.ts.map +1 -0
  156. package/lib/outbox/binding-resolver.js +38 -0
  157. package/lib/outbox/binding-resolver.js.map +1 -0
  158. package/lib/outbox/capabilities.d.ts +48 -0
  159. package/lib/outbox/capabilities.d.ts.map +1 -0
  160. package/lib/outbox/capabilities.js +35 -0
  161. package/lib/outbox/capabilities.js.map +1 -0
  162. package/lib/outbox/index.d.ts +14 -0
  163. package/lib/outbox/index.d.ts.map +1 -0
  164. package/lib/outbox/index.js +14 -0
  165. package/lib/outbox/index.js.map +1 -0
  166. package/lib/outbox/service.d.ts +48 -0
  167. package/lib/outbox/service.d.ts.map +1 -0
  168. package/lib/outbox/service.js +74 -0
  169. package/lib/outbox/service.js.map +1 -0
  170. package/lib/outbox/target.d.ts +17 -0
  171. package/lib/outbox/target.d.ts.map +1 -0
  172. package/lib/outbox/target.js +15 -0
  173. package/lib/outbox/target.js.map +1 -0
  174. package/lib/outbox/tool-send.d.ts +19 -0
  175. package/lib/outbox/tool-send.d.ts.map +1 -0
  176. package/lib/outbox/tool-send.js +77 -0
  177. package/lib/outbox/tool-send.js.map +1 -0
  178. package/lib/outbox/types.d.ts +42 -0
  179. package/lib/outbox/types.d.ts.map +1 -0
  180. package/lib/outbox/types.js +30 -0
  181. package/lib/outbox/types.js.map +1 -0
  182. package/lib/plugin.d.ts +27 -0
  183. package/lib/plugin.d.ts.map +1 -0
  184. package/lib/plugin.js +47 -0
  185. package/lib/plugin.js.map +1 -0
  186. package/lib/reply-context-store.d.ts +69 -0
  187. package/lib/reply-context-store.d.ts.map +1 -0
  188. package/lib/reply-context-store.js +75 -0
  189. package/lib/reply-context-store.js.map +1 -0
  190. package/lib/reply-router.d.ts +138 -0
  191. package/lib/reply-router.d.ts.map +1 -0
  192. package/lib/reply-router.js +674 -0
  193. package/lib/reply-router.js.map +1 -0
  194. package/lib/session-router.d.ts +49 -0
  195. package/lib/session-router.d.ts.map +1 -0
  196. package/lib/session-router.js +45 -0
  197. package/lib/session-router.js.map +1 -0
  198. package/lib/workspace-resolver.d.ts +67 -0
  199. package/lib/workspace-resolver.d.ts.map +1 -0
  200. package/lib/workspace-resolver.js +102 -0
  201. package/lib/workspace-resolver.js.map +1 -0
  202. package/package.json +103 -0
@@ -0,0 +1,89 @@
1
+ /**
2
+ * The `/help` command (spec §13).
3
+ *
4
+ * Discovery is read LIVE from the official registry — never from a static
5
+ * list: `deps.listCommands(agent)` returns the effective view after global +
6
+ * agent-scope shadowing, so Harness plugins that register new commands
7
+ * (e.g. /compact, /goal, /plan) appear on the channel side without a channel
8
+ * upgrade. `/help <name>` resolves one command via `deps.findCommand`.
9
+ * The registry is reached through deps (bridged from the plugin ctx) — never
10
+ * through `invocation.agent.ctx`, which the agent-loop scope does not inject.
11
+ */
12
+ import {} from '@deepseek-ai/dsh-commands';
13
+ const copy = {
14
+ zh: {
15
+ title: '可用指令',
16
+ none: '当前没有可用指令。',
17
+ unknown: '未知指令:',
18
+ usage: '用法',
19
+ descriptions: {
20
+ stop: '立即停止当前任务',
21
+ new: '开启全新会话',
22
+ help: '列出可用指令或查看单个指令用法',
23
+ status: '查看当前会话、Agent 与模型状态',
24
+ version: '查看渠道 Bundle 版本、Harness 基线与更新提示',
25
+ models: '列出已注册的模型 Provider 及模型',
26
+ model: '查看或切换当前会话模型',
27
+ },
28
+ },
29
+ en: {
30
+ title: 'Available commands',
31
+ none: 'No commands are currently available.',
32
+ unknown: 'Unknown command: ',
33
+ usage: 'Usage',
34
+ descriptions: {
35
+ stop: 'Stop the current task immediately',
36
+ new: 'Start a new session',
37
+ help: 'List available commands or show usage for one command',
38
+ status: 'Show the current session, agent, and model status',
39
+ version: 'Show the channel bundle version, Harness baseline, and update hint',
40
+ models: 'List registered model providers and their models',
41
+ model: 'Show or change the current session model',
42
+ },
43
+ },
44
+ };
45
+ function descriptionFor(locale, name, fallback) {
46
+ const descriptions = copy[locale].descriptions;
47
+ return descriptions[name] ?? fallback;
48
+ }
49
+ function usageFor(name, hint) {
50
+ return '/' + name + (hint ? ' ' + hint : '');
51
+ }
52
+ export function createHelpCommand(deps) {
53
+ return {
54
+ name: 'help',
55
+ description: 'List available commands or show usage for one command',
56
+ input: { hint: '[command]' },
57
+ handler(invocation) {
58
+ const locale = deps.locale();
59
+ const strings = copy[locale];
60
+ const name = invocation.rawInput.trim();
61
+ if (name.length > 0) {
62
+ const def = deps.findCommand(invocation.agent, name);
63
+ if (!def) {
64
+ return { kind: 'error', text: strings.unknown + '`/' + name + '`' };
65
+ }
66
+ const lines = ['**/' + def.name + '**'];
67
+ const description = descriptionFor(locale, def.name, def.description);
68
+ if (description)
69
+ lines.push('', description);
70
+ if (def.input?.hint) {
71
+ lines.push('', '**' + strings.usage + '**', '`' + usageFor(def.name, def.input.hint) + '`');
72
+ }
73
+ return { kind: 'success', text: lines.join('\n') };
74
+ }
75
+ const defs = deps.listCommands(invocation.agent);
76
+ if (defs.length === 0) {
77
+ return { kind: 'success', text: strings.none };
78
+ }
79
+ const lines = ['**' + strings.title + '**', ''];
80
+ for (const def of defs) {
81
+ const usage = usageFor(def.name, def.input?.hint);
82
+ const description = descriptionFor(locale, def.name, def.description);
83
+ lines.push('- `' + usage + '`' + (description ? ' - ' + description : ''));
84
+ }
85
+ return { kind: 'success', text: lines.join('\n') };
86
+ },
87
+ };
88
+ }
89
+ //# sourceMappingURL=help.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/commands/help.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Channel command plane.
3
+ *
4
+ * Composes the channel command factories and installs them into an Agent
5
+ * scoped context via the official `@deepseek-ai/dsh-commands` registry —
6
+ * there is no custom ChannelCommandRegistry / CommandMap here. Each factory
7
+ * returns an official `CommandDefinition`; `installChannelCommands` mounts a
8
+ * command-injected child plugin under the Agent's exact context. Channel
9
+ * commands register in the AGENT scope, so they shadow same-named globals and
10
+ * a same-scope duplicate throws (no custom priority/reserved-name system —
11
+ * spec §11/§43).
12
+ *
13
+ * The `deps` argument is the bridge hook surface channel commands need —
14
+ * every capability a handler uses arrives as a NARROW injected function or
15
+ * object, mirroring `/new`'s `startNewSession`. Handlers must NEVER read
16
+ * Harness services through `invocation.agent.ctx` (the agent-loop scoped
17
+ * context does not inject `commands` / `llm` — Cordis throws "without
18
+ * inject"); the bridge lazily bridges them through `deps` instead, exactly
19
+ * like the official compact/goal/plan commands close over their plugin ctx.
20
+ */
21
+ import { type Context } from '@deepseek-ai/cordis';
22
+ import type { Agent } from '@deepseek-ai/dsh-agent';
23
+ import type { CommandDefinition, CommandDescriptor } from '@deepseek-ai/dsh-commands';
24
+ import type { LlmCallConfig, LlmModelInfo, LlmProviderInfo, LlmResolvedModelInfo } from '@deepseek-ai/dsh-llm';
25
+ import type { ChannelModelSelectionController } from '../model-selection.js';
26
+ import type { ChannelCommandLocale } from './locale.js';
27
+ /**
28
+ * Narrow LLM seam handed to model commands (discovery + exact resolution).
29
+ * Structural subset of `ctx.llm` (`LlmRuntime`); the bridge bridges it lazily
30
+ * so handlers never touch the agent scoped context.
31
+ */
32
+ export interface ChannelModelCatalog {
33
+ /** Registered provider routes (display metadata). */
34
+ listProviders(): LlmProviderInfo[];
35
+ /** Advisory model catalog for one provider (never request validation). */
36
+ listModels(provider: string): Promise<LlmModelInfo[]>;
37
+ /** Exact model metadata resolution, independent of the advisory catalog. */
38
+ resolveModelInfo(provider: string, model: string, signal?: AbortSignal): Promise<LlmResolvedModelInfo>;
39
+ /** Validate a call config (incl. reasoning effort) against the exact model. */
40
+ resolveCallConfig(config: LlmCallConfig, signal?: AbortSignal): Promise<LlmCallConfig>;
41
+ }
42
+ /**
43
+ * Sanitized bundle update status (structural mirror of channel-control's
44
+ * `BundleUpdateStatus`; channel-harness carries no dependency edge on the
45
+ * control-plane package — it probes it live via `ctx.get('channelControl')`).
46
+ */
47
+ export interface ChannelVersionInfo {
48
+ currentVersion: string;
49
+ update?: {
50
+ version: string;
51
+ tag: 'latest' | 'next';
52
+ crossLine: boolean;
53
+ commands: string[];
54
+ };
55
+ checkedAt?: number;
56
+ }
57
+ /** Bridge-provided capabilities available to channel commands. */
58
+ export interface ChannelCommandDependencies {
59
+ /** Start a brand-new Harness session for the current conversation. */
60
+ startNewSession(agent: Agent): Promise<void>;
61
+ /** Harness session/default model view used by /status, /model and images. */
62
+ modelSelection: ChannelModelSelectionController;
63
+ /** Effective command view for an agent (global + agent-scope shadow). */
64
+ listCommands(agent: Agent): readonly CommandDescriptor[];
65
+ /** Resolve one effective command definition (scoped shadow or global). */
66
+ findCommand(agent: Agent, name: string): CommandDefinition | undefined;
67
+ /** Current explicit Harness Host locale; evaluated for every invocation. */
68
+ locale(): ChannelCommandLocale;
69
+ /** Harness LLM catalog seam (discovery + exact resolution), bridged lazily. */
70
+ llm: ChannelModelCatalog;
71
+ /**
72
+ * Live bundle update-status probe for /version (bridged from the plugin ctx
73
+ * over `ctx.get('channelControl')`). Optional: undefined when the control
74
+ * plane is absent — /version then degrades to the version-only output.
75
+ */
76
+ versionInfo?(): Promise<ChannelVersionInfo | undefined>;
77
+ /**
78
+ * Per-conversation mirror toggle backing (issue #5). The bridge binds it to
79
+ * the durable binding store; the state lives on `SessionBinding.mirror`.
80
+ */
81
+ mirror?: {
82
+ /** Current mirror state for the agent's bound conversation. */
83
+ get(agent: Agent): Promise<boolean>;
84
+ /** Toggle and persist the mirror state. */
85
+ set(agent: Agent, on: boolean): Promise<void>;
86
+ };
87
+ /**
88
+ * Rebind/attach an existing session to the current conversation (issue #6).
89
+ * `resolve` never mutates: it fail-closes on ambiguous prefixes, sessions
90
+ * bound elsewhere, and preset conflicts. `confirm` performs the rebind.
91
+ */
92
+ bind?: {
93
+ resolve(agent: Agent, query: string): Promise<ChannelBindResolution>;
94
+ confirm(agent: Agent, sessionId: string): Promise<void>;
95
+ };
96
+ }
97
+ /**
98
+ * Outcome of the fail-closed `/bind` resolution (issue #6). `resolved` still
99
+ * carries the two refusal flags — `boundElsewhere` / `conflict` — so the
100
+ * command can present the exact refusal reason before any mutation.
101
+ */
102
+ export interface ChannelBindResolution {
103
+ kind: 'resolved' | 'missing' | 'ambiguous';
104
+ /** Unique target when `kind: 'resolved'`. */
105
+ sessionId?: string;
106
+ /** Ambiguous prefix candidates when `kind: 'ambiguous'` (bounded list). */
107
+ candidates?: string[];
108
+ /** Persisted Agent preset of the target (undefined = none recorded). */
109
+ preset?: string;
110
+ /** Target is already bound to a different conversation. */
111
+ boundElsewhere?: boolean;
112
+ /** Target's persisted preset conflicts with this conversation's route. */
113
+ conflict?: boolean;
114
+ }
115
+ export type ChannelCommandDisposer = () => Promise<void>;
116
+ /**
117
+ * Install the channel commands on an Agent scoped context. Registrations live
118
+ * for the life of that Agent scope and unwind together with it when the Agent
119
+ * is disposed.
120
+ */
121
+ export declare function installChannelCommands(agentCtx: Context, deps: ChannelCommandDependencies): Promise<ChannelCommandDisposer>;
122
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Channel command plane.
3
+ *
4
+ * Composes the channel command factories and installs them into an Agent
5
+ * scoped context via the official `@deepseek-ai/dsh-commands` registry —
6
+ * there is no custom ChannelCommandRegistry / CommandMap here. Each factory
7
+ * returns an official `CommandDefinition`; `installChannelCommands` mounts a
8
+ * command-injected child plugin under the Agent's exact context. Channel
9
+ * commands register in the AGENT scope, so they shadow same-named globals and
10
+ * a same-scope duplicate throws (no custom priority/reserved-name system —
11
+ * spec §11/§43).
12
+ *
13
+ * The `deps` argument is the bridge hook surface channel commands need —
14
+ * every capability a handler uses arrives as a NARROW injected function or
15
+ * object, mirroring `/new`'s `startNewSession`. Handlers must NEVER read
16
+ * Harness services through `invocation.agent.ctx` (the agent-loop scoped
17
+ * context does not inject `commands` / `llm` — Cordis throws "without
18
+ * inject"); the bridge lazily bridges them through `deps` instead, exactly
19
+ * like the official compact/goal/plan commands close over their plugin ctx.
20
+ */
21
+ import {} from '@deepseek-ai/cordis';
22
+ import { createNewCommand } from './new.js';
23
+ import { createStopCommand } from './stop.js';
24
+ import { createHelpCommand } from './help.js';
25
+ import { createStatusCommand } from './status.js';
26
+ import { createModelsCommand } from './models.js';
27
+ import { createModelCommand } from './model.js';
28
+ import { createVersionCommand } from './version.js';
29
+ import { createMirrorCommand } from './mirror.js';
30
+ import { createBindCommand } from './bind.js';
31
+ const commandFactories = [
32
+ createStopCommand,
33
+ createNewCommand,
34
+ createHelpCommand,
35
+ createStatusCommand,
36
+ createModelsCommand,
37
+ createModelCommand,
38
+ createVersionCommand,
39
+ createMirrorCommand,
40
+ createBindCommand,
41
+ ];
42
+ /**
43
+ * Install the channel commands on an Agent scoped context. Registrations live
44
+ * for the life of that Agent scope and unwind together with it when the Agent
45
+ * is disposed.
46
+ */
47
+ export function installChannelCommands(agentCtx, deps) {
48
+ const fiber = agentCtx.inject(['commands'], function* channelCommands(ctx) {
49
+ for (const factory of commandFactories) {
50
+ yield ctx.commands.register(factory(deps));
51
+ }
52
+ });
53
+ return fiber.await().then(() => {
54
+ let disposing;
55
+ return () => disposing ??= quiesceFiber(fiber);
56
+ });
57
+ }
58
+ async function quiesceFiber(fiber) {
59
+ await Promise.resolve(fiber.dispose());
60
+ while (fiber.inertia !== undefined)
61
+ await fiber.inertia;
62
+ }
63
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAgB,MAAM,qBAAqB,CAAC;AAInD,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAkG9C,MAAM,gBAAgB,GAAG;IACvB,iBAAiB;IACjB,gBAAgB;IAChB,iBAAiB;IACjB,mBAAmB;IACnB,mBAAmB;IACnB,kBAAkB;IAClB,oBAAoB;IACpB,mBAAmB;IACnB,iBAAiB;CAClB,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CACpC,QAAiB,EACjB,IAAgC;IAEhC,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,CAAC,eAAe,CAAC,GAAG;QACvE,KAAK,MAAM,OAAO,IAAI,gBAAgB,EAAE,CAAC;YACvC,MAAM,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC,CAAC,CAAC;IACH,OAAO,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;QAC7B,IAAI,SAAoC,CAAC;QACzC,OAAO,GAAG,EAAE,CAAC,SAAS,KAAK,YAAY,CAAC,KAAK,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,KAAoC;IAC9D,MAAM,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACvC,OAAO,KAAK,CAAC,OAAO,KAAK,SAAS;QAAE,MAAM,KAAK,CAAC,OAAO,CAAC;AAC1D,CAAC"}
@@ -0,0 +1,9 @@
1
+ /** Languages persisted by Harness's `locale.preference` settings namespace. */
2
+ export type ChannelCommandLocale = 'zh' | 'en';
3
+ /**
4
+ * Read the public Harness locale namespace through an optional settings seam.
5
+ * Browser-only navigator fallback is unavailable to IM channels, so an absent
6
+ * or invalid explicit preference preserves the channel's historical zh copy.
7
+ */
8
+ export declare function commandLocaleFromSettings(settings: unknown): ChannelCommandLocale;
9
+ //# sourceMappingURL=locale.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locale.d.ts","sourceRoot":"","sources":["../../src/commands/locale.ts"],"names":[],"mappings":"AAEA,+EAA+E;AAC/E,MAAM,MAAM,oBAAoB,GAAG,IAAI,GAAG,IAAI,CAAC;AAY/C;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,OAAO,GAAG,oBAAoB,CAYjF"}
@@ -0,0 +1,27 @@
1
+ import { z } from 'zod';
2
+ const settingsReaderSchema = z.custom((value) => typeof value === 'object' && value !== null &&
3
+ typeof Reflect.get(value, 'get') === 'function', { message: 'expected a Harness settings reader' });
4
+ const localeSettingsSchema = z.object({
5
+ preference: z.enum(['zh', 'en']).optional(),
6
+ }).passthrough();
7
+ /**
8
+ * Read the public Harness locale namespace through an optional settings seam.
9
+ * Browser-only navigator fallback is unavailable to IM channels, so an absent
10
+ * or invalid explicit preference preserves the channel's historical zh copy.
11
+ */
12
+ export function commandLocaleFromSettings(settings) {
13
+ const reader = settingsReaderSchema.safeParse(settings);
14
+ if (!reader.success)
15
+ return 'zh';
16
+ try {
17
+ // SettingsProvider.get relies on its receiver; call the validated method
18
+ // against the original service rather than zod's parsed object.
19
+ const section = reader.data.get.call(settings, 'locale');
20
+ const parsed = localeSettingsSchema.safeParse(section);
21
+ return parsed.success ? (parsed.data.preference ?? 'zh') : 'zh';
22
+ }
23
+ catch {
24
+ return 'zh';
25
+ }
26
+ }
27
+ //# sourceMappingURL=locale.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locale.js","sourceRoot":"","sources":["../../src/commands/locale.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CACnC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;IACpD,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,UAAU,EACjD,EAAE,OAAO,EAAE,oCAAoC,EAAE,CAClD,CAAC;AAEF,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC5C,CAAC,CAAC,WAAW,EAAE,CAAC;AAEjB;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,QAAiB;IACzD,MAAM,MAAM,GAAG,oBAAoB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACxD,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IACjC,IAAI,CAAC;QACH,yEAAyE;QACzE,gEAAgE;QAChE,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,oBAAoB,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACvD,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAClE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The `/mirror` command (issue #5).
3
+ *
4
+ * Opt-in per-conversation toggle: when ON, turns initiated OUTSIDE the channel
5
+ * (web/CLI) on this bound session deliver their final assistant text to the
6
+ * bound conversation as buffered replies. Default OFF — a non-channel turn
7
+ * never auto-routes without explicit owner consent. The state lives on the
8
+ * durable binding (`SessionBinding.mirror`), so it survives restarts and is
9
+ * consulted by the ReplyRouter at delivery time.
10
+ */
11
+ import { type CommandDefinition } from '@deepseek-ai/dsh-commands';
12
+ import type { ChannelCommandDependencies } from './index.js';
13
+ export declare function createMirrorCommand(deps: ChannelCommandDependencies): CommandDefinition;
14
+ //# sourceMappingURL=mirror.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mirror.d.ts","sourceRoot":"","sources":["../../src/commands/mirror.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAE7D,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,0BAA0B,GAAG,iBAAiB,CAiCvF"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * The `/mirror` command (issue #5).
3
+ *
4
+ * Opt-in per-conversation toggle: when ON, turns initiated OUTSIDE the channel
5
+ * (web/CLI) on this bound session deliver their final assistant text to the
6
+ * bound conversation as buffered replies. Default OFF — a non-channel turn
7
+ * never auto-routes without explicit owner consent. The state lives on the
8
+ * durable binding (`SessionBinding.mirror`), so it survives restarts and is
9
+ * consulted by the ReplyRouter at delivery time.
10
+ */
11
+ import {} from '@deepseek-ai/dsh-commands';
12
+ export function createMirrorCommand(deps) {
13
+ return {
14
+ name: 'mirror',
15
+ description: 'Mirror web-initiated replies to this conversation (opt-in)',
16
+ async handler(invocation) {
17
+ if (!deps.mirror) {
18
+ return { kind: 'error', text: '当前部署不支持镜像模式。' };
19
+ }
20
+ const arg = invocation.rawInput.trim().toLowerCase();
21
+ if (arg === '') {
22
+ const on = await deps.mirror.get(invocation.agent);
23
+ return {
24
+ kind: 'success',
25
+ text: on
26
+ ? '镜像模式:已开启。Web 端发起的回复会同步发送到本会话。'
27
+ : '镜像模式:已关闭。Web 端发起的回复不会发送到本会话(用法:/mirror on|off)。',
28
+ };
29
+ }
30
+ if (arg !== 'on' && arg !== 'off') {
31
+ return { kind: 'error', text: '用法:/mirror on|off(不带参数查看当前状态)。' };
32
+ }
33
+ const on = arg === 'on';
34
+ await deps.mirror.set(invocation.agent, on);
35
+ return {
36
+ kind: 'success',
37
+ text: on
38
+ ? '镜像模式已开启:Web 端发起的回复将同步发送到本会话。'
39
+ : '镜像模式已关闭:Web 端发起的回复不再发送到本会话。',
40
+ };
41
+ },
42
+ };
43
+ }
44
+ //# sourceMappingURL=mirror.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mirror.js","sourceRoot":"","sources":["../../src/commands/mirror.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAA0B,MAAM,2BAA2B,CAAC;AAGnE,MAAM,UAAU,mBAAmB,CAAC,IAAgC;IAClE,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,4DAA4D;QACzE,KAAK,CAAC,OAAO,CAAC,UAAU;YACtB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACjB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;YACjD,CAAC;YACD,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YAErD,IAAI,GAAG,KAAK,EAAE,EAAE,CAAC;gBACf,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;gBACnD,OAAO;oBACL,IAAI,EAAE,SAAS;oBACf,IAAI,EAAE,EAAE;wBACN,CAAC,CAAC,+BAA+B;wBACjC,CAAC,CAAC,iDAAiD;iBACtD,CAAC;YACJ,CAAC;YACD,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;gBAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,gCAAgC,EAAE,CAAC;YACnE,CAAC;YAED,MAAM,EAAE,GAAG,GAAG,KAAK,IAAI,CAAC;YACxB,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC5C,OAAO;gBACL,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,EAAE;oBACN,CAAC,CAAC,8BAA8B;oBAChC,CAAC,CAAC,6BAA6B;aAClC,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * The `/model` command (spec §18–§29).
3
+ *
4
+ * Harness owns model routing. The command validates the requested model and
5
+ * delegates the current-Session switch to the official Host RPC or the
6
+ * headless Agent model-selection hook. The same operation updates the shared
7
+ * default so future Sessions use the selected model as well.
8
+ *
9
+ * Validation: provider must come from `ctx.llm.listProviders()` (spec §28);
10
+ * the exact model is resolved ONCE via `ctx.llm.resolveModelInfo` — catalog
11
+ * membership is ADVISORY and never rejects a model id (spec §17/§29). An
12
+ * optional reasoning effort is then validated against that exact model's own
13
+ * `reasoning.efforts` metadata (the same predicate the official
14
+ * `resolveCallConfig` applies), so unsupported efforts reject without
15
+ * provider I/O and without a second metadata resolution.
16
+ */
17
+ import { type CommandDefinition } from '@deepseek-ai/dsh-commands';
18
+ import type { ChannelCommandDependencies } from './index.js';
19
+ export declare function createModelCommand(deps: ChannelCommandDependencies): CommandDefinition;
20
+ //# sourceMappingURL=model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/commands/model.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAInE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAE7D,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,0BAA0B,GAAG,iBAAiB,CAkFtF"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * The `/model` command (spec §18–§29).
3
+ *
4
+ * Harness owns model routing. The command validates the requested model and
5
+ * delegates the current-Session switch to the official Host RPC or the
6
+ * headless Agent model-selection hook. The same operation updates the shared
7
+ * default so future Sessions use the selected model as well.
8
+ *
9
+ * Validation: provider must come from `ctx.llm.listProviders()` (spec §28);
10
+ * the exact model is resolved ONCE via `ctx.llm.resolveModelInfo` — catalog
11
+ * membership is ADVISORY and never rejects a model id (spec §17/§29). An
12
+ * optional reasoning effort is then validated against that exact model's own
13
+ * `reasoning.efforts` metadata (the same predicate the official
14
+ * `resolveCallConfig` applies), so unsupported efforts reject without
15
+ * provider I/O and without a second metadata resolution.
16
+ */
17
+ import {} from '@deepseek-ai/dsh-commands';
18
+ import { ReasoningEffortId } from '@deepseek-ai/dsh-llm';
19
+ export function createModelCommand(deps) {
20
+ return {
21
+ name: 'model',
22
+ description: 'Show or switch the current model',
23
+ input: { hint: '[<provider> <model> [<reasoningEffort>]]' },
24
+ async handler(invocation) {
25
+ const llm = deps.llm;
26
+ const args = invocation.rawInput
27
+ .trim()
28
+ .split(/\s+/)
29
+ .filter((token) => token.length > 0);
30
+ if (args.length === 0) {
31
+ const selection = await deps.modelSelection.current(invocation.agent);
32
+ if (!selection) {
33
+ return { kind: 'success', text: ['当前模型', '', '(未解析到模型选择)'].join('\n') };
34
+ }
35
+ return { kind: 'success', text: formatSelection('当前模型', selection) };
36
+ }
37
+ if (args.length > 3) {
38
+ return { kind: 'error', text: '用法:/model [<provider> <model> [<reasoningEffort>]]' };
39
+ }
40
+ const [providerId, modelId, effort] = args;
41
+ if (!modelId) {
42
+ return { kind: 'error', text: '用法:/model [<provider> <model> [<reasoningEffort>]]' };
43
+ }
44
+ // 1. Provider must be a registered route (spec §28).
45
+ const providers = llm.listProviders();
46
+ if (!providers.some((p) => p.id === providerId)) {
47
+ return {
48
+ kind: 'error',
49
+ text: '未找到 Provider: ' + providerId + (providers.length > 0 ? '\n\n可用:\n' + providers.map((p) => p.id).join('\n') : ''),
50
+ };
51
+ }
52
+ // 2. Exact model metadata resolution (catalog membership is advisory).
53
+ let resolved;
54
+ try {
55
+ resolved = await llm.resolveModelInfo(providerId, modelId, invocation.signal);
56
+ }
57
+ catch (error) {
58
+ return { kind: 'error', text: '模型解析失败:' + errorMessage(error) };
59
+ }
60
+ // 3. Reasoning-effort validation against the exact model's metadata
61
+ // (spec §29). `resolved.reasoning.efforts` is the adapter-owned truth
62
+ // for this exact route; the same predicate the official
63
+ // `resolveCallConfig` applies — reject an explicit unsupported effort
64
+ // here, without a second metadata resolution or provider I/O.
65
+ let reasoningEffort;
66
+ if (effort) {
67
+ const supported = resolved?.reasoning?.efforts ?? [];
68
+ if (!supported.some((e) => String(e.id) === effort)) {
69
+ return {
70
+ kind: 'error',
71
+ text: 'Reasoning effort 不被支持: ' + effort + (supported.length > 0 ? '\n\n支持:' + supported.map((e) => String(e.id)).join(', ') : ''),
72
+ };
73
+ }
74
+ reasoningEffort = ReasoningEffortId(effort);
75
+ }
76
+ // 4. Delegate the live Session switch. The controller also persists the
77
+ // shared default for future Sessions, matching Harness's model command.
78
+ const selection = {
79
+ provider: providerId,
80
+ model: modelId,
81
+ ...(reasoningEffort ? { reasoningEffort } : {}),
82
+ };
83
+ try {
84
+ await deps.modelSelection.select(invocation.agent, selection);
85
+ }
86
+ catch (error) {
87
+ return { kind: 'error', text: '模型切换失败:' + errorMessage(error) };
88
+ }
89
+ // 5. Report success.
90
+ return {
91
+ kind: 'success',
92
+ text: formatSelection('模型已切换:', selection) + '\n\n当前会话从下一次模型执行开始生效;该选择也会成为新会话默认。',
93
+ };
94
+ },
95
+ };
96
+ }
97
+ function formatSelection(header, selection) {
98
+ const lines = [header, '', 'Provider: ' + selection.provider, 'Model: ' + selection.model];
99
+ if (selection.reasoningEffort)
100
+ lines.push('Reasoning: ' + String(selection.reasoningEffort));
101
+ return lines.join('\n');
102
+ }
103
+ function errorMessage(error) {
104
+ return error instanceof Error ? error.message : String(error);
105
+ }
106
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/commands/model.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The `/models` command (spec §15–§17).
3
+ *
4
+ * Model DISCOVERY only: reads the Harness LLM adapter registry through the
5
+ * official `deps.llm` catalog seam (listProviders / listModels) — the channel never
6
+ * touches provider HTTP endpoints and never treats the catalog as
7
+ * authoritative. Catalog membership is ADVISORY (spec §17): it is used for
8
+ * display only; `/model` performs exact resolution separately. A provider
9
+ * whose model listing fails must not fail the whole command (spec §15).
10
+ */
11
+ import { type CommandDefinition } from '@deepseek-ai/dsh-commands';
12
+ import type { ChannelCommandDependencies } from './index.js';
13
+ export declare function createModelsCommand(deps: ChannelCommandDependencies): CommandDefinition;
14
+ //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/commands/models.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,OAAO,KAAK,EAAE,0BAA0B,EAAuB,MAAM,YAAY,CAAC;AAElF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,0BAA0B,GAAG,iBAAiB,CAkCvF"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * The `/models` command (spec §15–§17).
3
+ *
4
+ * Model DISCOVERY only: reads the Harness LLM adapter registry through the
5
+ * official `deps.llm` catalog seam (listProviders / listModels) — the channel never
6
+ * touches provider HTTP endpoints and never treats the catalog as
7
+ * authoritative. Catalog membership is ADVISORY (spec §17): it is used for
8
+ * display only; `/model` performs exact resolution separately. A provider
9
+ * whose model listing fails must not fail the whole command (spec §15).
10
+ */
11
+ import {} from '@deepseek-ai/dsh-commands';
12
+ export function createModelsCommand(deps) {
13
+ return {
14
+ name: 'models',
15
+ description: 'List registered model providers and their models',
16
+ input: { hint: '[provider]' },
17
+ async handler(invocation) {
18
+ const llm = deps.llm;
19
+ const providers = llm.listProviders();
20
+ const filter = invocation.rawInput.trim();
21
+ if (filter.length > 0) {
22
+ const provider = providers.find((p) => p.id === filter);
23
+ if (!provider) {
24
+ return {
25
+ kind: 'error',
26
+ text: '未找到 Provider: ' + filter + availableSuffix(providers),
27
+ };
28
+ }
29
+ return { kind: 'success', text: (await buildProviderLines(llm, provider)).join('\n') };
30
+ }
31
+ if (providers.length === 0) {
32
+ return { kind: 'success', text: '当前没有已注册的模型 Provider。' };
33
+ }
34
+ const sections = await Promise.all(providers.map((p) => buildProviderLines(llm, p)));
35
+ const lines = [];
36
+ for (const section of sections) {
37
+ if (lines.length > 0)
38
+ lines.push('');
39
+ lines.push(...section);
40
+ }
41
+ return { kind: 'success', text: lines.join('\n') };
42
+ },
43
+ };
44
+ }
45
+ function availableSuffix(providers) {
46
+ if (providers.length === 0)
47
+ return '';
48
+ return '\n\n可用:\n' + providers.map((p) => p.id).join('\n');
49
+ }
50
+ async function buildProviderLines(llm, provider) {
51
+ const lines = [provider.name + ' (' + provider.id + ')'];
52
+ try {
53
+ const models = await llm.listModels(provider.id);
54
+ if (models.length === 0) {
55
+ lines.push('- (无模型)');
56
+ }
57
+ else {
58
+ for (const model of models)
59
+ lines.push('- ' + model.id);
60
+ }
61
+ }
62
+ catch {
63
+ lines.push('- 模型目录获取失败');
64
+ }
65
+ return lines;
66
+ }
67
+ //# sourceMappingURL=models.js.map