@krtclcdy/tersio 1.0.4 → 2.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.
- package/README.md +22 -9
- package/extensions/ai-addons-updater/index.js +166 -238
- package/extensions/caveman-session/index.js +48 -67
- package/extensions/combo-toggle/index.js +55 -69
- package/extensions/lib/utils.js +77 -24
- package/extensions/rtk-session/index.js +48 -63
- package/extensions/shared/mode-reinforcement.js +11 -14
- package/extensions/shared/plugin-settings.js +18 -16
- package/extensions/shared/session-state.js +77 -45
- package/package.json +6 -15
- package/tersio.js +673 -750
- package/extensions/amanai-reward/index.js +0 -24
- package/extensions/amanai-reward/pi.js +0 -32
|
@@ -1,31 +1,23 @@
|
|
|
1
|
-
import os from
|
|
2
|
-
import path from
|
|
3
|
-
import {
|
|
4
|
-
import { readRtkDefault } from
|
|
1
|
+
import os from 'node:os';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { asPromptArray, getSharedComboState, isComboPresetActive, isOmpSubagentPrompt, lastCustomValue, normalizeInputCommand, paintStatusBar, sessionEntries, setSharedComboMode } from '../shared/session-state.js';
|
|
4
|
+
import { readRtkDefault } from '../shared/plugin-settings.js';
|
|
5
5
|
const DEFAULT_ENABLED = false;
|
|
6
6
|
function asBoolean(value) {
|
|
7
|
-
if (typeof value ===
|
|
7
|
+
if (typeof value === 'boolean')
|
|
8
8
|
return value;
|
|
9
|
-
if (value ===
|
|
9
|
+
if (value === 'on' || value === 'true')
|
|
10
10
|
return true;
|
|
11
|
-
if (value ===
|
|
11
|
+
if (value === 'off' || value === 'false')
|
|
12
12
|
return false;
|
|
13
13
|
return null;
|
|
14
14
|
}
|
|
15
15
|
function resolveEnabled(entries) {
|
|
16
|
-
|
|
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;
|
|
16
|
+
return lastCustomValue(entries, 'rtk-mode', (data) => asBoolean(data?.enabled));
|
|
25
17
|
}
|
|
26
|
-
const IS_WINDOWS = process.platform ===
|
|
18
|
+
const IS_WINDOWS = process.platform === 'win32';
|
|
27
19
|
const HOME = os.homedir();
|
|
28
|
-
const RTK_BINARY = path.join(HOME,
|
|
20
|
+
const RTK_BINARY = path.join(HOME, '.bun', 'bin', IS_WINDOWS ? 'rtk.exe' : 'rtk');
|
|
29
21
|
const RTK_PROMPT = `RTK mode active for this session.
|
|
30
22
|
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
23
|
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.`;
|
|
@@ -41,50 +33,43 @@ export default function rtkSessionExtension(pi) {
|
|
|
41
33
|
if (!c?.ui?.setStatus)
|
|
42
34
|
return;
|
|
43
35
|
// Combo owns the bar when any preset is active; keep ours empty to avoid duplication.
|
|
44
|
-
if (
|
|
45
|
-
c.ui.setStatus(
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
if (!enabled) {
|
|
49
|
-
c.ui.setStatus("rtk", undefined);
|
|
36
|
+
if (isComboPresetActive() || !enabled) {
|
|
37
|
+
c.ui.setStatus('rtk', undefined);
|
|
50
38
|
return;
|
|
51
39
|
}
|
|
52
|
-
|
|
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}`);
|
|
40
|
+
paintStatusBar(c.ui, 'rtk', '⚡', 'rtk: ON', isActive);
|
|
56
41
|
}
|
|
57
42
|
function setEnabled(next, ctx) {
|
|
58
43
|
enabled = Boolean(next);
|
|
59
|
-
pi.appendEntry?.(
|
|
60
|
-
setSharedComboMode(
|
|
44
|
+
pi.appendEntry?.('rtk-mode', { enabled });
|
|
45
|
+
setSharedComboMode('rtk', enabled);
|
|
61
46
|
syncStatus(ctx);
|
|
62
|
-
ctx?.ui?.notify?.(`RTK mode ${enabled ?
|
|
47
|
+
ctx?.ui?.notify?.(`RTK mode ${enabled ? 'on' : 'off'}.`, 'info');
|
|
63
48
|
}
|
|
64
|
-
pi.setLabel?.(
|
|
65
|
-
pi.registerCommand?.(
|
|
66
|
-
description:
|
|
49
|
+
pi.setLabel?.('RTK session toggle');
|
|
50
|
+
pi.registerCommand?.('rtk', {
|
|
51
|
+
description: 'Toggle RTK compact shell-output guidance for this session',
|
|
67
52
|
handler: async (args, ctx) => {
|
|
68
|
-
const arg = String(args ||
|
|
69
|
-
if (!arg || arg ===
|
|
70
|
-
ctx?.ui?.notify?.(`RTK: ${enabled ?
|
|
53
|
+
const arg = String(args || '').trim().toLowerCase();
|
|
54
|
+
if (!arg || arg === 'status') {
|
|
55
|
+
ctx?.ui?.notify?.(`RTK: ${enabled ? 'on' : 'off'}`, 'info');
|
|
71
56
|
return;
|
|
72
57
|
}
|
|
73
|
-
if ([
|
|
58
|
+
if (['on', 'enable', 'enabled', 'true'].includes(arg)) {
|
|
74
59
|
setEnabled(true, ctx);
|
|
75
60
|
return;
|
|
76
61
|
}
|
|
77
|
-
if ([
|
|
62
|
+
if (['off', 'disable', 'disabled', 'false'].includes(arg)) {
|
|
78
63
|
setEnabled(false, ctx);
|
|
79
64
|
return;
|
|
80
65
|
}
|
|
81
|
-
ctx?.ui?.notify?.(
|
|
66
|
+
ctx?.ui?.notify?.('Usage: /rtk [on|off|status]', 'warning');
|
|
82
67
|
},
|
|
83
68
|
});
|
|
84
69
|
pi.registerTool?.({
|
|
85
|
-
name:
|
|
86
|
-
label:
|
|
87
|
-
description:
|
|
70
|
+
name: 'rtk_run',
|
|
71
|
+
label: 'RTK Run',
|
|
72
|
+
description: 'Run the installed `rtk` binary for compact command output when RTK mode is enabled.',
|
|
88
73
|
parameters: z.object({
|
|
89
74
|
args: z.array(z.string()).min(1).describe("Arguments passed to rtk, e.g. ['git','status'] or ['read','src/index.ts']"),
|
|
90
75
|
}),
|
|
@@ -92,60 +77,60 @@ export default function rtkSessionExtension(pi) {
|
|
|
92
77
|
if (!enabled) {
|
|
93
78
|
return {
|
|
94
79
|
isError: true,
|
|
95
|
-
content: [{ type:
|
|
80
|
+
content: [{ type: 'text', text: 'RTK mode is off. Run /rtk on for this session, or use bash explicitly.' }],
|
|
96
81
|
details: { enabled },
|
|
97
82
|
};
|
|
98
83
|
}
|
|
99
|
-
onUpdate?.({ content: [{ type:
|
|
84
|
+
onUpdate?.({ content: [{ type: 'text', text: `rtk ${params.args.join(' ')}` }], details: { phase: 'start' } });
|
|
100
85
|
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(
|
|
86
|
+
const text = [result.stdout, result.stderr].filter(Boolean).join('\n');
|
|
102
87
|
return {
|
|
103
88
|
isError: result.code !== 0,
|
|
104
|
-
content: [{ type:
|
|
89
|
+
content: [{ type: 'text', text: text || `rtk exited ${result.code}` }],
|
|
105
90
|
details: { code: result.code, killed: result.killed, enabled },
|
|
106
91
|
};
|
|
107
92
|
},
|
|
108
93
|
});
|
|
109
|
-
pi.on(
|
|
110
|
-
if (event?.source ===
|
|
94
|
+
pi.on('input', async (event) => {
|
|
95
|
+
if (event?.source === 'extension')
|
|
111
96
|
return;
|
|
112
|
-
const t =
|
|
113
|
-
if (t ===
|
|
97
|
+
const t = normalizeInputCommand(event?.text);
|
|
98
|
+
if (t === 'rtk on' || t === 'use rtk')
|
|
114
99
|
setEnabled(true);
|
|
115
|
-
if (t ===
|
|
100
|
+
if (t === 'rtk off' || t === 'stop rtk')
|
|
116
101
|
setEnabled(false);
|
|
117
102
|
});
|
|
118
103
|
function restoreEnabled(ctx) {
|
|
119
|
-
const entries =
|
|
104
|
+
const entries = sessionEntries(ctx);
|
|
120
105
|
// Persisted session state wins; a fresh session falls back to the
|
|
121
106
|
// installer/user-configured default (off unless configured).
|
|
122
107
|
const persisted = resolveEnabled(entries);
|
|
123
|
-
enabled = typeof persisted ===
|
|
108
|
+
enabled = typeof persisted === 'boolean' ? persisted : readRtkDefault();
|
|
124
109
|
syncStatus(ctx);
|
|
125
110
|
}
|
|
126
|
-
pi.on(
|
|
111
|
+
pi.on('session_start', async (_event, ctx) => {
|
|
127
112
|
restoreEnabled(ctx);
|
|
128
|
-
ctx?.ui?.notify?.(`RTK loaded: ${enabled ?
|
|
113
|
+
ctx?.ui?.notify?.(`RTK loaded: ${enabled ? 'on' : 'off'}`, 'info');
|
|
129
114
|
});
|
|
130
|
-
pi.on(
|
|
115
|
+
pi.on('session_branch', async (_event, ctx) => {
|
|
131
116
|
restoreEnabled(ctx);
|
|
132
117
|
});
|
|
133
|
-
pi.on(
|
|
118
|
+
pi.on('session_tree', async (_event, ctx) => {
|
|
134
119
|
restoreEnabled(ctx);
|
|
135
120
|
});
|
|
136
|
-
pi.on(
|
|
121
|
+
pi.on('agent_start', async (_event, ctx) => {
|
|
137
122
|
isActive = true;
|
|
138
123
|
syncStatus(ctx);
|
|
139
124
|
});
|
|
140
|
-
pi.on(
|
|
125
|
+
pi.on('agent_end', async (_event, ctx) => {
|
|
141
126
|
isActive = false;
|
|
142
127
|
syncStatus(ctx);
|
|
143
128
|
});
|
|
144
|
-
pi.on(
|
|
145
|
-
const active = isOmpSubagentPrompt(event.systemPrompt) ? getSharedComboState().rtk ===
|
|
129
|
+
pi.on('before_agent_start', async (event) => {
|
|
130
|
+
const active = isOmpSubagentPrompt(event.systemPrompt) ? getSharedComboState().rtk === 'on' : enabled;
|
|
146
131
|
if (!active)
|
|
147
132
|
return;
|
|
148
|
-
const base =
|
|
133
|
+
const base = asPromptArray(event.systemPrompt);
|
|
149
134
|
return { systemPrompt: [...base, RTK_PROMPT] };
|
|
150
135
|
});
|
|
151
136
|
}
|
|
@@ -1,28 +1,25 @@
|
|
|
1
|
-
import { reconcileSharedComboEntries } from
|
|
2
|
-
const MARKER =
|
|
3
|
-
function entriesFrom(ctx) {
|
|
4
|
-
return ctx?.sessionManager?.getBranch?.() || ctx?.sessionManager?.getEntries?.() || [];
|
|
5
|
-
}
|
|
1
|
+
import { asPromptArray, reconcileSharedComboEntries, sessionEntries, systemPromptIncludes } from './session-state.js';
|
|
2
|
+
const MARKER = 'SUPREME TOKEN SAVER MODES ACTIVE';
|
|
6
3
|
function instruction(state) {
|
|
7
4
|
const modes = [
|
|
8
|
-
state.caveman !==
|
|
9
|
-
state.rtk ===
|
|
10
|
-
state.ponytail !==
|
|
5
|
+
state.caveman !== 'off' && `caveman=${state.caveman}`,
|
|
6
|
+
state.rtk === 'on' && 'rtk=on',
|
|
7
|
+
state.ponytail !== 'off' && `ponytail=${state.ponytail}`,
|
|
11
8
|
].filter(Boolean);
|
|
12
9
|
if (!modes.length)
|
|
13
10
|
return null;
|
|
14
|
-
return `${MARKER}: ${modes.join(
|
|
11
|
+
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
12
|
}
|
|
16
13
|
export default function modeReinforcementExtension(pi) {
|
|
17
|
-
pi.setLabel?.(
|
|
18
|
-
pi.on(
|
|
14
|
+
pi.setLabel?.('Tersio mode reinforcement');
|
|
15
|
+
pi.on('before_agent_start', async (event, ctx) => {
|
|
19
16
|
if (!ctx?.hasUI)
|
|
20
17
|
return;
|
|
21
|
-
const text = instruction(reconcileSharedComboEntries(
|
|
18
|
+
const text = instruction(reconcileSharedComboEntries(sessionEntries(ctx)));
|
|
22
19
|
if (!text)
|
|
23
20
|
return;
|
|
24
|
-
const base =
|
|
25
|
-
if (base
|
|
21
|
+
const base = asPromptArray(event.systemPrompt);
|
|
22
|
+
if (systemPromptIncludes(base, MARKER))
|
|
26
23
|
return;
|
|
27
24
|
return { systemPrompt: [...base, text] };
|
|
28
25
|
});
|
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
// written by `omp plugin config set @krtclcdy/tersio <key> <value>` and by
|
|
4
4
|
// the installer profile step. Tolerant: any parse failure yields {} so every
|
|
5
5
|
// caller falls back to its own default.
|
|
6
|
-
import { existsSync, readFileSync } from
|
|
7
|
-
import os from
|
|
8
|
-
import path from
|
|
9
|
-
export const PLUGIN_NAME =
|
|
6
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
7
|
+
import os from 'node:os';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
export const PLUGIN_NAME = '@krtclcdy/tersio';
|
|
10
10
|
function lockPaths() {
|
|
11
|
-
const configHome = process.env.XDG_CONFIG_HOME || path.join(os.homedir(),
|
|
11
|
+
const configHome = process.env.XDG_CONFIG_HOME || path.join(os.homedir(), '.config');
|
|
12
12
|
return [
|
|
13
|
-
path.join(os.homedir(),
|
|
14
|
-
path.join(configHome,
|
|
13
|
+
path.join(os.homedir(), '.omp', 'plugins', 'omp-plugins.lock.json'),
|
|
14
|
+
path.join(configHome, 'omp', 'plugins', 'omp-plugins.lock.json'),
|
|
15
15
|
];
|
|
16
16
|
}
|
|
17
17
|
// `settings[PLUGIN_NAME]` in the lock file; empty object when missing.
|
|
@@ -20,26 +20,28 @@ export function readPluginSettings() {
|
|
|
20
20
|
if (!existsSync(p))
|
|
21
21
|
continue;
|
|
22
22
|
try {
|
|
23
|
-
const config = JSON.parse(readFileSync(p,
|
|
23
|
+
const config = JSON.parse(readFileSync(p, 'utf8'));
|
|
24
24
|
const values = config.settings?.[PLUGIN_NAME];
|
|
25
|
-
if (values && typeof values ===
|
|
25
|
+
if (values && typeof values === 'object' && !Array.isArray(values))
|
|
26
26
|
return values;
|
|
27
27
|
}
|
|
28
28
|
catch { /* tolerate corrupt file */ }
|
|
29
29
|
}
|
|
30
30
|
return {};
|
|
31
31
|
}
|
|
32
|
-
const COMBO_LEVELS = new Set([
|
|
32
|
+
const COMBO_LEVELS = new Set(['off', 'medium', 'balanced', 'max']);
|
|
33
|
+
const CAVEMAN_MODES = new Set(['off', 'lite', 'full', 'ultra', 'wenyan']);
|
|
34
|
+
function readStringDefault(key, valid) {
|
|
35
|
+
const raw = readPluginSettings()[key];
|
|
36
|
+
return typeof raw === 'string' && valid.has(raw) ? raw : 'off';
|
|
37
|
+
}
|
|
33
38
|
export function readComboDefault() {
|
|
34
|
-
|
|
35
|
-
return typeof raw === "string" && COMBO_LEVELS.has(raw) ? raw : "off";
|
|
39
|
+
return readStringDefault('comboDefault', COMBO_LEVELS);
|
|
36
40
|
}
|
|
37
|
-
const CAVEMAN_MODES = new Set(["off", "lite", "full", "ultra", "wenyan"]);
|
|
38
41
|
export function readCavemanDefault() {
|
|
39
|
-
|
|
40
|
-
return typeof raw === "string" && CAVEMAN_MODES.has(raw) ? raw : "off";
|
|
42
|
+
return readStringDefault('cavemanDefault', CAVEMAN_MODES);
|
|
41
43
|
}
|
|
42
44
|
export function readRtkDefault() {
|
|
43
45
|
const raw = readPluginSettings().rtkDefault;
|
|
44
|
-
return typeof raw ===
|
|
46
|
+
return typeof raw === 'boolean' ? raw : false;
|
|
45
47
|
}
|
|
@@ -1,41 +1,49 @@
|
|
|
1
|
-
const BRIDGE_KEY = Symbol.for(
|
|
2
|
-
export const OMP_SUBAGENT_MARKER =
|
|
1
|
+
const BRIDGE_KEY = Symbol.for('tersio/combo-session-state');
|
|
2
|
+
export const OMP_SUBAGENT_MARKER = 'You are operating on a piece of work assigned to you by the main agent.';
|
|
3
3
|
export const COMBO_LEVELS = Object.freeze({
|
|
4
|
-
off: Object.freeze({ level:
|
|
5
|
-
medium: Object.freeze({ level:
|
|
6
|
-
balanced: Object.freeze({ level:
|
|
7
|
-
max: Object.freeze({ level:
|
|
4
|
+
off: Object.freeze({ level: 'off', caveman: 'off', rtk: 'off', ponytail: 'off' }),
|
|
5
|
+
medium: Object.freeze({ level: 'medium', caveman: 'lite', rtk: 'on', ponytail: 'lite' }),
|
|
6
|
+
balanced: Object.freeze({ level: 'balanced', caveman: 'full', rtk: 'on', ponytail: 'full' }),
|
|
7
|
+
max: Object.freeze({ level: 'max', caveman: 'ultra', rtk: 'on', ponytail: 'ultra' }),
|
|
8
8
|
});
|
|
9
9
|
const MODE_VALUES = {
|
|
10
|
-
caveman: new Set([
|
|
11
|
-
rtk: new Set([
|
|
12
|
-
ponytail: new Set([
|
|
10
|
+
caveman: new Set(['off', 'lite', 'full', 'ultra', 'wenyan']),
|
|
11
|
+
rtk: new Set(['off', 'on']),
|
|
12
|
+
ponytail: new Set(['off', 'lite', 'full', 'ultra', 'review']),
|
|
13
13
|
};
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
const MODE_ENTRY_TYPES = {
|
|
15
|
+
'caveman-mode': 'caveman',
|
|
16
|
+
'rtk-mode': 'rtk',
|
|
17
|
+
'ponytail-mode': 'ponytail',
|
|
18
|
+
};
|
|
19
|
+
export function normalizeMode(name, value) {
|
|
20
|
+
if (name === 'rtk' && typeof value === 'boolean')
|
|
21
|
+
return value ? 'on' : 'off';
|
|
22
|
+
const mode = String(value ?? '').trim().toLowerCase();
|
|
18
23
|
return MODE_VALUES[name]?.has(mode) ? mode : null;
|
|
19
24
|
}
|
|
20
|
-
function deriveLevel(modes) {
|
|
21
|
-
for (const level of
|
|
25
|
+
export function deriveLevel(modes) {
|
|
26
|
+
for (const level of Object.keys(COMBO_LEVELS)) {
|
|
22
27
|
const preset = COMBO_LEVELS[level];
|
|
23
|
-
if (preset.caveman === modes
|
|
28
|
+
if (preset.caveman === modes?.caveman && preset.rtk === modes?.rtk && preset.ponytail === modes?.ponytail)
|
|
24
29
|
return level;
|
|
25
30
|
}
|
|
26
|
-
return
|
|
31
|
+
return 'custom';
|
|
32
|
+
}
|
|
33
|
+
function isPresetLevel(value) {
|
|
34
|
+
return Object.prototype.hasOwnProperty.call(COMBO_LEVELS, value);
|
|
27
35
|
}
|
|
28
36
|
function isKnownLevel(value) {
|
|
29
|
-
return value ===
|
|
37
|
+
return value === 'custom' || isPresetLevel(value);
|
|
30
38
|
}
|
|
31
39
|
function levelForIndividualModes(modes) {
|
|
32
|
-
return modes.caveman ===
|
|
40
|
+
return modes.caveman === 'off' && modes.rtk === 'off' && modes.ponytail === 'off' ? 'off' : 'custom';
|
|
33
41
|
}
|
|
34
42
|
function normalizedState(modes, level = deriveLevel(modes)) {
|
|
35
43
|
const state = {
|
|
36
|
-
caveman: normalizeMode(
|
|
37
|
-
rtk: normalizeMode(
|
|
38
|
-
ponytail: normalizeMode(
|
|
44
|
+
caveman: normalizeMode('caveman', modes?.caveman) || 'off',
|
|
45
|
+
rtk: normalizeMode('rtk', modes?.rtk) || 'off',
|
|
46
|
+
ponytail: normalizeMode('ponytail', modes?.ponytail) || 'off',
|
|
39
47
|
};
|
|
40
48
|
return Object.freeze({ level: isKnownLevel(level) ? level : deriveLevel(state), ...state });
|
|
41
49
|
}
|
|
@@ -52,19 +60,54 @@ function publish(state) {
|
|
|
52
60
|
shared.listener?.(state);
|
|
53
61
|
return state;
|
|
54
62
|
}
|
|
63
|
+
export function normalizeInputCommand(value) {
|
|
64
|
+
return String(value || '').trim().toLowerCase().replace(/[.!?\s]+$/, '');
|
|
65
|
+
}
|
|
66
|
+
export function asPromptArray(systemPrompt) {
|
|
67
|
+
return Array.isArray(systemPrompt) ? systemPrompt : [systemPrompt];
|
|
68
|
+
}
|
|
69
|
+
export function systemPromptIncludes(systemPrompt, marker) {
|
|
70
|
+
return asPromptArray(systemPrompt).some((prompt) => typeof prompt === 'string' && prompt.includes(marker));
|
|
71
|
+
}
|
|
55
72
|
export function isOmpSubagentPrompt(systemPrompt) {
|
|
56
|
-
|
|
57
|
-
return prompts.some((prompt) => typeof prompt === "string" && prompt.includes(OMP_SUBAGENT_MARKER));
|
|
73
|
+
return systemPromptIncludes(systemPrompt, OMP_SUBAGENT_MARKER);
|
|
58
74
|
}
|
|
59
75
|
export function normalizeComboLevel(value) {
|
|
60
|
-
const level = String(value ||
|
|
61
|
-
return
|
|
76
|
+
const level = String(value || '').trim().toLowerCase();
|
|
77
|
+
return isPresetLevel(level) ? level : null;
|
|
78
|
+
}
|
|
79
|
+
export function paintStatusBar(ui, key, emoji, label, isActive) {
|
|
80
|
+
const theme = ui?.theme;
|
|
81
|
+
const indicator = isActive && theme?.fg ? theme.fg('accent', emoji) : emoji;
|
|
82
|
+
ui?.setStatus?.(key, theme?.fg ? `${indicator} ${theme.fg('muted', label)}` : `${indicator} ${label}`);
|
|
83
|
+
}
|
|
84
|
+
// Last-wins scan for a custom session entry; skips entries whose value fails
|
|
85
|
+
// to parse so a corrupt write never shadows an older valid one.
|
|
86
|
+
export function lastCustomValue(entries, customType, pick) {
|
|
87
|
+
if (!Array.isArray(entries))
|
|
88
|
+
return null;
|
|
89
|
+
for (let i = entries.length - 1; i >= 0; i -= 1) {
|
|
90
|
+
const entry = entries[i];
|
|
91
|
+
if (entry?.type !== 'custom' || entry?.customType !== customType)
|
|
92
|
+
continue;
|
|
93
|
+
const value = pick(entry?.data);
|
|
94
|
+
if (value !== null && value !== undefined)
|
|
95
|
+
return value;
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
export function sessionEntries(ctx) {
|
|
100
|
+
return ctx?.sessionManager?.getBranch?.() || ctx?.sessionManager?.getEntries?.() || [];
|
|
62
101
|
}
|
|
63
102
|
export function getSharedComboState() {
|
|
64
103
|
return bridge().state;
|
|
65
104
|
}
|
|
105
|
+
export function isComboPresetActive() {
|
|
106
|
+
const level = getSharedComboState().level;
|
|
107
|
+
return level !== 'off' && isPresetLevel(level);
|
|
108
|
+
}
|
|
66
109
|
export function setSharedComboLevel(value) {
|
|
67
|
-
const level = normalizeComboLevel(value) ||
|
|
110
|
+
const level = normalizeComboLevel(value) || 'off';
|
|
68
111
|
return publish(normalizedState(COMBO_LEVELS[level], level));
|
|
69
112
|
}
|
|
70
113
|
export function setSharedComboMode(name, value) {
|
|
@@ -76,12 +119,12 @@ export function setSharedComboMode(name, value) {
|
|
|
76
119
|
}
|
|
77
120
|
export function reconcileSharedComboEntries(entries) {
|
|
78
121
|
let modes = { ...COMBO_LEVELS.off };
|
|
79
|
-
let level =
|
|
122
|
+
let level = 'off';
|
|
80
123
|
if (Array.isArray(entries)) {
|
|
81
124
|
for (const entry of entries) {
|
|
82
|
-
if (entry?.type !==
|
|
125
|
+
if (entry?.type !== 'custom')
|
|
83
126
|
continue;
|
|
84
|
-
if (entry.customType ===
|
|
127
|
+
if (entry.customType === 'combo-level') {
|
|
85
128
|
const preset = normalizeComboLevel(entry?.data?.level);
|
|
86
129
|
if (preset) {
|
|
87
130
|
modes = { ...COMBO_LEVELS[preset] };
|
|
@@ -89,16 +132,10 @@ export function reconcileSharedComboEntries(entries) {
|
|
|
89
132
|
}
|
|
90
133
|
continue;
|
|
91
134
|
}
|
|
92
|
-
const name = entry.customType
|
|
93
|
-
? "caveman"
|
|
94
|
-
: entry.customType === "rtk-mode"
|
|
95
|
-
? "rtk"
|
|
96
|
-
: entry.customType === "ponytail-mode"
|
|
97
|
-
? "ponytail"
|
|
98
|
-
: null;
|
|
135
|
+
const name = MODE_ENTRY_TYPES[entry.customType ?? ''] ?? null;
|
|
99
136
|
if (!name)
|
|
100
137
|
continue;
|
|
101
|
-
const value = name ===
|
|
138
|
+
const value = name === 'rtk' ? entry?.data?.enabled : entry?.data?.mode;
|
|
102
139
|
const mode = normalizeMode(name, value);
|
|
103
140
|
if (mode) {
|
|
104
141
|
modes[name] = mode;
|
|
@@ -109,13 +146,8 @@ export function reconcileSharedComboEntries(entries) {
|
|
|
109
146
|
return publish(normalizedState(modes, level));
|
|
110
147
|
}
|
|
111
148
|
export function setSharedComboListener(listener) {
|
|
112
|
-
|
|
113
|
-
shared.listener = typeof listener === "function" ? listener : null;
|
|
114
|
-
return () => {
|
|
115
|
-
if (shared.listener === listener)
|
|
116
|
-
shared.listener = null;
|
|
117
|
-
};
|
|
149
|
+
bridge().listener = typeof listener === 'function' ? listener : null;
|
|
118
150
|
}
|
|
119
151
|
export function resetSharedComboState() {
|
|
120
|
-
return setSharedComboLevel(
|
|
152
|
+
return setSharedComboLevel('off');
|
|
121
153
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@krtclcdy/tersio",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "✂️ Token-saving OMP add-ons: terse Caveman replies, compact RTK shell output, lean Ponytail code calls — one-command combo presets.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"omp",
|
|
7
7
|
"tersio",
|
|
@@ -11,9 +11,7 @@
|
|
|
11
11
|
"caveman-mode",
|
|
12
12
|
"rtk-rust-token-killer",
|
|
13
13
|
"ponytail-omp",
|
|
14
|
-
"extensions"
|
|
15
|
-
"amanai-reward-detector",
|
|
16
|
-
"pi-package"
|
|
14
|
+
"extensions"
|
|
17
15
|
],
|
|
18
16
|
"license": "MIT",
|
|
19
17
|
"author": "KurutoDenzeru",
|
|
@@ -31,10 +29,8 @@
|
|
|
31
29
|
},
|
|
32
30
|
"omp": {
|
|
33
31
|
"name": "Tersio",
|
|
34
|
-
"description": "
|
|
35
|
-
"extensions": [
|
|
36
|
-
"./extensions/amanai-reward/index.js"
|
|
37
|
-
],
|
|
32
|
+
"description": "Toggleable Caveman/RTK/Ponytail session modes with Combo presets",
|
|
33
|
+
"extensions": [],
|
|
38
34
|
"features": {
|
|
39
35
|
"caveman": {
|
|
40
36
|
"description": "Caveman terse-reply session mode (/caveman)",
|
|
@@ -109,11 +105,6 @@
|
|
|
109
105
|
}
|
|
110
106
|
}
|
|
111
107
|
},
|
|
112
|
-
"pi": {
|
|
113
|
-
"extensions": [
|
|
114
|
-
"./extensions/amanai-reward/pi.js"
|
|
115
|
-
]
|
|
116
|
-
},
|
|
117
108
|
"files": [
|
|
118
109
|
"tersio.js",
|
|
119
110
|
"extensions/**/*.js"
|
|
@@ -125,7 +116,7 @@
|
|
|
125
116
|
"check": "tsc --noEmit",
|
|
126
117
|
"doctor": "node tersio.js --doctor",
|
|
127
118
|
"dry-run": "node tersio.js --dry-run --scope user --yes",
|
|
128
|
-
"test": "tsx --test test/*.test.ts"
|
|
119
|
+
"test": "tsx --test test/*.test.ts test/*/*.test.ts"
|
|
129
120
|
},
|
|
130
121
|
"engines": {
|
|
131
122
|
"node": ">=18"
|