@buyi1net/pi-toolkit 0.0.1

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 (129) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +45 -0
  3. package/assembler.ts +127 -0
  4. package/config.ts +201 -0
  5. package/i18n.ts +693 -0
  6. package/index.ts +99 -0
  7. package/menu/items.ts +264 -0
  8. package/menu/panels.ts +91 -0
  9. package/menu/settings-list.ts +84 -0
  10. package/menu/theme.ts +31 -0
  11. package/menu/toolkit-menu.ts +139 -0
  12. package/module.ts +156 -0
  13. package/modules/eyes/chain.ts +173 -0
  14. package/modules/eyes/config.ts +319 -0
  15. package/modules/eyes/index.ts +161 -0
  16. package/modules/eyes/menu.ts +828 -0
  17. package/modules/eyes/pi-model-backend.ts +245 -0
  18. package/modules/eyes/resilience.ts +161 -0
  19. package/modules/eyes/vision-bridge.ts +232 -0
  20. package/modules/eyes/vision-cache.ts +86 -0
  21. package/modules/eyes/vision-json.ts +19 -0
  22. package/modules/eyes/vision-preprocess.ts +192 -0
  23. package/modules/eyes/vision-probe.ts +21 -0
  24. package/modules/eyes/vision-prompt.ts +90 -0
  25. package/modules/eyes/vision-tool.ts +59 -0
  26. package/modules/eyes/vision-types.ts +33 -0
  27. package/modules/index.ts +10 -0
  28. package/modules/subagents/agents/researcher.md +51 -0
  29. package/modules/subagents/agents/scout.md +40 -0
  30. package/modules/subagents/agents/worker.md +79 -0
  31. package/modules/subagents/config.json.example +6 -0
  32. package/modules/subagents/config.ts +144 -0
  33. package/modules/subagents/index.ts +91 -0
  34. package/modules/subagents/menu.ts +388 -0
  35. package/modules/subagents/src/activity.ts +511 -0
  36. package/modules/subagents/src/agents.ts +126 -0
  37. package/modules/subagents/src/command.ts +37 -0
  38. package/modules/subagents/src/dependencies.ts +246 -0
  39. package/modules/subagents/src/diagnostics.ts +13 -0
  40. package/modules/subagents/src/display.ts +94 -0
  41. package/modules/subagents/src/headless.ts +342 -0
  42. package/modules/subagents/src/herdr.ts +203 -0
  43. package/modules/subagents/src/index.ts +2798 -0
  44. package/modules/subagents/src/inspect-tool.ts +839 -0
  45. package/modules/subagents/src/launch-config.ts +196 -0
  46. package/modules/subagents/src/layout-budget.ts +26 -0
  47. package/modules/subagents/src/list-tool.ts +292 -0
  48. package/modules/subagents/src/message-tool.ts +808 -0
  49. package/modules/subagents/src/names.ts +17 -0
  50. package/modules/subagents/src/pane-layout.ts +49 -0
  51. package/modules/subagents/src/params.ts +145 -0
  52. package/modules/subagents/src/renderers.ts +181 -0
  53. package/modules/subagents/src/result.ts +43 -0
  54. package/modules/subagents/src/retention.ts +114 -0
  55. package/modules/subagents/src/route-error.ts +212 -0
  56. package/modules/subagents/src/routing.ts +235 -0
  57. package/modules/subagents/src/runtime-registry.ts +159 -0
  58. package/modules/subagents/src/session.ts +801 -0
  59. package/modules/subagents/src/status.ts +513 -0
  60. package/modules/subagents/src/stop-tool.ts +235 -0
  61. package/modules/subagents/src/subagent-done.ts +590 -0
  62. package/modules/subagents/src/subagent-tool.ts +1155 -0
  63. package/modules/subagents/src/surface.ts +355 -0
  64. package/modules/subagents/src/team-dispatch-tool.ts +219 -0
  65. package/modules/subagents/src/team.ts +232 -0
  66. package/modules/subagents/src/tmux.ts +210 -0
  67. package/modules/subagents/src/tools/safe-bash.ts +72 -0
  68. package/modules/subagents/src/types.ts +131 -0
  69. package/modules/tui/adapter/provider-usage.ts +143 -0
  70. package/modules/tui/config.ts +50 -0
  71. package/modules/tui/index.ts +120 -0
  72. package/modules/tui/kernel/pkg/shared/grok-subscription.ts +169 -0
  73. package/modules/tui/kernel/pkg/shared/official-subscription.ts +237 -0
  74. package/modules/tui/kernel/pkg/shared/provider-catalog.ts +367 -0
  75. package/modules/tui/kernel/pkg/shared/provider-contracts.ts +150 -0
  76. package/modules/tui/kernel/pkg/shared/provider-display.ts +55 -0
  77. package/modules/tui/kernel/pkg/shared/provider-parsers.ts +171 -0
  78. package/modules/tui/kernel/pkg/shared/volcengine.ts +191 -0
  79. package/modules/tui/kernel/pkg/shared/zhipu.ts +149 -0
  80. package/modules/tui/kernel/pkg/usage-core/index.ts +335 -0
  81. package/modules/tui/kernel/pkg/usage-core/provider-routes.ts +187 -0
  82. package/modules/tui/kernel/pkg/usage-node/index.ts +635 -0
  83. package/modules/tui/kernel/pkg/usage-node/provider-usage.ts +388 -0
  84. package/modules/tui/kernel/usage-core.ts +2 -0
  85. package/modules/tui/kernel/usage-node.ts +2 -0
  86. package/modules/tui/menu.ts +418 -0
  87. package/modules/tui/plugin/editor.ts +396 -0
  88. package/modules/tui/plugin/footer.ts +161 -0
  89. package/modules/tui/plugin/index.ts +30 -0
  90. package/modules/tui/plugin/lifecycle.ts +637 -0
  91. package/modules/tui/plugin/package-order.ts +169 -0
  92. package/modules/tui/plugin/screen-transition.ts +203 -0
  93. package/modules/tui/plugin/settings-config.ts +297 -0
  94. package/modules/tui/plugin/status-sources.ts +49 -0
  95. package/modules/tui/plugin/transition-gate.ts +261 -0
  96. package/modules/tui/renderer/custom-header.ts +157 -0
  97. package/modules/tui/renderer/editor.ts +70 -0
  98. package/modules/tui/renderer/header.ts +72 -0
  99. package/modules/tui/renderer/icons.ts +149 -0
  100. package/modules/tui/renderer/pi-installer-logo.ts +194 -0
  101. package/modules/tui/status/auto-compaction.ts +67 -0
  102. package/modules/tui/status/project-status.ts +655 -0
  103. package/modules/tui/status/provider-status.ts +120 -0
  104. package/modules/tui/status/runtime-status.ts +307 -0
  105. package/modules/tui/status/session-status.ts +325 -0
  106. package/modules/tui/status/status-config.ts +95 -0
  107. package/modules/tui/status/status-segments.ts +263 -0
  108. package/modules/tui/status/turn-telemetry.ts +466 -0
  109. package/modules/tui/themes/LICENSE.pi-themes-bundle +21 -0
  110. package/modules/tui/themes/UPSTREAM.md +7 -0
  111. package/modules/tui/themes/catppuccin-latte.json +80 -0
  112. package/modules/tui/themes/catppuccin-mocha.json +79 -0
  113. package/modules/tui/themes/crimson-noir.json +85 -0
  114. package/modules/tui/themes/dracula.json +79 -0
  115. package/modules/tui/themes/everforest-dark.json +85 -0
  116. package/modules/tui/themes/gruvbox-dark.json +85 -0
  117. package/modules/tui/themes/gruvbox-light.json +85 -0
  118. package/modules/tui/themes/matrix.json +85 -0
  119. package/modules/tui/themes/nord.json +85 -0
  120. package/modules/tui/themes/one-dark.json +85 -0
  121. package/modules/tui/themes/rose-pine-dawn.json +85 -0
  122. package/modules/tui/themes/rose-pine.json +85 -0
  123. package/modules/tui/themes/solarized-dark.json +85 -0
  124. package/modules/tui/themes/solarized-light.json +85 -0
  125. package/modules/tui/themes/tokyo-night-storm.json +79 -0
  126. package/modules/tui/themes/tokyo-night.json +79 -0
  127. package/package.json +28 -0
  128. package/services.ts +38 -0
  129. package/toolkit.ts +147 -0
