@aiwayds/dsh-tui-pi 0.1.0 → 0.3.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.
- package/README.md +205 -68
- package/lib/agent-manager.d.ts +125 -0
- package/lib/agent-manager.js +298 -0
- package/lib/agent-manager.js.map +1 -0
- package/lib/agents.d.ts +30 -0
- package/lib/agents.js +468 -0
- package/lib/agents.js.map +1 -0
- package/lib/append-system.d.ts +2 -0
- package/lib/append-system.js +1 -1
- package/lib/append-system.js.map +1 -1
- package/lib/dsh-events.d.ts +12 -0
- package/lib/editor.d.ts +58 -0
- package/lib/editor.js +92 -0
- package/lib/editor.js.map +1 -1
- package/lib/footer.d.ts +8 -0
- package/lib/footer.js +8 -0
- package/lib/footer.js.map +1 -1
- package/lib/hotkeys.d.ts +93 -0
- package/lib/hotkeys.js +305 -0
- package/lib/hotkeys.js.map +1 -0
- package/lib/index.js +342 -38
- package/lib/index.js.map +1 -1
- package/lib/keymap.d.ts +177 -0
- package/lib/keymap.js +189 -0
- package/lib/keymap.js.map +1 -0
- package/lib/live-widgets.d.ts +82 -29
- package/lib/live-widgets.js +222 -92
- package/lib/live-widgets.js.map +1 -1
- package/lib/messages.d.ts +4 -2
- package/lib/messages.js +8 -3
- package/lib/messages.js.map +1 -1
- package/lib/panels.d.ts +177 -0
- package/lib/panels.js +331 -0
- package/lib/panels.js.map +1 -0
- package/lib/provider-catalog.d.ts +31 -8
- package/lib/provider-catalog.js +63 -8
- package/lib/provider-catalog.js.map +1 -1
- package/lib/selectors.d.ts +12 -1
- package/lib/selectors.js +5 -2
- package/lib/selectors.js.map +1 -1
- package/lib/session.d.ts +36 -0
- package/lib/session.js +171 -10
- package/lib/session.js.map +1 -1
- package/lib/settings.d.ts +1 -2
- package/lib/settings.js +29 -2
- package/lib/settings.js.map +1 -1
- package/lib/subagent-policy.d.ts +58 -0
- package/lib/subagent-policy.js +137 -0
- package/lib/subagent-policy.js.map +1 -0
- package/lib/subagent-viewer.d.ts +49 -0
- package/lib/subagent-viewer.js +523 -0
- package/lib/subagent-viewer.js.map +1 -0
- package/lib/theme/index.js +4 -0
- package/lib/theme/index.js.map +1 -1
- package/lib/theme/palette.d.ts +21 -3
- package/lib/theme/palette.js +27 -6
- package/lib/theme/palette.js.map +1 -1
- package/lib/theme-settings.d.ts +39 -4
- package/lib/theme-settings.js +69 -12
- package/lib/theme-settings.js.map +1 -1
- package/lib/tui.d.ts +32 -12
- package/lib/tui.js +109 -36
- package/lib/tui.js.map +1 -1
- package/package.json +3 -4
- package/patches/@earendil-works__pi-tui.patch +206 -2
- package/scripts/dev-install.mjs +87 -0
- package/scripts/link-dsh-closure.mjs +85 -0
|
@@ -2,11 +2,15 @@
|
|
|
2
2
|
* Built-in provider directory for the Models category's add-provider flow —
|
|
3
3
|
* pure data plus pure functions, no TTY and no services touched.
|
|
4
4
|
*
|
|
5
|
-
* The
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* The directory mirrors the web Models page: it lists every installed
|
|
6
|
+
* llm-pi-ai catalog route that takes an API key (36 routes in pi-ai 0.82.1),
|
|
7
|
+
* and the add-provider flow prefers the live `listConfigurableProviders()`
|
|
8
|
+
* directory at runtime (see `directoryProviderEntries`) with this static
|
|
9
|
+
* mirror as the fallback. The shape matches the web Models page and
|
|
10
|
+
* pi-agent's /login flow: the user picks a provider from the directory
|
|
11
|
+
* (never free-form JSON), enters exactly one secret, and the flow finishes.
|
|
12
|
+
* A directory entry carries everything the write needs so the TUI never asks
|
|
13
|
+
* for a field the user should not have to see:
|
|
10
14
|
*
|
|
11
15
|
* - friendly display name (row label; the pi-ai route key stays internal),
|
|
12
16
|
* - one-line auth hint (the oauth-selector `[API key]` idea),
|
|
@@ -47,9 +51,13 @@ export interface ProviderCatalogEntry {
|
|
|
47
51
|
models?: readonly CatalogModel[];
|
|
48
52
|
}
|
|
49
53
|
/**
|
|
50
|
-
* The built-in provider directory the Add-provider picker offers
|
|
51
|
-
*
|
|
52
|
-
*
|
|
54
|
+
* The built-in provider directory the Add-provider picker offers — mirrors
|
|
55
|
+
* the web Models directory: every installed llm-pi-ai catalog route that
|
|
56
|
+
* takes an API key (36 routes in pi-ai 0.82.1). Sorted by display name; every
|
|
57
|
+
* route key names a pi-ai catalog provider, so each entry stores nothing but
|
|
58
|
+
* the credential. At runtime the add flow prefers the live directory (see
|
|
59
|
+
* `directoryProviderEntries`); this list is the static fallback and the
|
|
60
|
+
* friendly name/hint source.
|
|
53
61
|
*/
|
|
54
62
|
export declare const PROVIDER_CATALOG: readonly ProviderCatalogEntry[];
|
|
55
63
|
/** One directory entry by route key, or `undefined` for an unknown route. */
|
|
@@ -80,6 +88,21 @@ export declare function providerProfileFor(entry: ProviderCatalogEntry): {
|
|
|
80
88
|
};
|
|
81
89
|
/** Directory entries the user has not configured yet (in directory order). */
|
|
82
90
|
export declare function unconfiguredCatalogEntries(configured: ReadonlySet<string>): ProviderCatalogEntry[];
|
|
91
|
+
/**
|
|
92
|
+
* Build the add-provider picker entries from the live configurable-provider
|
|
93
|
+
* directory, in directory order — the same source the web Models page
|
|
94
|
+
* renders, so the TUI stays in lockstep with pi-ai without a hardcoded
|
|
95
|
+
* mirror. Static catalog entries supply the friendly name/hint when a route
|
|
96
|
+
* is known; unknown routes fall back to the route key itself. Configured and
|
|
97
|
+
* hand-declared routes are excluded (declared routes come from profiles, so
|
|
98
|
+
* the `configured` filter already covers them; `declared` is a defensive
|
|
99
|
+
* second guard). Callers fall back to `unconfiguredCatalogEntries` when the
|
|
100
|
+
* live directory is unavailable.
|
|
101
|
+
*/
|
|
102
|
+
export declare function directoryProviderEntries(directory: ReadonlyArray<{
|
|
103
|
+
provider: string;
|
|
104
|
+
declared?: boolean;
|
|
105
|
+
}>, configured: ReadonlySet<string>): ProviderCatalogEntry[];
|
|
83
106
|
/** One llm-pi-ai provider profile as stored in settings — the subset we read. */
|
|
84
107
|
export interface ProviderProfile {
|
|
85
108
|
displayName?: string;
|
package/lib/provider-catalog.js
CHANGED
|
@@ -2,11 +2,15 @@
|
|
|
2
2
|
* Built-in provider directory for the Models category's add-provider flow —
|
|
3
3
|
* pure data plus pure functions, no TTY and no services touched.
|
|
4
4
|
*
|
|
5
|
-
* The
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* The directory mirrors the web Models page: it lists every installed
|
|
6
|
+
* llm-pi-ai catalog route that takes an API key (36 routes in pi-ai 0.82.1),
|
|
7
|
+
* and the add-provider flow prefers the live `listConfigurableProviders()`
|
|
8
|
+
* directory at runtime (see `directoryProviderEntries`) with this static
|
|
9
|
+
* mirror as the fallback. The shape matches the web Models page and
|
|
10
|
+
* pi-agent's /login flow: the user picks a provider from the directory
|
|
11
|
+
* (never free-form JSON), enters exactly one secret, and the flow finishes.
|
|
12
|
+
* A directory entry carries everything the write needs so the TUI never asks
|
|
13
|
+
* for a field the user should not have to see:
|
|
10
14
|
*
|
|
11
15
|
* - friendly display name (row label; the pi-ai route key stays internal),
|
|
12
16
|
* - one-line auth hint (the oauth-selector `[API key]` idea),
|
|
@@ -23,20 +27,50 @@
|
|
|
23
27
|
* `api`/`baseURL`/`models` — no TUI change needed.
|
|
24
28
|
*/
|
|
25
29
|
/**
|
|
26
|
-
* The built-in provider directory the Add-provider picker offers
|
|
27
|
-
*
|
|
28
|
-
*
|
|
30
|
+
* The built-in provider directory the Add-provider picker offers — mirrors
|
|
31
|
+
* the web Models directory: every installed llm-pi-ai catalog route that
|
|
32
|
+
* takes an API key (36 routes in pi-ai 0.82.1). Sorted by display name; every
|
|
33
|
+
* route key names a pi-ai catalog provider, so each entry stores nothing but
|
|
34
|
+
* the credential. At runtime the add flow prefers the live directory (see
|
|
35
|
+
* `directoryProviderEntries`); this list is the static fallback and the
|
|
36
|
+
* friendly name/hint source.
|
|
29
37
|
*/
|
|
30
38
|
export const PROVIDER_CATALOG = [
|
|
39
|
+
{ id: 'amazon-bedrock', name: 'Amazon Bedrock', hint: 'AWS credentials or bearer token', catalogRoute: true },
|
|
40
|
+
{ id: 'ant-ling', name: 'Ant Ling', hint: 'API key', catalogRoute: true },
|
|
31
41
|
{ id: 'anthropic', name: 'Anthropic', hint: 'API key', catalogRoute: true },
|
|
42
|
+
{ id: 'azure-openai-responses', name: 'Azure OpenAI', hint: 'API key', catalogRoute: true },
|
|
43
|
+
{ id: 'cerebras', name: 'Cerebras', hint: 'API key', catalogRoute: true },
|
|
44
|
+
{ id: 'cloudflare-ai-gateway', name: 'Cloudflare AI Gateway', hint: 'API key', catalogRoute: true },
|
|
45
|
+
{ id: 'cloudflare-workers-ai', name: 'Cloudflare Workers AI', hint: 'API key', catalogRoute: true },
|
|
32
46
|
{ id: 'deepseek', name: 'DeepSeek', hint: 'API key', catalogRoute: true },
|
|
47
|
+
{ id: 'fireworks', name: 'Fireworks', hint: 'API key', catalogRoute: true },
|
|
48
|
+
{ id: 'github-copilot', name: 'GitHub Copilot', hint: 'GitHub Copilot token', catalogRoute: true },
|
|
33
49
|
{ id: 'google', name: 'Google Gemini', hint: 'API key', catalogRoute: true },
|
|
50
|
+
{ id: 'google-vertex', name: 'Google Vertex AI', hint: 'Google Cloud credentials', catalogRoute: true },
|
|
34
51
|
{ id: 'groq', name: 'Groq', hint: 'API key', catalogRoute: true },
|
|
52
|
+
{ id: 'huggingface', name: 'Hugging Face', hint: 'Hugging Face token', catalogRoute: true },
|
|
53
|
+
{ id: 'kimi-coding', name: 'Kimi For Coding', hint: 'API key', catalogRoute: true },
|
|
54
|
+
{ id: 'minimax', name: 'MiniMax', hint: 'API key', catalogRoute: true },
|
|
55
|
+
{ id: 'minimax-cn', name: 'MiniMax CN', hint: 'API key', catalogRoute: true },
|
|
35
56
|
{ id: 'mistral', name: 'Mistral', hint: 'API key', catalogRoute: true },
|
|
57
|
+
{ id: 'moonshotai', name: 'Moonshot AI', hint: 'API key', catalogRoute: true },
|
|
58
|
+
{ id: 'moonshotai-cn', name: 'Moonshot AI CN', hint: 'API key', catalogRoute: true },
|
|
59
|
+
{ id: 'nvidia', name: 'NVIDIA', hint: 'API key', catalogRoute: true },
|
|
36
60
|
{ id: 'openai', name: 'OpenAI', hint: 'API key', catalogRoute: true },
|
|
37
61
|
{ id: 'opencode-go', name: 'OpenCode Go', hint: 'API key · OpenAI-compatible gateway', catalogRoute: true },
|
|
62
|
+
{ id: 'opencode', name: 'OpenCode Zen', hint: 'API key', catalogRoute: true },
|
|
38
63
|
{ id: 'openrouter', name: 'OpenRouter', hint: 'API key', catalogRoute: true },
|
|
64
|
+
{ id: 'qwen-token-plan', name: 'Qwen Token Plan', hint: 'API key', catalogRoute: true },
|
|
65
|
+
{ id: 'qwen-token-plan-cn', name: 'Qwen Token Plan CN', hint: 'API key', catalogRoute: true },
|
|
39
66
|
{ id: 'together', name: 'Together AI', hint: 'API key', catalogRoute: true },
|
|
67
|
+
{ id: 'vercel-ai-gateway', name: 'Vercel AI Gateway', hint: 'API key', catalogRoute: true },
|
|
68
|
+
{ id: 'xiaomi', name: 'Xiaomi', hint: 'API key', catalogRoute: true },
|
|
69
|
+
{ id: 'xiaomi-token-plan-ams', name: 'Xiaomi Token Plan AMS', hint: 'API key', catalogRoute: true },
|
|
70
|
+
{ id: 'xiaomi-token-plan-cn', name: 'Xiaomi Token Plan CN', hint: 'API key', catalogRoute: true },
|
|
71
|
+
{ id: 'xiaomi-token-plan-sgp', name: 'Xiaomi Token Plan SGP', hint: 'API key', catalogRoute: true },
|
|
72
|
+
{ id: 'zai', name: 'Z.AI', hint: 'API key', catalogRoute: true },
|
|
73
|
+
{ id: 'zai-coding-cn', name: 'Z.AI Coding CN', hint: 'API key', catalogRoute: true },
|
|
40
74
|
{ id: 'xai', name: 'xAI', hint: 'API key', catalogRoute: true },
|
|
41
75
|
];
|
|
42
76
|
/** One directory entry by route key, or `undefined` for an unknown route. */
|
|
@@ -76,6 +110,27 @@ export function providerProfileFor(entry) {
|
|
|
76
110
|
export function unconfiguredCatalogEntries(configured) {
|
|
77
111
|
return PROVIDER_CATALOG.filter(entry => !configured.has(entry.id));
|
|
78
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* Build the add-provider picker entries from the live configurable-provider
|
|
115
|
+
* directory, in directory order — the same source the web Models page
|
|
116
|
+
* renders, so the TUI stays in lockstep with pi-ai without a hardcoded
|
|
117
|
+
* mirror. Static catalog entries supply the friendly name/hint when a route
|
|
118
|
+
* is known; unknown routes fall back to the route key itself. Configured and
|
|
119
|
+
* hand-declared routes are excluded (declared routes come from profiles, so
|
|
120
|
+
* the `configured` filter already covers them; `declared` is a defensive
|
|
121
|
+
* second guard). Callers fall back to `unconfiguredCatalogEntries` when the
|
|
122
|
+
* live directory is unavailable.
|
|
123
|
+
*/
|
|
124
|
+
export function directoryProviderEntries(directory, configured) {
|
|
125
|
+
return directory
|
|
126
|
+
.filter(entry => !configured.has(entry.provider) && entry.declared !== true)
|
|
127
|
+
.map(entry => catalogEntry(entry.provider) ?? {
|
|
128
|
+
id: entry.provider,
|
|
129
|
+
name: entry.provider,
|
|
130
|
+
hint: 'API key',
|
|
131
|
+
catalogRoute: true,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
79
134
|
/**
|
|
80
135
|
* Build the display facts for one provider row. Pure — the caller supplies
|
|
81
136
|
* the environment lookup (`process.env`) and the (possibly undefined) profile
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-catalog.js","sourceRoot":"","sources":["../src/provider-catalog.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"provider-catalog.js","sourceRoot":"","sources":["../src/provider-catalog.ts"],"names":[],"mappings":"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"}
|
package/lib/selectors.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { Context } from '@deepseek-ai/cordis';
|
|
8
8
|
import type { ModelSelection } from '@deepseek-ai/dsh-agent';
|
|
9
|
-
import type { ReasoningEffortId } from '@deepseek-ai/dsh-llm';
|
|
9
|
+
import type { LlmReasoningEffortInfo, ReasoningEffortId } from '@deepseek-ai/dsh-llm';
|
|
10
10
|
import { type TUI } from '@earendil-works/pi-tui';
|
|
11
11
|
import type { ThemePreference, TuiTheme } from './theme/index.ts';
|
|
12
12
|
/** Outcome of the reasoning effort picker overlay. */
|
|
@@ -18,6 +18,17 @@ export type PickEffortResult = {
|
|
|
18
18
|
kind: 'effort';
|
|
19
19
|
effort: ReasoningEffortId | 'default';
|
|
20
20
|
};
|
|
21
|
+
/**
|
|
22
|
+
* Run the reasoning effort SelectList overlay over the given efforts. Resolves
|
|
23
|
+
* with the chosen effort (`'default'` meaning no override), or `undefined`
|
|
24
|
+
* when cancelled. The row matching `selectedEffort` is preselected when
|
|
25
|
+
* present. `afterShow` runs once the overlay is up (used by the two-stage
|
|
26
|
+
* model picker to hide the previous stage only after this one owns focus);
|
|
27
|
+
* focus returns to `restoreFocus` on close.
|
|
28
|
+
*/
|
|
29
|
+
export declare function openEffortPicker(tui: TUI, theme: TuiTheme, efforts: readonly LlmReasoningEffortInfo[], selectedEffort: ReasoningEffortId | undefined, restoreFocus: () => void, afterShow?: () => void): Promise<{
|
|
30
|
+
effort: ReasoningEffortId | 'default';
|
|
31
|
+
} | undefined>;
|
|
21
32
|
/**
|
|
22
33
|
* Open the reasoning effort picker for the current model. Resolves with the
|
|
23
34
|
* picked outcome: the model exposes no selectable efforts (`unsupported`),
|
package/lib/selectors.js
CHANGED
|
@@ -21,7 +21,7 @@ const DEFAULT_EFFORT_ITEM = {
|
|
|
21
21
|
* model picker to hide the previous stage only after this one owns focus);
|
|
22
22
|
* focus returns to `restoreFocus` on close.
|
|
23
23
|
*/
|
|
24
|
-
function openEffortPicker(tui, theme, efforts, selectedEffort, restoreFocus, afterShow) {
|
|
24
|
+
export function openEffortPicker(tui, theme, efforts, selectedEffort, restoreFocus, afterShow) {
|
|
25
25
|
const items = [
|
|
26
26
|
DEFAULT_EFFORT_ITEM,
|
|
27
27
|
...efforts.map(effort => ({
|
|
@@ -237,7 +237,10 @@ export async function pickModel(ctx, tui, theme, current, restoreFocus) {
|
|
|
237
237
|
});
|
|
238
238
|
return;
|
|
239
239
|
}
|
|
240
|
-
|
|
240
|
+
// No kept effort: default the stage-2 cursor to `high` rather than the
|
|
241
|
+
// adapter-default row. openEffortPicker's findIndex guard falls back to
|
|
242
|
+
// the first row when the model does not offer the level.
|
|
243
|
+
const chosen = await openEffortPicker(tui, theme, efforts, keptEffort ?? 'high', restoreFocus,
|
|
241
244
|
// Hide stage 1 only after stage 2 took focus.
|
|
242
245
|
() => overlay.hide());
|
|
243
246
|
if (chosen === undefined) {
|
package/lib/selectors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selectors.js","sourceRoot":"","sources":["../src/selectors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAE,UAAU,EAAiD,MAAM,wBAAwB,CAAA;AAClG,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAejD,qEAAqE;AACrE,MAAM,mBAAmB,GAAe;IACtC,KAAK,EAAE,SAAS;IAChB,KAAK,EAAE,oBAAoB;IAC3B,WAAW,EAAE,uDAAuD;CACrE,CAAA;AAED;;;;;;;GAOG;AACH,
|
|
1
|
+
{"version":3,"file":"selectors.js","sourceRoot":"","sources":["../src/selectors.ts"],"names":[],"mappings":"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"}
|
package/lib/session.d.ts
CHANGED
|
@@ -20,6 +20,8 @@ export interface BridgeCallbacks {
|
|
|
20
20
|
onStatus(status: 'idle' | 'running'): void;
|
|
21
21
|
/** Live snapshot of tracked subagent (child session) rows, on any change. */
|
|
22
22
|
onLive(agents: readonly AgentView[]): void;
|
|
23
|
+
/** A tracked child completed one more turn (the "rounds" the policy caps). */
|
|
24
|
+
onTurnCount?(childId: string, count: number): void;
|
|
23
25
|
}
|
|
24
26
|
/** Incrementally maintained footer statistics (all O(1) reads). */
|
|
25
27
|
export interface BridgeStats {
|
|
@@ -51,6 +53,15 @@ export declare class DshSessionBridge {
|
|
|
51
53
|
private readonly agentViews;
|
|
52
54
|
/** Child session ids whose own events we fold into the agent views. */
|
|
53
55
|
private readonly childSessions;
|
|
56
|
+
/**
|
|
57
|
+
* Per-child event ring buffer — the raw transcript the subagent viewer
|
|
58
|
+
* renders. Capped so a runaway child cannot grow the process unboundedly;
|
|
59
|
+
* the oldest events drop off (the viewer shows a "history truncated" hint
|
|
60
|
+
* when the cap is hit).
|
|
61
|
+
*/
|
|
62
|
+
private readonly childLogs;
|
|
63
|
+
/** Per-child completed turn count — the "rounds" the policy caps. */
|
|
64
|
+
private readonly turnCounts;
|
|
54
65
|
/**
|
|
55
66
|
* Session ids that can own tracked children (this session first, then every
|
|
56
67
|
* tracked child — delegation nests). Used to match `parentSession` headers
|
|
@@ -64,6 +75,18 @@ export declare class DshSessionBridge {
|
|
|
64
75
|
getStats(): BridgeStats;
|
|
65
76
|
/** Current session id, when one exists. */
|
|
66
77
|
getSessionId(): SessionId | undefined;
|
|
78
|
+
/** Sorted snapshot of every tracked child (running and settled). */
|
|
79
|
+
getAgentViews(): readonly AgentView[];
|
|
80
|
+
/** Children still running (`outcome` unset) — the live count the guard caps. */
|
|
81
|
+
getLiveChildren(): readonly AgentView[];
|
|
82
|
+
/** The buffered transcript of one child, in log order (capped, maybe truncated). */
|
|
83
|
+
getChildLog(childId: string): readonly SessionEvent[];
|
|
84
|
+
/** Completed turn count of one child ("rounds"). */
|
|
85
|
+
getTurnCount(childId: string): number;
|
|
86
|
+
/** Whether one child settled (a continuable child may resume later). */
|
|
87
|
+
isChildSettled(childId: string): boolean;
|
|
88
|
+
/** True when the child's buffered transcript dropped its oldest events. */
|
|
89
|
+
isChildLogTruncated(childId: string): boolean;
|
|
67
90
|
/** Queue one user prompt, creating the session lazily on first use. */
|
|
68
91
|
prompt(text: string): Promise<void>;
|
|
69
92
|
/** The live agent, creating the session lazily when needed. */
|
|
@@ -128,6 +151,8 @@ export declare class DshSessionBridge {
|
|
|
128
151
|
private foldTracked;
|
|
129
152
|
/** Push the current agent views (stable order) to the renderer. */
|
|
130
153
|
private emitLive;
|
|
154
|
+
/** Append one child-session event to its transcript buffer, dropping the oldest at the cap. */
|
|
155
|
+
private appendChildLog;
|
|
131
156
|
private ensureSession;
|
|
132
157
|
/**
|
|
133
158
|
* Seed `selection`/`selectionRef` from the composed default — without
|
|
@@ -155,3 +180,14 @@ export declare class DshSessionBridge {
|
|
|
155
180
|
* @returns undefined on success, the failure message otherwise.
|
|
156
181
|
*/
|
|
157
182
|
export declare function persistDefaultModel(ctx: Context, selection: ModelSelection): Promise<string | undefined>;
|
|
183
|
+
/**
|
|
184
|
+
* Stash the current session id on the process-global store so a subsequent
|
|
185
|
+
* hot-reload in the same process can resume it. Pass undefined to clear the
|
|
186
|
+
* stash (no session current).
|
|
187
|
+
*/
|
|
188
|
+
export declare function stashSessionIdForReload(id: SessionId | undefined): void;
|
|
189
|
+
/**
|
|
190
|
+
* Consume (read-and-delete) a previously stashed session id, or undefined when
|
|
191
|
+
* none was stashed. One-shot: a second call returns undefined.
|
|
192
|
+
*/
|
|
193
|
+
export declare function takeStashedSessionId(): SessionId | undefined;
|
package/lib/session.js
CHANGED
|
@@ -14,6 +14,49 @@ import { createUserMessage } from '@deepseek-ai/dsh-llm';
|
|
|
14
14
|
import { settingsNamespace, SettingsConflictError } from '@deepseek-ai/dsh-settings';
|
|
15
15
|
import { SessionId } from '@deepseek-ai/dsh-session';
|
|
16
16
|
import { isAgentEnd, isAgentStart, isLlmRetry, isSubagentDescriptor } from "./dsh-events.js";
|
|
17
|
+
/**
|
|
18
|
+
* Per-child transcript buffer cap. 2000 events covers a long delegated task's
|
|
19
|
+
* assistant/tool/user rows (~a few hundred KB at worst) while bounding a
|
|
20
|
+
* runaway child; the viewer flags truncation instead of dropping silently.
|
|
21
|
+
*/
|
|
22
|
+
const CHILD_LOG_CAP = 2000;
|
|
23
|
+
/** Tail marker for `llm/retry` events (no text content — the row shows it is re-working). */
|
|
24
|
+
const RETRY_MARKER = '↻ retry';
|
|
25
|
+
/** Strip ANSI SGR escape sequences (the only escapes collected into assistant text). */
|
|
26
|
+
function stripAnsi(text) {
|
|
27
|
+
return text.replace(/\x1b\[[0-9;]*m/g, '');
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Last visible text line of an `assistant/message` event's content, or
|
|
31
|
+
* undefined when it carries no text block. Defensive: reads through an
|
|
32
|
+
* `unknown` shape (the declaring package's content model is not imported
|
|
33
|
+
* here) and never throws — a missing/unexpected field simply yields nothing.
|
|
34
|
+
*/
|
|
35
|
+
function lastTextLine(data) {
|
|
36
|
+
const content = data?.message?.content;
|
|
37
|
+
if (!Array.isArray(content))
|
|
38
|
+
return undefined;
|
|
39
|
+
let blockText;
|
|
40
|
+
for (const block of content) {
|
|
41
|
+
const b = block;
|
|
42
|
+
if (b?.type === 'text' && typeof b.text === 'string' && b.text !== '') {
|
|
43
|
+
blockText = b.text;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (blockText === undefined)
|
|
47
|
+
return undefined;
|
|
48
|
+
// Last non-blank line of the text body, whitespace-folded so a wrapped/
|
|
49
|
+
// CRLF stream collapses onto one row.
|
|
50
|
+
const body = stripAnsi(blockText).replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
|
51
|
+
const lines = body.split('\n');
|
|
52
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
53
|
+
const line = lines[i].trim();
|
|
54
|
+
if (line === '')
|
|
55
|
+
continue;
|
|
56
|
+
return line.replace(/\s+/g, ' ');
|
|
57
|
+
}
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
17
60
|
export class DshSessionBridge {
|
|
18
61
|
ctx;
|
|
19
62
|
callbacks;
|
|
@@ -39,6 +82,15 @@ export class DshSessionBridge {
|
|
|
39
82
|
agentViews = new Map();
|
|
40
83
|
/** Child session ids whose own events we fold into the agent views. */
|
|
41
84
|
childSessions = new Set();
|
|
85
|
+
/**
|
|
86
|
+
* Per-child event ring buffer — the raw transcript the subagent viewer
|
|
87
|
+
* renders. Capped so a runaway child cannot grow the process unboundedly;
|
|
88
|
+
* the oldest events drop off (the viewer shows a "history truncated" hint
|
|
89
|
+
* when the cap is hit).
|
|
90
|
+
*/
|
|
91
|
+
childLogs = new Map();
|
|
92
|
+
/** Per-child completed turn count — the "rounds" the policy caps. */
|
|
93
|
+
turnCounts = new Map();
|
|
42
94
|
/**
|
|
43
95
|
* Session ids that can own tracked children (this session first, then every
|
|
44
96
|
* tracked child — delegation nests). Used to match `parentSession` headers
|
|
@@ -74,6 +126,7 @@ export class DshSessionBridge {
|
|
|
74
126
|
&& !this.agentViews.has(sessionKey)) {
|
|
75
127
|
this.agentViews.set(sessionKey, {
|
|
76
128
|
childId: sessionKey,
|
|
129
|
+
parentSession: String(header.parentSession),
|
|
77
130
|
label: `subagent ${sessionKey.slice(0, 8)}`,
|
|
78
131
|
startedAt: event.time,
|
|
79
132
|
tokens: 0,
|
|
@@ -87,6 +140,12 @@ export class DshSessionBridge {
|
|
|
87
140
|
if (this.trackedSessions.has(sessionKey)) {
|
|
88
141
|
this.foldTracked(sessionKey, event);
|
|
89
142
|
}
|
|
143
|
+
// Buffer the child's OWN log for the viewer (not the parent's workflow
|
|
144
|
+
// rows, which carry no child transcript). The buffer is capped; the
|
|
145
|
+
// viewer reports truncation when the head dropped off.
|
|
146
|
+
if (this.childSessions.has(sessionKey)) {
|
|
147
|
+
this.appendChildLog(sessionKey, event);
|
|
148
|
+
}
|
|
90
149
|
if (this.sessionId !== undefined && session.id === this.sessionId) {
|
|
91
150
|
this.applyEvent(event);
|
|
92
151
|
this.callbacks.onEvent(event);
|
|
@@ -107,6 +166,30 @@ export class DshSessionBridge {
|
|
|
107
166
|
getSessionId() {
|
|
108
167
|
return this.sessionId;
|
|
109
168
|
}
|
|
169
|
+
/** Sorted snapshot of every tracked child (running and settled). */
|
|
170
|
+
getAgentViews() {
|
|
171
|
+
return [...this.agentViews.values()].sort((a, b) => a.startedAt - b.startedAt || a.childId.localeCompare(b.childId));
|
|
172
|
+
}
|
|
173
|
+
/** Children still running (`outcome` unset) — the live count the guard caps. */
|
|
174
|
+
getLiveChildren() {
|
|
175
|
+
return this.getAgentViews().filter(view => view.outcome === undefined);
|
|
176
|
+
}
|
|
177
|
+
/** The buffered transcript of one child, in log order (capped, maybe truncated). */
|
|
178
|
+
getChildLog(childId) {
|
|
179
|
+
return this.childLogs.get(childId) ?? [];
|
|
180
|
+
}
|
|
181
|
+
/** Completed turn count of one child ("rounds"). */
|
|
182
|
+
getTurnCount(childId) {
|
|
183
|
+
return this.turnCounts.get(childId) ?? 0;
|
|
184
|
+
}
|
|
185
|
+
/** Whether one child settled (a continuable child may resume later). */
|
|
186
|
+
isChildSettled(childId) {
|
|
187
|
+
return this.agentViews.get(childId)?.outcome !== undefined;
|
|
188
|
+
}
|
|
189
|
+
/** True when the child's buffered transcript dropped its oldest events. */
|
|
190
|
+
isChildLogTruncated(childId) {
|
|
191
|
+
return (this.childLogs.get(childId)?.length ?? 0) >= CHILD_LOG_CAP;
|
|
192
|
+
}
|
|
110
193
|
/** Queue one user prompt, creating the session lazily on first use. */
|
|
111
194
|
async prompt(text) {
|
|
112
195
|
const handle = await this.ensureSession();
|
|
@@ -169,6 +252,8 @@ export class DshSessionBridge {
|
|
|
169
252
|
this.running = false;
|
|
170
253
|
this.agentViews.clear();
|
|
171
254
|
this.childSessions.clear();
|
|
255
|
+
this.childLogs.clear();
|
|
256
|
+
this.turnCounts.clear();
|
|
172
257
|
this.trackedSessions.clear();
|
|
173
258
|
this.runSeqToChild.clear();
|
|
174
259
|
if (handle !== undefined)
|
|
@@ -197,6 +282,8 @@ export class DshSessionBridge {
|
|
|
197
282
|
this.stats.cacheHitRate = undefined;
|
|
198
283
|
this.agentViews.clear();
|
|
199
284
|
this.childSessions.clear();
|
|
285
|
+
this.childLogs.clear();
|
|
286
|
+
this.turnCounts.clear();
|
|
200
287
|
this.trackedSessions.clear();
|
|
201
288
|
this.runSeqToChild.clear();
|
|
202
289
|
this.emitLive();
|
|
@@ -351,14 +438,23 @@ export class DshSessionBridge {
|
|
|
351
438
|
}
|
|
352
439
|
}
|
|
353
440
|
if (this.childSessions.has(sessionId)) {
|
|
441
|
+
// Round counting is view-independent: every completed turn of the child
|
|
442
|
+
// is one round, even once the view settled (continuable children resume).
|
|
443
|
+
if (event.type === 'turn/end') {
|
|
444
|
+
const count = (this.turnCounts.get(sessionId) ?? 0) + 1;
|
|
445
|
+
this.turnCounts.set(sessionId, count);
|
|
446
|
+
this.callbacks.onTurnCount?.(sessionId, count);
|
|
447
|
+
}
|
|
354
448
|
const view = this.agentViews.get(sessionId);
|
|
355
449
|
if (view !== undefined) {
|
|
356
450
|
if (isSubagentDescriptor(event)) {
|
|
357
451
|
if (view.provider !== event.data.provider
|
|
452
|
+
|| view.mode !== event.data.mode
|
|
358
453
|
|| (event.data.label !== undefined && view.label !== event.data.label)) {
|
|
359
454
|
this.agentViews.set(sessionId, {
|
|
360
455
|
...view,
|
|
361
456
|
provider: event.data.provider,
|
|
457
|
+
mode: event.data.mode,
|
|
362
458
|
...(event.data.label === undefined ? {} : { label: event.data.label }),
|
|
363
459
|
});
|
|
364
460
|
changed = true;
|
|
@@ -366,21 +462,36 @@ export class DshSessionBridge {
|
|
|
366
462
|
}
|
|
367
463
|
else if (event.type === 'assistant/message') {
|
|
368
464
|
const usage = event.data.usage;
|
|
369
|
-
|
|
370
|
-
|
|
465
|
+
const delta = usage === undefined
|
|
466
|
+
? 0
|
|
467
|
+
: usage.inputTokens + usage.outputTokens
|
|
371
468
|
+ (usage.cacheReadTokens ?? 0) + (usage.cacheWriteTokens ?? 0);
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
469
|
+
const lastLine = lastTextLine(event.data);
|
|
470
|
+
const tokensChanged = delta > 0;
|
|
471
|
+
const lineChanged = lastLine !== undefined && lastLine !== view.lastLine;
|
|
472
|
+
if (tokensChanged || lineChanged) {
|
|
473
|
+
// One set: neither delta nor lastLine may clobber the other.
|
|
474
|
+
this.agentViews.set(sessionId, {
|
|
475
|
+
...view,
|
|
476
|
+
...(tokensChanged ? { tokens: view.tokens + delta } : {}),
|
|
477
|
+
...(lineChanged ? { lastLine } : {}),
|
|
478
|
+
});
|
|
479
|
+
changed = true;
|
|
376
480
|
}
|
|
377
481
|
}
|
|
378
482
|
else if (isLlmRetry(event)) {
|
|
379
|
-
|
|
483
|
+
// No text content — surface a fixed marker so the row shows the
|
|
484
|
+
// child is (re)working. Merged into one set so the retry counters
|
|
485
|
+
// and the marker can't clobber each other.
|
|
486
|
+
const retryChanged = view.retries !== event.data.retry || view.maxRetries !== event.data.maxRetries;
|
|
487
|
+
const lineChanged = view.lastLine !== RETRY_MARKER;
|
|
488
|
+
if (retryChanged || lineChanged) {
|
|
380
489
|
this.agentViews.set(sessionId, {
|
|
381
490
|
...view,
|
|
382
|
-
|
|
383
|
-
|
|
491
|
+
...(retryChanged
|
|
492
|
+
? { retries: event.data.retry, maxRetries: event.data.maxRetries }
|
|
493
|
+
: {}),
|
|
494
|
+
...(lineChanged ? { lastLine: RETRY_MARKER } : {}),
|
|
384
495
|
});
|
|
385
496
|
changed = true;
|
|
386
497
|
}
|
|
@@ -390,6 +501,11 @@ export class DshSessionBridge {
|
|
|
390
501
|
this.agentViews.set(sessionId, { ...view, lastTool: event.data.name });
|
|
391
502
|
changed = true;
|
|
392
503
|
}
|
|
504
|
+
const toolLine = `⚙ ${event.data.name}`;
|
|
505
|
+
if (toolLine !== view.lastLine) {
|
|
506
|
+
this.agentViews.set(sessionId, { ...view, lastLine: toolLine });
|
|
507
|
+
changed = true;
|
|
508
|
+
}
|
|
393
509
|
}
|
|
394
510
|
else if (event.type === 'request/context') {
|
|
395
511
|
const contextWindow = event.data.contextWindow;
|
|
@@ -417,7 +533,18 @@ export class DshSessionBridge {
|
|
|
417
533
|
}
|
|
418
534
|
/** Push the current agent views (stable order) to the renderer. */
|
|
419
535
|
emitLive() {
|
|
420
|
-
this.callbacks.onLive(
|
|
536
|
+
this.callbacks.onLive(this.getAgentViews());
|
|
537
|
+
}
|
|
538
|
+
/** Append one child-session event to its transcript buffer, dropping the oldest at the cap. */
|
|
539
|
+
appendChildLog(childId, event) {
|
|
540
|
+
let log = this.childLogs.get(childId);
|
|
541
|
+
if (log === undefined) {
|
|
542
|
+
log = [];
|
|
543
|
+
this.childLogs.set(childId, log);
|
|
544
|
+
}
|
|
545
|
+
if (log.length >= CHILD_LOG_CAP)
|
|
546
|
+
log.shift();
|
|
547
|
+
log.push(event);
|
|
421
548
|
}
|
|
422
549
|
async ensureSession() {
|
|
423
550
|
// A resume in flight would otherwise race this check: the handle is only
|
|
@@ -552,4 +679,38 @@ export async function persistDefaultModel(ctx, selection) {
|
|
|
552
679
|
}
|
|
553
680
|
}
|
|
554
681
|
}
|
|
682
|
+
// Reload survival for the current session. `/reload` evicts this plugin's
|
|
683
|
+
// entire user-code module closure from the ESM/CJS caches, so module-level
|
|
684
|
+
// state does not survive — but the reload happens in the SAME dsh process, so
|
|
685
|
+
// process-global state does. These two helpers stash the current session id on
|
|
686
|
+
// `globalThis` before a reload tears this fiber down, and the freshly re-imported
|
|
687
|
+
// module consumes it in the new fiber so the TUI resumes the previously current
|
|
688
|
+
// session instead of lazily creating a fresh one on the next prompt. A real dsh
|
|
689
|
+
// process restart resets the stash, so a fresh start still lazily creates a new
|
|
690
|
+
// session. The stash is one-shot: `takeStashedSessionId` reads and deletes.
|
|
691
|
+
const LAST_SESSION_ID_KEY = Symbol.for('dsh-tui-pi.lastSessionId');
|
|
692
|
+
/**
|
|
693
|
+
* Stash the current session id on the process-global store so a subsequent
|
|
694
|
+
* hot-reload in the same process can resume it. Pass undefined to clear the
|
|
695
|
+
* stash (no session current).
|
|
696
|
+
*/
|
|
697
|
+
export function stashSessionIdForReload(id) {
|
|
698
|
+
const store = globalThis;
|
|
699
|
+
if (id === undefined) {
|
|
700
|
+
delete store[LAST_SESSION_ID_KEY];
|
|
701
|
+
}
|
|
702
|
+
else {
|
|
703
|
+
store[LAST_SESSION_ID_KEY] = String(id);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* Consume (read-and-delete) a previously stashed session id, or undefined when
|
|
708
|
+
* none was stashed. One-shot: a second call returns undefined.
|
|
709
|
+
*/
|
|
710
|
+
export function takeStashedSessionId() {
|
|
711
|
+
const store = globalThis;
|
|
712
|
+
const raw = store[LAST_SESSION_ID_KEY];
|
|
713
|
+
delete store[LAST_SESSION_ID_KEY];
|
|
714
|
+
return typeof raw === 'string' ? SessionId(raw) : undefined;
|
|
715
|
+
}
|
|
555
716
|
//# sourceMappingURL=session.js.map
|