pi-ui-extend 0.1.34 → 0.1.35
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 +20 -0
- package/dist/app/app.js +4 -2
- package/dist/app/constants.d.ts +2 -1
- package/dist/app/constants.js +6 -1
- package/dist/app/input/input-controller.d.ts +4 -1
- package/dist/app/input/input-controller.js +95 -16
- package/dist/app/input/input-paste-handler.js +3 -1
- package/dist/app/input/terminal-edit-shortcuts.d.ts +20 -0
- package/dist/app/input/terminal-edit-shortcuts.js +50 -16
- package/dist/app/rendering/conversation-entry-renderer.d.ts +1 -0
- package/dist/app/rendering/conversation-entry-renderer.js +1 -1
- package/dist/app/rendering/conversation-tool-renderer.d.ts +1 -0
- package/dist/app/rendering/conversation-tool-renderer.js +21 -0
- package/dist/app/rendering/conversation-viewport.d.ts +3 -0
- package/dist/app/rendering/conversation-viewport.js +41 -5
- package/dist/app/rendering/editor-layout-renderer.js +3 -2
- package/dist/app/rendering/editor-panels.js +27 -10
- package/dist/app/runtime.d.ts +1 -0
- package/dist/app/runtime.js +33 -14
- package/dist/app/session/session-event-controller.d.ts +7 -0
- package/dist/app/session/session-event-controller.js +78 -0
- package/dist/app/session/tabs-controller.js +3 -1
- package/dist/app/subagents/subagents-widget-controller.d.ts +10 -2
- package/dist/app/subagents/subagents-widget-controller.js +141 -70
- package/dist/app/terminal/terminal-controller.d.ts +10 -0
- package/dist/app/terminal/terminal-controller.js +91 -2
- package/dist/app/todo/todo-model.js +2 -0
- package/dist/app/todo/todo-widget-controller.d.ts +2 -0
- package/dist/app/todo/todo-widget-controller.js +17 -7
- package/dist/app/types.d.ts +4 -0
- package/dist/bundled-extensions/question/tui.js +8 -1
- package/dist/bundled-extensions/session-title/index.js +65 -14
- package/dist/input-editor-files.js +23 -4
- package/dist/markdown-format.d.ts +4 -1
- package/dist/markdown-format.js +76 -9
- package/external/pi-tools-suite/README.md +71 -1
- package/external/pi-tools-suite/package.json +3 -3
- package/external/pi-tools-suite/src/async-subagents/commands.ts +12 -6
- package/external/pi-tools-suite/src/async-subagents/index.ts +133 -37
- package/external/pi-tools-suite/src/context-usage.ts +6 -1
- package/external/pi-tools-suite/src/dcp/commands.ts +3 -2
- package/external/pi-tools-suite/src/dcp/compress-tool.ts +9 -4
- package/external/pi-tools-suite/src/dcp/config.ts +142 -6
- package/external/pi-tools-suite/src/dcp/index.ts +20 -8
- package/external/pi-tools-suite/src/dcp/prompts.ts +17 -9
- package/external/pi-tools-suite/src/dcp/pruner-candidates.ts +59 -15
- package/external/pi-tools-suite/src/dcp/pruner-metadata.ts +6 -8
- package/external/pi-tools-suite/src/dcp/pruner-nudge.ts +3 -3
- package/external/pi-tools-suite/src/default-pi-tools-suite-config.ts +51 -1
- package/external/pi-tools-suite/src/glm-coding-discipline/index.ts +16 -11
- package/external/pi-tools-suite/src/model-tools/index.ts +24 -12
- package/external/pi-tools-suite/src/prompt-commands/index.ts +11 -2
- package/external/pi-tools-suite/src/telegram-mirror/index.ts +66 -27
- package/external/pi-tools-suite/src/todo/index.ts +87 -16
- package/external/pi-tools-suite/src/todo/state/store.ts +41 -10
- package/external/pi-tools-suite/src/todo/todo.ts +49 -6
- package/external/pi-tools-suite/src/tool-descriptions.ts +4 -4
- package/package.json +7 -5
|
@@ -71,30 +71,45 @@ export function renderTodoPanel(details, expanded, width, colors) {
|
|
|
71
71
|
export function renderSubagentsPanel(state, expanded, width, colors) {
|
|
72
72
|
if (!state)
|
|
73
73
|
return [];
|
|
74
|
-
const
|
|
74
|
+
const runs = state.runs?.length
|
|
75
|
+
? state.runs
|
|
76
|
+
: [{ runDir: state.runDir, agents: state.agents, ...(state.tasks === undefined ? {} : { tasks: state.tasks }) }];
|
|
77
|
+
const activeRuns = runs
|
|
78
|
+
.map((run) => ({ ...run, activeAgents: activeSubagentStates(run.agents) }))
|
|
79
|
+
.filter((run) => run.activeAgents.length > 0);
|
|
80
|
+
const activeAgents = activeRuns.flatMap((run) => run.activeAgents);
|
|
75
81
|
if (activeAgents.length === 0)
|
|
76
82
|
return [];
|
|
77
83
|
const target = { kind: "subagents-panel" };
|
|
78
|
-
const previewById = taskPreviewMap(state.tasks);
|
|
79
|
-
const runName = subagentRunName(state.runDir);
|
|
80
84
|
const titleSuffix = state.live ? "" : " (snapshot)";
|
|
81
85
|
const stats = formatSubagentsPanelStats(activeAgents);
|
|
82
86
|
const headerText = `subagents ${expanded ? "▾" : "▸"}${stats ? ` ${stats}` : ""}${titleSuffix}`;
|
|
83
87
|
const contentWidth = Math.max(1, width);
|
|
84
88
|
if (!expanded) {
|
|
85
|
-
const
|
|
89
|
+
const runSummary = activeRuns.length === 1 ? subagentRunName(activeRuns[0]?.runDir ?? state.runDir) : `${activeRuns.length} runs`;
|
|
90
|
+
const collapsedText = `${headerText} — ${runSummary}`;
|
|
86
91
|
return [{ text: padOrTrimPlain(ellipsizeDisplay(collapsedText, contentWidth), width), colorOverride: colors.accent, target }];
|
|
87
92
|
}
|
|
88
93
|
const lines = [];
|
|
89
|
-
const
|
|
94
|
+
const flattenedRuns = activeRuns.flatMap((run) => {
|
|
95
|
+
const previewById = taskPreviewMap(run.tasks);
|
|
96
|
+
return run.activeAgents.map((agent, index) => ({
|
|
97
|
+
runDir: run.runDir,
|
|
98
|
+
agent,
|
|
99
|
+
preview: previewById.get(agent.id),
|
|
100
|
+
showRunLabel: activeRuns.length > 1 && index === 0,
|
|
101
|
+
}));
|
|
102
|
+
});
|
|
103
|
+
const visibleAgents = flattenedRuns.slice(0, SUBAGENTS_WIDGET_MAX_ROWS);
|
|
90
104
|
const rowWidth = contentWidth;
|
|
91
105
|
const now = Date.now();
|
|
92
|
-
for (const
|
|
93
|
-
const preview =
|
|
106
|
+
for (const visibleRun of visibleAgents) {
|
|
107
|
+
const { agent, preview } = visibleRun;
|
|
94
108
|
const model = subagentModelThinkingLabel(preview);
|
|
95
109
|
const task = preview?.task?.trim() || preview?.scope?.trim() || "task unavailable";
|
|
96
110
|
const icon = subagentStatusIcon(agent.status);
|
|
97
|
-
const
|
|
111
|
+
const runLabel = visibleRun.showRunLabel ? `${subagentRunName(visibleRun.runDir)} ` : "";
|
|
112
|
+
const prefix = `${runLabel}${icon} ${agent.id} ${model} `;
|
|
98
113
|
const suffix = ` ${formatElapsedSince(agent.startedAt, now)}`;
|
|
99
114
|
const taskWidth = Math.max(8, rowWidth - stringDisplayWidth(prefix) - stringDisplayWidth(suffix));
|
|
100
115
|
const taskText = ellipsizeDisplay(task, taskWidth);
|
|
@@ -102,22 +117,24 @@ export function renderSubagentsPanel(state, expanded, width, colors) {
|
|
|
102
117
|
lines.push({
|
|
103
118
|
text: padOrTrimPlain(text, width),
|
|
104
119
|
colorOverride: colors.muted,
|
|
105
|
-
segments: subagentPanelLineSegments({ text, icon, agentId: agent.id, model, taskText, prefix, status: agent.status }, colors),
|
|
120
|
+
segments: subagentPanelLineSegments({ text, icon, agentId: agent.id, model, taskText, prefix, runLabel, status: agent.status }, colors),
|
|
106
121
|
target,
|
|
107
122
|
});
|
|
108
123
|
}
|
|
109
|
-
const hidden =
|
|
124
|
+
const hidden = flattenedRuns.length - visibleAgents.length;
|
|
110
125
|
if (hidden > 0)
|
|
111
126
|
lines.push({ text: padOrTrimPlain(`+${hidden} more`, width), variant: "muted", target });
|
|
112
127
|
return lines;
|
|
113
128
|
}
|
|
114
129
|
function subagentPanelLineSegments(input, colors) {
|
|
115
130
|
const iconStart = input.text.indexOf(input.icon);
|
|
131
|
+
const runLabelStart = input.runLabel ? input.text.indexOf(input.runLabel) : -1;
|
|
116
132
|
const nameStart = input.text.indexOf(input.agentId, iconStart + input.icon.length);
|
|
117
133
|
const modelStart = input.text.indexOf(input.model, nameStart + input.agentId.length);
|
|
118
134
|
const taskStart = input.prefix.length;
|
|
119
135
|
const suffixStart = taskStart + input.taskText.length;
|
|
120
136
|
return [
|
|
137
|
+
...(runLabelStart >= 0 ? [{ start: runLabelStart, end: runLabelStart + input.runLabel.length, foreground: colors.warning }] : []),
|
|
121
138
|
{ start: iconStart, end: iconStart + input.icon.length, foreground: subagentStatusColor(input.status, colors), bold: true },
|
|
122
139
|
{ start: nameStart, end: nameStart + input.agentId.length, foreground: colors.accent, bold: true },
|
|
123
140
|
{ start: modelStart, end: modelStart + input.model.length, foreground: colors.info },
|
package/dist/app/runtime.d.ts
CHANGED
|
@@ -38,6 +38,7 @@ export declare function prioritizeBundledQuestionExtension(base: LoadExtensionsR
|
|
|
38
38
|
export type CreatePixRuntimeOptions = {
|
|
39
39
|
eventBus?: EventBus;
|
|
40
40
|
config?: PixConfig;
|
|
41
|
+
reuseServicesFrom?: AgentSessionRuntime;
|
|
41
42
|
};
|
|
42
43
|
type RuntimeSessionManagerModelState = Pick<SessionManager, "getEntries" | "getBranch">;
|
|
43
44
|
export declare function resolvePixRuntimeModelRef(options: Pick<AppOptions, "modelRef">, sessionManager: RuntimeSessionManagerModelState, config?: PixConfig): string | undefined;
|
package/dist/app/runtime.js
CHANGED
|
@@ -220,26 +220,20 @@ export function resolveSessionModelRefFromTail(entries) {
|
|
|
220
220
|
}
|
|
221
221
|
export async function createPixRuntime(options, runtimeOptions = {}) {
|
|
222
222
|
const agentDir = getAgentDir();
|
|
223
|
+
const reusableServices = reusableRuntimeServices(runtimeOptions.reuseServicesFrom, options.cwd, agentDir);
|
|
223
224
|
const createRuntime = async ({ cwd, sessionManager, sessionStartEvent }) => {
|
|
224
225
|
const config = runtimeOptions.config ?? loadPixConfig(cwd);
|
|
225
226
|
const effectiveModelRef = resolvePixRuntimeModelRef(options, sessionManager, config);
|
|
226
227
|
const parsedModel = effectiveModelRef ? parseModelRef(effectiveModelRef) : undefined;
|
|
227
228
|
const initialThinkingLevel = resolvePixRuntimeInitialThinkingLevel(options, sessionManager, config);
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
resourceLoaderOptions: {
|
|
235
|
-
...(config.ignoreContextFiles ? { noContextFiles: true } : {}),
|
|
229
|
+
const services = reusableServices && sameRuntimeServiceTarget(reusableServices, cwd, agentDir)
|
|
230
|
+
? reusableServices
|
|
231
|
+
: await createPixRuntimeServices({
|
|
232
|
+
cwd,
|
|
233
|
+
agentDir,
|
|
234
|
+
config,
|
|
236
235
|
...(runtimeOptions.eventBus === undefined ? {} : { eventBus: runtimeOptions.eventBus }),
|
|
237
|
-
|
|
238
|
-
additionalExtensionPaths: bundledExtensionPaths,
|
|
239
|
-
extensionsOverride: prioritizeBundledQuestionExtension,
|
|
240
|
-
}),
|
|
241
|
-
},
|
|
242
|
-
});
|
|
236
|
+
});
|
|
243
237
|
services.modelRegistry.refresh();
|
|
244
238
|
const model = parsedModel ? services.modelRegistry.find(parsedModel.provider, parsedModel.modelId) : undefined;
|
|
245
239
|
if (parsedModel && !model) {
|
|
@@ -285,3 +279,28 @@ export async function createPixRuntime(options, runtimeOptions = {}) {
|
|
|
285
279
|
: SessionManager.create(options.cwd),
|
|
286
280
|
});
|
|
287
281
|
}
|
|
282
|
+
async function createPixRuntimeServices(options) {
|
|
283
|
+
await ensureBundledSkillsInstalledOnce();
|
|
284
|
+
await ensurePiToolsSuiteExtensionInstalledOnce({ agentDir: options.agentDir });
|
|
285
|
+
const bundledExtensionPaths = await getBundledExtensionPathsAsync();
|
|
286
|
+
return await createAgentSessionServices({
|
|
287
|
+
cwd: options.cwd,
|
|
288
|
+
agentDir: options.agentDir,
|
|
289
|
+
resourceLoaderOptions: {
|
|
290
|
+
...(options.config.ignoreContextFiles ? { noContextFiles: true } : {}),
|
|
291
|
+
...(options.eventBus === undefined ? {} : { eventBus: options.eventBus }),
|
|
292
|
+
...(bundledExtensionPaths.length === 0 ? {} : {
|
|
293
|
+
additionalExtensionPaths: bundledExtensionPaths,
|
|
294
|
+
extensionsOverride: prioritizeBundledQuestionExtension,
|
|
295
|
+
}),
|
|
296
|
+
},
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
function reusableRuntimeServices(runtime, cwd, agentDir) {
|
|
300
|
+
const services = runtime?.services;
|
|
301
|
+
return services && sameRuntimeServiceTarget(services, cwd, agentDir) ? services : undefined;
|
|
302
|
+
}
|
|
303
|
+
function sameRuntimeServiceTarget(services, cwd, agentDir) {
|
|
304
|
+
return normalizePathForCompare(services.cwd) === normalizePathForCompare(cwd)
|
|
305
|
+
&& normalizePathForCompare(services.agentDir) === normalizePathForCompare(agentDir);
|
|
306
|
+
}
|
|
@@ -19,6 +19,7 @@ export type AppSessionEventControllerState = {
|
|
|
19
19
|
currentAssistantTextBlockContentIndex: number | undefined;
|
|
20
20
|
assistantTextBlocksByContentIndex: Map<number, string>;
|
|
21
21
|
currentThinkingEntryId: string | undefined;
|
|
22
|
+
currentThinkingEntryStartedAt: number | undefined;
|
|
22
23
|
assistantMessageClosed: boolean;
|
|
23
24
|
assistantTextBuffer: string;
|
|
24
25
|
entryRenderVersions: Map<string, number>;
|
|
@@ -74,6 +75,8 @@ export declare class AppSessionEventController {
|
|
|
74
75
|
private historyEntries;
|
|
75
76
|
private historyWindowStart;
|
|
76
77
|
private currentThinkingEntryId;
|
|
78
|
+
private currentThinkingEntryStartedAt;
|
|
79
|
+
private thinkingElapsedRenderTimer;
|
|
77
80
|
private assistantMessageClosed;
|
|
78
81
|
private assistantTextBuffer;
|
|
79
82
|
constructor(host: AppSessionEventControllerHost);
|
|
@@ -133,7 +136,11 @@ export declare class AppSessionEventController {
|
|
|
133
136
|
private appendThinkingText;
|
|
134
137
|
private finishCurrentThinkingEntry;
|
|
135
138
|
private reconcileThinkingText;
|
|
139
|
+
private syncThinkingElapsedRenderTimer;
|
|
140
|
+
private startThinkingElapsedRenderTimer;
|
|
141
|
+
private stopThinkingElapsedRenderTimer;
|
|
136
142
|
private currentThinkingLevel;
|
|
143
|
+
private reconcileAssistantTextFromFinalMessage;
|
|
137
144
|
private renderAssistantToolCallsFromMessage;
|
|
138
145
|
private upsertPendingToolCall;
|
|
139
146
|
private upsertToolEntry;
|
|
@@ -26,6 +26,8 @@ export class AppSessionEventController {
|
|
|
26
26
|
historyEntries = [];
|
|
27
27
|
historyWindowStart = 0;
|
|
28
28
|
currentThinkingEntryId;
|
|
29
|
+
currentThinkingEntryStartedAt;
|
|
30
|
+
thinkingElapsedRenderTimer;
|
|
29
31
|
assistantMessageClosed = false;
|
|
30
32
|
assistantTextBuffer = "";
|
|
31
33
|
constructor(host) {
|
|
@@ -44,6 +46,7 @@ export class AppSessionEventController {
|
|
|
44
46
|
currentAssistantTextBlockContentIndex: this.currentAssistantTextBlockContentIndex,
|
|
45
47
|
assistantTextBlocksByContentIndex: new Map(this.assistantTextBlocksByContentIndex),
|
|
46
48
|
currentThinkingEntryId: this.currentThinkingEntryId,
|
|
49
|
+
currentThinkingEntryStartedAt: this.currentThinkingEntryStartedAt,
|
|
47
50
|
assistantMessageClosed: this.assistantMessageClosed,
|
|
48
51
|
assistantTextBuffer: this.assistantTextBuffer,
|
|
49
52
|
entryRenderVersions: new Map(this.entryRenderVersions),
|
|
@@ -71,6 +74,8 @@ export class AppSessionEventController {
|
|
|
71
74
|
for (const [key, value] of state.assistantTextBlocksByContentIndex)
|
|
72
75
|
this.assistantTextBlocksByContentIndex.set(key, value);
|
|
73
76
|
this.currentThinkingEntryId = state.currentThinkingEntryId;
|
|
77
|
+
this.currentThinkingEntryStartedAt = state.currentThinkingEntryStartedAt;
|
|
78
|
+
this.syncThinkingElapsedRenderTimer();
|
|
74
79
|
this.assistantMessageClosed = state.assistantMessageClosed;
|
|
75
80
|
this.assistantTextBuffer = state.assistantTextBuffer;
|
|
76
81
|
this.entryRenderVersions.clear();
|
|
@@ -94,6 +99,8 @@ export class AppSessionEventController {
|
|
|
94
99
|
this.assistantTextBlocksByContentIndex.clear();
|
|
95
100
|
this.finalizedToolCallContentIndexes.clear();
|
|
96
101
|
this.currentThinkingEntryId = undefined;
|
|
102
|
+
this.currentThinkingEntryStartedAt = undefined;
|
|
103
|
+
this.stopThinkingElapsedRenderTimer();
|
|
97
104
|
this.assistantMessageClosed = false;
|
|
98
105
|
this.assistantTextBuffer = "";
|
|
99
106
|
this.olderHistoryLoader = undefined;
|
|
@@ -563,6 +570,7 @@ export class AppSessionEventController {
|
|
|
563
570
|
this.handleToolCallStreamUpdate(assistantEvent.contentIndex, assistantEvent.partial, assistantEvent.toolCall);
|
|
564
571
|
break;
|
|
565
572
|
case "done":
|
|
573
|
+
this.reconcileAssistantTextFromFinalMessage(assistantEvent.message);
|
|
566
574
|
this.renderAssistantToolCallsFromMessage(assistantEvent.message);
|
|
567
575
|
this.finishCurrentThinkingEntry();
|
|
568
576
|
this.flushAssistantTextBuffer(true);
|
|
@@ -754,12 +762,15 @@ export class AppSessionEventController {
|
|
|
754
762
|
: undefined;
|
|
755
763
|
if (!entry || entry.kind !== "thinking") {
|
|
756
764
|
const level = this.currentThinkingLevel();
|
|
765
|
+
const startedAt = this.currentThinkingEntryStartedAt ?? Date.now();
|
|
766
|
+
this.currentThinkingEntryStartedAt = startedAt;
|
|
757
767
|
entry = {
|
|
758
768
|
id: createId("thinking"),
|
|
759
769
|
kind: "thinking",
|
|
760
770
|
text: "",
|
|
761
771
|
expanded: this.host.toolDefaultExpanded(THINKING_TOOL_NAME),
|
|
762
772
|
...(level === undefined ? {} : { level }),
|
|
773
|
+
startedAt,
|
|
763
774
|
status: "running",
|
|
764
775
|
};
|
|
765
776
|
this.addEntry(entry);
|
|
@@ -770,17 +781,24 @@ export class AppSessionEventController {
|
|
|
770
781
|
delete entry.level;
|
|
771
782
|
else
|
|
772
783
|
entry.level = level;
|
|
784
|
+
entry.startedAt ??= this.currentThinkingEntryStartedAt ?? Date.now();
|
|
785
|
+
this.currentThinkingEntryStartedAt = entry.startedAt;
|
|
786
|
+
delete entry.finishedAt;
|
|
773
787
|
entry.status = "running";
|
|
774
788
|
entry.text += delta;
|
|
789
|
+
this.startThinkingElapsedRenderTimer();
|
|
775
790
|
this.touchEntry(entry);
|
|
776
791
|
}
|
|
777
792
|
finishCurrentThinkingEntry() {
|
|
778
793
|
const entry = this.currentThinkingEntryId ? this.findEntry(this.currentThinkingEntryId) : undefined;
|
|
779
794
|
if (entry?.kind === "thinking" && entry.status !== "done") {
|
|
780
795
|
entry.status = "done";
|
|
796
|
+
entry.finishedAt ??= Date.now();
|
|
781
797
|
this.touchEntry(entry);
|
|
782
798
|
}
|
|
783
799
|
this.currentThinkingEntryId = undefined;
|
|
800
|
+
this.currentThinkingEntryStartedAt = undefined;
|
|
801
|
+
this.stopThinkingElapsedRenderTimer();
|
|
784
802
|
}
|
|
785
803
|
reconcileThinkingText(content) {
|
|
786
804
|
let entry = this.currentThinkingEntryId
|
|
@@ -788,12 +806,15 @@ export class AppSessionEventController {
|
|
|
788
806
|
: undefined;
|
|
789
807
|
if (!entry || entry.kind !== "thinking") {
|
|
790
808
|
const level = this.currentThinkingLevel();
|
|
809
|
+
const startedAt = this.currentThinkingEntryStartedAt ?? Date.now();
|
|
810
|
+
this.currentThinkingEntryStartedAt = startedAt;
|
|
791
811
|
entry = {
|
|
792
812
|
id: createId("thinking"),
|
|
793
813
|
kind: "thinking",
|
|
794
814
|
text: "",
|
|
795
815
|
expanded: this.host.toolDefaultExpanded(THINKING_TOOL_NAME),
|
|
796
816
|
...(level === undefined ? {} : { level }),
|
|
817
|
+
startedAt,
|
|
797
818
|
status: "running",
|
|
798
819
|
};
|
|
799
820
|
this.addEntry(entry);
|
|
@@ -806,13 +827,63 @@ export class AppSessionEventController {
|
|
|
806
827
|
delete entry.level;
|
|
807
828
|
else
|
|
808
829
|
entry.level = level;
|
|
830
|
+
entry.startedAt ??= this.currentThinkingEntryStartedAt ?? Date.now();
|
|
831
|
+
this.currentThinkingEntryStartedAt = entry.startedAt;
|
|
832
|
+
delete entry.finishedAt;
|
|
809
833
|
entry.status = "running";
|
|
834
|
+
this.startThinkingElapsedRenderTimer();
|
|
810
835
|
this.touchEntry(entry);
|
|
811
836
|
}
|
|
812
837
|
}
|
|
838
|
+
syncThinkingElapsedRenderTimer() {
|
|
839
|
+
const entry = this.currentThinkingEntryId ? this.findEntry(this.currentThinkingEntryId) : undefined;
|
|
840
|
+
if (entry?.kind === "thinking" && entry.status === "running" && entry.startedAt !== undefined) {
|
|
841
|
+
this.startThinkingElapsedRenderTimer();
|
|
842
|
+
return;
|
|
843
|
+
}
|
|
844
|
+
this.stopThinkingElapsedRenderTimer();
|
|
845
|
+
}
|
|
846
|
+
startThinkingElapsedRenderTimer() {
|
|
847
|
+
if (this.thinkingElapsedRenderTimer)
|
|
848
|
+
return;
|
|
849
|
+
this.thinkingElapsedRenderTimer = setInterval(() => {
|
|
850
|
+
if (!this.host.isRunning()) {
|
|
851
|
+
this.stopThinkingElapsedRenderTimer();
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
854
|
+
this.host.scheduleRender();
|
|
855
|
+
}, 1000);
|
|
856
|
+
this.thinkingElapsedRenderTimer.unref?.();
|
|
857
|
+
}
|
|
858
|
+
stopThinkingElapsedRenderTimer() {
|
|
859
|
+
if (!this.thinkingElapsedRenderTimer)
|
|
860
|
+
return;
|
|
861
|
+
clearInterval(this.thinkingElapsedRenderTimer);
|
|
862
|
+
this.thinkingElapsedRenderTimer = undefined;
|
|
863
|
+
}
|
|
813
864
|
currentThinkingLevel() {
|
|
814
865
|
return this.host.runtime()?.session.thinkingLevel;
|
|
815
866
|
}
|
|
867
|
+
reconcileAssistantTextFromFinalMessage(message) {
|
|
868
|
+
const openContentIndex = this.currentAssistantTextBlockContentIndex;
|
|
869
|
+
if (openContentIndex !== undefined) {
|
|
870
|
+
const content = assistantTextContentAt(message, openContentIndex);
|
|
871
|
+
if (content !== undefined)
|
|
872
|
+
this.reconcileAssistantTextBlock(content, openContentIndex);
|
|
873
|
+
return;
|
|
874
|
+
}
|
|
875
|
+
const textBlocks = assistantTextContents(message);
|
|
876
|
+
if (textBlocks.length !== 1)
|
|
877
|
+
return;
|
|
878
|
+
const entry = this.currentAssistantEntryId ? this.findEntry(this.currentAssistantEntryId) : undefined;
|
|
879
|
+
if (entry?.kind !== "assistant")
|
|
880
|
+
return;
|
|
881
|
+
const visibleText = assistantStreamVisibleTextForCompleteBlock(textBlocks[0] ?? "", false);
|
|
882
|
+
if (!visibleText || entry.text === visibleText)
|
|
883
|
+
return;
|
|
884
|
+
entry.text = visibleText;
|
|
885
|
+
this.touchEntry(entry);
|
|
886
|
+
}
|
|
816
887
|
renderAssistantToolCallsFromMessage(message) {
|
|
817
888
|
if (!isRecord(message) || !Array.isArray(message.content))
|
|
818
889
|
return;
|
|
@@ -893,6 +964,8 @@ export class AppSessionEventController {
|
|
|
893
964
|
this.currentAssistantTextBlockStartLength = undefined;
|
|
894
965
|
this.currentAssistantTextBlockContentIndex = undefined;
|
|
895
966
|
this.currentThinkingEntryId = undefined;
|
|
967
|
+
this.currentThinkingEntryStartedAt = undefined;
|
|
968
|
+
this.stopThinkingElapsedRenderTimer();
|
|
896
969
|
this.assistantTextBuffer = "";
|
|
897
970
|
this.assistantTextBlocksByContentIndex.clear();
|
|
898
971
|
this.finalizedToolCallContentIndexes.clear();
|
|
@@ -916,6 +989,11 @@ function assistantTextContentAt(value, contentIndex) {
|
|
|
916
989
|
const block = value.content[contentIndex];
|
|
917
990
|
return isRecord(block) && block.type === "text" && typeof block.text === "string" ? block.text : undefined;
|
|
918
991
|
}
|
|
992
|
+
function assistantTextContents(value) {
|
|
993
|
+
if (!isRecord(value) || !Array.isArray(value.content))
|
|
994
|
+
return [];
|
|
995
|
+
return value.content.flatMap((block) => (isRecord(block) && block.type === "text" && typeof block.text === "string" ? [block.text] : []));
|
|
996
|
+
}
|
|
919
997
|
function assistantStreamVisibleTextForCompleteBlock(text, hasVisibleTextBeforeBlock) {
|
|
920
998
|
let buffer = text;
|
|
921
999
|
let visibleText = "";
|
|
@@ -641,7 +641,9 @@ export class AppTabsController {
|
|
|
641
641
|
void this.saveTabs();
|
|
642
642
|
this.scheduleTabPrewarm();
|
|
643
643
|
const cachedView = this.sessionViewsByTabId.get(target.id);
|
|
644
|
-
|
|
644
|
+
const cachedViewNeedsHistoryReload = this.tabIdsNeedingHistoryReload.has(target.id)
|
|
645
|
+
&& this.sessionActivity(targetRuntime.session) !== "running";
|
|
646
|
+
if (cachedView && this.host.restoreSessionView && !cachedViewNeedsHistoryReload) {
|
|
645
647
|
this.host.restoreSessionView(cachedView);
|
|
646
648
|
this.restoreDeferredUserMessages(target.id);
|
|
647
649
|
this.host.setSessionStatus(targetRuntime.session);
|
|
@@ -13,7 +13,9 @@ export declare class AppSubagentsWidgetController {
|
|
|
13
13
|
private pollTimer;
|
|
14
14
|
private pollInFlight;
|
|
15
15
|
private currentRunDir;
|
|
16
|
+
private currentRunDirs;
|
|
16
17
|
private state;
|
|
18
|
+
private readonly runFreshnessByRunDir;
|
|
17
19
|
private readonly taskPreviewsByRunDir;
|
|
18
20
|
private readonly snapshotByRunDir;
|
|
19
21
|
private refreshGeneration;
|
|
@@ -32,10 +34,16 @@ export declare class AppSubagentsWidgetController {
|
|
|
32
34
|
private schedulePoll;
|
|
33
35
|
private poll;
|
|
34
36
|
private refreshFromFiles;
|
|
35
|
-
private
|
|
37
|
+
private findActiveRegistryRunDirsForCurrentSession;
|
|
36
38
|
private registryRunDirsNewestFirst;
|
|
37
|
-
private clearMissingRunAndMaybeSelectReplacement;
|
|
38
39
|
private clearCachedRun;
|
|
40
|
+
private buildStateFromRuns;
|
|
41
|
+
private orderRuns;
|
|
42
|
+
private orderRunDirs;
|
|
43
|
+
private rememberRunFreshness;
|
|
44
|
+
private runFreshness;
|
|
45
|
+
private runFreshnessFromAgents;
|
|
46
|
+
private parseRunTimestamp;
|
|
39
47
|
private updateState;
|
|
40
48
|
private isCurrentGeneration;
|
|
41
49
|
private shouldContinuePolling;
|