@krtclcdy/tersio 1.0.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.
@@ -0,0 +1,153 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { fileURLToPath } from "node:url";
3
+ import { dirname, join } from "node:path";
4
+ import { COMBO_LEVELS, getSharedComboState, isOmpSubagentPrompt, setSharedComboMode } from "../shared/session-state.js";
5
+ import { readCavemanDefault } from "../shared/plugin-settings.js";
6
+ const CAVERN_DIR = dirname(fileURLToPath(import.meta.url));
7
+ const RULE_PATH = join(CAVERN_DIR, "rule.md");
8
+ const FALLBACK_FULL_RULE = `Respond terse like smart caveman. All technical substance stay. Only fluff die.
9
+
10
+ Rules:
11
+ - Drop articles (a/an/the), filler (just/really/basically), pleasantries, hedging.
12
+ - Fragments OK. Short synonyms. Technical terms exact. Code unchanged.
13
+ - Pattern: [thing] [action] [reason]. [next step].
14
+ - Not: "Sure! I'd be happy to help you with that."
15
+ - Yes: "Bug in auth middleware. Fix:"
16
+
17
+ Auto-clarity: drop caveman for security warnings, irreversible actions, or when user seems confused. Resume after.`;
18
+ // ponytail: synchronous read each full-mode injection; ceiling = small file, cold session start. Upgrade path: cache file contents + mtime, invalidate on change.
19
+ function readFullRule() {
20
+ try {
21
+ return readFileSync(RULE_PATH, "utf8");
22
+ }
23
+ catch {
24
+ return FALLBACK_FULL_RULE;
25
+ }
26
+ }
27
+ const DEFAULT_MODE = "off";
28
+ const MODES = new Set(["off", "lite", "full", "ultra", "wenyan"]);
29
+ const INSTRUCTIONS = {
30
+ lite: `Caveman lite active for this session.
31
+ Respond concise. Drop pleasantries, filler, and hedging. Keep complete technical substance. Code, commands, paths, errors, commits, and PR text stay normal/exact.`,
32
+ full: () => `Caveman full active for this session.\n${readFullRule()}`,
33
+ ultra: `Caveman ultra active for this session.
34
+ Maximum terse prose. Fragments preferred. No pleasantries, no tour, no recap unless needed. Keep all technical substance exact. Code, commands, commits, PR text, paths, and errors stay normal/exact. Drop caveman for security warnings, irreversible actions, or user confusion.`,
35
+ wenyan: `Caveman wenyan active for this session.
36
+ Use ultra-terse classical-Chinese-style prose only where it preserves clarity for the user. Keep technical terms, code, commands, commits, PR text, paths, and errors exact. If clarity would suffer, use caveman full instead.`,
37
+ };
38
+ function normalizeMode(value) {
39
+ const mode = String(value || "").trim().toLowerCase();
40
+ return MODES.has(mode) ? mode : null;
41
+ }
42
+ function resolveMode(entries, fallback = DEFAULT_MODE) {
43
+ if (!Array.isArray(entries))
44
+ return fallback;
45
+ for (let i = entries.length - 1; i >= 0; i -= 1) {
46
+ const entry = entries[i];
47
+ if (entry?.type !== "custom" || entry?.customType !== "caveman-mode")
48
+ continue;
49
+ const mode = normalizeMode(entry?.data?.mode);
50
+ if (mode)
51
+ return mode;
52
+ }
53
+ return fallback;
54
+ }
55
+ function isOffCommand(text) {
56
+ const t = String(text || "").trim().toLowerCase().replace(/[.!?\s]+$/, "");
57
+ return t === "stop caveman" || t === "normal mode" || t === "caveman off";
58
+ }
59
+ export default function cavemanSessionExtension(pi) {
60
+ let currentMode = DEFAULT_MODE;
61
+ let isActive = false;
62
+ let lastCtx = undefined;
63
+ function syncStatus(ctx) {
64
+ if (ctx)
65
+ lastCtx = ctx;
66
+ const c = ctx || lastCtx;
67
+ if (!c?.ui?.setStatus)
68
+ return;
69
+ // Combo owns the bar when any preset is active; keep ours empty to avoid duplication.
70
+ if (getSharedComboState().level in COMBO_LEVELS && getSharedComboState().level !== "off") {
71
+ c.ui.setStatus("caveman", undefined);
72
+ return;
73
+ }
74
+ if (currentMode === "off") {
75
+ c.ui.setStatus("caveman", undefined);
76
+ return;
77
+ }
78
+ const theme = c.ui.theme;
79
+ const indicator = isActive && theme?.fg ? theme.fg("accent", "🪨") : "🪨";
80
+ const label = `caveman: ${currentMode.toUpperCase()}`;
81
+ c.ui.setStatus("caveman", theme?.fg ? `${indicator} ${theme.fg("muted", label)}` : `${indicator} ${label}`);
82
+ }
83
+ function setMode(mode, ctx) {
84
+ const normalized = normalizeMode(mode);
85
+ if (!normalized)
86
+ return false;
87
+ currentMode = normalized;
88
+ pi.appendEntry?.("caveman-mode", { mode: normalized });
89
+ setSharedComboMode("caveman", normalized);
90
+ syncStatus(ctx);
91
+ ctx?.ui?.notify?.(`Caveman mode ${normalized === "off" ? "off" : `set to ${normalized}`}.`, "info");
92
+ return true;
93
+ }
94
+ pi.setLabel?.("Caveman session toggle");
95
+ pi.registerCommand?.("caveman", {
96
+ description: "Toggle terse caveman replies for this session",
97
+ handler: async (args, ctx) => {
98
+ const arg = String(args || "").trim().toLowerCase();
99
+ if (!arg || arg === "on") {
100
+ setMode("full", ctx);
101
+ return;
102
+ }
103
+ if (arg === "status") {
104
+ ctx?.ui?.notify?.(`Caveman: ${currentMode}`, "info");
105
+ return;
106
+ }
107
+ if (!setMode(arg, ctx)) {
108
+ ctx?.ui?.notify?.("Usage: /caveman [lite|full|ultra|wenyan|off|status]", "warning");
109
+ }
110
+ },
111
+ });
112
+ pi.on("input", async (event) => {
113
+ if (event?.source === "extension")
114
+ return;
115
+ if (currentMode !== "off" && isOffCommand(event?.text))
116
+ setMode("off");
117
+ });
118
+ function restoreMode(ctx) {
119
+ const entries = ctx?.sessionManager?.getBranch?.() || ctx?.sessionManager?.getEntries?.() || [];
120
+ // Persisted session state wins; a fresh session falls back to the
121
+ // installer/user-configured default (off unless configured).
122
+ const persisted = resolveMode(entries, "");
123
+ currentMode = persisted || readCavemanDefault();
124
+ syncStatus(ctx);
125
+ }
126
+ pi.on("session_start", async (_event, ctx) => {
127
+ restoreMode(ctx);
128
+ ctx?.ui?.notify?.(`Caveman loaded: ${currentMode}`, "info");
129
+ });
130
+ pi.on("session_branch", async (_event, ctx) => {
131
+ restoreMode(ctx);
132
+ });
133
+ pi.on("session_tree", async (_event, ctx) => {
134
+ restoreMode(ctx);
135
+ });
136
+ pi.on("agent_start", async (_event, ctx) => {
137
+ isActive = true;
138
+ syncStatus(ctx);
139
+ });
140
+ pi.on("agent_end", async (_event, ctx) => {
141
+ isActive = false;
142
+ syncStatus(ctx);
143
+ });
144
+ pi.on("before_agent_start", async (event) => {
145
+ const mode = isOmpSubagentPrompt(event.systemPrompt) ? getSharedComboState().caveman : currentMode;
146
+ if (!mode || mode === "off")
147
+ return;
148
+ const def = INSTRUCTIONS[mode];
149
+ const instruction = typeof def === "function" ? def() : def;
150
+ const base = Array.isArray(event.systemPrompt) ? event.systemPrompt : [event.systemPrompt];
151
+ return { systemPrompt: [...base, instruction] };
152
+ });
153
+ }
@@ -0,0 +1,157 @@
1
+ // /combo session toggle — set all three (caveman, rtk, ponytail) at once.
2
+ // Modes: off | medium | balanced | max
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { createRequire } from "node:module";
6
+ import { COMBO_LEVELS, getSharedComboState, isOmpSubagentPrompt, normalizeComboLevel, reconcileSharedComboEntries, setSharedComboLevel, setSharedComboListener, } from "../shared/session-state.js";
7
+ import { readComboDefault } from "../shared/plugin-settings.js";
8
+ const require = createRequire(import.meta.url);
9
+ function ponytailFallback(mode) {
10
+ const intensity = mode === "lite"
11
+ ? "Prefer the simplest correct solution."
12
+ : mode === "review"
13
+ ? "Review only for avoidable complexity; recommend the smallest correct replacement."
14
+ : "Use the minimum correct solution. Delete or reuse before adding.";
15
+ return `🦥 PONYTAIL MODE ACTIVE — level: ${mode}\n${intensity} Understand the path first and fix root causes, not symptoms. Prefer the standard library and YAGNI. Avoid speculative abstractions and dependencies. Preserve correctness. Verify changed behavior.`;
16
+ }
17
+ function entriesFrom(ctx) {
18
+ return ctx?.sessionManager?.getBranch?.() || ctx?.sessionManager?.getEntries?.() || [];
19
+ }
20
+ function levelSummary(state) {
21
+ return `caveman=${state.caveman} rtk=${state.rtk} ponytail=${state.ponytail}`;
22
+ }
23
+ function hasPonytailInstructions(systemPrompt) {
24
+ const prompts = Array.isArray(systemPrompt) ? systemPrompt : [systemPrompt];
25
+ return prompts.some((prompt) => typeof prompt === "string" && prompt.includes("PONYTAIL MODE ACTIVE"));
26
+ }
27
+ function loadPonytailInstructions(mode) {
28
+ try {
29
+ const installed = path.join(os.homedir(), ".omp", "plugins", "node_modules", "@dietrichgebert", "ponytail", "hooks", "ponytail-instructions.js");
30
+ const { getPonytailInstructions } = require(installed);
31
+ if (typeof getPonytailInstructions === "function")
32
+ return getPonytailInstructions(mode);
33
+ }
34
+ catch { }
35
+ return ponytailFallback(mode);
36
+ }
37
+ export default function comboToggleExtension(pi) {
38
+ pi.setLabel?.("Combo session toggle (all 3 add-ons)");
39
+ let currentState = getSharedComboState();
40
+ let lastCtx = undefined;
41
+ function syncStatus(ctx) {
42
+ if (ctx)
43
+ lastCtx = ctx;
44
+ const c = ctx || lastCtx;
45
+ if (!c?.ui?.setStatus)
46
+ return;
47
+ // Single unified bar replaces the three per-extension bars while a preset is
48
+ // active. In custom/off, the individual bars come back and combo stays clear.
49
+ if (currentState.level !== "medium" && currentState.level !== "balanced" && currentState.level !== "max") {
50
+ c.ui.setStatus("combo", undefined);
51
+ return;
52
+ }
53
+ const theme = c.ui.theme;
54
+ const c0 = currentState.caveman.toUpperCase();
55
+ const r = currentState.rtk.toUpperCase();
56
+ const p = currentState.ponytail.toUpperCase();
57
+ const lvl = currentState.level.toUpperCase();
58
+ const label = `combo ${lvl}: 🪨caveman=${c0} ⚡rtk=${r} 🦥ponytail=${p}`;
59
+ c.ui.setStatus("combo", theme?.fg ? `${theme.fg("accent", "🧩")} ${theme.fg("muted", label)}` : `🧩 ${label}`);
60
+ // Clobber any sibling bars another extension may have painted in a race
61
+ // during session_start — our bar is canonical for the duration of the preset.
62
+ c.ui.setStatus("caveman", undefined);
63
+ c.ui.setStatus("rtk", undefined);
64
+ c.ui.setStatus("ponytail", undefined);
65
+ }
66
+ function useState(state, ctx) {
67
+ currentState = state;
68
+ syncStatus(ctx);
69
+ return state;
70
+ }
71
+ function reconcile(ctx) {
72
+ if (!ctx?.hasUI)
73
+ return currentState;
74
+ return useState(reconcileSharedComboEntries(entriesFrom(ctx)), ctx);
75
+ }
76
+ function listen(ctx) {
77
+ if (ctx?.hasUI)
78
+ setSharedComboListener((state) => useState(state));
79
+ }
80
+ pi.registerCommand?.("combo", {
81
+ description: "Toggle all 3 OMP add-ons at once. Usage: /combo <off|medium|balanced|max|status>",
82
+ handler: async (args, ctx) => {
83
+ listen(ctx);
84
+ const arg = String(args || "").trim().toLowerCase();
85
+ if (!arg || arg === "status") {
86
+ const state = reconcile(ctx);
87
+ ctx?.ui?.notify?.(`Combo: ${state.level === "custom" ? "INACTIVE" : state.level.toUpperCase()} (${levelSummary(state)})`, "info");
88
+ return;
89
+ }
90
+ if (arg === "help") {
91
+ ctx?.ui?.notify?.("/combo off — disables all 3 (caveman, rtk, ponytail)\n" +
92
+ "/combo medium — light: caveman=lite, rtk=on, ponytail=lite\n" +
93
+ "/combo balanced — middle: caveman=full, rtk=on, ponytail=full\n" +
94
+ "/combo max — aggressive: caveman=ultra, rtk=on, ponytail=ultra", "info");
95
+ return;
96
+ }
97
+ const level = normalizeComboLevel(arg);
98
+ if (!level) {
99
+ ctx?.ui?.notify?.(`Unknown combo level: ${arg}. Use: off | medium | balanced | max`, "warning");
100
+ return;
101
+ }
102
+ const modes = COMBO_LEVELS[level];
103
+ // Persist per-extension state so they restore on session_start
104
+ pi.appendEntry?.("caveman-mode", { mode: modes.caveman });
105
+ pi.appendEntry?.("rtk-mode", { enabled: modes.rtk === "on" });
106
+ pi.appendEntry?.("ponytail-mode", { mode: modes.ponytail });
107
+ pi.appendEntry?.("combo-level", { level });
108
+ useState(setSharedComboLevel(level), ctx);
109
+ ctx?.ui?.notify?.(`Combo ${level} applied: ${levelSummary(currentState)}`, "info");
110
+ if (ctx?.reload)
111
+ await ctx.reload();
112
+ },
113
+ });
114
+ pi.on("session_start", async (_event, ctx) => {
115
+ listen(ctx);
116
+ if (ctx?.hasUI)
117
+ reconcile(ctx);
118
+ else
119
+ syncStatus(ctx);
120
+ // Installer/user-configured default applies only to a fresh session with
121
+ // no persisted state — real session state always wins.
122
+ if (getSharedComboState().level === "off" && !(ctx?.sessionManager?.getBranch?.() || ctx?.sessionManager?.getEntries?.() || []).length) {
123
+ const fallback = readComboDefault();
124
+ if (fallback !== "off") {
125
+ useState(setSharedComboLevel(fallback), ctx);
126
+ ctx?.ui?.notify?.(`Combo default applied: ${fallback}`, "info");
127
+ }
128
+ }
129
+ });
130
+ pi.on("session_branch", async (_event, ctx) => {
131
+ listen(ctx);
132
+ if (ctx?.hasUI)
133
+ reconcile(ctx);
134
+ });
135
+ pi.on("session_tree", async (_event, ctx) => {
136
+ listen(ctx);
137
+ if (ctx?.hasUI)
138
+ reconcile(ctx);
139
+ });
140
+ pi.on("agent_start", async (_event, ctx) => {
141
+ listen(ctx);
142
+ if (ctx?.hasUI)
143
+ reconcile(ctx);
144
+ });
145
+ pi.on("before_agent_start", async (event, ctx) => {
146
+ if (ctx?.hasUI)
147
+ reconcile(ctx);
148
+ if (!isOmpSubagentPrompt(event.systemPrompt))
149
+ return;
150
+ const mode = getSharedComboState().ponytail;
151
+ if (mode === "off" || hasPonytailInstructions(event.systemPrompt))
152
+ return;
153
+ const base = Array.isArray(event.systemPrompt) ? event.systemPrompt : [event.systemPrompt];
154
+ return { systemPrompt: [...base, loadPonytailInstructions(mode)] };
155
+ });
156
+ // Slash commands only; natural-language input caused accidental toggles and has no reload context.
157
+ }
@@ -0,0 +1,101 @@
1
+ // Shared helpers for the installer and the AI add-ons updater.
2
+ // Node built-ins only — this module must stay dependency-free.
3
+ import { createHash } from "node:crypto";
4
+ import { createWriteStream } from "node:fs";
5
+ import fs from "node:fs/promises";
6
+ import https from "node:https";
7
+ import path from "node:path";
8
+ // Promise.withResolvers is Node 22+; the package supports Node 18+.
9
+ // ponytail: swap for the built-in when engines bumps to >=22.
10
+ function withResolvers() {
11
+ let resolve;
12
+ let reject;
13
+ const promise = new Promise((res, rej) => { resolve = res; reject = rej; });
14
+ return { promise, resolve, reject };
15
+ }
16
+ export function httpsGet(url, opts = {}) {
17
+ const { promise, resolve, reject } = withResolvers();
18
+ const maxRedirects = opts.maxRedirects ?? 5;
19
+ const req = https.get(url, { headers: { "User-Agent": "tersio", Accept: "application/json,*/*" } }, (res) => {
20
+ if (res.statusCode !== undefined && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
21
+ if (maxRedirects <= 0) {
22
+ res.resume();
23
+ reject(new Error(`Too many redirects fetching ${url}`));
24
+ return;
25
+ }
26
+ res.resume();
27
+ const next = new URL(res.headers.location, url).href;
28
+ resolve(httpsGet(next, { maxRedirects: maxRedirects - 1 }));
29
+ return;
30
+ }
31
+ if (res.statusCode !== 200) {
32
+ res.resume();
33
+ reject(new Error(`HTTP ${res.statusCode} for ${url}`));
34
+ return;
35
+ }
36
+ let body = "";
37
+ // ponytail: streamed accumulation — fine for tens of KB; stream-pipe if assets ever exceed a few MB.
38
+ res.setEncoding("utf8");
39
+ res.on("data", (chunk) => { body += chunk; });
40
+ res.on("end", () => resolve(body));
41
+ });
42
+ req.on("error", reject);
43
+ req.setTimeout(30000, () => req.destroy(new Error(`Timeout fetching ${url}`)));
44
+ return promise;
45
+ }
46
+ export function httpsDownload(url, dest, opts = {}) {
47
+ const { promise, resolve, reject } = withResolvers();
48
+ const maxRedirects = opts.maxRedirects ?? 5;
49
+ const req = https.get(url, { headers: { "User-Agent": "tersio", Accept: "*/*" } }, (res) => {
50
+ if (res.statusCode !== undefined && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
51
+ if (maxRedirects <= 0) {
52
+ res.resume();
53
+ reject(new Error(`Too many redirects downloading ${url}`));
54
+ return;
55
+ }
56
+ res.resume();
57
+ const next = new URL(res.headers.location, url).href;
58
+ resolve(httpsDownload(next, dest, { maxRedirects: maxRedirects - 1 }));
59
+ return;
60
+ }
61
+ if (res.statusCode !== 200) {
62
+ res.resume();
63
+ reject(new Error(`HTTP ${res.statusCode} for ${url}`));
64
+ return;
65
+ }
66
+ const file = createWriteStream(dest);
67
+ res.pipe(file);
68
+ file.on("finish", () => file.close(() => resolve()));
69
+ file.on("error", reject);
70
+ });
71
+ req.on("error", reject);
72
+ req.setTimeout(120000, () => req.destroy(new Error(`Timeout downloading ${url}`)));
73
+ return promise;
74
+ }
75
+ export function sha256Hex(text) {
76
+ return createHash("sha256").update(text, "utf8").digest("hex");
77
+ }
78
+ export async function sha256File(filePath) {
79
+ const buf = await fs.readFile(filePath);
80
+ return createHash("sha256").update(buf).digest("hex");
81
+ }
82
+ export function parseChecksum(checksumsText, assetName) {
83
+ const target = path.basename(assetName);
84
+ for (const line of checksumsText.split(/\r?\n/)) {
85
+ const m = line.match(/^([0-9a-fA-F]{64})\s+\*?(.+)$/);
86
+ if (m && path.basename(m[2]) === target)
87
+ return m[1].toLowerCase();
88
+ }
89
+ return null;
90
+ }
91
+ export async function readTextIfExists(p) {
92
+ try {
93
+ return await fs.readFile(p, "utf8");
94
+ }
95
+ catch {
96
+ return null;
97
+ }
98
+ }
99
+ export function normalizeRtkVersion(value) {
100
+ return String(value || "").replace(/^rtk\s+/i, "").replace(/^v/i, "").trim();
101
+ }
@@ -0,0 +1,151 @@
1
+ import os from "node:os";
2
+ import path from "node:path";
3
+ import { COMBO_LEVELS, getSharedComboState, isOmpSubagentPrompt, setSharedComboMode } from "../shared/session-state.js";
4
+ import { readRtkDefault } from "../shared/plugin-settings.js";
5
+ const DEFAULT_ENABLED = false;
6
+ function asBoolean(value) {
7
+ if (typeof value === "boolean")
8
+ return value;
9
+ if (value === "on" || value === "true")
10
+ return true;
11
+ if (value === "off" || value === "false")
12
+ return false;
13
+ return null;
14
+ }
15
+ function resolveEnabled(entries) {
16
+ if (!Array.isArray(entries))
17
+ return null;
18
+ for (let i = entries.length - 1; i >= 0; i -= 1) {
19
+ const entry = entries[i];
20
+ if (entry?.type !== "custom" || entry?.customType !== "rtk-mode")
21
+ continue;
22
+ return asBoolean(entry?.data?.enabled);
23
+ }
24
+ return null;
25
+ }
26
+ const IS_WINDOWS = process.platform === "win32";
27
+ const HOME = os.homedir();
28
+ const RTK_BINARY = path.join(HOME, ".bun", "bin", IS_WINDOWS ? "rtk.exe" : "rtk");
29
+ const RTK_PROMPT = `RTK mode active for this session.
30
+ Use Rust Token Killer for shell output that would otherwise be noisy. Prefer explicit RTK commands in bash: \`rtk git status\`, \`rtk git diff\`, \`rtk read <file>\`, \`rtk grep <pattern> <path>\`, \`rtk find <glob> <path>\`, \`rtk test <cmd...>\`, \`rtk tsc\`, \`rtk lint\`, or \`rtk <tool> ...\` for supported dev commands.
31
+ Do not use RTK when exact raw output is required, when a specialized OMP tool is required by system policy, or when the command changes state and RTK would hide important confirmation text. Specialized OMP tools still win: read/glob/grep/edit/lsp stay preferred over shell equivalents.`;
32
+ export default function rtkSessionExtension(pi) {
33
+ const { z } = pi.zod;
34
+ let enabled = DEFAULT_ENABLED;
35
+ let isActive = false;
36
+ let lastCtx = undefined;
37
+ function syncStatus(ctx) {
38
+ if (ctx)
39
+ lastCtx = ctx;
40
+ const c = ctx || lastCtx;
41
+ if (!c?.ui?.setStatus)
42
+ return;
43
+ // Combo owns the bar when any preset is active; keep ours empty to avoid duplication.
44
+ if (getSharedComboState().level in COMBO_LEVELS && getSharedComboState().level !== "off") {
45
+ c.ui.setStatus("rtk", undefined);
46
+ return;
47
+ }
48
+ if (!enabled) {
49
+ c.ui.setStatus("rtk", undefined);
50
+ return;
51
+ }
52
+ const theme = c.ui.theme;
53
+ const indicator = isActive && theme?.fg ? theme.fg("accent", "âš¡") : "âš¡";
54
+ const label = "rtk: ON";
55
+ c.ui.setStatus("rtk", theme?.fg ? `${indicator} ${theme.fg("muted", label)}` : `${indicator} ${label}`);
56
+ }
57
+ function setEnabled(next, ctx) {
58
+ enabled = Boolean(next);
59
+ pi.appendEntry?.("rtk-mode", { enabled });
60
+ setSharedComboMode("rtk", enabled);
61
+ syncStatus(ctx);
62
+ ctx?.ui?.notify?.(`RTK mode ${enabled ? "on" : "off"}.`, "info");
63
+ }
64
+ pi.setLabel?.("RTK session toggle");
65
+ pi.registerCommand?.("rtk", {
66
+ description: "Toggle RTK compact shell-output guidance for this session",
67
+ handler: async (args, ctx) => {
68
+ const arg = String(args || "").trim().toLowerCase();
69
+ if (!arg || arg === "status") {
70
+ ctx?.ui?.notify?.(`RTK: ${enabled ? "on" : "off"}`, "info");
71
+ return;
72
+ }
73
+ if (["on", "enable", "enabled", "true"].includes(arg)) {
74
+ setEnabled(true, ctx);
75
+ return;
76
+ }
77
+ if (["off", "disable", "disabled", "false"].includes(arg)) {
78
+ setEnabled(false, ctx);
79
+ return;
80
+ }
81
+ ctx?.ui?.notify?.("Usage: /rtk [on|off|status]", "warning");
82
+ },
83
+ });
84
+ pi.registerTool?.({
85
+ name: "rtk_run",
86
+ label: "RTK Run",
87
+ description: "Run the installed `rtk` binary for compact command output when RTK mode is enabled.",
88
+ parameters: z.object({
89
+ args: z.array(z.string()).min(1).describe("Arguments passed to rtk, e.g. ['git','status'] or ['read','src/index.ts']"),
90
+ }),
91
+ async execute(_toolCallId, params, signal, onUpdate, ctx) {
92
+ if (!enabled) {
93
+ return {
94
+ isError: true,
95
+ content: [{ type: "text", text: "RTK mode is off. Run /rtk on for this session, or use bash explicitly." }],
96
+ details: { enabled },
97
+ };
98
+ }
99
+ onUpdate?.({ content: [{ type: "text", text: `rtk ${params.args.join(" ")}` }], details: { phase: "start" } });
100
+ const result = await pi.exec(RTK_BINARY, params.args, { signal, cwd: ctx?.cwd || pi.cwd });
101
+ const text = [result.stdout, result.stderr].filter(Boolean).join(result.stdout && result.stderr ? "\n" : "");
102
+ return {
103
+ isError: result.code !== 0,
104
+ content: [{ type: "text", text: text || `rtk exited ${result.code}` }],
105
+ details: { code: result.code, killed: result.killed, enabled },
106
+ };
107
+ },
108
+ });
109
+ pi.on("input", async (event) => {
110
+ if (event?.source === "extension")
111
+ return;
112
+ const t = String(event?.text || "").trim().toLowerCase().replace(/[.!?\s]+$/, "");
113
+ if (t === "rtk on" || t === "use rtk")
114
+ setEnabled(true);
115
+ if (t === "rtk off" || t === "stop rtk")
116
+ setEnabled(false);
117
+ });
118
+ function restoreEnabled(ctx) {
119
+ const entries = ctx?.sessionManager?.getBranch?.() || ctx?.sessionManager?.getEntries?.() || [];
120
+ // Persisted session state wins; a fresh session falls back to the
121
+ // installer/user-configured default (off unless configured).
122
+ const persisted = resolveEnabled(entries);
123
+ enabled = typeof persisted === "boolean" ? persisted : readRtkDefault();
124
+ syncStatus(ctx);
125
+ }
126
+ pi.on("session_start", async (_event, ctx) => {
127
+ restoreEnabled(ctx);
128
+ ctx?.ui?.notify?.(`RTK loaded: ${enabled ? "on" : "off"}`, "info");
129
+ });
130
+ pi.on("session_branch", async (_event, ctx) => {
131
+ restoreEnabled(ctx);
132
+ });
133
+ pi.on("session_tree", async (_event, ctx) => {
134
+ restoreEnabled(ctx);
135
+ });
136
+ pi.on("agent_start", async (_event, ctx) => {
137
+ isActive = true;
138
+ syncStatus(ctx);
139
+ });
140
+ pi.on("agent_end", async (_event, ctx) => {
141
+ isActive = false;
142
+ syncStatus(ctx);
143
+ });
144
+ pi.on("before_agent_start", async (event) => {
145
+ const active = isOmpSubagentPrompt(event.systemPrompt) ? getSharedComboState().rtk === "on" : enabled;
146
+ if (!active)
147
+ return;
148
+ const base = Array.isArray(event.systemPrompt) ? event.systemPrompt : [event.systemPrompt];
149
+ return { systemPrompt: [...base, RTK_PROMPT] };
150
+ });
151
+ }
@@ -0,0 +1,72 @@
1
+ // Headroom proxy presence for the combo status bar.
2
+ // Wrap-marker read is sync so paint stays cheap; proxy /health is probed async,
3
+ // cached per port, and callers repaint when the probe settles.
4
+ import { readFileSync } from "node:fs";
5
+ import https from "node:https";
6
+ import os from "node:os";
7
+ import path from "node:path";
8
+ export const HEADROOM_MARKER = "# managed by `headroom wrap omp`";
9
+ const PROBE_TTL_MS = 60_000;
10
+ function modelsPath() {
11
+ const base = process.env.PI_CODING_AGENT_DIR?.trim();
12
+ if (base)
13
+ return path.join(path.resolve(base), "models.yml");
14
+ return path.join(os.homedir(), ".omp", "agent", "models.yml");
15
+ }
16
+ export function readHeadroomWrap() {
17
+ let raw;
18
+ try {
19
+ raw = readFileSync(modelsPath(), "utf8");
20
+ }
21
+ catch {
22
+ return { wrapped: false, port: null };
23
+ }
24
+ if (!raw.includes(HEADROOM_MARKER))
25
+ return { wrapped: false, port: null };
26
+ const match = raw.match(/baseUrl:\s*https?:\/\/127\.0\.0\.1:(\d+)/);
27
+ return { wrapped: true, port: match ? Number(match[1]) : null };
28
+ }
29
+ function probeProxy(port) {
30
+ return new Promise((resolve) => {
31
+ const req = https.get({ host: "127.0.0.1", port, path: "/health", timeout: 2000 }, (res) => {
32
+ res.resume();
33
+ resolve(res.statusCode !== undefined && res.statusCode < 500);
34
+ });
35
+ req.on("timeout", () => { req.destroy(); resolve(false); });
36
+ req.on("error", () => resolve(false));
37
+ });
38
+ }
39
+ let lastPort;
40
+ let lastHealthy = true;
41
+ let lastProbeAt = 0;
42
+ let inflight = null;
43
+ export function refreshHeadroomStatus() {
44
+ if (inflight)
45
+ return inflight;
46
+ inflight = (async () => {
47
+ const { wrapped, port } = readHeadroomWrap();
48
+ if (!wrapped || port === null) {
49
+ lastPort = port;
50
+ lastHealthy = true;
51
+ lastProbeAt = Date.now();
52
+ return;
53
+ }
54
+ lastHealthy = await probeProxy(port);
55
+ lastPort = port;
56
+ lastProbeAt = Date.now();
57
+ })();
58
+ inflight.then(() => { inflight = null; }, () => { inflight = null; });
59
+ return inflight;
60
+ }
61
+ export function getHeadroomStatus() {
62
+ const { wrapped, port } = readHeadroomWrap();
63
+ if (!wrapped)
64
+ return "off";
65
+ if (port !== null && port === lastPort && Date.now() - lastProbeAt < PROBE_TTL_MS) {
66
+ return lastHealthy ? "on" : "stale";
67
+ }
68
+ // No fresh probe for this port: kick one off and assume on until a probe
69
+ // says otherwise, so first paint never blocks on the network.
70
+ void refreshHeadroomStatus();
71
+ return port !== null && port === lastPort && !lastHealthy ? "stale" : "on";
72
+ }
@@ -0,0 +1,29 @@
1
+ import { reconcileSharedComboEntries } from "./session-state.js";
2
+ const MARKER = "SUPREME TOKEN SAVER MODES ACTIVE";
3
+ function entriesFrom(ctx) {
4
+ return ctx?.sessionManager?.getBranch?.() || ctx?.sessionManager?.getEntries?.() || [];
5
+ }
6
+ function instruction(state) {
7
+ const modes = [
8
+ state.caveman !== "off" && `caveman=${state.caveman}`,
9
+ state.rtk === "on" && "rtk=on",
10
+ state.ponytail !== "off" && `ponytail=${state.ponytail}`,
11
+ ].filter(Boolean);
12
+ if (!modes.length)
13
+ return null;
14
+ return `${MARKER}: ${modes.join(" · ")}. Keep these active for the entire response: concise Caveman prose, RTK for eligible noisy shell output, and the smallest correct Ponytail solution. Do not weaken or disable a mode unless the user explicitly asks.`;
15
+ }
16
+ export default function modeReinforcementExtension(pi) {
17
+ pi.setLabel?.("Tersio mode reinforcement");
18
+ pi.on("before_agent_start", async (event, ctx) => {
19
+ if (!ctx?.hasUI)
20
+ return;
21
+ const text = instruction(reconcileSharedComboEntries(entriesFrom(ctx)));
22
+ if (!text)
23
+ return;
24
+ const base = Array.isArray(event.systemPrompt) ? event.systemPrompt : [event.systemPrompt];
25
+ if (base.some((prompt) => typeof prompt === "string" && prompt.includes(MARKER)))
26
+ return;
27
+ return { systemPrompt: [...base, text] };
28
+ });
29
+ }