@thoth-agents/pi-thoth-theme 0.4.0 → 0.6.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 +20 -0
- package/dist/index.ts +236 -26
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -27,6 +27,26 @@ from the repository root. Restart Pi after installation.
|
|
|
27
27
|
Select the `thoth` theme in Pi's theme settings. Theme selection is independent
|
|
28
28
|
of the module toggles below.
|
|
29
29
|
|
|
30
|
+
## User messages
|
|
31
|
+
|
|
32
|
+
The `thoth` theme renders user messages in `#E8DCB5` on `#120E0A`.
|
|
33
|
+
The extension surrounds the original Markdown with a top `╭── <icon> user ─…╮`
|
|
34
|
+
and bottom `╰─…╯` frame, separated from the content by blank lines. Both borders
|
|
35
|
+
fill the content width after Pi's horizontal padding and adapt on terminal resize.
|
|
36
|
+
Framing is skipped when the width is missing, invalid, or too narrow to fit the
|
|
37
|
+
title, one fill cell and the closing corner (13 columns with the current icons).
|
|
38
|
+
This is display-only: stored messages, assistant replies and thinking are unchanged.
|
|
39
|
+
Blank content and already-framed messages are left alone. The frame is independent
|
|
40
|
+
of the optional modules below.
|
|
41
|
+
|
|
42
|
+
The frame reuses `icons`: `"nerd"` (the existing default) selects nf-fa-user
|
|
43
|
+
(U+F007), `"unicode"` selects `●` (U+25CF), and `"ascii"` selects `@`.
|
|
44
|
+
Set `"icons": "nerd"` in the package configuration and use a Nerd Font in your
|
|
45
|
+
terminal for the Nerd glyph; use `"icons": "unicode"` for its Unicode fallback.
|
|
46
|
+
|
|
47
|
+
Markdown accents and syntax colors remain shared with assistant messages; only
|
|
48
|
+
ordinary user text and the frame use `userMessageText` (`#E8DCB5`).
|
|
49
|
+
|
|
30
50
|
## Modules
|
|
31
51
|
|
|
32
52
|
- **Status line**: a responsive footer below the input showing cumulative
|
package/dist/index.ts
CHANGED
|
@@ -139,6 +139,9 @@ var init_render_kit = __esm({
|
|
|
139
139
|
completed: "\u2713",
|
|
140
140
|
deleted: "\u2713",
|
|
141
141
|
failed: "\u2717",
|
|
142
|
+
timedOut: "\u25F7",
|
|
143
|
+
resolved: "\u21BB",
|
|
144
|
+
expectedExit: "\u2713",
|
|
142
145
|
cancelled: "\u2717",
|
|
143
146
|
interrupted: "\u2717",
|
|
144
147
|
blocked: "\u2717"
|
|
@@ -159,6 +162,9 @@ var init_panel_frame = __esm({
|
|
|
159
162
|
}
|
|
160
163
|
});
|
|
161
164
|
|
|
165
|
+
// src/index.ts
|
|
166
|
+
import { visibleWidth as visibleWidth8 } from "@earendil-works/pi-tui";
|
|
167
|
+
|
|
162
168
|
// ../pi-core/src/validation.ts
|
|
163
169
|
function isRecord(value) {
|
|
164
170
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -521,6 +527,7 @@ function cachedComponent(renderFn) {
|
|
|
521
527
|
|
|
522
528
|
// src/shared/icons.ts
|
|
523
529
|
var ICONS = {
|
|
530
|
+
user: { nerd: "\uF007", unicode: "\u25CF", ascii: "@" },
|
|
524
531
|
branch: { nerd: "\uE0A0", unicode: "\u2442", ascii: "git" },
|
|
525
532
|
folder: { nerd: "\uF07C", unicode: "dir", ascii: "dir" },
|
|
526
533
|
model: { nerd: "\u{F06A9}", unicode: "\u25CF", ascii: "*" },
|
|
@@ -592,7 +599,10 @@ var STATUS_ICONS = {
|
|
|
592
599
|
running: { nerd: "\u25D0", unicode: "\u25D0", ascii: "*" },
|
|
593
600
|
completed: { nerd: "\uF00C", unicode: "\u2713", ascii: "+" },
|
|
594
601
|
failed: { nerd: "\uF00D", unicode: "\u2717", ascii: "x" },
|
|
595
|
-
|
|
602
|
+
timedOut: { nerd: "\uF017", unicode: "\u25F7", ascii: "T" },
|
|
603
|
+
resolved: { nerd: "\uF021", unicode: "\u21BB", ascii: "~" },
|
|
604
|
+
expectedExit: { nerd: "\uF00C", unicode: "\u2713", ascii: "+" },
|
|
605
|
+
cancelled: { ...STOP, ascii: "#" },
|
|
596
606
|
interrupted: STOP,
|
|
597
607
|
stopping: STOP,
|
|
598
608
|
deleted: BLOCKED,
|
|
@@ -967,6 +977,9 @@ var STATUS_ROLE = {
|
|
|
967
977
|
running: "accent",
|
|
968
978
|
completed: "success",
|
|
969
979
|
failed: "error",
|
|
980
|
+
timedOut: "warning",
|
|
981
|
+
resolved: "muted",
|
|
982
|
+
expectedExit: "dim",
|
|
970
983
|
cancelled: "muted",
|
|
971
984
|
interrupted: "warning",
|
|
972
985
|
stopping: "warning",
|
|
@@ -978,13 +991,16 @@ var TOOL_FOOTER_STATUS = {
|
|
|
978
991
|
completed: "completed",
|
|
979
992
|
deleted: "completed",
|
|
980
993
|
failed: "failed",
|
|
994
|
+
timedOut: "timedOut",
|
|
995
|
+
resolved: "resolved",
|
|
996
|
+
expectedExit: "expectedExit",
|
|
981
997
|
cancelled: "failed",
|
|
982
998
|
interrupted: "failed",
|
|
983
999
|
blocked: "failed"
|
|
984
1000
|
};
|
|
985
1001
|
function startsWithFooterGlyph(footer, mode) {
|
|
986
1002
|
const plain = stripTerminalSequences(footer);
|
|
987
|
-
return ["completed", "failed"].some((status) => {
|
|
1003
|
+
return ["completed", "failed", "timedOut", "resolved", "expectedExit"].some((status) => {
|
|
988
1004
|
const glyph = statusIcon(status, mode);
|
|
989
1005
|
return plain.startsWith(glyph) && (plain.length === glyph.length || /^\s/u.test(plain.slice(glyph.length)));
|
|
990
1006
|
});
|
|
@@ -1729,43 +1745,71 @@ function decorateEditor(editor, deps) {
|
|
|
1729
1745
|
import { truncateToWidth as truncateToWidth7, visibleWidth as visibleWidth6 } from "@earendil-works/pi-tui";
|
|
1730
1746
|
function createWorkingState(requestRender) {
|
|
1731
1747
|
let startedAt;
|
|
1748
|
+
let pendingBackground = 0;
|
|
1732
1749
|
let ticker;
|
|
1733
1750
|
let disposed = false;
|
|
1734
1751
|
function stop() {
|
|
1735
1752
|
if (ticker !== void 0) clearInterval(ticker);
|
|
1736
1753
|
ticker = void 0;
|
|
1737
|
-
|
|
1754
|
+
}
|
|
1755
|
+
function syncTicker() {
|
|
1756
|
+
if (startedAt === void 0 && pendingBackground === 0) {
|
|
1757
|
+
stop();
|
|
1758
|
+
} else if (ticker === void 0) {
|
|
1759
|
+
ticker = setInterval(requestRender, 50);
|
|
1760
|
+
ticker.unref?.();
|
|
1761
|
+
}
|
|
1762
|
+
requestRender();
|
|
1738
1763
|
}
|
|
1739
1764
|
return {
|
|
1740
1765
|
get isWorking() {
|
|
1741
|
-
return startedAt !== void 0;
|
|
1766
|
+
return startedAt !== void 0 || pendingBackground > 0;
|
|
1742
1767
|
},
|
|
1743
1768
|
start() {
|
|
1744
1769
|
if (disposed) return;
|
|
1745
|
-
stop();
|
|
1746
1770
|
startedAt = Date.now();
|
|
1747
|
-
|
|
1748
|
-
ticker.unref?.();
|
|
1749
|
-
requestRender();
|
|
1771
|
+
syncTicker();
|
|
1750
1772
|
},
|
|
1751
1773
|
end() {
|
|
1752
1774
|
if (disposed) return;
|
|
1753
|
-
|
|
1754
|
-
|
|
1775
|
+
startedAt = void 0;
|
|
1776
|
+
syncTicker();
|
|
1777
|
+
},
|
|
1778
|
+
setPendingBackground(count) {
|
|
1779
|
+
if (disposed || pendingBackground === count) return;
|
|
1780
|
+
pendingBackground = count;
|
|
1781
|
+
syncTicker();
|
|
1755
1782
|
},
|
|
1756
1783
|
status(indicator, width, styleMuted = (text) => text, frame, mode = "nerd") {
|
|
1757
1784
|
const ready = `${icon("ready", mode)} ready`;
|
|
1758
1785
|
const separator2 = icon("separator", mode);
|
|
1786
|
+
const now = frame?.now ?? Date.now();
|
|
1787
|
+
const fallback = () => {
|
|
1788
|
+
if (pendingBackground === 0)
|
|
1789
|
+
return styleMuted(truncateToWidth7(ready, width, ""));
|
|
1790
|
+
const glyphs = frames("workingFrames", mode);
|
|
1791
|
+
const glyph = glyphs[Math.floor(now / 200) % glyphs.length];
|
|
1792
|
+
const label2 = renderWorkingIndicator(
|
|
1793
|
+
`${glyph} working${icon("ellipsis", mode)}`,
|
|
1794
|
+
frame ?? createBreathingFrame(now),
|
|
1795
|
+
styleMuted,
|
|
1796
|
+
glyphs
|
|
1797
|
+
);
|
|
1798
|
+
return truncateToWidth7(
|
|
1799
|
+
`${label2}${styleMuted(` ${separator2} ${pendingBackground} bg`)}`,
|
|
1800
|
+
width,
|
|
1801
|
+
""
|
|
1802
|
+
);
|
|
1803
|
+
};
|
|
1759
1804
|
if (!indicator || typeof indicator !== "object" || !("renderInBorder" in indicator) || typeof indicator.renderInBorder !== "function") {
|
|
1760
|
-
return
|
|
1805
|
+
return fallback();
|
|
1761
1806
|
}
|
|
1762
1807
|
const working = "kind" in indicator && indicator.kind === "working";
|
|
1763
|
-
const now = frame?.now ?? Date.now();
|
|
1764
1808
|
const elapsed = working && startedAt !== void 0 ? ` ${separator2} ${formatDuration(Math.floor((now - startedAt) / 1e3) * 1e3)}` : "";
|
|
1765
1809
|
const nativeWidth = Math.max(1, width - visibleWidth6(elapsed));
|
|
1766
1810
|
const native = indicator.renderInBorder(nativeWidth);
|
|
1767
1811
|
if (typeof native !== "string" || visibleWidth6(native) === 0) {
|
|
1768
|
-
return
|
|
1812
|
+
return fallback();
|
|
1769
1813
|
}
|
|
1770
1814
|
const fitted = truncateToWidth7(native, nativeWidth, "");
|
|
1771
1815
|
const label = working && startedAt !== void 0 ? renderWorkingIndicator(
|
|
@@ -1782,11 +1826,107 @@ function createWorkingState(requestRender) {
|
|
|
1782
1826
|
},
|
|
1783
1827
|
dispose() {
|
|
1784
1828
|
disposed = true;
|
|
1829
|
+
startedAt = void 0;
|
|
1830
|
+
pendingBackground = 0;
|
|
1785
1831
|
stop();
|
|
1786
1832
|
}
|
|
1787
1833
|
};
|
|
1788
1834
|
}
|
|
1789
1835
|
|
|
1836
|
+
// src/status-line/orca-child-hold.ts
|
|
1837
|
+
var memoryKey = /* @__PURE__ */ Symbol.for("@thoth-agents/pi-thoth-theme/orca-child-holds");
|
|
1838
|
+
function createOrcaChildHold(events) {
|
|
1839
|
+
const processState = globalThis;
|
|
1840
|
+
processState[memoryKey] ??= /* @__PURE__ */ new Map();
|
|
1841
|
+
const sessions = processState[memoryKey];
|
|
1842
|
+
let announced = /* @__PURE__ */ new Set();
|
|
1843
|
+
let subagents = [];
|
|
1844
|
+
let background = [];
|
|
1845
|
+
let timer;
|
|
1846
|
+
let disposed = false;
|
|
1847
|
+
function reconcile(prefix, tasks) {
|
|
1848
|
+
const live = /* @__PURE__ */ new Set();
|
|
1849
|
+
const byId = /* @__PURE__ */ new Map();
|
|
1850
|
+
for (const task of tasks) {
|
|
1851
|
+
if (disposed) return;
|
|
1852
|
+
const id = `${prefix}${task.id}`;
|
|
1853
|
+
if (!byId.has(id)) byId.set(id, task);
|
|
1854
|
+
if (!task.live) continue;
|
|
1855
|
+
live.add(id);
|
|
1856
|
+
if (announced.has(id)) continue;
|
|
1857
|
+
announced.add(id);
|
|
1858
|
+
events.emit("task:subagent:lifecycle", {
|
|
1859
|
+
id,
|
|
1860
|
+
status: "started",
|
|
1861
|
+
agent: task.agent,
|
|
1862
|
+
...task.description ? { description: task.description } : {}
|
|
1863
|
+
});
|
|
1864
|
+
}
|
|
1865
|
+
for (const id of announced) {
|
|
1866
|
+
if (disposed) return;
|
|
1867
|
+
if (!id.startsWith(prefix) || live.has(id)) continue;
|
|
1868
|
+
announced.delete(id);
|
|
1869
|
+
const status = byId.get(id)?.status;
|
|
1870
|
+
events.emit("task:subagent:lifecycle", {
|
|
1871
|
+
id,
|
|
1872
|
+
status: status === "failed" || status === "timed_out" ? "failed" : status === "cancelled" || status === "interrupted" ? "aborted" : "completed"
|
|
1873
|
+
});
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
return {
|
|
1877
|
+
startSession(sessionId) {
|
|
1878
|
+
if (disposed) return;
|
|
1879
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
1880
|
+
announced = sessions.get(sessionId) ?? /* @__PURE__ */ new Set();
|
|
1881
|
+
sessions.set(sessionId, announced);
|
|
1882
|
+
subagents = [];
|
|
1883
|
+
background = [];
|
|
1884
|
+
timer = setTimeout(() => {
|
|
1885
|
+
timer = void 0;
|
|
1886
|
+
if (disposed) return;
|
|
1887
|
+
reconcile("thoth:subagent:", subagents);
|
|
1888
|
+
reconcile("thoth:bg:", background);
|
|
1889
|
+
}, 0);
|
|
1890
|
+
timer.unref?.();
|
|
1891
|
+
},
|
|
1892
|
+
updateSubagents(data) {
|
|
1893
|
+
if (disposed) return;
|
|
1894
|
+
subagents = [
|
|
1895
|
+
...data.tasks.map((task) => ({
|
|
1896
|
+
id: task.id,
|
|
1897
|
+
live: task.mode === "background" && (task.status === "queued" || task.status === "running" || task.status === "stopping"),
|
|
1898
|
+
status: task.status,
|
|
1899
|
+
agent: task.agent,
|
|
1900
|
+
description: task.displayName
|
|
1901
|
+
})),
|
|
1902
|
+
...data.history.map((task) => ({
|
|
1903
|
+
id: task.id,
|
|
1904
|
+
live: false,
|
|
1905
|
+
status: task.status,
|
|
1906
|
+
agent: task.agent
|
|
1907
|
+
}))
|
|
1908
|
+
];
|
|
1909
|
+
if (timer === void 0) reconcile("thoth:subagent:", subagents);
|
|
1910
|
+
},
|
|
1911
|
+
updateBackground(data) {
|
|
1912
|
+
if (disposed) return;
|
|
1913
|
+
background = data.tasks.map((task) => ({
|
|
1914
|
+
id: task.id,
|
|
1915
|
+
live: task.status === "running",
|
|
1916
|
+
status: task.status,
|
|
1917
|
+
agent: task.kind === "command_watch" ? "watch" : "process",
|
|
1918
|
+
description: task.name
|
|
1919
|
+
}));
|
|
1920
|
+
if (timer === void 0) reconcile("thoth:bg:", background);
|
|
1921
|
+
},
|
|
1922
|
+
dispose() {
|
|
1923
|
+
disposed = true;
|
|
1924
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
1925
|
+
timer = void 0;
|
|
1926
|
+
}
|
|
1927
|
+
};
|
|
1928
|
+
}
|
|
1929
|
+
|
|
1790
1930
|
// src/status-line/throughput.ts
|
|
1791
1931
|
function createThroughputTracker() {
|
|
1792
1932
|
let pending;
|
|
@@ -1930,6 +2070,7 @@ function registerStatusLine(pi, ctx, config) {
|
|
|
1930
2070
|
requestRender();
|
|
1931
2071
|
};
|
|
1932
2072
|
const working = createWorkingState(invalidateRender);
|
|
2073
|
+
const orcaChildHold = createOrcaChildHold(pi.events);
|
|
1933
2074
|
const editorDecorations = /* @__PURE__ */ new Set();
|
|
1934
2075
|
const refreshSession = () => {
|
|
1935
2076
|
if (disposed) return;
|
|
@@ -1937,7 +2078,12 @@ function registerStatusLine(pi, ctx, config) {
|
|
|
1937
2078
|
invalidateRender();
|
|
1938
2079
|
};
|
|
1939
2080
|
let offSubagentUsage;
|
|
2081
|
+
let offBackgroundWork = [];
|
|
1940
2082
|
unsubs.push(() => offSubagentUsage?.());
|
|
2083
|
+
unsubs.push(() => {
|
|
2084
|
+
for (const off of offBackgroundWork) off();
|
|
2085
|
+
offBackgroundWork = [];
|
|
2086
|
+
});
|
|
1941
2087
|
if (footerData?.onBranchChange) {
|
|
1942
2088
|
unsubs.push(footerData.onBranchChange(invalidateRender));
|
|
1943
2089
|
}
|
|
@@ -1958,7 +2104,50 @@ function registerStatusLine(pi, ctx, config) {
|
|
|
1958
2104
|
data: {}
|
|
1959
2105
|
});
|
|
1960
2106
|
};
|
|
2107
|
+
const subscribeAndRequestBackgroundWork = () => {
|
|
2108
|
+
const sessionId = ctx.sessionManager.getSessionId();
|
|
2109
|
+
for (const off of offBackgroundWork) off();
|
|
2110
|
+
orcaChildHold.startSession(sessionId);
|
|
2111
|
+
let subagentPending = 0;
|
|
2112
|
+
let backgroundPending = 0;
|
|
2113
|
+
if (inputBoxEnabled) working.setPendingBackground(0);
|
|
2114
|
+
offBackgroundWork = [
|
|
2115
|
+
subscribe(pi.events, SUBAGENTS_STATE_CHANNEL, {
|
|
2116
|
+
sessionId,
|
|
2117
|
+
onSnapshot: ({ data }) => {
|
|
2118
|
+
if (disposed) return;
|
|
2119
|
+
orcaChildHold.updateSubagents(data);
|
|
2120
|
+
subagentPending = data.tasks.filter(
|
|
2121
|
+
(task) => task.mode === "background" && (task.status === "queued" || task.status === "running" || task.status === "stopping")
|
|
2122
|
+
).length;
|
|
2123
|
+
if (inputBoxEnabled)
|
|
2124
|
+
working.setPendingBackground(subagentPending + backgroundPending);
|
|
2125
|
+
}
|
|
2126
|
+
}),
|
|
2127
|
+
subscribe(pi.events, BACKGROUND_STATE_CHANNEL, {
|
|
2128
|
+
sessionId,
|
|
2129
|
+
onSnapshot: ({ data }) => {
|
|
2130
|
+
if (disposed) return;
|
|
2131
|
+
orcaChildHold.updateBackground(data);
|
|
2132
|
+
backgroundPending = data.counts.running;
|
|
2133
|
+
if (inputBoxEnabled)
|
|
2134
|
+
working.setPendingBackground(subagentPending + backgroundPending);
|
|
2135
|
+
}
|
|
2136
|
+
})
|
|
2137
|
+
];
|
|
2138
|
+
for (const channel of [
|
|
2139
|
+
SUBAGENTS_STATE_REQUEST,
|
|
2140
|
+
BACKGROUND_STATE_REQUEST
|
|
2141
|
+
]) {
|
|
2142
|
+
request(pi.events, channel, {
|
|
2143
|
+
source: "@thoth-agents/pi-thoth-theme",
|
|
2144
|
+
sessionId,
|
|
2145
|
+
data: {}
|
|
2146
|
+
});
|
|
2147
|
+
}
|
|
2148
|
+
};
|
|
1961
2149
|
if (pi?.on) {
|
|
2150
|
+
unsubs.push(pi.on("session_shutdown", dispose));
|
|
1962
2151
|
unsubs.push(
|
|
1963
2152
|
pi.on("session_start", () => {
|
|
1964
2153
|
if (disposed) return;
|
|
@@ -1967,6 +2156,7 @@ function registerStatusLine(pi, ctx, config) {
|
|
|
1967
2156
|
if (inputBoxEnabled) working.end();
|
|
1968
2157
|
refreshSession();
|
|
1969
2158
|
subscribeAndRequestSubagentUsage();
|
|
2159
|
+
subscribeAndRequestBackgroundWork();
|
|
1970
2160
|
})
|
|
1971
2161
|
);
|
|
1972
2162
|
if (inputBoxEnabled) {
|
|
@@ -1992,6 +2182,22 @@ function registerStatusLine(pi, ctx, config) {
|
|
|
1992
2182
|
unsubs.push(pi.on("thinking_level_select", invalidateRender));
|
|
1993
2183
|
}
|
|
1994
2184
|
subscribeAndRequestSubagentUsage();
|
|
2185
|
+
subscribeAndRequestBackgroundWork();
|
|
2186
|
+
function dispose() {
|
|
2187
|
+
if (disposed) return;
|
|
2188
|
+
disposed = true;
|
|
2189
|
+
working.dispose();
|
|
2190
|
+
orcaChildHold.dispose();
|
|
2191
|
+
for (const decoration of editorDecorations) decoration.dispose();
|
|
2192
|
+
editorDecorations.clear();
|
|
2193
|
+
for (const unsub of unsubs) {
|
|
2194
|
+
try {
|
|
2195
|
+
unsub();
|
|
2196
|
+
} catch {
|
|
2197
|
+
}
|
|
2198
|
+
}
|
|
2199
|
+
unsubs.length = 0;
|
|
2200
|
+
}
|
|
1995
2201
|
return {
|
|
1996
2202
|
getStatusSnapshot,
|
|
1997
2203
|
render(width) {
|
|
@@ -2025,19 +2231,7 @@ function registerStatusLine(pi, ctx, config) {
|
|
|
2025
2231
|
return cachedLines;
|
|
2026
2232
|
},
|
|
2027
2233
|
invalidate: invalidateRender,
|
|
2028
|
-
dispose
|
|
2029
|
-
disposed = true;
|
|
2030
|
-
working.dispose();
|
|
2031
|
-
for (const decoration of editorDecorations) decoration.dispose();
|
|
2032
|
-
editorDecorations.clear();
|
|
2033
|
-
for (const unsub of unsubs) {
|
|
2034
|
-
try {
|
|
2035
|
-
unsub();
|
|
2036
|
-
} catch {
|
|
2037
|
-
}
|
|
2038
|
-
}
|
|
2039
|
-
unsubs.length = 0;
|
|
2040
|
-
}
|
|
2234
|
+
dispose
|
|
2041
2235
|
};
|
|
2042
2236
|
});
|
|
2043
2237
|
}
|
|
@@ -4115,6 +4309,22 @@ function registerWelcome(pi, ctx, config, options) {
|
|
|
4115
4309
|
// src/index.ts
|
|
4116
4310
|
function thothTheme(pi) {
|
|
4117
4311
|
const config = loadConfig();
|
|
4312
|
+
pi.registerMarkdownTransformer((markdown, context) => {
|
|
4313
|
+
if (context.messageType !== "user" || !markdown.trim()) return markdown;
|
|
4314
|
+
if (/^╭── [\uF007●@] user ─+╮\r?\n\r?\n[\s\S]*\r?\n\r?\n╰─+╯$/.test(markdown))
|
|
4315
|
+
return markdown;
|
|
4316
|
+
const width = context.availableWidth;
|
|
4317
|
+
const title = `\u256D\u2500\u2500 ${icon("user", config.icons)} user `;
|
|
4318
|
+
const titleWidth = visibleWidth8(title);
|
|
4319
|
+
if (!Number.isInteger(width) || width < titleWidth + 2) return markdown;
|
|
4320
|
+
const top = `${title}${"\u2500".repeat(width - titleWidth - 1)}\u256E`;
|
|
4321
|
+
const bottom = `\u2570${"\u2500".repeat(width - 2)}\u256F`;
|
|
4322
|
+
return `${top}
|
|
4323
|
+
|
|
4324
|
+
${markdown}
|
|
4325
|
+
|
|
4326
|
+
${bottom}`;
|
|
4327
|
+
});
|
|
4118
4328
|
const owner = {};
|
|
4119
4329
|
const cwd = process.cwd();
|
|
4120
4330
|
const resolveToolRenderers = config.tools.enabled ? createToolRendererResolver(pi, config, cwd) : void 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thoth-agents/pi-thoth-theme",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Modular Thoth theme, status line, tool styling, and welcome header for Pi.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"@earendil-works/pi-tui": "1.0.2",
|
|
51
51
|
"@earendil-works/pi-ai": "1.0.2",
|
|
52
52
|
"@rolldown/binding-wasm32-wasi": "^1.2.4",
|
|
53
|
-
"@thoth-agents/pi-core": "^0.
|
|
53
|
+
"@thoth-agents/pi-core": "^0.5.0"
|
|
54
54
|
},
|
|
55
55
|
"upstream": {
|
|
56
56
|
"repository": "https://github.com/QuangThai/pi-omp-theme",
|