@oh-my-pi/pi-tui 18.2.6 → 18.2.7
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/CHANGELOG.md +19 -0
- package/THIRD-PARTY-NOTICES.txt +0 -37
- package/dist/types/glyph-protocol.d.ts +62 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/overlays/model-browser.d.ts +9 -3
- package/dist/types/prompt/gradient-highlight.d.ts +2 -2
- package/dist/types/prompt/magic-keywords.d.ts +37 -10
- package/dist/types/setup/scenes/glyph.d.ts +6 -1
- package/dist/types/terminal-capabilities.d.ts +8 -0
- package/dist/types/terminal.d.ts +16 -0
- package/dist/types/theme/mermaid-cache.d.ts +2 -2
- package/dist/types/tools/eval.d.ts +5 -4
- package/dist/types/tools/find.d.ts +82 -0
- package/dist/types/tools/web-search.d.ts +4 -0
- package/package.json +9 -9
- package/src/glyph-protocol.ts +143 -0
- package/src/index.ts +2 -0
- package/src/overlays/model-browser.ts +47 -6
- package/src/overlays/model-hub.ts +122 -33
- package/src/prompt/gradient-highlight.ts +3 -3
- package/src/prompt/macos-spelling.ts +7 -1
- package/src/prompt/magic-keywords.ts +103 -21
- package/src/prompt/markdown-prose.ts +2 -2
- package/src/prompt/tips.txt +1 -0
- package/src/setup/scenes/glyph.ts +8 -1
- package/src/terminal-capabilities.ts +12 -0
- package/src/terminal.ts +151 -2
- package/src/theme/glyph-bundle.json +797 -0
- package/src/theme/mermaid-cache.ts +5 -4
- package/src/tools/eval.ts +14 -7
- package/src/tools/find.ts +255 -0
- package/src/tools/hub.ts +2 -0
- package/src/tools/index.ts +2 -0
- package/src/tools/web-search.ts +5 -0
- package/src/tui.ts +7 -0
- package/dist/types/prompt/magic-keyword-boundary.d.ts +0 -9
- package/dist/types/prompt/orchestrate.d.ts +0 -13
- package/dist/types/prompt/ultrathink.d.ts +0 -13
- package/dist/types/prompt/workflow.d.ts +0 -13
- package/src/prompt/magic-keyword-boundary.ts +0 -23
- package/src/prompt/orchestrate.ts +0 -26
- package/src/prompt/ultrathink.ts +0 -26
- package/src/prompt/workflow.ts +0 -26
package/src/prompt/tips.txt
CHANGED
|
@@ -10,6 +10,7 @@ Did you know? Each kitty/tmux/cmux/zellij/wezterm split keeps its own session
|
|
|
10
10
|
Drop the word `ultrathink` in your message for harder multi-step reasoning — watch it glow rainbow as you type
|
|
11
11
|
Say `orchestrate` in your message to drive a multi-phase task with parallel subagents — watch it glow as you type
|
|
12
12
|
Say `workflowz` in your message to drive the task with parallel subagents in eval — watch it glow as you type
|
|
13
|
+
Bulk data to classify or triage? Say `jevify` in your message — the eval kernel's `judge()` processes the batch and you read only what it flags — watch it glow as you type
|
|
13
14
|
Log in to several accounts of the same provider — `/login` again — and omp load-balances across them automatically
|
|
14
15
|
Run `omp auth-broker serve` once and every machine pulls live tokens over the wire — refresh keys never leave the host; `omp auth-gateway` fronts it as a drop-in proxy any OpenAI-compatible client can hit
|
|
15
16
|
Press alt+p (or /switch) to switch provider, and ctrl+p to cycle role models smol -> slow -> etc
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type SgrMouseEvent } from "../../mouse";
|
|
2
|
+
import { TERMINAL } from "../../terminal-capabilities";
|
|
2
3
|
import { type SelectItem, SelectList } from "../../components/select-list";
|
|
3
4
|
import { Text } from "../../components/text";
|
|
4
5
|
import { WizardStep } from "../../components/wizard-step";
|
|
@@ -111,10 +112,16 @@ class GlyphSceneController implements SetupSceneController {
|
|
|
111
112
|
}
|
|
112
113
|
}
|
|
113
114
|
|
|
114
|
-
/**
|
|
115
|
+
/**
|
|
116
|
+
* Preview and persist the terminal glyph preset. Skipped once the Glyph
|
|
117
|
+
* Protocol handshake confirmed the terminal renders omp's bundled icons: every
|
|
118
|
+
* row renders cleanly there, and the default `unicode` preset already upgrades
|
|
119
|
+
* to nerd at runtime while staying safe on terminals without the protocol.
|
|
120
|
+
*/
|
|
115
121
|
export const glyphSetupScene: SetupScene = {
|
|
116
122
|
id: "glyph-mode",
|
|
117
123
|
title: "Choose glyph mode",
|
|
118
124
|
minVersion: 1,
|
|
125
|
+
shouldRun: () => !TERMINAL.glyphProtocol,
|
|
119
126
|
mount: host => new GlyphSceneController(host),
|
|
120
127
|
};
|
|
@@ -732,6 +732,12 @@ export interface RuntimeTerminal extends TerminalInfo {
|
|
|
732
732
|
textSizing: boolean;
|
|
733
733
|
/** Whether the terminal implements colon-subparameter styled underlines (curly + colored). */
|
|
734
734
|
styledUnderlines: boolean;
|
|
735
|
+
/**
|
|
736
|
+
* Whether the terminal answered the Glyph Protocol support query with a
|
|
737
|
+
* `glyf`-capable reply and the bundled icons have been registered. Probe-
|
|
738
|
+
* driven: false until {@link ProcessTerminal} resolves it.
|
|
739
|
+
*/
|
|
740
|
+
glyphProtocol: boolean;
|
|
735
741
|
}
|
|
736
742
|
|
|
737
743
|
export const TERMINAL: RuntimeTerminal = (() => {
|
|
@@ -763,6 +769,7 @@ export const TERMINAL: RuntimeTerminal = (() => {
|
|
|
763
769
|
// depth), so Apple Terminal and other unproven hosts fall back to the flat
|
|
764
770
|
// CSI 4 m / CSI 24 m underline the typo renderer needs to avoid black bars.
|
|
765
771
|
resolved.styledUnderlines = detectStyledUnderlineSupport(resolved.id, Bun.env);
|
|
772
|
+
resolved.glyphProtocol = false;
|
|
766
773
|
return resolved;
|
|
767
774
|
})();
|
|
768
775
|
|
|
@@ -788,6 +795,11 @@ export function setTerminalDeccara(enabled: boolean): void {
|
|
|
788
795
|
TERMINAL.deccara = enabled;
|
|
789
796
|
}
|
|
790
797
|
|
|
798
|
+
/** Record the Glyph Protocol probe result (called by ProcessTerminal). */
|
|
799
|
+
export function setTerminalGlyphProtocol(supported: boolean): void {
|
|
800
|
+
TERMINAL.glyphProtocol = supported;
|
|
801
|
+
}
|
|
802
|
+
|
|
791
803
|
/** Override screen-to-scrollback clear support for targeted renderer tests. */
|
|
792
804
|
export function setTerminalScreenToScrollback(enabled: boolean): void {
|
|
793
805
|
TERMINAL.supportsScreenToScrollback = enabled;
|
package/src/terminal.ts
CHANGED
|
@@ -5,6 +5,14 @@ import { $env, isBunTestRuntime, isTerminalHeadless, isWsl } from "@oh-my-pi/pi-
|
|
|
5
5
|
import * as logger from "@oh-my-pi/pi-utils/logger";
|
|
6
6
|
import * as postmortem from "@oh-my-pi/pi-utils/postmortem";
|
|
7
7
|
import { restoreTerminalStderr, suppressTerminalStderr } from "@oh-my-pi/pi-utils/stderr-guard";
|
|
8
|
+
import {
|
|
9
|
+
encodeBundledGlyphRegistrations,
|
|
10
|
+
encodeGlyphCoverageQuery,
|
|
11
|
+
encodeGlyphSupportQuery,
|
|
12
|
+
GLYPH_CONFIRMATION_CODEPOINT,
|
|
13
|
+
isGlyphProtocolSequence,
|
|
14
|
+
parseGlyphProtocolReply,
|
|
15
|
+
} from "./glyph-protocol";
|
|
8
16
|
import { setKittyProtocolActive } from "./keys";
|
|
9
17
|
import { StdinBuffer } from "./stdin-buffer";
|
|
10
18
|
import {
|
|
@@ -12,6 +20,7 @@ import {
|
|
|
12
20
|
NotifyProtocol,
|
|
13
21
|
setCellDimensions,
|
|
14
22
|
setOsc99Supported,
|
|
23
|
+
setTerminalGlyphProtocol,
|
|
15
24
|
TERMINAL,
|
|
16
25
|
} from "./terminal-capabilities";
|
|
17
26
|
import { isInsideTmux, wrapTmuxPassthrough } from "./tmux";
|
|
@@ -456,6 +465,13 @@ export type TerminalAppearanceRequestToken = number;
|
|
|
456
465
|
* set, 4 permanently reset) when the terminal answered DECRQM.
|
|
457
466
|
*/
|
|
458
467
|
export type PrivateModeReportHandler = (mode: number, supported: boolean, confirmed?: boolean, status?: number) => void;
|
|
468
|
+
/**
|
|
469
|
+
* Fired once when the Glyph Protocol handshake resolves. `supported` is true
|
|
470
|
+
* only after the bundled icons were written and the terminal confirmed (via a
|
|
471
|
+
* `q` coverage query) that a registered codepoint is served from its
|
|
472
|
+
* glossary, so a host can safely repaint — or switch to the nerd preset.
|
|
473
|
+
*/
|
|
474
|
+
export type GlyphProtocolReportHandler = (supported: boolean) => void;
|
|
459
475
|
|
|
460
476
|
/**
|
|
461
477
|
* Cursor shapes addressable via DECSCUSR (`CSI <n> SP q`). `"default"` (0) hands the shape back to
|
|
@@ -616,6 +632,14 @@ export interface Terminal {
|
|
|
616
632
|
* `status` is the DECRPM value when the terminal answered DECRQM.
|
|
617
633
|
*/
|
|
618
634
|
onPrivateModeReport?(callback: PrivateModeReportHandler): void;
|
|
635
|
+
/**
|
|
636
|
+
* Register a callback fired once the startup Glyph Protocol handshake
|
|
637
|
+
* resolves (see {@link GlyphProtocolReportHandler}). A subscriber that
|
|
638
|
+
* arrives after the handshake already resolved is called immediately with
|
|
639
|
+
* the stored outcome. Optional so custom Terminals built against older
|
|
640
|
+
* pi-tui versions keep working.
|
|
641
|
+
*/
|
|
642
|
+
onGlyphProtocolReport?(callback: GlyphProtocolReportHandler): void;
|
|
619
643
|
}
|
|
620
644
|
|
|
621
645
|
/**
|
|
@@ -637,7 +661,8 @@ type Da1SentinelOwner =
|
|
|
637
661
|
| { kind: "keyboard" }
|
|
638
662
|
| { kind: "osc11" }
|
|
639
663
|
| { kind: "privateMode"; mode: number }
|
|
640
|
-
| { kind: "osc99Probe"; id: string }
|
|
664
|
+
| { kind: "osc99Probe"; id: string }
|
|
665
|
+
| { kind: "glyphProtocol"; phase: "support" | "confirm" };
|
|
641
666
|
|
|
642
667
|
let nextOsc99ProbeId = 1;
|
|
643
668
|
|
|
@@ -761,6 +786,14 @@ export class ProcessTerminal implements Terminal {
|
|
|
761
786
|
#osc99PendingId: string | undefined;
|
|
762
787
|
#osc99ResponseBuffer = "";
|
|
763
788
|
#osc99Capabilities = new Map<string, string>();
|
|
789
|
+
/**
|
|
790
|
+
* Handshake phase: `support` awaits the `s` reply, `confirm` awaits the `q`
|
|
791
|
+
* coverage reply sent after the bundle was written.
|
|
792
|
+
*/
|
|
793
|
+
#glyphProtocolPhase: "idle" | "support" | "confirm" = "idle";
|
|
794
|
+
#glyphProtocolReplyBuffer = "";
|
|
795
|
+
#glyphProtocolResult: boolean | undefined;
|
|
796
|
+
#glyphProtocolCallbacks: GlyphProtocolReportHandler[] = [];
|
|
764
797
|
#privateCsiResponseBuffer = "";
|
|
765
798
|
#da1SentinelOwners: Da1SentinelOwner[] = [];
|
|
766
799
|
/** Resolved DECRQM support per private mode (mode → supported). */
|
|
@@ -860,6 +893,13 @@ export class ProcessTerminal implements Terminal {
|
|
|
860
893
|
this.#privateModeCallbacks.push(callback);
|
|
861
894
|
}
|
|
862
895
|
|
|
896
|
+
onGlyphProtocolReport(callback: GlyphProtocolReportHandler): void {
|
|
897
|
+
this.#glyphProtocolCallbacks.push(callback);
|
|
898
|
+
// The handshake runs from enableInput(), which can precede the host's
|
|
899
|
+
// subscription during startup; replay so the outcome is never missed.
|
|
900
|
+
if (this.#glyphProtocolResult !== undefined) callback(this.#glyphProtocolResult);
|
|
901
|
+
}
|
|
902
|
+
|
|
863
903
|
start(
|
|
864
904
|
onInput: (data: string) => void,
|
|
865
905
|
onResize: () => void,
|
|
@@ -996,6 +1036,11 @@ export class ProcessTerminal implements Terminal {
|
|
|
996
1036
|
// without leaking probe bytes to application input.
|
|
997
1037
|
this.#queryOsc99Support();
|
|
998
1038
|
|
|
1039
|
+
// Glyph Protocol support query (`s` verb), same DA1 sentinel FIFO. A reply
|
|
1040
|
+
// triggers the bundled icon registration so the nerd symbol preset renders
|
|
1041
|
+
// without a patched font installed.
|
|
1042
|
+
this.#queryGlyphProtocolSupport();
|
|
1043
|
+
|
|
999
1044
|
// Subscribe to Mode 2031 appearance change notifications.
|
|
1000
1045
|
// When the terminal reports a change, we re-query OSC 11 to get the
|
|
1001
1046
|
// actual background color (following Neovim convention) with 100ms debounce.
|
|
@@ -1133,7 +1178,8 @@ export class ProcessTerminal implements Terminal {
|
|
|
1133
1178
|
this.#privateCsiResponseBuffer.length === 0 &&
|
|
1134
1179
|
this.#inBandResizeBuffer.length === 0 &&
|
|
1135
1180
|
this.#osc11ResponseBuffer.length === 0 &&
|
|
1136
|
-
this.#osc99ResponseBuffer.length === 0
|
|
1181
|
+
this.#osc99ResponseBuffer.length === 0 &&
|
|
1182
|
+
this.#glyphProtocolReplyBuffer.length === 0
|
|
1137
1183
|
) {
|
|
1138
1184
|
if (this.#inputHandler) {
|
|
1139
1185
|
this.#inputHandler(sequence);
|
|
@@ -1292,6 +1338,13 @@ export class ProcessTerminal implements Terminal {
|
|
|
1292
1338
|
this.#resolveOsc99Support(owner.id, false);
|
|
1293
1339
|
break;
|
|
1294
1340
|
}
|
|
1341
|
+
case "glyphProtocol": {
|
|
1342
|
+
// The support-phase sentinel is answered after the `s` reply that
|
|
1343
|
+
// already advanced the handshake; only a sentinel from the phase
|
|
1344
|
+
// still awaiting its reply means that reply never came.
|
|
1345
|
+
if (owner.phase === this.#glyphProtocolPhase) this.#resolveGlyphProtocolSupport(false);
|
|
1346
|
+
break;
|
|
1347
|
+
}
|
|
1295
1348
|
}
|
|
1296
1349
|
return;
|
|
1297
1350
|
}
|
|
@@ -1376,6 +1429,23 @@ export class ProcessTerminal implements Terminal {
|
|
|
1376
1429
|
}
|
|
1377
1430
|
}
|
|
1378
1431
|
|
|
1432
|
+
// Glyph Protocol APC replies (`ESC _ 25a1 ; … ESC \`). Swallowed for
|
|
1433
|
+
// the whole session, not just while the probe is outstanding: an APC is
|
|
1434
|
+
// exclusively terminal->host data, and registrations use `reply=0`, so
|
|
1435
|
+
// any late `r`/`c` acknowledgement must never reach the composer.
|
|
1436
|
+
if (this.#glyphProtocolReplyBuffer || sequence.startsWith("\x1b_25a1;")) {
|
|
1437
|
+
if (this.#glyphProtocolReplyBuffer && sequence.startsWith("\x1b") && sequence !== "\x1b\\") {
|
|
1438
|
+
this.#glyphProtocolReplyBuffer = "";
|
|
1439
|
+
} else {
|
|
1440
|
+
this.#glyphProtocolReplyBuffer += sequence;
|
|
1441
|
+
if (!this.#glyphProtocolReplyBuffer.endsWith("\x1b\\")) return;
|
|
1442
|
+
const reply = this.#glyphProtocolReplyBuffer;
|
|
1443
|
+
this.#glyphProtocolReplyBuffer = "";
|
|
1444
|
+
this.#handleGlyphProtocolReply(reply);
|
|
1445
|
+
return;
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1379
1449
|
// Mode 2031 change notification: re-query OSC 11 with 100ms debounce
|
|
1380
1450
|
// (Neovim convention — coalesces rapid notifications during transitions)
|
|
1381
1451
|
const appearanceMatch = sequence.match(appearanceDsrPattern);
|
|
@@ -1504,6 +1574,80 @@ export class ProcessTerminal implements Terminal {
|
|
|
1504
1574
|
setOsc99Supported(supported);
|
|
1505
1575
|
}
|
|
1506
1576
|
|
|
1577
|
+
#shouldQueryGlyphProtocolSupport(): boolean {
|
|
1578
|
+
// `PI_NO_GLYPH_PROTOCOL=1` keeps the terminal's own font coverage (tofu
|
|
1579
|
+
// included) — the registration shadows a system Nerd Font at render time.
|
|
1580
|
+
if ($env.PI_NO_GLYPH_PROTOCOL === "1") return false;
|
|
1581
|
+
// Same multiplexer rule as the OSC 99 probe: tmux/screen cannot route the
|
|
1582
|
+
// APC reply back to the sending pane, so it would leak as literal text.
|
|
1583
|
+
if (isInsideTerminalMultiplexer($env)) return false;
|
|
1584
|
+
return !isBunTestRuntime() || $env.PI_TUI_GLYPH_PROTOCOL_PROBE === "1";
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
#queryGlyphProtocolSupport(): void {
|
|
1588
|
+
setTerminalGlyphProtocol(false);
|
|
1589
|
+
this.#glyphProtocolPhase = "idle";
|
|
1590
|
+
this.#glyphProtocolResult = undefined;
|
|
1591
|
+
this.#glyphProtocolReplyBuffer = "";
|
|
1592
|
+
if (this.#dead || !this.#shouldQueryGlyphProtocolSupport()) return;
|
|
1593
|
+
this.#glyphProtocolPhase = "support";
|
|
1594
|
+
this.#da1SentinelOwners.push({ kind: "glyphProtocol", phase: "support" });
|
|
1595
|
+
this.#safeWrite(`${encodeGlyphSupportQuery()}\x1b[c`);
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
#handleGlyphProtocolReply(sequence: string): void {
|
|
1599
|
+
if (!isGlyphProtocolSequence(sequence)) return;
|
|
1600
|
+
const reply = parseGlyphProtocolReply(sequence);
|
|
1601
|
+
if (!reply) {
|
|
1602
|
+
logger.debug("Glyph Protocol: unparsable reply", { sequence });
|
|
1603
|
+
return;
|
|
1604
|
+
}
|
|
1605
|
+
if (reply.verb === "s" && this.#glyphProtocolPhase === "support") {
|
|
1606
|
+
// Every bundled payload is `fmt=glyf`; a terminal that recognises the
|
|
1607
|
+
// protocol but advertises no formats would reject each registration.
|
|
1608
|
+
if (!reply.formats.includes("glyf") || this.#dead) {
|
|
1609
|
+
this.#resolveGlyphProtocolSupport(false);
|
|
1610
|
+
return;
|
|
1611
|
+
}
|
|
1612
|
+
// Registrations are fire-and-forget (`reply=0`); the coverage query
|
|
1613
|
+
// that follows them is the success check — the terminal processes the
|
|
1614
|
+
// stream in order, so a `glossary` answer proves the bundle landed.
|
|
1615
|
+
this.#glyphProtocolPhase = "confirm";
|
|
1616
|
+
this.#da1SentinelOwners.push({ kind: "glyphProtocol", phase: "confirm" });
|
|
1617
|
+
this.#safeWrite(
|
|
1618
|
+
`${encodeBundledGlyphRegistrations()}${encodeGlyphCoverageQuery(GLYPH_CONFIRMATION_CODEPOINT)}\x1b[c`,
|
|
1619
|
+
);
|
|
1620
|
+
return;
|
|
1621
|
+
}
|
|
1622
|
+
if (reply.verb === "q" && this.#glyphProtocolPhase === "confirm" && reply.cp === GLYPH_CONFIRMATION_CODEPOINT) {
|
|
1623
|
+
const confirmed = reply.coverage.includes("glossary");
|
|
1624
|
+
if (!confirmed) logger.warn("Glyph Protocol: registered codepoint not served from glossary", reply);
|
|
1625
|
+
this.#resolveGlyphProtocolSupport(confirmed);
|
|
1626
|
+
return;
|
|
1627
|
+
}
|
|
1628
|
+
// Registrations are sent with `reply=0`, so this is a terminal that
|
|
1629
|
+
// ignored the reply gate or a stray acknowledgement: keep it out of input.
|
|
1630
|
+
if ((reply.verb === "r" || reply.verb === "c") && reply.status !== 0) {
|
|
1631
|
+
logger.warn("Glyph Protocol: registration rejected", reply);
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
/** Finish the handshake in either phase and notify subscribers once. */
|
|
1636
|
+
#resolveGlyphProtocolSupport(supported: boolean): void {
|
|
1637
|
+
if (this.#glyphProtocolPhase === "idle") return;
|
|
1638
|
+
this.#glyphProtocolPhase = "idle";
|
|
1639
|
+
this.#glyphProtocolReplyBuffer = "";
|
|
1640
|
+
this.#glyphProtocolResult = supported;
|
|
1641
|
+
setTerminalGlyphProtocol(supported);
|
|
1642
|
+
for (const cb of this.#glyphProtocolCallbacks) {
|
|
1643
|
+
try {
|
|
1644
|
+
cb(supported);
|
|
1645
|
+
} catch {
|
|
1646
|
+
// Ignore subscriber errors — capability reporting must not crash input.
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1507
1651
|
/**
|
|
1508
1652
|
* Parse an OSC 11 background color response and compute BT.601 luminance.
|
|
1509
1653
|
* Handles 1-, 2-, 3-, and 4-digit XParseColor hex components.
|
|
@@ -1810,6 +1954,11 @@ export class ProcessTerminal implements Terminal {
|
|
|
1810
1954
|
this.#osc99ResponseBuffer = "";
|
|
1811
1955
|
this.#osc99Capabilities.clear();
|
|
1812
1956
|
setOsc99Supported(false);
|
|
1957
|
+
this.#glyphProtocolPhase = "idle";
|
|
1958
|
+
this.#glyphProtocolResult = undefined;
|
|
1959
|
+
this.#glyphProtocolReplyBuffer = "";
|
|
1960
|
+
this.#glyphProtocolCallbacks = [];
|
|
1961
|
+
setTerminalGlyphProtocol(false);
|
|
1813
1962
|
this.#privateCsiResponseBuffer = "";
|
|
1814
1963
|
this.#inBandResizeBuffer = "";
|
|
1815
1964
|
this.#da1SentinelOwners.length = 0;
|