dsh-connect 0.6.7 → 0.7.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 (55) hide show
  1. package/lib/binding.d.ts +2 -0
  2. package/lib/binding.d.ts.map +1 -1
  3. package/lib/binding.js +1 -1
  4. package/lib/binding.js.map +1 -1
  5. package/lib/commands.d.ts +10 -1
  6. package/lib/commands.d.ts.map +1 -1
  7. package/lib/commands.js +18 -6
  8. package/lib/commands.js.map +1 -1
  9. package/lib/dedup.d.ts +31 -0
  10. package/lib/dedup.d.ts.map +1 -0
  11. package/lib/dedup.js +52 -0
  12. package/lib/dedup.js.map +1 -0
  13. package/lib/i18n.d.ts +17 -1
  14. package/lib/i18n.d.ts.map +1 -1
  15. package/lib/i18n.js +34 -2
  16. package/lib/i18n.js.map +1 -1
  17. package/lib/index.d.ts +17 -4
  18. package/lib/index.d.ts.map +1 -1
  19. package/lib/index.js +9 -2
  20. package/lib/index.js.map +1 -1
  21. package/lib/menu-controller.d.ts +71 -0
  22. package/lib/menu-controller.d.ts.map +1 -0
  23. package/lib/menu-controller.js +284 -0
  24. package/lib/menu-controller.js.map +1 -0
  25. package/lib/menus.d.ts +62 -0
  26. package/lib/menus.d.ts.map +1 -0
  27. package/lib/menus.js +99 -0
  28. package/lib/menus.js.map +1 -0
  29. package/lib/mirror-lock.d.ts +51 -0
  30. package/lib/mirror-lock.d.ts.map +1 -0
  31. package/lib/mirror-lock.js +56 -0
  32. package/lib/mirror-lock.js.map +1 -0
  33. package/lib/retry.d.ts +35 -0
  34. package/lib/retry.d.ts.map +1 -0
  35. package/lib/retry.js +41 -0
  36. package/lib/retry.js.map +1 -0
  37. package/lib/runner.d.ts +93 -95
  38. package/lib/runner.d.ts.map +1 -1
  39. package/lib/runner.js +259 -714
  40. package/lib/runner.js.map +1 -1
  41. package/lib/scheduler.d.ts +46 -0
  42. package/lib/scheduler.d.ts.map +1 -0
  43. package/lib/scheduler.js +162 -0
  44. package/lib/scheduler.js.map +1 -0
  45. package/lib/service.d.ts +27 -0
  46. package/lib/service.d.ts.map +1 -1
  47. package/lib/service.js +106 -3
  48. package/lib/service.js.map +1 -1
  49. package/lib/stream.d.ts +62 -2
  50. package/lib/stream.d.ts.map +1 -1
  51. package/lib/stream.js +270 -0
  52. package/lib/stream.js.map +1 -1
  53. package/lib/types.d.ts +19 -0
  54. package/lib/types.d.ts.map +1 -1
  55. package/package.json +2 -2
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,CAAC,MAAM,0BAA0B,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,oBAAoB,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEhK,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEvE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEvD,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAgBrC,qDAAqD;AACrD,MAAM,CAAC,MAAM,IAAI,GAAG,SAAS,CAAC;AAE9B,6EAA6E;AAC7E,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,QAAQ,EAAE,UAAU,EAAE,mBAAmB,CAAC,CAAC;AAElE,wEAAwE;AACxE,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7B,qFAAqF;IACrF,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,yEAAyE;IACzE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,oEAAoE;IACpE,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC/B,uFAAuF;IACvF,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;IAClE,4DAA4D;IAC5D,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IACjD,qDAAqD;IACrD,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC/B,iDAAiD;IACjD,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC/B,qDAAqD;IACrD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,0EAA0E;IAC1E,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE;IACvB,6FAA6F;IAC7F,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE;IAC7B,+EAA+E;IAC/E,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;IAChF,4GAA4G;IAC5G,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE;CAC9B,CAAC,CAAC;AAQH,qFAAqF;AACrF,MAAM,UAAU,KAAK,CAAC,GAAY,EAAE,SAA+B,EAAE;IACnE,sEAAsE;IACtE,yEAAyE;IACzE,KAAK,IAAI,cAAc,CAAC,GAAG,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC;AAC7C,CAAC;AAED,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Menu navigation controller.
3
+ *
4
+ * Renders card menus and routes button / dropdown selections to the per-chat
5
+ * driver (`MenuHost`). The driver owns session / queue / lock runtime state;
6
+ * this controller only needs the read-only hosts (messages, adapter, bindings)
7
+ * plus the side-effect callbacks that perform an action, so the menu concern is
8
+ * split out without the controller reaching into the driver's mutable state.
9
+ * @module dsh-connect/menu-controller
10
+ */
11
+ import type { Context } from "@deepseek-ai/cordis";
12
+ import type { ModelSelection } from "@deepseek-ai/dsh-agent";
13
+ import type { Messages, Language } from "./i18n.js";
14
+ import type { ChannelAdapter, InboundMessage, OutboundTarget } from "./types.js";
15
+ import type { BindingStore } from "./binding.js";
16
+ import type { NotifyLevel } from "./stream.js";
17
+ import { type MenuId } from "./menus.js";
18
+ /** Read-only surface `MenuController` needs from the per-chat driver. */
19
+ export interface MenuHost {
20
+ readonly t: Messages;
21
+ workDir: string;
22
+ readonly adapter: ChannelAdapter;
23
+ readonly language: Language;
24
+ readonly bindings: BindingStore;
25
+ readonly channel: string;
26
+ readonly chatKey: string;
27
+ readonly notifyLevel: NotifyLevel;
28
+ readonly progressTimeoutMs: number;
29
+ readonly ctx: Context;
30
+ defaultSelection(): ModelSelection;
31
+ listWorkspaces(): {
32
+ path: string;
33
+ title: string;
34
+ }[];
35
+ menuTitle(menuId: MenuId): string;
36
+ rootMenuSections(): readonly {
37
+ title: string;
38
+ ids: readonly string[];
39
+ columnsPerRow?: number;
40
+ }[];
41
+ newChat(msg: InboundMessage): Promise<void>;
42
+ setLanguage(lang: Language, target: OutboundTarget, msg: InboundMessage): Promise<void>;
43
+ setReasoning(effort: string | undefined, msg: InboundMessage): Promise<void>;
44
+ setNotifyLevel(level: NotifyLevel, target: OutboundTarget, msg: InboundMessage): Promise<void>;
45
+ setProgressTimeout(ms: number, target: OutboundTarget, msg: InboundMessage): Promise<void>;
46
+ setModel(provider: string, model: string, msg: InboundMessage): Promise<void>;
47
+ showStatus(target: OutboundTarget): Promise<void>;
48
+ showTasks(target: OutboundTarget): Promise<void>;
49
+ showHistory(target: OutboundTarget, limit: number): Promise<void>;
50
+ showGoals(target: OutboundTarget): Promise<void>;
51
+ showSchedule(target: OutboundTarget): Promise<void>;
52
+ showPlugins(target: OutboundTarget): Promise<void>;
53
+ showSettings(target: OutboundTarget): Promise<void>;
54
+ compact(target: OutboundTarget): Promise<void>;
55
+ collectWorkdirSessions(): Promise<{
56
+ sessionId: string;
57
+ title: string;
58
+ }[]>;
59
+ switchTo(sessionId: string, ownerKey: string): Promise<void>;
60
+ confirmAction(target: OutboundTarget, promptText: string, messageId?: string): Promise<boolean>;
61
+ }
62
+ export declare class MenuController {
63
+ private readonly host;
64
+ constructor(host: MenuHost);
65
+ openMenu(target: OutboundTarget, msg: InboundMessage, menuId: MenuId, stack?: MenuId[], cardId?: string): Promise<void>;
66
+ private menuItems;
67
+ private modelMenuItems;
68
+ private reasoningMenuItems;
69
+ private listModelChoices;
70
+ }
71
+ //# sourceMappingURL=menu-controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menu-controller.d.ts","sourceRoot":"","sources":["../src/menu-controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,284 @@
1
+ import { menuRender } from "./menus.js";
2
+ export class MenuController {
3
+ host;
4
+ constructor(host) {
5
+ this.host = host;
6
+ }
7
+ async openMenu(target, msg, menuId, stack = [], cardId) {
8
+ const items = await this.menuItems(menuId);
9
+ const options = items.map((i) => ({ id: i.id, label: i.label }));
10
+ options.push({ id: "menu:exit", label: this.host.t.menuExit });
11
+ if (stack.length > 0)
12
+ options.push({ id: "menu:back", label: this.host.t.menuBack });
13
+ // Determine columns per row based on menu type
14
+ // Workspace and chat lists use 1 column (full width), others use 2 columns
15
+ const columnsPerRow = (menuId === "workspace" || menuId === "chat") ? 1 : 2;
16
+ // Pre-select the current model when the model menu renders as a dropdown,
17
+ // so the card opens on the active model instead of an empty placeholder.
18
+ const current = this.host.defaultSelection();
19
+ const dropInitial = menuId === "model" && current.provider !== "" && current.model !== ""
20
+ ? "model:" + current.provider + ":" + current.model
21
+ : undefined;
22
+ const { choice, messageId } = await this.host.adapter.promptChoice(target, {
23
+ title: this.host.menuTitle(menuId),
24
+ options,
25
+ columnsPerRow,
26
+ // Data-heavy menus collapse to a dropdown; every other menu stays a
27
+ // button grid so a full submenu never reads as a single closed/empty select.
28
+ render: menuRender(menuId),
29
+ ...(menuId === "root" ? { sections: this.host.rootMenuSections(), footer: this.host.t.rootMenuFooter } : {}),
30
+ ...(dropInitial !== undefined && options.some((o) => o.id === dropInitial) ? { initialOption: dropInitial } : {}),
31
+ }, cardId);
32
+ if (choice === undefined)
33
+ return;
34
+ if (choice === "menu:exit") {
35
+ await this.host.adapter.closeMenu(messageId, this.host.t.menuClosed);
36
+ return;
37
+ }
38
+ if (choice === "menu:back") {
39
+ const parent = stack[stack.length - 1];
40
+ await this.openMenu(target, msg, parent, stack.slice(0, -1), messageId);
41
+ return;
42
+ }
43
+ const item = items.find((i) => i.id === choice);
44
+ if (item === undefined) {
45
+ // The tap belonged to a previous card generation (e.g. a rapid second
46
+ // tap on the old menu while the new one was still being redrawn). Don't
47
+ // silently swallow it: redraw the current menu so the chain stays usable.
48
+ await this.openMenu(target, msg, menuId, stack, messageId);
49
+ return;
50
+ }
51
+ const feedback = await item.onSelect(target, msg, messageId);
52
+ if (item.leaf === true) {
53
+ // Every leaf press must answer visibly: send the action's result feedback
54
+ // (if any) before returning to the root menu on the same card.
55
+ if (feedback !== undefined && feedback !== "") {
56
+ await this.host.adapter.sendText(target, feedback).catch(() => undefined);
57
+ }
58
+ await this.openMenu(target, msg, "root", [], messageId);
59
+ }
60
+ }
61
+ async menuItems(menuId) {
62
+ switch (menuId) {
63
+ case "root":
64
+ return [
65
+ { id: "workspace", label: this.host.t.menuWorkspaceAction, onSelect: (t, m, cardId) => this.openMenu(t, m, "workspace", ["root"], cardId) },
66
+ { id: "chat", label: this.host.t.menuChatAction, onSelect: (t, m, cardId) => this.openMenu(t, m, "chat", ["root"], cardId) },
67
+ { id: "status", label: this.host.t.menuStatusAction, leaf: true, onSelect: async (t) => { await this.host.showStatus(t); } },
68
+ { id: "task", label: this.host.t.menuTaskAction, leaf: true, onSelect: async (t) => { await this.host.showTasks(t); } },
69
+ { id: "history", label: this.host.t.menuHistoryAction, leaf: true, onSelect: async (t) => { await this.host.showHistory(t, 10); } },
70
+ { id: "goals", label: this.host.t.menuGoalsAction, leaf: true, onSelect: async (t) => { await this.host.showGoals(t); } },
71
+ { id: "schedule", label: this.host.t.menuScheduleAction, leaf: true, onSelect: async (t) => { await this.host.showSchedule(t); } },
72
+ { id: "compact", label: this.host.t.menuCompactAction, leaf: true, onSelect: async (t) => { await this.host.compact(t); } },
73
+ { id: "plugins", label: this.host.t.menuPluginsAction, leaf: true, onSelect: async (t) => { await this.host.showPlugins(t); } },
74
+ { id: "settings", label: this.host.t.menuSettingsAction, onSelect: (t, m, cardId) => this.openMenu(t, m, "settings", ["root"], cardId) },
75
+ ];
76
+ case "workspace": {
77
+ const workspaces = this.host.listWorkspaces();
78
+ return workspaces.map((w) => ({
79
+ id: `dir:${w.path}`,
80
+ label: `${w.path === this.host.workDir ? "● " : ""}${w.title}${w.title !== w.path ? ` (${w.path})` : ""}`,
81
+ leaf: true,
82
+ onSelect: async (t, m) => {
83
+ this.host.workDir = w.path;
84
+ await this.host.newChat(m);
85
+ return this.host.t.dirSwitched(w.path);
86
+ },
87
+ }));
88
+ }
89
+ case "chat": {
90
+ const binding = this.host.bindings.get(this.host.channel, this.host.chatKey);
91
+ const active = binding?.sessionId;
92
+ const hasWebMirror = binding?.webMirrorSessionId !== undefined;
93
+ const items = (await this.host.collectWorkdirSessions()).map(({ sessionId, title }) => {
94
+ const isMirrored = hasWebMirror && binding?.webMirrorSessionId === sessionId;
95
+ const mirrorIndicator = isMirrored ? ` ${this.host.t.webMirrorIndicator}` : "";
96
+ const activeIndicator = sessionId === active ? "●" : "○";
97
+ return {
98
+ id: `session:${sessionId}`,
99
+ label: `${activeIndicator} ${title || sessionId}${mirrorIndicator}`,
100
+ leaf: true,
101
+ onSelect: async (t, m) => {
102
+ await this.host.switchTo(sessionId, m.senderKey);
103
+ return this.host.t.sessionSwitched(title || sessionId);
104
+ },
105
+ };
106
+ });
107
+ if (items.length === 0) {
108
+ items.push({
109
+ id: "none:history",
110
+ label: this.host.t.noSessionsInWorkdir(this.host.workDir),
111
+ leaf: true,
112
+ onSelect: async () => this.host.t.noSessionsInWorkdir(this.host.workDir),
113
+ });
114
+ }
115
+ items.push({
116
+ id: "action:new",
117
+ label: this.host.t.menuNewChat,
118
+ leaf: true,
119
+ onSelect: async (t, m, messageId) => {
120
+ // Reuse the menu card for the confirm prompt so no stale card is left behind.
121
+ if (await this.host.confirmAction(t, this.host.t.confirmNewText, messageId)) {
122
+ await this.host.newChat(m);
123
+ return this.host.t.newChatDone;
124
+ }
125
+ return this.host.t.actionCancelled;
126
+ },
127
+ });
128
+ return items;
129
+ }
130
+ case "settings":
131
+ return [
132
+ { id: "model", label: this.host.t.menuSettingsModel, onSelect: (t, m, cardId) => this.openMenu(t, m, "model", ["settings", "root"], cardId) },
133
+ { id: "reasoning", label: this.host.t.menuSettingsReasoning, onSelect: (t, m, cardId) => this.openMenu(t, m, "reasoning", ["settings", "root"], cardId) },
134
+ { id: "notify", label: this.host.t.menuSettingsNotify, onSelect: (t, m, cardId) => this.openMenu(t, m, "notify", ["settings", "root"], cardId) },
135
+ { id: "progress", label: this.host.t.menuSettingsProgress, onSelect: (t, m, cardId) => this.openMenu(t, m, "progress", ["settings", "root"], cardId) },
136
+ { id: "language", label: this.host.t.menuSettingsLanguage, onSelect: (t, m, cardId) => this.openMenu(t, m, "language", ["settings", "root"], cardId) },
137
+ { id: "overview", label: this.host.t.menuSettingsOverview, leaf: true, onSelect: async (t) => { await this.host.showSettings(t); } },
138
+ ];
139
+ case "language":
140
+ return [
141
+ {
142
+ id: "lang:zh",
143
+ label: `${this.host.language === "zh" ? "● " : ""}${this.host.t.languageZh}`,
144
+ leaf: true,
145
+ onSelect: async (t, m) => { await this.host.setLanguage("zh", t, m); },
146
+ },
147
+ {
148
+ id: "lang:en",
149
+ label: `${this.host.language === "en" ? "● " : ""}${this.host.t.languageEn}`,
150
+ leaf: true,
151
+ onSelect: async (t, m) => { await this.host.setLanguage("en", t, m); },
152
+ },
153
+ ];
154
+ case "model":
155
+ return await this.modelMenuItems();
156
+ case "reasoning":
157
+ return this.reasoningMenuItems();
158
+ case "notify":
159
+ return [
160
+ { id: "full", label: this.host.t.notifyFull },
161
+ { id: "important", label: this.host.t.notifyImportant },
162
+ { id: "result", label: this.host.t.notifyResult },
163
+ ].map((o) => ({
164
+ id: `notify:${o.id}`,
165
+ label: `${this.host.notifyLevel === o.id ? "● " : ""}${o.label}`,
166
+ leaf: true,
167
+ onSelect: async (t, m) => {
168
+ await this.host.setNotifyLevel(o.id, t, m);
169
+ },
170
+ }));
171
+ case "progress": {
172
+ const presets = [
173
+ { id: "progress:0", label: this.host.t.progressOff, ms: 0 },
174
+ { id: "progress:120000", label: this.host.t.progressMinutes(2), ms: 2 * 60_000 },
175
+ { id: "progress:300000", label: this.host.t.progressMinutes(5), ms: 5 * 60_000 },
176
+ { id: "progress:600000", label: this.host.t.progressMinutes(10), ms: 10 * 60_000 },
177
+ { id: "progress:900000", label: this.host.t.progressMinutes(15), ms: 15 * 60_000 },
178
+ { id: "progress:1800000", label: this.host.t.progressMinutes(30), ms: 30 * 60_000 },
179
+ ];
180
+ return presets.map((o) => ({
181
+ id: o.id,
182
+ label: `${this.host.progressTimeoutMs === o.ms ? "● " : ""}${o.label}`,
183
+ leaf: true,
184
+ onSelect: async (t, m) => {
185
+ await this.host.setProgressTimeout(o.ms, t, m);
186
+ },
187
+ }));
188
+ }
189
+ }
190
+ }
191
+ async modelMenuItems() {
192
+ const choices = await this.listModelChoices();
193
+ const current = this.host.defaultSelection();
194
+ const items = choices.map((c) => ({
195
+ id: `model:${c.provider}:${c.model}`,
196
+ label: `${c.provider === current.provider && c.model === current.model ? "● " : ""}${c.name}`,
197
+ leaf: true,
198
+ onSelect: async (t, m) => {
199
+ await this.host.setModel(c.provider, c.model, m);
200
+ return this.host.t.modelSet(c.name);
201
+ },
202
+ }));
203
+ if (items.length === 0) {
204
+ items.push({ id: "model:none", label: this.host.t.noModelsFound, leaf: true, onSelect: async () => this.host.t.noModelsFound });
205
+ }
206
+ return items;
207
+ }
208
+ reasoningMenuItems() {
209
+ const current = this.host.defaultSelection();
210
+ const efforts = [
211
+ { id: "low", name: this.host.t.effortLow },
212
+ { id: "medium", name: this.host.t.effortMedium },
213
+ { id: "high", name: this.host.t.effortHigh },
214
+ ];
215
+ const items = [
216
+ {
217
+ id: "effort:default",
218
+ label: `${current.reasoningEffort === undefined ? "● " : ""}${this.host.t.effortDefault}`,
219
+ leaf: true,
220
+ onSelect: async (t, m) => {
221
+ await this.host.setReasoning(undefined, m);
222
+ return this.host.t.reasoningSet(this.host.t.effortDefault);
223
+ },
224
+ },
225
+ ];
226
+ for (const e of efforts) {
227
+ items.push({
228
+ id: `effort:${e.id}`,
229
+ label: `${e.id === current.reasoningEffort ? "● " : ""}${e.name}`,
230
+ leaf: true,
231
+ onSelect: async (t, m) => {
232
+ await this.host.setReasoning(e.id, m);
233
+ return this.host.t.reasoningSet(e.name);
234
+ },
235
+ });
236
+ }
237
+ return items;
238
+ }
239
+ async listModelChoices() {
240
+ const llm = this.host.ctx.get("llm");
241
+ const logger = this.host.ctx.get("logger")?.info;
242
+ const live = llm?.listProviders?.() ?? [];
243
+ const configurable = llm?.listConfigurableProviders?.() ?? [];
244
+ // Merge live registered routes with the configurable-provider directory so a
245
+ // configured provider whose adapter registers lazily (on first request) still
246
+ // appears in the menu instead of silently dropping it.
247
+ const seen = new Set();
248
+ const labelOf = new Map();
249
+ const providers = [];
250
+ for (const p of live) {
251
+ if (!seen.has(p.id)) {
252
+ seen.add(p.id);
253
+ providers.push(p.id);
254
+ labelOf.set(p.id, p.name || p.id);
255
+ }
256
+ }
257
+ for (const d of configurable) {
258
+ if (!seen.has(d.provider)) {
259
+ seen.add(d.provider);
260
+ providers.push(d.provider);
261
+ labelOf.set(d.provider, d.displayName || d.provider);
262
+ }
263
+ }
264
+ const out = [];
265
+ const zeroModel = [];
266
+ for (const pid of providers) {
267
+ let models = [];
268
+ try {
269
+ models = (await llm?.listModels?.(pid)) ?? [];
270
+ }
271
+ catch { /* adapter not registered */ }
272
+ if (models.length === 0) {
273
+ zeroModel.push(pid);
274
+ continue;
275
+ }
276
+ for (const m of models) {
277
+ out.push({ provider: pid, model: m.id, name: this.host.t.modelName(m.name || m.id, labelOf.get(pid) || pid) });
278
+ }
279
+ }
280
+ logger?.("connect: model catalog -- live=" + live.length + " configurable=" + configurable.length + " providers=" + providers.length + " models=" + out.length);
281
+ return out;
282
+ }
283
+ }
284
+ //# sourceMappingURL=menu-controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menu-controller.js","sourceRoot":"","sources":["../src/menu-controller.ts"],"names":[],"mappings":"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"}
package/lib/menus.d.ts ADDED
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Menu rendering types and pure label/data helpers.
3
+ *
4
+ * The menu concern is split out from the per-chat driver so that the mapping
5
+ * from a menu id / end-reason / goal phase to a localized label, and the
6
+ * workspace listing, can be tested and reused without the driver's runtime
7
+ * state. Everything here is a pure function of its arguments (no `this`).
8
+ * @module dsh-connect/menus
9
+ */
10
+ import type { Messages } from "./i18n.js";
11
+ import type { InboundMessage, OutboundTarget, TurnReason } from "./types.js";
12
+ export type MenuId = "root" | "workspace" | "chat" | "settings" | "model" | "reasoning" | "notify" | "language" | "progress";
13
+ export interface MenuItem {
14
+ id: string;
15
+ label: string;
16
+ /** Leaf action: after it runs, the menu returns to the root menu on the same card. */
17
+ leaf?: boolean;
18
+ /**
19
+ * `messageId` is the menu card id: pass it to `openMenu` to navigate in place,
20
+ * or close the card. A returned string is sent to the chat as the action's
21
+ * result feedback before the menu returns, so every button press answers
22
+ * visibly instead of leaving the user to guess whether it worked.
23
+ */
24
+ onSelect: (target: OutboundTarget, msg: InboundMessage, messageId: string) => Promise<string | void>;
25
+ }
26
+ /** Localized menu title for a menu id. */
27
+ export declare function menuTitle(menuId: MenuId, t: Messages): string;
28
+ /** Named root-menu sections: workspace / chat (1 col), task / system (2 col). */
29
+ export declare function rootMenuSections(t: Messages): readonly {
30
+ title: string;
31
+ ids: readonly string[];
32
+ columnsPerRow?: number;
33
+ }[];
34
+ /** Localized label for a turn end reason. */
35
+ export declare function reasonLabel(reason: TurnReason, t: Messages): string;
36
+ /** Localized label for a goal phase. */
37
+ export declare function goalPhaseLabel(phase: string, t: Messages): string;
38
+ export interface WorkspaceInfo {
39
+ path: string;
40
+ title: string;
41
+ }
42
+ /** Dedupe (case-insensitive, trailing-slash-normalized) the workspace candidates. */
43
+ export declare function listWorkspaces(opts: {
44
+ registry?: {
45
+ list?: () => readonly {
46
+ path: string;
47
+ title: string;
48
+ }[];
49
+ } | undefined;
50
+ workDir: string;
51
+ currentDirLabel: string;
52
+ workspaces: readonly string[];
53
+ }): WorkspaceInfo[];
54
+ /**
55
+ * Which render mode a menu should use. Data-heavy menus (model / session /
56
+ * workspace) collapse to a single select_static so the card stays compact;
57
+ * every other menu stays a button grid — a full menu must never read as a
58
+ * single closed/empty select. This is a pure function so it can be unit-tested
59
+ * (a naive "auto when many options" collapses settings/language etc. too).
60
+ */
61
+ export declare function menuRender(menuId: MenuId): "dropdown" | "buttons";
62
+ //# sourceMappingURL=menus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menus.d.ts","sourceRoot":"","sources":["../src/menus.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7E,MAAM,MAAM,MAAM,GACd,MAAM,GACN,WAAW,GACX,MAAM,GACN,UAAU,GACV,OAAO,GACP,WAAW,GACX,QAAQ,GACR,UAAU,GACV,UAAU,CAAC;AAEf,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,sFAAsF;IACtF,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;;OAKG;IACH,QAAQ,EAAE,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACtG;AAED,0CAA0C;AAC1C,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAqB7D;AAED,iFAAiF;AACjF,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,QAAQ,GAAG,SAAS;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,CAO1H;AAED,6CAA6C;AAC7C,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAiBnE;AAED,wCAAwC;AACxC,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAajE;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qFAAqF;AACrF,wBAAgB,cAAc,CAAC,IAAI,EAAE;IACnC,QAAQ,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,SAAS;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAAE,GAAG,SAAS,CAAC;IACnF,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CAC/B,GAAG,aAAa,EAAE,CAclB;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAIjE"}
package/lib/menus.js ADDED
@@ -0,0 +1,99 @@
1
+ /** Localized menu title for a menu id. */
2
+ export function menuTitle(menuId, t) {
3
+ switch (menuId) {
4
+ case "root":
5
+ return t.menuRoot;
6
+ case "workspace":
7
+ return t.menuWorkspace;
8
+ case "chat":
9
+ return t.menuChat;
10
+ case "settings":
11
+ return t.menuSettings;
12
+ case "model":
13
+ return t.menuModel;
14
+ case "reasoning":
15
+ return t.menuReasoning;
16
+ case "notify":
17
+ return t.menuNotify;
18
+ case "language":
19
+ return t.menuSettingsLanguage;
20
+ case "progress":
21
+ return t.progressMenuTitle;
22
+ }
23
+ }
24
+ /** Named root-menu sections: workspace / chat (1 col), task / system (2 col). */
25
+ export function rootMenuSections(t) {
26
+ return [
27
+ { title: t.rootSectionWorkspace, ids: ["workspace"], columnsPerRow: 1 },
28
+ { title: t.rootSectionChat, ids: ["chat", "history"], columnsPerRow: 1 },
29
+ { title: t.rootSectionTask, ids: ["task", "goals", "schedule"], columnsPerRow: 2 },
30
+ { title: t.rootSectionSystem, ids: ["status", "plugins", "compact", "settings"], columnsPerRow: 2 },
31
+ ];
32
+ }
33
+ /** Localized label for a turn end reason. */
34
+ export function reasonLabel(reason, t) {
35
+ switch (reason) {
36
+ case "completed":
37
+ return t.reasonCompleted;
38
+ case "aborted":
39
+ return t.reasonAborted;
40
+ case "blocked":
41
+ return t.reasonBlocked;
42
+ case "error":
43
+ return t.reasonError;
44
+ case "max-tokens":
45
+ return t.reasonMaxTokens;
46
+ case "interrupted":
47
+ return t.reasonInterrupted;
48
+ default:
49
+ return t.reasonUnknown;
50
+ }
51
+ }
52
+ /** Localized label for a goal phase. */
53
+ export function goalPhaseLabel(phase, t) {
54
+ switch (phase) {
55
+ case "active":
56
+ return t.goalPhaseActive;
57
+ case "paused":
58
+ return t.goalPhasePaused;
59
+ case "blocked":
60
+ return t.goalPhaseBlocked;
61
+ case "complete":
62
+ return t.goalPhaseComplete;
63
+ default:
64
+ return phase;
65
+ }
66
+ }
67
+ /** Dedupe (case-insensitive, trailing-slash-normalized) the workspace candidates. */
68
+ export function listWorkspaces(opts) {
69
+ const out = [];
70
+ const seen = new Set();
71
+ const add = (path, title) => {
72
+ if (path === "")
73
+ return;
74
+ const key = path.replace(/[\\/]+$/, "").toLowerCase();
75
+ if (seen.has(key))
76
+ return;
77
+ seen.add(key);
78
+ out.push({ path, title: title || path });
79
+ };
80
+ add(opts.workDir, opts.currentDirLabel);
81
+ for (const w of opts.registry?.list?.() ?? [])
82
+ add(w.path, w.title);
83
+ for (const p of opts.workspaces)
84
+ add(p, p);
85
+ return out;
86
+ }
87
+ /**
88
+ * Which render mode a menu should use. Data-heavy menus (model / session /
89
+ * workspace) collapse to a single select_static so the card stays compact;
90
+ * every other menu stays a button grid — a full menu must never read as a
91
+ * single closed/empty select. This is a pure function so it can be unit-tested
92
+ * (a naive "auto when many options" collapses settings/language etc. too).
93
+ */
94
+ export function menuRender(menuId) {
95
+ return menuId === "model" || menuId === "chat" || menuId === "workspace"
96
+ ? "dropdown"
97
+ : "buttons";
98
+ }
99
+ //# sourceMappingURL=menus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menus.js","sourceRoot":"","sources":["../src/menus.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Pure lock-state machine for the Feishu ↔ Web mirror mutual exclusion.
3
+ *
4
+ * A mirrored chat has two writers: the Feishu runner (chat side) and the Web
5
+ * GUI (which reads/writes the shared DSH session directly). The `lockOwner`
6
+ * field on a binding records which channel currently owns write access so the
7
+ * two sides do not drive the same session concurrently. This module contains
8
+ * every transition as a pure function over a `LockState`-shaped object — no
9
+ * I/O, no adapter calls — so the state machine is unit-testable in isolation.
10
+ * @module dsh-connect/mirror-lock
11
+ */
12
+ /** Default lock timeout (5 minutes) when a binding has no explicit timeout. */
13
+ export declare const DEFAULT_LOCK_TIMEOUT_MS: number;
14
+ /** One message parked in `queuedMessages` while the session lock is held. */
15
+ export interface QueuedMessage {
16
+ text: string;
17
+ senderKey: string;
18
+ timestamp: number;
19
+ replyRef?: string;
20
+ images?: readonly string[];
21
+ files?: readonly string[];
22
+ /** Channel the message originated on; used when replaying after lock release. */
23
+ channel?: string;
24
+ }
25
+ /** The lock-related slice of a `ChatBinding` (structural; keeps this module decoupled). */
26
+ export interface LockState {
27
+ lockOwner?: "feishu" | "web";
28
+ lockAcquiredAt?: number;
29
+ lockTimeoutMs?: number;
30
+ queuedMessages?: QueuedMessage[];
31
+ }
32
+ /** True when a lock exists and its acquisition timestamp is older than its timeout. */
33
+ export declare function isLockTimedOut(state: LockState, now?: number): boolean;
34
+ /**
35
+ * Whether `channel` may write to the session. A timed-out lock counts as
36
+ * free (the caller normally releases it and notifies the user).
37
+ */
38
+ export declare function canWrite(state: LockState, channel: "feishu" | "web", now?: number): boolean;
39
+ /**
40
+ * Acquire (or renew) the lock for `channel`. Returns the next state when the
41
+ * lock is free, timed out, or already owned by `channel`; `undefined` when a
42
+ * different channel currently holds a live lock. Generic over the full state
43
+ * object so callers keep their complete binding type.
44
+ */
45
+ export declare function acquire<S extends LockState>(state: S, channel: "feishu" | "web", now?: number): S | undefined;
46
+ /**
47
+ * Release the lock, preserving every other field (including the parked queue —
48
+ * the caller drains `queuedMessages` before or after releasing).
49
+ */
50
+ export declare function release<S extends LockState>(state: S): S;
51
+ //# sourceMappingURL=mirror-lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mirror-lock.d.ts","sourceRoot":"","sources":["../src/mirror-lock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,+EAA+E;AAC/E,eAAO,MAAM,uBAAuB,QAAgB,CAAC;AAErD,6EAA6E;AAC7E,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,iFAAiF;IACjF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,2FAA2F;AAC3F,MAAM,WAAW,SAAS;IACxB,SAAS,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;CAClC;AAED,uFAAuF;AACvF,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,SAAa,GAAG,OAAO,CAI1E;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,GAAG,KAAK,EAAE,GAAG,SAAa,GAAG,OAAO,CAI/F;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,QAAQ,GAAG,KAAK,EAAE,GAAG,SAAa,GAAG,CAAC,GAAG,SAAS,CAUjH;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,SAAS,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAExD"}