@@ -0,0 +1,388 @@
1
+ // 子代理配置子菜单:子代理组里的 `子代理配置` 行打开这一页(原生 SettingsList 形态)。
2
+ // 页面五行:
3
+ // 状态显示 —— 对应 pi-toolkit.json `modules.subagents.status.enabled`(开/关)
4
+ // fast 档模型 —— SelectList 选模型,候选来自 ctx.modelRegistry
5
+ // balanced 档模型
6
+ // deep 档模型
7
+ // tier 路由状态 —— 只读展示当前生效的 tier 路由解析结果
8
+ //
9
+ // 写盘落点(工单 04 归一裁决)全在 pi-toolkit.json 的 `modules.subagents` 节;
10
+ // tier 解析仍是六级覆盖链,本页只写第 4 级。缺映射时行描述直接用
11
+ // src/routing.ts 的原版报错文案(不翻译、不改写),与真正 spawn 时抛出的字符串一致。
12
+
13
+ import { type ExtensionContext, type ModelRegistry } from "@earendil-works/pi-coding-agent";
14
+ import { Container, type SettingItem, Text } from "@earendil-works/pi-tui";
15
+ import type { Translator } from "../../i18n.ts";
16
+ import { ChoicePicker } from "../../menu/panels.ts";
17
+ import { I18nSettingsList } from "../../menu/settings-list.ts";
18
+ import type { MenuTheme } from "../../menu/theme.ts";
19
+ import type { ModuleMenuContext } from "../../module.ts";
20
+ import {
21
+ loadEffectiveTierConfig,
22
+ MODEL_TIERS,
23
+ readSubagentsSection,
24
+ saveStatusEnabled,
25
+ saveTierModel,
26
+ tierRouteError,
27
+ type ModelTier,
28
+ type TierConfigLoadResult,
29
+ type TierMapping,
30
+ } from "./config.ts";
31
+ import { loadStatusConfig } from "./src/status.ts";
32
+
33
+ /**
34
+ * 包内 config.json(→ config.json.example)的 status.enabled:
35
+ * 本节点未声明时的兜底默认。读不出来时按开启处理(与 example 一致)。
36
+ */
37
+ export function readPackageStatusEnabled(): boolean {
38
+ try {
39
+ return loadStatusConfig().enabled;
40
+ } catch {
41
+ return true;
42
+ }
43
+ }
44
+
45
+ /** 分组页里的入口行 id */
46
+ export const SUBAGENTS_MENU_ITEM_ID = "subagents.settings";
47
+
48
+ const ROW_STATUS = "subagents.settings.status";
49
+ const ROW_ROUTE = "subagents.settings.route";
50
+
51
+ export function tierRowId(tier: ModelTier): string {
52
+ return `subagents.settings.tier.${tier}`;
53
+ }
54
+
55
+ /** 面板行的 id 清单(渲染顺序,自测用) */
56
+ export function panelRowIds(): readonly string[] {
57
+ return [ROW_STATUS, ...MODEL_TIERS.map(tierRowId), ROW_ROUTE];
58
+ }
59
+
60
+ /** 菜单需要的模型注册表能力(取 ModelRegistry 的子集,方便 headless 自测塞 stub) */
61
+ export type TierMenuRegistry = Pick<ModelRegistry, "getAll" | "hasConfiguredAuth">;
62
+
63
+ export interface TierCandidate {
64
+ readonly provider: string;
65
+ readonly modelId: string;
66
+ /** 该供应商已配置认证;只用于排序与候选描述 */
67
+ readonly authenticated: boolean;
68
+ }
69
+
70
+ export function tierCandidateValue(candidate: { provider: string; modelId: string }): string {
71
+ return `${candidate.provider}/${candidate.modelId}`;
72
+ }
73
+
74
+ /** 候选 = 模型目录里的全部模型;已认证的排前面,其余按 provider/model 排序 */
75
+ export function discoverTierCandidates(registry: TierMenuRegistry): TierCandidate[] {
76
+ const candidates: TierCandidate[] = [];
77
+ const seen = new Set<string>();
78
+ for (const model of registry.getAll()) {
79
+ const selection = { provider: model.provider, modelId: model.id };
80
+ const key = tierCandidateValue(selection);
81
+ if (seen.has(key)) continue;
82
+ seen.add(key);
83
+ candidates.push({ ...selection, authenticated: registry.hasConfiguredAuth(model) });
84
+ }
85
+ candidates.sort((left, right) => {
86
+ if (left.authenticated !== right.authenticated) return left.authenticated ? -1 : 1;
87
+ return tierCandidateValue(left).localeCompare(tierCandidateValue(right));
88
+ });
89
+ return candidates;
90
+ }
91
+
92
+ /** 一行里展示的 tier 取值:没配就显示"未配置"文案 */
93
+ export function tierRowValue(tier: ModelTier, mapping: TierMapping, t: Translator): string {
94
+ return mapping[tier] ?? t("module.subagents.tier.unmapped");
95
+ }
96
+
97
+ /** 只读路由摘要:逐档展示取值,配置读取本身出错时把原版错误一并带上 */
98
+ export function tierRoutingSummary(
99
+ load: TierConfigLoadResult,
100
+ mapping: TierMapping,
101
+ t: Translator,
102
+ ): string {
103
+ const parts = MODEL_TIERS.map((tier) => `${tier}=${tierRowValue(tier, mapping, t)}`);
104
+ if (load.error) return `${parts.join(" · ")} · ${load.error}`;
105
+ return parts.join(" · ");
106
+ }
107
+
108
+ /**
109
+ * 第一档缺映射时的原版报错文案。取 src/routing.ts 的 resolveTierForParams 输出,
110
+ * 与真正 spawn 时抛出的字符串逐字一致;三档都配齐时返回 undefined。
111
+ */
112
+ export function firstTierProblem(
113
+ mapping: TierMapping,
114
+ load: () => TierConfigLoadResult,
115
+ ): string | undefined {
116
+ for (const tier of MODEL_TIERS) {
117
+ if (mapping[tier]) continue;
118
+ const error = tierRouteError(tier, load);
119
+ if (error) return error;
120
+ }
121
+ return undefined;
122
+ }
123
+
124
+ export interface SubagentsMenuRuntime {
125
+ /** 写盘后重载状态中枢的内存副本,让 getConfig() 跟上磁盘 */
126
+ reload: () => Promise<void>;
127
+ }
128
+
129
+ export interface SubagentsPanelOptions {
130
+ readonly t: Translator;
131
+ readonly theme: MenuTheme;
132
+ readonly context: ExtensionContext;
133
+ readonly agentDir: string;
134
+ readonly runtime: SubagentsMenuRuntime;
135
+ readonly requestRender: () => void;
136
+ /** 读本模块配置节(实时) */
137
+ readonly getSection: () => Record<string, unknown>;
138
+ /** 包内 config.json(→ example)的 status.enabled,作为本节点未声明时的兜底默认 */
139
+ readonly packageStatusEnabled: boolean;
140
+ readonly onDone: (value: string) => void;
141
+ }
142
+
143
+ function describeError(error: unknown): string {
144
+ return error instanceof Error ? error.message : String(error);
145
+ }
146
+
147
+ // ─────────────────────────────────────────────────────────────
148
+ // 纯逻辑:面板行的数值与状态
149
+ // ─────────────────────────────────────────────────────────────
150
+
151
+ export interface SubagentsPanelState {
152
+ readonly mapping: TierMapping;
153
+ readonly statusEnabled: boolean | undefined;
154
+ readonly problems: readonly string[];
155
+ }
156
+
157
+ export function readPanelState(section: Record<string, unknown>): SubagentsPanelState {
158
+ const view = readSubagentsSection(section);
159
+ return { mapping: view.tier, statusEnabled: view.statusEnabled, problems: view.problems };
160
+ }
161
+
162
+ /** 状态显示开关的显示值:本节点未声明时展示包内兜底默认 */
163
+ export function statusRowValue(
164
+ state: SubagentsPanelState,
165
+ fallbackEnabled: boolean,
166
+ t: Translator,
167
+ ): string {
168
+ const enabled = state.statusEnabled ?? fallbackEnabled;
169
+ return enabled ? t("common.on") : t("common.off");
170
+ }
171
+
172
+ /** 已配置档位计数文案(入口行的当前值) */
173
+ export function configuredCountValue(mapping: TierMapping, t: Translator): string {
174
+ const configured = MODEL_TIERS.filter((tier) => mapping[tier]).length;
175
+ return t("module.subagents.menu.value", { configured, total: MODEL_TIERS.length });
176
+ }
177
+
178
+ export interface SaveOutcome {
179
+ readonly ok: boolean;
180
+ readonly error?: string;
181
+ }
182
+
183
+ /** 写一档 tier 并让状态中枢重载配置;返回结果供 UI 与自测判定 */
184
+ export async function saveTier(
185
+ options: SubagentsPanelOptions,
186
+ tier: ModelTier,
187
+ model: string,
188
+ ): Promise<SaveOutcome> {
189
+ try {
190
+ await saveTierModel(tier, model, { agentDir: options.agentDir });
191
+ await options.runtime.reload();
192
+ return { ok: true };
193
+ } catch (error) {
194
+ return { ok: false, error: describeError(error) };
195
+ }
196
+ }
197
+
198
+ /** 写状态显示开关并让状态中枢重载配置 */
199
+ export async function saveStatus(
200
+ options: SubagentsPanelOptions,
201
+ enabled: boolean,
202
+ ): Promise<SaveOutcome> {
203
+ try {
204
+ await saveStatusEnabled(enabled, { agentDir: options.agentDir });
205
+ await options.runtime.reload();
206
+ return { ok: true };
207
+ } catch (error) {
208
+ return { ok: false, error: describeError(error) };
209
+ }
210
+ }
211
+
212
+ // ─────────────────────────────────────────────────────────────
213
+ // UI:配置面板
214
+ // ─────────────────────────────────────────────────────────────
215
+
216
+ export class SubagentsPanel extends Container {
217
+ private readonly options: SubagentsPanelOptions;
218
+ private list: I18nSettingsList | undefined;
219
+ private candidates: TierCandidate[];
220
+ private state: SubagentsPanelState;
221
+
222
+ constructor(options: SubagentsPanelOptions) {
223
+ super();
224
+ this.options = options;
225
+ this.candidates = discoverTierCandidates(options.context.modelRegistry);
226
+ this.state = readPanelState(options.getSection());
227
+ this.addChild(new Text(options.theme.title(options.t("module.subagents.menu.label")), 1, 0));
228
+ this.list = new I18nSettingsList({
229
+ items: this.buildItems(),
230
+ maxVisible: 8,
231
+ theme: options.theme.settings,
232
+ t: options.t,
233
+ onChange: () => {},
234
+ onCancel: () => this.close(),
235
+ });
236
+ this.addChild(this.list);
237
+ }
238
+
239
+ /** 当前生效的 tier 配置(与 spawn 同一规则) */
240
+ loadTierConfig(): TierConfigLoadResult {
241
+ return loadEffectiveTierConfig({ cwd: this.options.context.cwd, agentDir: this.options.agentDir });
242
+ }
243
+
244
+ handleInput(data: string): void {
245
+ this.list?.handleInput(data);
246
+ }
247
+
248
+ private close(): void {
249
+ this.options.onDone(configuredCountValue(this.state.mapping, this.options.t));
250
+ }
251
+
252
+ /** 写盘失败只提示,不改任何取值 */
253
+ private reportSave(outcome: SaveOutcome): void {
254
+ if (outcome.ok) return;
255
+ this.options.context.ui.notify(
256
+ this.options.t("notify.saveFailed", { reason: outcome.error ?? "" }),
257
+ "error",
258
+ );
259
+ }
260
+
261
+ private refreshRows(): void {
262
+ this.state = readPanelState(this.options.getSection());
263
+ const t = this.options.t;
264
+ for (const tier of MODEL_TIERS) {
265
+ this.list?.updateValue(tierRowId(tier), tierRowValue(tier, this.state.mapping, t));
266
+ }
267
+ this.list?.updateValue(ROW_STATUS, statusRowValue(this.state, this.options.packageStatusEnabled, t));
268
+ this.list?.updateValue(ROW_ROUTE, tierRoutingSummary(this.loadTierConfig(), this.state.mapping, t));
269
+ this.options.requestRender();
270
+ }
271
+
272
+ private tierDescription(tier: ModelTier): string {
273
+ if (this.state.mapping[tier]) {
274
+ return this.options.t("module.subagents.tier.description", { tier });
275
+ }
276
+ // 缺映射:直接用 src/routing.ts 的原版报错文案(不翻译,保证与原版逐字一致)
277
+ return tierRouteError(tier, () => this.loadTierConfig())
278
+ ?? this.options.t("module.subagents.tier.description", { tier });
279
+ }
280
+
281
+ private buildItems(): SettingItem[] {
282
+ const t = this.options.t;
283
+ const items: SettingItem[] = [];
284
+
285
+ items.push({
286
+ id: ROW_STATUS,
287
+ label: t("module.subagents.status.label"),
288
+ description: t("module.subagents.status.description"),
289
+ currentValue: statusRowValue(this.state, this.options.packageStatusEnabled, t),
290
+ submenu: (_currentValue, done) => {
291
+ const enabledNow = (this.state.statusEnabled ?? this.options.packageStatusEnabled) === true;
292
+ return new ChoicePicker({
293
+ title: t("module.subagents.status.label"),
294
+ theme: this.options.theme,
295
+ t,
296
+ options: [
297
+ { value: "true", label: t("common.on"), ...(enabledNow ? { description: t("common.current") } : {}) },
298
+ { value: "false", label: t("common.off"), ...(enabledNow ? {} : { description: t("common.current") }) },
299
+ ],
300
+ onSelect: (value, label) => {
301
+ void (async () => {
302
+ const outcome = await saveStatus(this.options, value === "true");
303
+ this.reportSave(outcome);
304
+ if (outcome.ok) this.refreshRows();
305
+ done(outcome.ok ? label : undefined);
306
+ })();
307
+ },
308
+ onCancel: () => done(),
309
+ });
310
+ },
311
+ });
312
+
313
+ for (const tier of MODEL_TIERS) {
314
+ items.push({
315
+ id: tierRowId(tier),
316
+ label: t("module.subagents.tier.label", { tier }),
317
+ description: this.tierDescription(tier),
318
+ currentValue: tierRowValue(tier, this.state.mapping, t),
319
+ submenu: (_currentValue, done) =>
320
+ new ChoicePicker({
321
+ title: t("module.subagents.tier.label", { tier }),
322
+ theme: this.options.theme,
323
+ t,
324
+ options: this.candidates.map((candidate) => ({
325
+ value: tierCandidateValue(candidate),
326
+ label: tierCandidateValue(candidate),
327
+ description: candidate.authenticated
328
+ ? t("module.subagents.tier.authenticated")
329
+ : t("module.subagents.tier.noAuthRequired"),
330
+ })),
331
+ onSelect: (value, label) => {
332
+ void (async () => {
333
+ const outcome = await saveTier(this.options, tier, value);
334
+ this.reportSave(outcome);
335
+ if (outcome.ok) this.refreshRows();
336
+ done(outcome.ok ? label : undefined);
337
+ })();
338
+ },
339
+ onCancel: () => done(),
340
+ }),
341
+ });
342
+ }
343
+
344
+ items.push({
345
+ id: ROW_ROUTE,
346
+ label: t("module.subagents.route.label"),
347
+ description: t("module.subagents.route.description"),
348
+ currentValue: tierRoutingSummary(this.loadTierConfig(), this.state.mapping, t),
349
+ });
350
+
351
+ return items;
352
+ }
353
+ }
354
+
355
+ /** 模块的菜单行:一行入口,进去是子代理配置页 */
356
+ export function buildSubagentsMenuItems(
357
+ context: ModuleMenuContext,
358
+ runtime: SubagentsMenuRuntime,
359
+ ): readonly SettingItem[] {
360
+ const t = context.t;
361
+ const section = context.getConfig();
362
+ const state = readPanelState(section);
363
+ const load = () =>
364
+ loadEffectiveTierConfig({ cwd: context.context.cwd, agentDir: context.agentDir });
365
+ // 缺映射(或本节点配置非法)时把原版报错摆在入口行的描述里,不进子菜单也能看见
366
+ const problem = firstTierProblem(state.mapping, load) ?? state.problems[0];
367
+
368
+ return [
369
+ {
370
+ id: SUBAGENTS_MENU_ITEM_ID,
371
+ label: t("module.subagents.menu.label"),
372
+ description: problem ?? t("module.subagents.menu.description"),
373
+ currentValue: configuredCountValue(state.mapping, t),
374
+ submenu: (_currentValue, done) =>
375
+ new SubagentsPanel({
376
+ t,
377
+ theme: context.theme,
378
+ context: context.context,
379
+ agentDir: context.agentDir,
380
+ runtime,
381
+ requestRender: () => context.requestRender(),
382
+ getSection: () => context.getConfig(),
383
+ packageStatusEnabled: readPackageStatusEnabled(),
384
+ onDone: (value) => done(value),
385
+ }),
386
+ },
387
+ ];
388
+ }