@krtclcdy/tersio 2.25.3 → 2.25.4
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 +2 -2
- package/dist/cli/doctor-fix.js +1 -1
- package/dist/cli/doctor.js +1 -1
- package/dist/cli/install.js +37 -8
- package/dist/cli/manifest.js +1 -0
- package/dist/extensions/ai-addons-updater/index.js +3 -3
- package/dist/extensions/caveman-session/index.js +10 -3
- package/dist/extensions/combo-toggle/index.js +2 -2
- package/dist/extensions/opencode/server.js +45 -1
- package/dist/extensions/rtk-filter/index.js +87 -0
- package/dist/extensions/rtk-session/index.js +3 -2
- package/dist/extensions/shared/host.js +18 -12
- package/dist/extensions/shared/session-state.js +3 -1
- package/extensions/ai-addons-updater/index.ts +2 -3
- package/extensions/caveman-session/index.ts +10 -3
- package/extensions/combo-toggle/index.ts +2 -2
- package/extensions/opencode/server.ts +38 -1
- package/extensions/rtk-filter/index.ts +90 -0
- package/extensions/rtk-session/index.ts +3 -2
- package/extensions/shared/host.ts +26 -13
- package/extensions/shared/session-state.ts +3 -1
- package/extensions/shared/types.ts +10 -2
- package/package.json +2 -1
- package/dist/cli/headroom-install.js +0 -266
- package/dist/cli/headroom.js +0 -492
- package/dist/extensions/headroom-session/index.js +0 -93
- package/dist/extensions/shared/headroom.js +0 -131
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
// Headroom is a local proxy that compresses input-side context. Agent-neutral core: one adapter row per agent, no agent name in the logic below.
|
|
2
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
3
|
-
import { patchPluginSettings, readPluginSettings } from './plugin-settings.js';
|
|
4
|
-
export const HEADROOM_AGENTS = ['omp', 'pi', 'opencode'];
|
|
5
|
-
export const HEADROOM_DEFAULT_PORT = 8787;
|
|
6
|
-
/** Lowest Headroom the spike verified. */
|
|
7
|
-
export const HEADROOM_MIN_VERSION = '0.40.0';
|
|
8
|
-
/** Newest Headroom the spike verified; a newer one only warns. */
|
|
9
|
-
export const HEADROOM_TESTED_VERSION = '0.40.0';
|
|
10
|
-
/** What to say when the binary is absent. Headroom ships with the add-ons, so the fix is a Tersio install, not a hand-run Python tool. */
|
|
11
|
-
export const HEADROOM_INSTALL_HINT = 'run `tersio install` (or `tersio update`) to add the bundled Headroom add-on';
|
|
12
|
-
/** Native or manual, from the spike's `wrap` table. */
|
|
13
|
-
export function headroomCapability(agent) {
|
|
14
|
-
return agent === 'pi' ? 'manual' : 'native';
|
|
15
|
-
}
|
|
16
|
-
export function isHeadroomAgent(value) {
|
|
17
|
-
return typeof value === 'string' && HEADROOM_AGENTS.includes(value);
|
|
18
|
-
}
|
|
19
|
-
/** `headroom 0.40.0` and a bare `0.40.0` both parse. */
|
|
20
|
-
export function parseHeadroomVersion(raw) {
|
|
21
|
-
const match = /\d+\.\d+\.\d+/.exec(String(raw ?? ''));
|
|
22
|
-
return match ? match[0] : null;
|
|
23
|
-
}
|
|
24
|
-
export function compareVersions(a, b) {
|
|
25
|
-
const left = a.split('.').map((part) => Number.parseInt(part, 10) || 0);
|
|
26
|
-
const right = b.split('.').map((part) => Number.parseInt(part, 10) || 0);
|
|
27
|
-
for (let i = 0; i < 3; i += 1) {
|
|
28
|
-
const delta = (left[i] ?? 0) - (right[i] ?? 0);
|
|
29
|
-
if (delta !== 0)
|
|
30
|
-
return delta > 0 ? 1 : -1;
|
|
31
|
-
}
|
|
32
|
-
return 0;
|
|
33
|
-
}
|
|
34
|
-
export function headroomVersionIssue(version) {
|
|
35
|
-
if (!version)
|
|
36
|
-
return 'unknown';
|
|
37
|
-
if (compareVersions(version, HEADROOM_MIN_VERSION) < 0)
|
|
38
|
-
return 'old';
|
|
39
|
-
if (compareVersions(version, HEADROOM_TESTED_VERSION) > 0)
|
|
40
|
-
return 'newer';
|
|
41
|
-
return 'ok';
|
|
42
|
-
}
|
|
43
|
-
function asAgentState(raw) {
|
|
44
|
-
if (!raw || typeof raw !== 'object' || Array.isArray(raw))
|
|
45
|
-
return null;
|
|
46
|
-
const value = raw;
|
|
47
|
-
return { enabled: value.enabled === true, wrappedByTersio: value.wrappedByTersio === true };
|
|
48
|
-
}
|
|
49
|
-
function asAgentMap(raw) {
|
|
50
|
-
if (!raw || typeof raw !== 'object' || Array.isArray(raw))
|
|
51
|
-
return {};
|
|
52
|
-
const out = {};
|
|
53
|
-
for (const [key, value] of Object.entries(raw)) {
|
|
54
|
-
if (!isHeadroomAgent(key))
|
|
55
|
-
continue;
|
|
56
|
-
const state = asAgentState(value);
|
|
57
|
-
if (state)
|
|
58
|
-
out[key] = state;
|
|
59
|
-
}
|
|
60
|
-
return out;
|
|
61
|
-
}
|
|
62
|
-
export function readHeadroomConfig() {
|
|
63
|
-
const settings = readPluginSettings();
|
|
64
|
-
const port = Number(settings.headroomPort);
|
|
65
|
-
return {
|
|
66
|
-
support: settings.headroomSupport === true,
|
|
67
|
-
port: Number.isInteger(port) && port > 0 && port < 65536 ? port : HEADROOM_DEFAULT_PORT,
|
|
68
|
-
agents: asAgentMap(settings.headroom),
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
export function headroomAgentState(config, agent) {
|
|
72
|
-
return config.agents[agent] ?? { enabled: false, wrappedByTersio: false };
|
|
73
|
-
}
|
|
74
|
-
/** The one write path for the kill switch, the port, and the per-agent flags. Keeps unrelated settings keys intact. */
|
|
75
|
-
export function writeHeadroomConfig(config) {
|
|
76
|
-
return patchPluginSettings({ headroomSupport: config.support, headroomPort: config.port, headroom: config.agents });
|
|
77
|
-
}
|
|
78
|
-
export function headroomProxyUrl(port = HEADROOM_DEFAULT_PORT) {
|
|
79
|
-
return `http://127.0.0.1:${port}`;
|
|
80
|
-
}
|
|
81
|
-
/** Fails open: a dead or absent proxy reports false, never an exception. */
|
|
82
|
-
export async function headroomProxyUp(port = HEADROOM_DEFAULT_PORT, timeoutMs = 400) {
|
|
83
|
-
try {
|
|
84
|
-
const res = await fetch(`${headroomProxyUrl(port)}/health`, { signal: AbortSignal.timeout(timeoutMs) });
|
|
85
|
-
return res.ok;
|
|
86
|
-
}
|
|
87
|
-
catch {
|
|
88
|
-
return false;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
export function headroomStatusSegment(state) {
|
|
92
|
-
if (state === null)
|
|
93
|
-
return null;
|
|
94
|
-
if (state === 'on')
|
|
95
|
-
return '🗜️ headroom=ON';
|
|
96
|
-
if (state === 'manual')
|
|
97
|
-
return '🗜️ headroom=ON (manual)';
|
|
98
|
-
if (state === 'down')
|
|
99
|
-
return '🗜️ headroom=DOWN';
|
|
100
|
-
return '🗜️ headroom=OFF';
|
|
101
|
-
}
|
|
102
|
-
// One process paints one status line, so a module mirror is enough. null means "no Headroom in this install".
|
|
103
|
-
let status = null;
|
|
104
|
-
export function getHeadroomStatus() {
|
|
105
|
-
return status;
|
|
106
|
-
}
|
|
107
|
-
export function setHeadroomStatus(next) {
|
|
108
|
-
status = next;
|
|
109
|
-
}
|
|
110
|
-
/** The status for one agent, from its stored flags. `off` when support is off or nothing is wired. */
|
|
111
|
-
export function headroomStatusFor(config, agent, proxyUp) {
|
|
112
|
-
if (!config.support)
|
|
113
|
-
return 'off';
|
|
114
|
-
const state = headroomAgentState(config, agent);
|
|
115
|
-
if (!state.enabled)
|
|
116
|
-
return 'off';
|
|
117
|
-
return proxyUp ? (headroomCapability(agent) === 'manual' ? 'manual' : 'on') : 'down';
|
|
118
|
-
}
|
|
119
|
-
/** True when the agent's config file already carries a Headroom marker. */
|
|
120
|
-
export function headroomWiringPresent(files) {
|
|
121
|
-
for (const file of files) {
|
|
122
|
-
try {
|
|
123
|
-
if (!existsSync(file))
|
|
124
|
-
continue;
|
|
125
|
-
if (/headroom|127\.0\.0\.1:8787/i.test(readFileSync(file, 'utf8')))
|
|
126
|
-
return true;
|
|
127
|
-
}
|
|
128
|
-
catch { /* unreadable counts as unwired */ }
|
|
129
|
-
}
|
|
130
|
-
return false;
|
|
131
|
-
}
|