pi-one-ui 0.1.1 → 0.2.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 +66 -39
- package/extensions/{shell → app/commands}/settings-previews.ts +7 -7
- package/extensions/app/config/renderer.ts +13 -63
- package/extensions/app/config/shell.ts +24 -138
- package/extensions/app/config/store.ts +290 -0
- package/extensions/app/host/pi-extension-port.ts +25 -0
- package/extensions/app/host/pi-ui-port.ts +52 -0
- package/extensions/app/host/tui-capabilities.ts +27 -0
- package/extensions/app/overlay/input-router.ts +63 -0
- package/extensions/app/overlay/overlay-manager.ts +39 -0
- package/extensions/{shell → app/overlay}/selector-border.ts +3 -3
- package/extensions/app/overlay/selector-controller.ts +104 -0
- package/extensions/app/ownership/layout-registry.ts +65 -0
- package/extensions/app/ownership.ts +21 -7
- package/extensions/app/panel.ts +261 -140
- package/extensions/app/runtime/event-coordinator.ts +84 -0
- package/extensions/app/runtime/render-scheduler.ts +56 -0
- package/extensions/app/runtime/runtime-state.ts +83 -0
- package/extensions/app/runtime/tui-runtime.ts +546 -0
- package/extensions/features/{context.ts → context-inspector/index.ts} +30 -23
- package/extensions/features/{shell/flush-docked-bash.ts → flush-docked-bash.ts} +1 -4
- package/extensions/index.ts +2 -48
- package/extensions/layouts/context/index.ts +188 -0
- package/extensions/{shell → layouts/context/message}/user-message-styles.ts +2 -2
- package/extensions/{shell → layouts/context/message}/user-message.ts +2 -2
- package/extensions/{transcript → layouts/context}/renderer/compact-mode.ts +17 -13
- package/extensions/layouts/context/renderer/context-refresh.ts +79 -0
- package/extensions/{transcript → layouts/context}/renderer/default-mode.ts +3 -3
- package/extensions/{transcript → layouts/context}/renderer/index.ts +14 -14
- package/extensions/{transcript → layouts/context}/renderer/mouse/hover.ts +2 -2
- package/extensions/{transcript → layouts/context}/renderer/mouse/interaction.ts +26 -7
- package/extensions/{transcript → layouts/context}/renderer/mouse/layout.ts +1 -1
- package/extensions/{transcript → layouts/context}/renderer/mouse/packets.ts +3 -3
- package/extensions/{transcript → layouts/context}/renderer/mouse/scroll.ts +12 -7
- package/extensions/{transcript → layouts/context}/renderer/tool/diff/diff-component.ts +2 -2
- package/extensions/{transcript → layouts/context}/renderer/tool/diff/diff-edit-render.ts +1 -1
- package/extensions/{transcript → layouts/context}/renderer/tool/diff/diff-highlight.ts +1 -1
- package/extensions/{transcript → layouts/context}/renderer/tool/diff/diff-layout.ts +1 -1
- package/extensions/{transcript → layouts/context}/renderer/tool/diff/diff-limits.ts +1 -1
- package/extensions/{transcript → layouts/context}/renderer/tool/diff/diff-palette.ts +1 -1
- package/extensions/{transcript → layouts/context}/renderer/tool/diff/diff-presentation.ts +1 -1
- package/extensions/{transcript → layouts/context}/renderer/tool/diff/diff-renderer.ts +1 -1
- package/extensions/{transcript → layouts/context}/renderer/tool/diff/diff-write-render.ts +1 -1
- package/extensions/{transcript → layouts/context}/renderer/tool/diff/index.ts +2 -2
- package/extensions/{transcript → layouts/context}/renderer/tool/grouping.ts +4 -4
- package/extensions/{transcript → layouts/context}/renderer/tool/message-display.ts +6 -4
- package/extensions/{transcript → layouts/context}/renderer/tool/names.ts +2 -2
- package/extensions/{transcript → layouts/context}/renderer/tool/result.ts +3 -3
- package/extensions/{features/agent-summary → layouts/context/summary}/core.ts +1 -1
- package/extensions/{features → layouts/context/thinking}/compact-thinking.ts +7 -7
- package/extensions/{shell → layouts/editor}/accent-rail-editor.ts +8 -8
- package/extensions/{shell → layouts/editor}/completion-menu.ts +3 -6
- package/extensions/layouts/editor/controller.ts +613 -0
- package/extensions/{shell → layouts/editor}/editor-metadata-format.ts +6 -3
- package/extensions/layouts/editor/factory.ts +159 -0
- package/extensions/layouts/editor/index.ts +16 -0
- package/extensions/{shell → layouts/editor}/minimalist-editor.ts +4 -4
- package/extensions/layouts/editor/ownership.ts +103 -0
- package/extensions/{shell → layouts/editor}/ui.ts +2 -2
- package/extensions/layouts/footer/controller.ts +392 -0
- package/extensions/layouts/footer/data.ts +41 -0
- package/extensions/{shell → layouts/footer}/extension-status.ts +2 -2
- package/extensions/{shell → layouts/footer}/footer-layout.ts +1 -1
- package/extensions/{shell → layouts/footer}/footer.ts +11 -8
- package/extensions/layouts/footer/index.ts +24 -0
- package/extensions/layouts/header/index.ts +5 -0
- package/extensions/{features/shell → layouts/header}/startup-header.ts +105 -19
- package/extensions/layouts/working-line/controller.ts +291 -0
- package/extensions/{shell → layouts/working-line}/interaction-summary.ts +3 -3
- package/extensions/{shell → layouts/working-line}/working-line-spinners.ts +1 -1
- package/extensions/{shell → layouts/working-line}/working-line.ts +4 -4
- package/extensions/{shell → services}/live-context.ts +29 -1
- package/extensions/services/project-refresh.ts +374 -0
- package/extensions/{shell → services}/project-state.ts +5 -5
- package/extensions/{shell/state.ts → services/session-state.ts} +75 -5
- package/extensions/{shell → shared}/format.ts +4 -4
- package/extensions/tools/component-tree.ts +6 -6
- package/package.json +4 -4
- package/extensions/shell/index.ts +0 -1659
- package/extensions/shell/project-refresh.ts +0 -130
- package/extensions/shell/settings-command.ts +0 -2144
- package/extensions/transcript/index.ts +0 -65
- package/extensions/transcript/renderer/transcript-refresh.ts +0 -79
- /package/extensions/{shell → app/ownership}/prototype-patch-registry.ts +0 -0
- /package/extensions/{shell → app/runtime}/session-lifecycle.ts +0 -0
- /package/extensions/features/{shell/aliases.ts → aliases.ts} +0 -0
- /package/extensions/features/{shell → legacy}/working-message.ts +0 -0
- /package/extensions/features/{reference → session-reference}/index.ts +0 -0
- /package/extensions/features/{reference → session-reference}/session.ts +0 -0
- /package/extensions/features/{reference/subagent.ts → subagent-autocomplete.ts} +0 -0
- /package/extensions/{shell → layouts/context/message}/user-message-osc.ts +0 -0
- /package/extensions/{transcript → layouts/context}/renderer/markdown-enhance.ts +0 -0
- /package/extensions/{transcript → layouts/context}/renderer/tool/diff/ATTRIBUTION.md +0 -0
- /package/extensions/{transcript → layouts/context}/renderer/tool/diff/ansi-utils.ts +0 -0
- /package/extensions/{transcript → layouts/context}/renderer/tool/diff/diff-header.ts +0 -0
- /package/extensions/{transcript → layouts/context}/renderer/tool/diff/diff-inline.ts +0 -0
- /package/extensions/{transcript → layouts/context}/renderer/tool/diff/diff-parse.ts +0 -0
- /package/extensions/{transcript → layouts/context}/renderer/tool/diff/diff-text.ts +0 -0
- /package/extensions/{transcript → layouts/context}/renderer/tool/diff/line-width-safety.ts +0 -0
- /package/extensions/{transcript → layouts/context}/renderer/tool/diff/shiki-highlight.ts +0 -0
- /package/extensions/{transcript → layouts/context}/renderer/tool/diff/write-execution.ts +0 -0
- /package/extensions/{transcript → layouts/context}/renderer/tool/show-more-hint.ts +0 -0
- /package/extensions/{features/agent-summary → layouts/context/summary}/index.ts +0 -0
- /package/extensions/{shell → layouts/editor}/accent-rail-layout-patch.ts +0 -0
- /package/extensions/{shell → layouts/editor}/editor-transfer.ts +0 -0
- /package/extensions/{shell → layouts/footer}/footer-format.ts +0 -0
- /package/extensions/{shell → layouts/working-line}/working-line-messages.ts +0 -0
- /package/extensions/{shell/git.ts → services/git-data.ts} +0 -0
- /package/extensions/{shell/package-version.ts → services/package-data.ts} +0 -0
- /package/extensions/{shell/runtime.ts → services/runtime-data.ts} +0 -0
- /package/extensions/{shell → services}/telemetry.ts +0 -0
- /package/extensions/{shell → shared}/icons.ts +0 -0
- /package/extensions/{shell → shared}/style.ts +0 -0
package/extensions/index.ts
CHANGED
|
@@ -1,52 +1,6 @@
|
|
|
1
1
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import {
|
|
3
|
-
import registerShell, {
|
|
4
|
-
type ShellExtensionOptions,
|
|
5
|
-
type ShellRuntimeController,
|
|
6
|
-
} from "./shell/index.ts";
|
|
7
|
-
import registerTranscript, {
|
|
8
|
-
type TranscriptExtensionOptions,
|
|
9
|
-
type TranscriptRuntimeController,
|
|
10
|
-
} from "./transcript/index.ts";
|
|
11
|
-
|
|
12
|
-
type Controllers = {
|
|
13
|
-
shell?: ShellRuntimeController;
|
|
14
|
-
renderer?: TranscriptRuntimeController;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
function registerOneUiCommand(
|
|
18
|
-
pi: ExtensionAPI,
|
|
19
|
-
controllers: Controllers,
|
|
20
|
-
): void {
|
|
21
|
-
pi.registerCommand("oneui", {
|
|
22
|
-
description: "Open pi-one-ui settings",
|
|
23
|
-
handler: async (_args, ctx) => {
|
|
24
|
-
await showOneUiPanel(ctx, controllers);
|
|
25
|
-
},
|
|
26
|
-
});
|
|
27
|
-
}
|
|
2
|
+
import { createTuiRuntime } from "./app/runtime/tui-runtime.ts";
|
|
28
3
|
|
|
29
4
|
export default function (pi: ExtensionAPI): void {
|
|
30
|
-
|
|
31
|
-
let rendererController: TranscriptRuntimeController | undefined;
|
|
32
|
-
const shellOptions: ShellExtensionOptions = {
|
|
33
|
-
registerCommand: false,
|
|
34
|
-
onRuntimeController: (controller) => {
|
|
35
|
-
shellController = controller;
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
const rendererOptions: TranscriptExtensionOptions = {
|
|
39
|
-
onRuntimeController: (controller) => {
|
|
40
|
-
rendererController = controller;
|
|
41
|
-
},
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
// One package, one management command. The internal owners remain explicit:
|
|
45
|
-
// Shell owns the terminal chrome; transcript owns tool and message rendering.
|
|
46
|
-
registerShell(pi, shellOptions);
|
|
47
|
-
registerTranscript(pi, rendererOptions);
|
|
48
|
-
registerOneUiCommand(pi, {
|
|
49
|
-
shell: shellController,
|
|
50
|
-
renderer: rendererController,
|
|
51
|
-
});
|
|
5
|
+
createTuiRuntime(pi).install();
|
|
52
6
|
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ExtensionAPI,
|
|
3
|
+
ExtensionContext,
|
|
4
|
+
Theme,
|
|
5
|
+
} from "@earendil-works/pi-coding-agent";
|
|
6
|
+
import { config } from "../../app/config/renderer.ts";
|
|
7
|
+
import { configStore, type ConfigRecord } from "../../app/config/store.ts";
|
|
8
|
+
import {
|
|
9
|
+
hasUnsupportedComponentStyle,
|
|
10
|
+
loadConfig,
|
|
11
|
+
mergeConfig,
|
|
12
|
+
saveUserMessagesComponentPatch,
|
|
13
|
+
type UserMessagesComponentConfig,
|
|
14
|
+
type ZentuiConfig,
|
|
15
|
+
} from "../../app/config/shell.ts";
|
|
16
|
+
import {
|
|
17
|
+
installUserMessageStyle,
|
|
18
|
+
removeUserMessageStyle,
|
|
19
|
+
} from "./message/user-message.ts";
|
|
20
|
+
|
|
21
|
+
// shell
|
|
22
|
+
import piAliases from "../../features/aliases.ts";
|
|
23
|
+
import { installFlushDockedBash } from "../../features/flush-docked-bash.ts";
|
|
24
|
+
|
|
25
|
+
// feature
|
|
26
|
+
import agentAutocomplete from "../../features/subagent-autocomplete.ts";
|
|
27
|
+
import agentSummary from "./summary/index.ts";
|
|
28
|
+
import context from "../../features/context-inspector/index.ts";
|
|
29
|
+
import sessionReference from "../../features/session-reference/index.ts";
|
|
30
|
+
import { installCompactThinking } from "./thinking/compact-thinking.ts";
|
|
31
|
+
|
|
32
|
+
// renderer
|
|
33
|
+
import registerContextRenderer, {
|
|
34
|
+
getCompactThinkingConfig,
|
|
35
|
+
} from "./renderer/index.ts";
|
|
36
|
+
import markdownEnhance from "./renderer/markdown-enhance.ts";
|
|
37
|
+
|
|
38
|
+
export type ContextRuntimeController = {
|
|
39
|
+
setMode: (mode: "on" | "compact" | "off", ctx: ExtensionContext) => void;
|
|
40
|
+
updateConfig: (
|
|
41
|
+
partial: Partial<typeof config>,
|
|
42
|
+
ctx: ExtensionContext,
|
|
43
|
+
) => void;
|
|
44
|
+
setUserMessagesComponent: (
|
|
45
|
+
patch: Partial<UserMessagesComponentConfig>,
|
|
46
|
+
ctx: ExtensionContext,
|
|
47
|
+
) => void;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export type ContextExtensionOptions = {
|
|
51
|
+
/**
|
|
52
|
+
* Exposes live context refresh to the unified settings panel.
|
|
53
|
+
*/
|
|
54
|
+
onRuntimeController?: (controller: ContextRuntimeController) => void;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
let contextConfig: ZentuiConfig = loadConfig();
|
|
58
|
+
let activeTheme: Theme | undefined;
|
|
59
|
+
let cleanupUserMessageStyle: () => void = () => {};
|
|
60
|
+
let userMessageStyleInstalled = false;
|
|
61
|
+
let unsubscribeConfig: () => void = () => {};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Reports whether a session context can safely install TUI-owned patches.
|
|
65
|
+
*/
|
|
66
|
+
function isTuiContext(ctx: ExtensionContext): boolean {
|
|
67
|
+
return ctx.mode === "tui" && ctx.hasUI;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Installs the Context-owned User Message renderer once for the active session.
|
|
72
|
+
*/
|
|
73
|
+
function installContextUserMessages(): void {
|
|
74
|
+
if (userMessageStyleInstalled || !activeTheme) return;
|
|
75
|
+
try {
|
|
76
|
+
cleanupUserMessageStyle = installUserMessageStyle(
|
|
77
|
+
() => activeTheme,
|
|
78
|
+
() => contextConfig,
|
|
79
|
+
);
|
|
80
|
+
userMessageStyleInstalled = true;
|
|
81
|
+
} catch {
|
|
82
|
+
cleanupUserMessageStyle = () => {};
|
|
83
|
+
userMessageStyleInstalled = false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Removes the Context-owned User Message renderer and clears its patch state.
|
|
89
|
+
*/
|
|
90
|
+
function uninstallContextUserMessages(): void {
|
|
91
|
+
try {
|
|
92
|
+
cleanupUserMessageStyle();
|
|
93
|
+
} finally {
|
|
94
|
+
cleanupUserMessageStyle = () => {};
|
|
95
|
+
userMessageStyleInstalled = false;
|
|
96
|
+
removeUserMessageStyle();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Reconciles User Message ownership with the latest shell configuration.
|
|
102
|
+
*/
|
|
103
|
+
function reconcileContextUserMessages(): void {
|
|
104
|
+
const enabled =
|
|
105
|
+
contextConfig.components.userMessages.enabled &&
|
|
106
|
+
!hasUnsupportedComponentStyle(contextConfig, "userMessages");
|
|
107
|
+
if (enabled) installContextUserMessages();
|
|
108
|
+
else uninstallContextUserMessages();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Starts the Context session binding and subscribes it to shared config updates.
|
|
113
|
+
*/
|
|
114
|
+
function startContextSession(ctx: ExtensionContext): void {
|
|
115
|
+
if (!isTuiContext(ctx)) return;
|
|
116
|
+
activeTheme = ctx.ui.theme;
|
|
117
|
+
contextConfig = loadConfig();
|
|
118
|
+
unsubscribeConfig();
|
|
119
|
+
unsubscribeConfig = configStore.subscribe((record: ConfigRecord) => {
|
|
120
|
+
contextConfig = mergeConfig(record);
|
|
121
|
+
reconcileContextUserMessages();
|
|
122
|
+
});
|
|
123
|
+
reconcileContextUserMessages();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Applies a User Message configuration patch owned by Context.
|
|
128
|
+
*
|
|
129
|
+
* @param patch User Message configuration changes.
|
|
130
|
+
* @param _ctx Active Pi extension context.
|
|
131
|
+
*/
|
|
132
|
+
function setContextUserMessages(
|
|
133
|
+
patch: Partial<UserMessagesComponentConfig>,
|
|
134
|
+
_ctx: ExtensionContext,
|
|
135
|
+
): void {
|
|
136
|
+
contextConfig = saveUserMessagesComponentPatch(patch);
|
|
137
|
+
if (patch.enabled !== undefined || patch.style !== undefined)
|
|
138
|
+
reconcileContextUserMessages();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Releases Context session bindings and restores the original User Message patch.
|
|
143
|
+
*/
|
|
144
|
+
function stopContextSession(): void {
|
|
145
|
+
unsubscribeConfig();
|
|
146
|
+
unsubscribeConfig = () => {};
|
|
147
|
+
uninstallContextUserMessages();
|
|
148
|
+
activeTheme = undefined;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Registers the Context layout, its renderer stack and its feature hooks.
|
|
153
|
+
*/
|
|
154
|
+
export default function (
|
|
155
|
+
pi: ExtensionAPI,
|
|
156
|
+
options: ContextExtensionOptions = {},
|
|
157
|
+
): void {
|
|
158
|
+
// shell chrome
|
|
159
|
+
if (config.enableAliases) piAliases(pi);
|
|
160
|
+
installFlushDockedBash();
|
|
161
|
+
// The thinking controller is queried directly by the context render stack.
|
|
162
|
+
markdownEnhance(pi);
|
|
163
|
+
registerContextRenderer(
|
|
164
|
+
pi,
|
|
165
|
+
undefined,
|
|
166
|
+
installCompactThinking(pi, getCompactThinkingConfig()),
|
|
167
|
+
{
|
|
168
|
+
onRuntimeController: (controller) =>
|
|
169
|
+
options.onRuntimeController?.({
|
|
170
|
+
...controller,
|
|
171
|
+
setUserMessagesComponent: setContextUserMessages,
|
|
172
|
+
}),
|
|
173
|
+
},
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
// features
|
|
177
|
+
if (config.enableContextCommand) context(pi);
|
|
178
|
+
if (config.enableSessionReference) sessionReference(pi);
|
|
179
|
+
if (config.enableSubagentAutocomplete) agentAutocomplete(pi);
|
|
180
|
+
if (config.enableAgentSummary) agentSummary(pi);
|
|
181
|
+
|
|
182
|
+
pi.on("session_start", (_event, ctx) => {
|
|
183
|
+
startContextSession(ctx);
|
|
184
|
+
});
|
|
185
|
+
pi.on("session_shutdown", () => {
|
|
186
|
+
stopContextSession();
|
|
187
|
+
});
|
|
188
|
+
}
|
|
@@ -5,12 +5,12 @@ import {
|
|
|
5
5
|
truncateToWidth,
|
|
6
6
|
visibleWidth,
|
|
7
7
|
} from "@earendil-works/pi-tui";
|
|
8
|
-
import type { ZentuiConfig } from "
|
|
8
|
+
import type { ZentuiConfig } from "../../../app/config/shell.ts";
|
|
9
9
|
import {
|
|
10
10
|
EDITOR_ACCENT_FALLBACK,
|
|
11
11
|
EDITOR_BORDER_FALLBACK,
|
|
12
12
|
renderStyleForSourceOrFallbackStrict,
|
|
13
|
-
} from "
|
|
13
|
+
} from "../../../shared/style.ts";
|
|
14
14
|
import { sanitizeUserMessageSourceText } from "./user-message-osc.ts";
|
|
15
15
|
|
|
16
16
|
export type UserMessageStyleRenderInput = {
|
|
@@ -3,11 +3,11 @@ import {
|
|
|
3
3
|
UserMessageComponent,
|
|
4
4
|
} from "@earendil-works/pi-coding-agent";
|
|
5
5
|
import { wrapTextWithAnsi } from "@earendil-works/pi-tui";
|
|
6
|
-
import type { ZentuiConfig } from "
|
|
6
|
+
import type { ZentuiConfig } from "../../../app/config/shell.ts";
|
|
7
7
|
import {
|
|
8
8
|
installPrototypePatch,
|
|
9
9
|
removePrototypePatch,
|
|
10
|
-
} from "
|
|
10
|
+
} from "../../../app/ownership/prototype-patch-registry.ts";
|
|
11
11
|
import {
|
|
12
12
|
sanitizeRenderedUserMessageLines,
|
|
13
13
|
sanitizeRenderedUserMessageText,
|
|
@@ -26,10 +26,10 @@ import {
|
|
|
26
26
|
Box,
|
|
27
27
|
Spacer,
|
|
28
28
|
} from "@earendil-works/pi-tui";
|
|
29
|
-
import { config, getToolDisplayConfig } from "
|
|
30
|
-
import { toolLoadingIcon } from "
|
|
31
|
-
import { sanitizeToolResultText } from "
|
|
32
|
-
import {
|
|
29
|
+
import { config, getToolDisplayConfig } from "../../../app/config/renderer.ts";
|
|
30
|
+
import { toolLoadingIcon } from "../../../tools/tool-loading-icon.ts";
|
|
31
|
+
import { sanitizeToolResultText } from "../../../tools/tool-result-sanitize.ts";
|
|
32
|
+
import { refreshContextComponent } from "./context-refresh.ts";
|
|
33
33
|
import { getMessageDisplayTheme } from "./tool/message-display.ts";
|
|
34
34
|
import { showMoreHintText } from "./tool/show-more-hint.ts";
|
|
35
35
|
import {
|
|
@@ -45,10 +45,13 @@ import {
|
|
|
45
45
|
renderExpandedToolResult,
|
|
46
46
|
scheduleAnimation,
|
|
47
47
|
} from "./tool/result.ts";
|
|
48
|
-
import { oneLine } from "
|
|
48
|
+
import { oneLine } from "../../../tools/format.ts";
|
|
49
49
|
import { paddedBackgroundRow } from "./tool/grouping.ts";
|
|
50
|
-
import {
|
|
51
|
-
|
|
50
|
+
import {
|
|
51
|
+
hasVisibleText,
|
|
52
|
+
stripBackgroundAnsi,
|
|
53
|
+
} from "../../../tools/ansi-text.ts";
|
|
54
|
+
import { walkComponentTree } from "../../../tools/component-tree.ts";
|
|
52
55
|
import {
|
|
53
56
|
ASSISTANT_REENTRY_DESCRIPTION,
|
|
54
57
|
ASSISTANT_REENTRY_KEY,
|
|
@@ -60,7 +63,7 @@ import {
|
|
|
60
63
|
COMPACT_THINKING_PATCH_KEY,
|
|
61
64
|
patchRegistry,
|
|
62
65
|
PROTOTYPE_ORIGINAL_KEY,
|
|
63
|
-
} from "
|
|
66
|
+
} from "../../../tools/patch-keys.ts";
|
|
64
67
|
|
|
65
68
|
/** compact 渲染层对 compact-thinking 的只读查询面(不建第二套计时器)。 */
|
|
66
69
|
export type CompactThinkingQuery = {
|
|
@@ -839,9 +842,10 @@ function collectMountedComponents(root: any): void {
|
|
|
839
842
|
tools.add(value);
|
|
840
843
|
}
|
|
841
844
|
});
|
|
842
|
-
//
|
|
843
|
-
//
|
|
844
|
-
//
|
|
845
|
+
// Replace tracking only after scanning components. The root often omits the
|
|
846
|
+
// context while a panel or custom UI is open,
|
|
847
|
+
// so clearing here would lose live updateContent/updateDisplay instances,
|
|
848
|
+
// and mode changes would require a /reload to rebuild them.
|
|
845
849
|
if (assistants.size > 0 || tools.size > 0) {
|
|
846
850
|
trackedAssistantComponents.clear();
|
|
847
851
|
trackedToolComponents.clear();
|
|
@@ -1421,7 +1425,7 @@ function refreshTrackedComponents(): void {
|
|
|
1421
1425
|
for (const component of [...trackedAssistantComponents]) {
|
|
1422
1426
|
try {
|
|
1423
1427
|
if (config.mode !== "compact") detachAssistantExpansion(component);
|
|
1424
|
-
|
|
1428
|
+
refreshContextComponent(component);
|
|
1425
1429
|
} catch {
|
|
1426
1430
|
trackedAssistantComponents.delete(component);
|
|
1427
1431
|
}
|
|
@@ -1429,7 +1433,7 @@ function refreshTrackedComponents(): void {
|
|
|
1429
1433
|
for (const component of [...trackedToolComponents]) {
|
|
1430
1434
|
try {
|
|
1431
1435
|
// 共享实现负责 updateDisplay;invalidate 属于 compact-mode 的跟踪语义。
|
|
1432
|
-
|
|
1436
|
+
refreshContextComponent(component);
|
|
1433
1437
|
component.invalidate?.();
|
|
1434
1438
|
} catch {
|
|
1435
1439
|
trackedToolComponents.delete(component);
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { AssistantMessage } from "@earendil-works/pi-ai";
|
|
2
|
+
import {
|
|
3
|
+
AssistantMessageComponent,
|
|
4
|
+
ToolExecutionComponent,
|
|
5
|
+
} from "@earendil-works/pi-coding-agent";
|
|
6
|
+
import { walkComponentTree } from "../../../tools/component-tree.ts";
|
|
7
|
+
import {
|
|
8
|
+
COMPACT_MODE_PATCH_KEY,
|
|
9
|
+
patchRegistry,
|
|
10
|
+
} from "../../../tools/patch-keys.ts";
|
|
11
|
+
|
|
12
|
+
// pi-coding-agent 类型声明中 AssistantMessageComponent 仅能以 value 形式使用,
|
|
13
|
+
// updateContent/lastMessage 用结构化类型访问。
|
|
14
|
+
type ContextComponentInternals = {
|
|
15
|
+
lastMessage?: AssistantMessage;
|
|
16
|
+
updateContent(message: AssistantMessage): void;
|
|
17
|
+
invalidate?(): void;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Refreshes one constructed context component.
|
|
22
|
+
*
|
|
23
|
+
* Assistant components receive their latest message, while tool components
|
|
24
|
+
* refresh their display so resumed content returns to the current shell.
|
|
25
|
+
*/
|
|
26
|
+
export function refreshContextComponent(value: unknown): boolean {
|
|
27
|
+
if (!value || typeof value !== "object") return false;
|
|
28
|
+
if (value instanceof AssistantMessageComponent) {
|
|
29
|
+
const self = value as unknown as ContextComponentInternals;
|
|
30
|
+
if (self.lastMessage) self.updateContent(self.lastMessage);
|
|
31
|
+
else self.invalidate?.();
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
if (value instanceof ToolExecutionComponent) {
|
|
35
|
+
// updateDisplay is private, but it is the only resume-time path that
|
|
36
|
+
// restores content to the correct shell container.
|
|
37
|
+
(value as unknown as { updateDisplay(): void }).updateDisplay();
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Asserts that compact-mode remains the outer patch in compact mode.
|
|
45
|
+
*
|
|
46
|
+
* Resume and reload can rebuild components without emitting a message update,
|
|
47
|
+
* so the ownership order is checked before any mounted component is refreshed.
|
|
48
|
+
*/
|
|
49
|
+
function assertCompactModeOutermost(): void {
|
|
50
|
+
try {
|
|
51
|
+
const patch = patchRegistry.get<{ assertAssistantOwnership?: () => void }>(
|
|
52
|
+
COMPACT_MODE_PATCH_KEY,
|
|
53
|
+
);
|
|
54
|
+
if (patch && typeof patch.assertAssistantOwnership === "function") {
|
|
55
|
+
patch.assertAssistantOwnership();
|
|
56
|
+
}
|
|
57
|
+
} catch {
|
|
58
|
+
// Continue scanning when compact-mode is absent or the assertion fails.
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Scans mounted roots and refreshes all constructed assistant and tool components.
|
|
64
|
+
*
|
|
65
|
+
* This covers reload, resume and compaction paths where Pi rebuilds components
|
|
66
|
+
* before the renderer patches are installed.
|
|
67
|
+
*/
|
|
68
|
+
export function refreshMountedContext(tui?: unknown): void {
|
|
69
|
+
if (!tui || typeof (tui as any).getMountedRoots !== "function") return;
|
|
70
|
+
// Fix patch order before refreshing so updateContent runs through the outer patch.
|
|
71
|
+
assertCompactModeOutermost();
|
|
72
|
+
walkComponentTree(tui, (value: any) => {
|
|
73
|
+
try {
|
|
74
|
+
refreshContextComponent(value);
|
|
75
|
+
} catch {
|
|
76
|
+
// Isolate one component failure; a later tree rebuild can retry it.
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
@@ -10,13 +10,13 @@ import {
|
|
|
10
10
|
config,
|
|
11
11
|
getToolDisplayConfig,
|
|
12
12
|
type CompactStyleMode,
|
|
13
|
-
} from "
|
|
13
|
+
} from "../../../app/config/renderer.ts";
|
|
14
14
|
import {
|
|
15
15
|
COMPONENT_TOOL_RENDER_MODE,
|
|
16
16
|
GLOBAL_TOOL_RENDER_PATCH,
|
|
17
17
|
patchRegistry,
|
|
18
18
|
TOOL_EXPANDED_BACKGROUND_PATCH,
|
|
19
|
-
} from "
|
|
19
|
+
} from "../../../tools/patch-keys.ts";
|
|
20
20
|
import { isToolCallHovered } from "./mouse/hover.ts";
|
|
21
21
|
import {
|
|
22
22
|
countLines,
|
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
toolIconColor,
|
|
37
37
|
toolViewportWidth,
|
|
38
38
|
} from "./tool/result.ts";
|
|
39
|
-
import { oneLine } from "
|
|
39
|
+
import { oneLine } from "../../../tools/format.ts";
|
|
40
40
|
import { showMoreHintText } from "./tool/show-more-hint.ts";
|
|
41
41
|
import { countWriteDiffStats } from "./tool/diff/diff-renderer.ts";
|
|
42
42
|
import {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import type { CompactThinkingController } from "
|
|
2
|
+
import type { CompactThinkingController } from "../thinking/compact-thinking.ts";
|
|
3
3
|
import {
|
|
4
4
|
installToolGrouping,
|
|
5
5
|
type ToolGroupingHooks,
|
|
@@ -15,11 +15,11 @@ import {
|
|
|
15
15
|
installToolExpandedBackground,
|
|
16
16
|
type DefaultModeHooks,
|
|
17
17
|
} from "./default-mode.ts";
|
|
18
|
-
import { isLazyProxyTui } from "
|
|
18
|
+
import { isLazyProxyTui } from "../../../tools/fullscreen-detect.ts";
|
|
19
19
|
import {
|
|
20
20
|
GLOBAL_COMPACTION_RENDER_PATCH,
|
|
21
21
|
patchRegistry,
|
|
22
|
-
} from "
|
|
22
|
+
} from "../../../tools/patch-keys.ts";
|
|
23
23
|
import {
|
|
24
24
|
config,
|
|
25
25
|
normalizeConfig,
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
updateConfig,
|
|
28
28
|
type CompactStyleMode,
|
|
29
29
|
type Config,
|
|
30
|
-
} from "
|
|
30
|
+
} from "../../../app/config/renderer.ts";
|
|
31
31
|
import {
|
|
32
32
|
installToolMouseInteraction,
|
|
33
33
|
resetToolHoverState,
|
|
@@ -58,7 +58,7 @@ import {
|
|
|
58
58
|
|
|
59
59
|
let compactModeHooks: CompactModeHooks | undefined;
|
|
60
60
|
|
|
61
|
-
function
|
|
61
|
+
function refreshCurrentContext(
|
|
62
62
|
ctx?: any,
|
|
63
63
|
toolGrouping?: ToolGroupingHooks,
|
|
64
64
|
): void {
|
|
@@ -94,15 +94,15 @@ function applyStyleMode(
|
|
|
94
94
|
tui.terminal?.write?.(TOOL_MOUSE_DISABLE);
|
|
95
95
|
}
|
|
96
96
|
} else if (mode === "compact") {
|
|
97
|
-
//
|
|
97
|
+
// Enter compact mode after collecting the current context and syncing ownership.
|
|
98
98
|
syncCompactMode(ctx);
|
|
99
99
|
}
|
|
100
|
-
//
|
|
101
|
-
//
|
|
102
|
-
|
|
100
|
+
// Reshape immediately and once more after the panel/custom UI unmounts and
|
|
101
|
+
// the main context is mounted again.
|
|
102
|
+
refreshCurrentContext(ctx, toolGrouping);
|
|
103
103
|
scheduleSessionRender(() => {
|
|
104
104
|
if (mode === "compact") syncCompactMode(ctx);
|
|
105
|
-
|
|
105
|
+
refreshCurrentContext(ctx, toolGrouping);
|
|
106
106
|
});
|
|
107
107
|
ctx.ui.notify(`Claude Code style: ${mode}`, "info");
|
|
108
108
|
}
|
|
@@ -180,7 +180,7 @@ export default function (
|
|
|
180
180
|
applyStyleMode(mode, ctx, installation?.toolGrouping),
|
|
181
181
|
updateConfig: (partial, ctx) => {
|
|
182
182
|
updateConfig(partial);
|
|
183
|
-
|
|
183
|
+
refreshCurrentContext(ctx, installation?.toolGrouping);
|
|
184
184
|
},
|
|
185
185
|
});
|
|
186
186
|
|
|
@@ -215,7 +215,7 @@ export default function (
|
|
|
215
215
|
hooks.toolGrouping.setTheme(ctx.ui.theme);
|
|
216
216
|
setMessageDisplayTheme(ctx.ui.theme);
|
|
217
217
|
ctx.ui.setStatus("ccstyle", undefined);
|
|
218
|
-
//
|
|
218
|
+
// Collect the resumed context before syncing compact patches and expansion state.
|
|
219
219
|
syncCompactMode(ctx);
|
|
220
220
|
// compact-thinking 的 session_start 处理在本 handler 之后执行(在其之上再装
|
|
221
221
|
// 一层 updateContent);延迟再同步一次,保证 compact 补丁最终位于外层。
|
|
@@ -225,7 +225,7 @@ export default function (
|
|
|
225
225
|
|
|
226
226
|
pi.on("session_compact", async (event, ctx) => {
|
|
227
227
|
const hooks = ensureTuiInstallation(ctx);
|
|
228
|
-
// Compaction rebuilds the
|
|
228
|
+
// Compaction rebuilds the context without session_start. Rebind after
|
|
229
229
|
// other TUI extensions may have replaced the root input dispatcher.
|
|
230
230
|
if (ctx?.mode === "tui" && ctx?.hasUI)
|
|
231
231
|
installToolMouseInteraction(ctx, mouseOwner);
|
|
@@ -270,7 +270,7 @@ export default function (
|
|
|
270
270
|
}
|
|
271
271
|
|
|
272
272
|
// ---- 对外导出:入口/测试实际消费的符号 ----
|
|
273
|
-
export { getCompactThinkingConfig } from "
|
|
273
|
+
export { getCompactThinkingConfig } from "../../../app/config/renderer.ts";
|
|
274
274
|
export {
|
|
275
275
|
humanizeMcpToolName,
|
|
276
276
|
isMcpToolDefinition,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { ThinkingPreviewBlock } from "
|
|
1
|
+
import { ThinkingPreviewBlock } from "../../thinking/compact-thinking.ts";
|
|
2
2
|
import { setHoveredCompactAssistant } from "../compact-mode.ts";
|
|
3
3
|
import {
|
|
4
4
|
patchRegistry,
|
|
5
5
|
TOOL_HOVER_STATE_KEY,
|
|
6
|
-
} from "
|
|
6
|
+
} from "../../../../tools/patch-keys.ts";
|
|
7
7
|
import {
|
|
8
8
|
isExpandedToolIoView,
|
|
9
9
|
invalidateIoView,
|
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
2
|
hasActiveTextPreview,
|
|
3
3
|
showTextPreview,
|
|
4
|
-
} from "
|
|
5
|
-
import { ThinkingPreviewBlock } from "
|
|
4
|
+
} from "../../../../features/context-inspector/index.ts";
|
|
5
|
+
import { ThinkingPreviewBlock } from "../../thinking/compact-thinking.ts";
|
|
6
|
+
import { inputRouter } from "../../../../app/overlay/input-router.ts";
|
|
7
|
+
import { overlayManager } from "../../../../app/overlay/overlay-manager.ts";
|
|
6
8
|
import {
|
|
7
9
|
patchRegistry,
|
|
8
10
|
TOOL_MOUSE_OWNER_KEY,
|
|
9
|
-
} from "
|
|
11
|
+
} from "../../../../tools/patch-keys.ts";
|
|
10
12
|
import { ToolGroupComponent } from "../tool/grouping.ts";
|
|
11
13
|
import {
|
|
12
14
|
isCompactAssistantComponent,
|
|
13
15
|
setHoveredCompactAssistant,
|
|
14
16
|
} from "../compact-mode.ts";
|
|
15
17
|
import { isMessageDisplayComponent } from "../tool/message-display.ts";
|
|
16
|
-
import { config } from "
|
|
17
|
-
import { isLazyProxyTui } from "
|
|
18
|
+
import { config } from "../../../../app/config/renderer.ts";
|
|
19
|
+
import { isLazyProxyTui } from "../../../../tools/fullscreen-detect.ts";
|
|
18
20
|
import { setToolTuiFullscreen } from "../tool/show-more-hint.ts";
|
|
19
21
|
import {
|
|
20
22
|
type ExpandedToolIoView,
|
|
@@ -934,6 +936,12 @@ export function resetToolHoverState(): void {
|
|
|
934
936
|
releaseFullscreenToolMouseMotion(getToolMouseTui());
|
|
935
937
|
}
|
|
936
938
|
|
|
939
|
+
/**
|
|
940
|
+
* Installs the Context mouse route through the shared input router.
|
|
941
|
+
*
|
|
942
|
+
* @param ctx Active TUI extension context.
|
|
943
|
+
* @param owner Ownership token used to make teardown safe across reloads.
|
|
944
|
+
*/
|
|
937
945
|
export function installToolMouseInteraction(
|
|
938
946
|
ctx: any,
|
|
939
947
|
owner: object = DEFAULT_TOOL_MOUSE_OWNER,
|
|
@@ -979,7 +987,18 @@ export function installToolMouseInteraction(
|
|
|
979
987
|
setScrollButtonWidget(widget);
|
|
980
988
|
return widget;
|
|
981
989
|
});
|
|
982
|
-
|
|
990
|
+
const removeMouseRoute = inputRouter.register(
|
|
991
|
+
(data) =>
|
|
992
|
+
overlayManager.hasActive() ? undefined : handleToolMouseInput(data),
|
|
993
|
+
100,
|
|
994
|
+
);
|
|
995
|
+
const removeHostInput = ctx.ui.onTerminalInput((data: string) =>
|
|
996
|
+
inputRouter.dispatch(data),
|
|
997
|
+
);
|
|
998
|
+
toolMouseInputUnsubscribe = () => {
|
|
999
|
+
removeHostInput();
|
|
1000
|
+
removeMouseRoute();
|
|
1001
|
+
};
|
|
983
1002
|
}
|
|
984
1003
|
|
|
985
1004
|
function refreshToolRendererComponents(tui: any): void {
|
|
@@ -992,7 +1011,7 @@ export function scheduleSessionRender(refresh?: () => void): void {
|
|
|
992
1011
|
const tui = getToolMouseTui();
|
|
993
1012
|
if (!tui || typeof tui.requestRender !== "function") return;
|
|
994
1013
|
if (sessionRenderTimer) clearTimeout(sessionRenderTimer);
|
|
995
|
-
// Restored
|
|
1014
|
+
// Restored context components are populated at different points for startup, reload,
|
|
996
1015
|
// and session replacement. Repaint after session_start and the surrounding UI
|
|
997
1016
|
// rebuild finish so messages are not left hidden until the next terminal input.
|
|
998
1017
|
sessionRenderTimer = setTimeout(() => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { visibleWidth } from "@earendil-works/pi-tui";
|
|
2
|
-
import { ThinkingPreviewBlock } from "
|
|
2
|
+
import { ThinkingPreviewBlock } from "../../thinking/compact-thinking.ts";
|
|
3
3
|
import { isCompactAssistantComponent } from "../compact-mode.ts";
|
|
4
4
|
import { ToolGroupComponent } from "../tool/grouping.ts";
|
|
5
5
|
import { isMessageDisplayComponent } from "../tool/message-display.ts";
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import type { ExpandedToolIoView, ToolIoSection } from "../tool/result.ts";
|
|
2
|
-
import { walkComponentTree } from "
|
|
2
|
+
import { walkComponentTree } from "../../../../tools/component-tree.ts";
|
|
3
3
|
export {
|
|
4
4
|
stripTerminalSequences,
|
|
5
5
|
stripTerminalSequencesPreservingLayout,
|
|
6
|
-
} from "
|
|
6
|
+
} from "../../../../tools/ansi-text.ts";
|
|
7
7
|
export {
|
|
8
8
|
parseSgrMousePackets,
|
|
9
9
|
isSgrLeftPress,
|
|
10
10
|
type SgrMousePacket,
|
|
11
|
-
} from "
|
|
11
|
+
} from "../../../../tools/sgr-mouse.ts";
|
|
12
12
|
|
|
13
13
|
/** Final painted placement of one outermost tool/group row after parent layout. */
|
|
14
14
|
export type FrameToolPlacement = {
|