@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,45 @@
1
+ // Plugin settings reader for the Tersio extensions.
2
+ // Reads omp's persisted plugin state (~/.omp/plugins/omp-plugins.lock.json),
3
+ // written by `omp plugin config set @krtclcdy/tersio <key> <value>` and by
4
+ // the installer profile step. Tolerant: any parse failure yields {} so every
5
+ // caller falls back to its own default.
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
+ function lockPaths() {
11
+ const configHome = process.env.XDG_CONFIG_HOME || path.join(os.homedir(), ".config");
12
+ return [
13
+ path.join(os.homedir(), ".omp", "plugins", "omp-plugins.lock.json"),
14
+ path.join(configHome, "omp", "plugins", "omp-plugins.lock.json"),
15
+ ];
16
+ }
17
+ // `settings[PLUGIN_NAME]` in the lock file; empty object when missing.
18
+ export function readPluginSettings() {
19
+ for (const p of lockPaths()) {
20
+ if (!existsSync(p))
21
+ continue;
22
+ try {
23
+ const config = JSON.parse(readFileSync(p, "utf8"));
24
+ const values = config.settings?.[PLUGIN_NAME];
25
+ if (values && typeof values === "object" && !Array.isArray(values))
26
+ return values;
27
+ }
28
+ catch { /* tolerate corrupt file */ }
29
+ }
30
+ return {};
31
+ }
32
+ const COMBO_LEVELS = new Set(["off", "medium", "balanced", "max"]);
33
+ export function readComboDefault() {
34
+ const raw = readPluginSettings().comboDefault;
35
+ return typeof raw === "string" && COMBO_LEVELS.has(raw) ? raw : "off";
36
+ }
37
+ const CAVEMAN_MODES = new Set(["off", "lite", "full", "ultra", "wenyan"]);
38
+ export function readCavemanDefault() {
39
+ const raw = readPluginSettings().cavemanDefault;
40
+ return typeof raw === "string" && CAVEMAN_MODES.has(raw) ? raw : "off";
41
+ }
42
+ export function readRtkDefault() {
43
+ const raw = readPluginSettings().rtkDefault;
44
+ return typeof raw === "boolean" ? raw : false;
45
+ }
@@ -0,0 +1,121 @@
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
+ export const COMBO_LEVELS = Object.freeze({
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
+ });
9
+ const MODE_VALUES = {
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
+ };
14
+ function normalizeMode(name, value) {
15
+ if (name === "rtk" && typeof value === "boolean")
16
+ return value ? "on" : "off";
17
+ const mode = String(value ?? "").trim().toLowerCase();
18
+ return MODE_VALUES[name]?.has(mode) ? mode : null;
19
+ }
20
+ function deriveLevel(modes) {
21
+ for (const level of ["off", "medium", "max"]) {
22
+ const preset = COMBO_LEVELS[level];
23
+ if (preset.caveman === modes.caveman && preset.rtk === modes.rtk && preset.ponytail === modes.ponytail)
24
+ return level;
25
+ }
26
+ return "custom";
27
+ }
28
+ function isKnownLevel(value) {
29
+ return value === "custom" || Object.prototype.hasOwnProperty.call(COMBO_LEVELS, value);
30
+ }
31
+ function levelForIndividualModes(modes) {
32
+ return modes.caveman === "off" && modes.rtk === "off" && modes.ponytail === "off" ? "off" : "custom";
33
+ }
34
+ function normalizedState(modes, level = deriveLevel(modes)) {
35
+ const state = {
36
+ caveman: normalizeMode("caveman", modes?.caveman) || "off",
37
+ rtk: normalizeMode("rtk", modes?.rtk) || "off",
38
+ ponytail: normalizeMode("ponytail", modes?.ponytail) || "off",
39
+ };
40
+ return Object.freeze({ level: isKnownLevel(level) ? level : deriveLevel(state), ...state });
41
+ }
42
+ function bridge() {
43
+ const existing = globalThis[BRIDGE_KEY];
44
+ if (existing?.state)
45
+ return existing;
46
+ const initial = normalizedState((existing || COMBO_LEVELS.off));
47
+ return (globalThis[BRIDGE_KEY] = { state: initial, listener: null });
48
+ }
49
+ function publish(state) {
50
+ const shared = bridge();
51
+ shared.state = state;
52
+ shared.listener?.(state);
53
+ return state;
54
+ }
55
+ export function isOmpSubagentPrompt(systemPrompt) {
56
+ const prompts = Array.isArray(systemPrompt) ? systemPrompt : [systemPrompt];
57
+ return prompts.some((prompt) => typeof prompt === "string" && prompt.includes(OMP_SUBAGENT_MARKER));
58
+ }
59
+ export function normalizeComboLevel(value) {
60
+ const level = String(value || "").trim().toLowerCase();
61
+ return Object.prototype.hasOwnProperty.call(COMBO_LEVELS, level) ? level : null;
62
+ }
63
+ export function getSharedComboState() {
64
+ return bridge().state;
65
+ }
66
+ export function setSharedComboLevel(value) {
67
+ const level = normalizeComboLevel(value) || "off";
68
+ return publish(normalizedState(COMBO_LEVELS[level], level));
69
+ }
70
+ export function setSharedComboMode(name, value) {
71
+ const mode = normalizeMode(name, value);
72
+ if (!mode)
73
+ return getSharedComboState();
74
+ const modes = { ...getSharedComboState(), [name]: mode };
75
+ return publish(normalizedState(modes, levelForIndividualModes(modes)));
76
+ }
77
+ export function reconcileSharedComboEntries(entries) {
78
+ let modes = { ...COMBO_LEVELS.off };
79
+ let level = "off";
80
+ if (Array.isArray(entries)) {
81
+ for (const entry of entries) {
82
+ if (entry?.type !== "custom")
83
+ continue;
84
+ if (entry.customType === "combo-level") {
85
+ const preset = normalizeComboLevel(entry?.data?.level);
86
+ if (preset) {
87
+ modes = { ...COMBO_LEVELS[preset] };
88
+ level = preset;
89
+ }
90
+ continue;
91
+ }
92
+ const name = entry.customType === "caveman-mode"
93
+ ? "caveman"
94
+ : entry.customType === "rtk-mode"
95
+ ? "rtk"
96
+ : entry.customType === "ponytail-mode"
97
+ ? "ponytail"
98
+ : null;
99
+ if (!name)
100
+ continue;
101
+ const value = name === "rtk" ? entry?.data?.enabled : entry?.data?.mode;
102
+ const mode = normalizeMode(name, value);
103
+ if (mode) {
104
+ modes[name] = mode;
105
+ level = levelForIndividualModes(modes);
106
+ }
107
+ }
108
+ }
109
+ return publish(normalizedState(modes, level));
110
+ }
111
+ export function setSharedComboListener(listener) {
112
+ const shared = bridge();
113
+ shared.listener = typeof listener === "function" ? listener : null;
114
+ return () => {
115
+ if (shared.listener === listener)
116
+ shared.listener = null;
117
+ };
118
+ }
119
+ export function resetSharedComboState() {
120
+ return setSharedComboLevel("off");
121
+ }
@@ -0,0 +1,3 @@
1
+ // Shared OMP extension host types. Structural — the real `pi` object comes
2
+ // from the OMP runtime; these describe the surface this package touches.
3
+ export {};
package/package.json ADDED
@@ -0,0 +1,125 @@
1
+ {
2
+ "name": "@krtclcdy/tersio",
3
+ "version": "1.0.0",
4
+ "description": "Amanai reward detector and three toggleable OMP extensions for terse replies, compact shell output, and minimal code decisions — with a manual updater and dry-run support.",
5
+ "keywords": [
6
+ "omp",
7
+ "tersio",
8
+ "token-saving",
9
+ "ai-tools",
10
+ "developer-tools",
11
+ "caveman-mode",
12
+ "rtk-rust-token-killer",
13
+ "ponytail-omp",
14
+ "extensions",
15
+ "amanai-reward-detector",
16
+ "pi-package"
17
+ ],
18
+ "license": "MIT",
19
+ "author": "KurutoDenzeru",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/KurutoDenzeru/tersio.git"
23
+ },
24
+ "homepage": "https://github.com/KurutoDenzeru/tersio",
25
+ "bugs": {
26
+ "url": "https://github.com/KurutoDenzeru/tersio/issues"
27
+ },
28
+ "type": "module",
29
+ "bin": {
30
+ "tersio": "tersio.js"
31
+ },
32
+ "omp": {
33
+ "name": "Tersio",
34
+ "description": "Amanai reward detector plus toggleable Caveman/RTK/Ponytail session modes with Combo presets",
35
+ "extensions": [
36
+ "./extensions/amanai-reward/index.js"
37
+ ],
38
+ "features": {
39
+ "caveman": {
40
+ "description": "Caveman terse-reply session mode (/caveman)",
41
+ "default": true,
42
+ "extensions": [
43
+ "./extensions/caveman-session/index.js"
44
+ ]
45
+ },
46
+ "rtk": {
47
+ "description": "RTK compact shell-output session mode (/rtk)",
48
+ "default": true,
49
+ "extensions": [
50
+ "./extensions/rtk-session/index.js"
51
+ ]
52
+ },
53
+ "ponytail": {
54
+ "description": "Combo toggle bar and Ponytail mode reinforcement (/combo, mode reinforcement)",
55
+ "default": true,
56
+ "extensions": [
57
+ "./extensions/combo-toggle/index.js",
58
+ "./extensions/shared/mode-reinforcement.js"
59
+ ]
60
+ },
61
+ "updater": {
62
+ "description": "In-session /ai-addons updater for Ponytail, RTK, and Caveman",
63
+ "default": true,
64
+ "extensions": [
65
+ "./extensions/ai-addons-updater/index.js"
66
+ ]
67
+ }
68
+ },
69
+ "settings": {
70
+ "comboDefault": {
71
+ "type": "enum",
72
+ "description": "Combo preset applied on session start when no session state exists",
73
+ "values": [
74
+ "off",
75
+ "medium",
76
+ "balanced",
77
+ "max"
78
+ ],
79
+ "default": "off"
80
+ },
81
+ "cavemanDefault": {
82
+ "type": "enum",
83
+ "description": "Caveman mode applied on session start when no session state exists",
84
+ "values": [
85
+ "off",
86
+ "lite",
87
+ "full",
88
+ "ultra",
89
+ "wenyan"
90
+ ],
91
+ "default": "off"
92
+ },
93
+ "rtkDefault": {
94
+ "type": "boolean",
95
+ "description": "RTK mode applied on session start when no session state exists",
96
+ "default": false
97
+ }
98
+ }
99
+ },
100
+ "pi": {
101
+ "extensions": [
102
+ "./extensions/amanai-reward/pi.js"
103
+ ]
104
+ },
105
+ "files": [
106
+ "tersio.js",
107
+ "extensions/**/*.js"
108
+ ],
109
+ "scripts": {
110
+ "clean": "rm -f tersio.js extensions/**/*.js",
111
+ "build": "tsc",
112
+ "check": "tsc --noEmit",
113
+ "doctor": "node tersio.js --doctor",
114
+ "dry-run": "node tersio.js --dry-run --scope user --yes",
115
+ "test": "tsx --test test/*.test.ts"
116
+ },
117
+ "engines": {
118
+ "node": ">=18"
119
+ },
120
+ "devDependencies": {
121
+ "@types/node": "^26.4.1",
122
+ "tsx": "^4.23.13",
123
+ "typescript": "^7.0.2"
124
+ }
125
+ }