@pi-archimedes/core 0.6.0 → 0.7.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/package.json +1 -1
- package/src/index.ts +1 -22
- package/src/startup/index.ts +1 -3
- package/src/message/index.ts +0 -147
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
|
3
3
|
import { TUI, type EditorTheme, type Component, type SettingItem } from "@earendil-works/pi-tui";
|
|
4
4
|
|
|
5
5
|
import { HephaestusEditor } from "./editor/index.js";
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
import { renderHeader, patchStartupListing, type ListingRef } from "./startup/index.js";
|
|
8
8
|
import { patchConsoleLog } from "./startup/capture.js";
|
|
9
9
|
import { patchThinkingRenderer } from "./thinking/patch.js";
|
|
@@ -55,7 +55,6 @@ export function getCoreSettingsItems(config: CoreConfig): SettingItem[] {
|
|
|
55
55
|
|
|
56
56
|
// Module-level state for session lifecycle (shared between session_start and session_shutdown)
|
|
57
57
|
let coreRef: ListingRef | undefined;
|
|
58
|
-
let coreResponseTimes: number[] | undefined;
|
|
59
58
|
let coreCtx: ExtensionContext | undefined;
|
|
60
59
|
|
|
61
60
|
export function registerCore(pi: ExtensionAPI): void {
|
|
@@ -70,12 +69,6 @@ export function registerCore(pi: ExtensionAPI): void {
|
|
|
70
69
|
const listingRef = g["listingRef"] as ListingRef | undefined;
|
|
71
70
|
if (listingRef) { listingRef.settled = true; }
|
|
72
71
|
|
|
73
|
-
// Clear response times
|
|
74
|
-
if (coreResponseTimes) { coreResponseTimes.length = 0; }
|
|
75
|
-
|
|
76
|
-
// Reset instance count
|
|
77
|
-
resetInstanceCount();
|
|
78
|
-
|
|
79
72
|
// Clear editor component override
|
|
80
73
|
if (coreCtx) { coreCtx.ui.setEditorComponent(undefined); }
|
|
81
74
|
});
|
|
@@ -110,10 +103,6 @@ export function registerCore(pi: ExtensionAPI): void {
|
|
|
110
103
|
};
|
|
111
104
|
ctx.ui.setHeader(headerFactory);
|
|
112
105
|
|
|
113
|
-
// Shared response times array (used by both patchUserMessage and message_end)
|
|
114
|
-
coreResponseTimes = [];
|
|
115
|
-
const responseTimes = coreResponseTimes;
|
|
116
|
-
|
|
117
106
|
// Set editor component
|
|
118
107
|
ctx.ui.setEditorComponent((tui: TUI, editorTheme: EditorTheme, keybindings: KeybindingsManager) => {
|
|
119
108
|
const theme = ctx.ui.theme;
|
|
@@ -127,9 +116,6 @@ export function registerCore(pi: ExtensionAPI): void {
|
|
|
127
116
|
// Patch thinking renderer
|
|
128
117
|
patchThinkingRenderer(() => ctx.ui.theme);
|
|
129
118
|
|
|
130
|
-
// Patch user message response time
|
|
131
|
-
patchUserMessage(() => ctx.ui.theme, responseTimes);
|
|
132
|
-
|
|
133
119
|
// Load config for thinking transformation
|
|
134
120
|
const config = loadCoreConfig();
|
|
135
121
|
|
|
@@ -139,13 +125,6 @@ export function registerCore(pi: ExtensionAPI): void {
|
|
|
139
125
|
if (config.codeUnindent) {
|
|
140
126
|
transformThinkingContent(event.message as any);
|
|
141
127
|
}
|
|
142
|
-
|
|
143
|
-
// Track response time from the raw message
|
|
144
|
-
const rawMsg = event.message as any;
|
|
145
|
-
if (rawMsg.duration) {
|
|
146
|
-
const idx = rawMsg.instanceIndex ?? responseTimes.length;
|
|
147
|
-
responseTimes[idx] = rawMsg.duration;
|
|
148
|
-
}
|
|
149
128
|
});
|
|
150
129
|
});
|
|
151
130
|
}
|
package/src/startup/index.ts
CHANGED
|
@@ -5,7 +5,6 @@ import { detectSection, parseSectionText, parseModelScope, formatColumns, buildI
|
|
|
5
5
|
import { fetchLatestVersion, compareVersions } from "./version.js";
|
|
6
6
|
import { patchConsoleLog } from "./capture.js";
|
|
7
7
|
import { stripAnsi } from "../text.js";
|
|
8
|
-
import { resetInstanceCount } from "../message/index.js";
|
|
9
8
|
import { Text, Spacer, Container, TUI, truncateToWidth, visibleWidth, type Component } from "@earendil-works/pi-tui";
|
|
10
9
|
|
|
11
10
|
// Symbol keys (survive hot-reload)
|
|
@@ -216,12 +215,11 @@ export function patchStartupListing(
|
|
|
216
215
|
}
|
|
217
216
|
});
|
|
218
217
|
|
|
219
|
-
// Patch clear() to
|
|
218
|
+
// Patch clear() to intercept container rebuild
|
|
220
219
|
if (!cc[PATCHED_CLEAR]) {
|
|
221
220
|
cc[PATCHED_CLEAR] = true;
|
|
222
221
|
const origClear = chat.clear.bind(chat);
|
|
223
222
|
chat.clear = () => {
|
|
224
|
-
resetInstanceCount();
|
|
225
223
|
return origClear();
|
|
226
224
|
};
|
|
227
225
|
}
|
package/src/message/index.ts
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import type { Theme, UserMessageComponent } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import { VERSION } from "@earendil-works/pi-coding-agent";
|
|
3
|
-
import { RESET, resolvePalette, setThemeBg } from "../chrome.js";
|
|
4
|
-
|
|
5
|
-
type UserMsgCtor = typeof UserMessageComponent & { [PATCHED]?: boolean; [PATCH_VERSION]?: string };
|
|
6
|
-
|
|
7
|
-
// ── Constants ──────────────────────────────────────────────
|
|
8
|
-
|
|
9
|
-
const PATCHED = Symbol.for("splashscreen:userMsgPatched");
|
|
10
|
-
const PATCH_VERSION = Symbol.for("splashscreen:userMsgPatchVersion");
|
|
11
|
-
// Match OSC133 B (zone end) or C (zone final). v0.67 moved these from line
|
|
12
|
-
// tail to line head — we strip from wherever they sit and re-emit at the end.
|
|
13
|
-
const OSC133_RE = /\x1b\]133;[BC]\x07/g;
|
|
14
|
-
const MSG_PADDING_X = 3;
|
|
15
|
-
const TIME_COL = 9;
|
|
16
|
-
|
|
17
|
-
// ── Instance tracking ──────────────────────────────────────
|
|
18
|
-
|
|
19
|
-
const instanceIndex = new WeakMap<object, number>();
|
|
20
|
-
let instanceCount = 0;
|
|
21
|
-
|
|
22
|
-
export function resetInstanceCount(): void {
|
|
23
|
-
instanceCount = 0;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function formatTime(ms: number): string {
|
|
27
|
-
if (ms < 1000) return `${ms}ms`;
|
|
28
|
-
if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;
|
|
29
|
-
const m = Math.floor(ms / 60000);
|
|
30
|
-
const s = Math.round((ms % 60000) / 1000);
|
|
31
|
-
return `${m}m ${s}s`;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// ── Patch ──────────────────────────────────────────────────
|
|
35
|
-
|
|
36
|
-
export function patchUserMessage(
|
|
37
|
-
getTheme: () => Theme,
|
|
38
|
-
responseTimes: number[],
|
|
39
|
-
): void {
|
|
40
|
-
try {
|
|
41
|
-
let lastBg = "";
|
|
42
|
-
const theme = getTheme();
|
|
43
|
-
const p = resolvePalette(theme);
|
|
44
|
-
lastBg = p.panelBg;
|
|
45
|
-
setThemeBg(theme, "userMessageBg", lastBg);
|
|
46
|
-
|
|
47
|
-
import("@earendil-works/pi-coding-agent").then(
|
|
48
|
-
({ UserMessageComponent }: { UserMessageComponent: UserMsgCtor }) => {
|
|
49
|
-
const currentVersion = VERSION ?? "unknown";
|
|
50
|
-
const patchVersion = UserMessageComponent[PATCH_VERSION];
|
|
51
|
-
// Skip if already patched for this version
|
|
52
|
-
if (UserMessageComponent[PATCHED] && patchVersion === currentVersion) return;
|
|
53
|
-
if (UserMessageComponent[PATCHED] && patchVersion && patchVersion !== currentVersion) {
|
|
54
|
-
console.warn(`[archimedes] Re-patching user message: pi version changed ${patchVersion} → ${currentVersion}`);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (
|
|
58
|
-
typeof UserMessageComponent.prototype.addChild !== "function" ||
|
|
59
|
-
typeof UserMessageComponent.prototype.render !== "function"
|
|
60
|
-
) {
|
|
61
|
-
console.warn("[splashscreen] UserMessageComponent shape changed — skipping patch");
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
UserMessageComponent[PATCHED] = true;
|
|
66
|
-
UserMessageComponent[PATCH_VERSION] = currentVersion;
|
|
67
|
-
|
|
68
|
-
const origAddChild = UserMessageComponent.prototype.addChild;
|
|
69
|
-
UserMessageComponent.prototype.addChild = function (child: any) {
|
|
70
|
-
if (child.paddingX !== undefined && !child._hephaestusPatched) {
|
|
71
|
-
child.paddingX = MSG_PADDING_X;
|
|
72
|
-
child._hephaestusPatched = true;
|
|
73
|
-
}
|
|
74
|
-
if (!instanceIndex.has(this)) {
|
|
75
|
-
instanceIndex.set(this, instanceCount++);
|
|
76
|
-
}
|
|
77
|
-
return origAddChild.call(this, child);
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
const origRender = UserMessageComponent.prototype.render;
|
|
81
|
-
UserMessageComponent.prototype.render = function (
|
|
82
|
-
width: number,
|
|
83
|
-
): string[] {
|
|
84
|
-
try {
|
|
85
|
-
const currentTheme = getTheme();
|
|
86
|
-
const p = resolvePalette(currentTheme);
|
|
87
|
-
const bg = p.panelBg;
|
|
88
|
-
if (bg !== lastBg) { setThemeBg(currentTheme, "userMessageBg", bg); lastBg = bg; }
|
|
89
|
-
|
|
90
|
-
const idx = instanceIndex.get(this);
|
|
91
|
-
const elapsed = idx !== undefined ? (responseTimes[idx] ?? 0) : 0;
|
|
92
|
-
const hasTime = idx !== undefined;
|
|
93
|
-
|
|
94
|
-
const contentWidth = width - TIME_COL;
|
|
95
|
-
const lines: string[] = origRender.call(this, contentWidth);
|
|
96
|
-
if (lines.length < 3) return lines;
|
|
97
|
-
|
|
98
|
-
const timeStr = elapsed > 0 ? formatTime(elapsed) : "";
|
|
99
|
-
const timeRight = 2;
|
|
100
|
-
const timeLabel = timeStr.length > 0 ? p.time(timeStr) : "";
|
|
101
|
-
// Column that shows "42ms" right-aligned with bg — spaces for visual
|
|
102
|
-
// alignment remain, but they're wrapped in panelBg so the copy buffer
|
|
103
|
-
// only contains the label text.
|
|
104
|
-
const timeContent =
|
|
105
|
-
p.panelBg +
|
|
106
|
-
" ".repeat(Math.max(0, TIME_COL - timeStr.length - timeRight)) +
|
|
107
|
-
timeLabel +
|
|
108
|
-
" ".repeat(timeRight);
|
|
109
|
-
// Use \x1b[K (erase-to-end-of-line) instead of literal spaces for the
|
|
110
|
-
// gap between content and time column. Visually fills with panelBg but
|
|
111
|
-
// leaves nothing in the copy buffer.
|
|
112
|
-
const gapFill = p.panelBg + "\x1b[K";
|
|
113
|
-
// Empty column: just bg fill to the end — no spaces in copy buffer
|
|
114
|
-
const emptyTimeCol = p.panelBg + "\x1b[K";
|
|
115
|
-
|
|
116
|
-
const firstContent = 0;
|
|
117
|
-
|
|
118
|
-
for (let i = 0; i < lines.length; i++) {
|
|
119
|
-
let line = lines[i]!;
|
|
120
|
-
|
|
121
|
-
// Extract any OSC133 B/C markers (shell zone end/final). v0.67 placed
|
|
122
|
-
// these at the head of the last line; older versions at the tail.
|
|
123
|
-
// Strip them from the content line; re-emit after the time column.
|
|
124
|
-
const oscMatches = line.match(OSC133_RE);
|
|
125
|
-
const oscSuffix = oscMatches ? oscMatches.join("") : "";
|
|
126
|
-
if (oscSuffix) line = line.replace(OSC133_RE, "");
|
|
127
|
-
|
|
128
|
-
// Strip trailing spaces from the content portion (PI pads to contentWidth
|
|
129
|
-
// with plain spaces) and replace with \x1b[K for visual fill without spaces
|
|
130
|
-
// in the copy buffer.
|
|
131
|
-
const strippedLine = line.replace(/((?:\x1b\[[\d;]*m)*)\s+$/, "$1");
|
|
132
|
-
const col = i === firstContent && hasTime ? timeContent : emptyTimeCol;
|
|
133
|
-
lines[i] = strippedLine + gapFill + col + oscSuffix;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
return lines;
|
|
137
|
-
} catch {
|
|
138
|
-
// During /resume, getTheme() may throw — fall back to default render
|
|
139
|
-
return origRender.call(this, width);
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
},
|
|
143
|
-
);
|
|
144
|
-
} catch {
|
|
145
|
-
/* skip if theme not ready */
|
|
146
|
-
}
|
|
147
|
-
}
|