@krtclcdy/tersio 1.0.2 → 1.0.3

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.
Files changed (2) hide show
  1. package/package.json +14 -2
  2. package/tersio.js +51 -16
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@krtclcdy/tersio",
3
- "version": "1.0.2",
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.",
3
+ "version": "1.0.3",
4
+ "description": "Amanai reward detector and three toggleable OMP extensions for terse replies, compact shell output, and minimal code decisions \u2014 with a manual updater and dry-run support.",
5
5
  "keywords": [
6
6
  "omp",
7
7
  "tersio",
@@ -94,6 +94,18 @@
94
94
  "type": "boolean",
95
95
  "description": "RTK mode applied on session start when no session state exists",
96
96
  "default": false
97
+ },
98
+ "ponytailDefault": {
99
+ "type": "enum",
100
+ "description": "Ponytail mode applied on session start when no session state exists (follows combo preset unless overridden)",
101
+ "values": [
102
+ "off",
103
+ "lite",
104
+ "full",
105
+ "ultra",
106
+ "review"
107
+ ],
108
+ "default": "off"
97
109
  }
98
110
  }
99
111
  },
package/tersio.js CHANGED
@@ -19,6 +19,14 @@ const { version: PACKAGE_VERSION } = createRequire(import.meta.url)("./package.j
19
19
  // Session-start mode defaults for fresh installs.
20
20
  const COMBO_DEFAULTS = { off: true, medium: true, balanced: true, max: true };
21
21
  const CAVEMAN_DEFAULTS = { off: true, lite: true, full: true, ultra: true, wenyan: true };
22
+ // ponytail: Combo preset implies all three modes. Mirrors COMBO_LEVELS in
23
+ // extensions/shared/session-state.ts (rtk as boolean here). Single source.
24
+ const COMBO_PRESET_MODES = {
25
+ off: { caveman: "off", rtk: false, ponytail: "off" },
26
+ medium: { caveman: "lite", rtk: true, ponytail: "lite" },
27
+ balanced: { caveman: "full", rtk: true, ponytail: "full" },
28
+ max: { caveman: "ultra", rtk: true, ponytail: "ultra" },
29
+ };
22
30
  function parseEnum(value, valid, flag) {
23
31
  if (value === undefined)
24
32
  return undefined;
@@ -84,9 +92,9 @@ Commands:
84
92
 
85
93
  Options:
86
94
  --scope user|project|both
87
- --combo-default off|medium|balanced|max
88
- --caveman-default off|lite|full|ultra|wenyan
89
- --rtk-default on|off
95
+ --combo-default off|medium|balanced|max (implies caveman, rtk, ponytail)
96
+ --caveman-default off|lite|full|ultra|wenyan (override; default follows combo)
97
+ --rtk-default on|off (override; default follows combo)
90
98
  --yes, -y
91
99
  --dry-run
92
100
  --verbose
@@ -165,8 +173,8 @@ async function ensureExtensionInConfig(configPath, extensionPath, label, options
165
173
  console.log(` [dry-run] would add ${label} to config.yml: ${normalizedPath}`);
166
174
  return true;
167
175
  }
168
- // Handle "extensions: []" (empty YAML array)
169
- const emptyArrayIdx = lines.findIndex((l) => /^\s*extensions\s*:\s*\[\s*\]\s*$/i.test(l));
176
+ // ponytail: omp ships "extensions: null"; appending list items under a null scalar breaks YAML parsing. Normalize null/~/[]/empty to a mapping key first.
177
+ const emptyArrayIdx = lines.findIndex((l) => /^\s*extensions\s*:\s*(?:\[\s*\]|null|~)?\s*$/i.test(l));
170
178
  if (emptyArrayIdx !== -1) {
171
179
  lines[emptyArrayIdx] = "extensions:";
172
180
  lines.splice(emptyArrayIdx + 1, 0, line, "");
@@ -210,6 +218,8 @@ async function ensureExtensionAfterConfigEntry(configPath, extensionPath, afterP
210
218
  lines.push("extensions:", line, "");
211
219
  }
212
220
  else {
221
+ if (/^\s*extensions\s*:\s*(?:\[\s*\]|null|~)?\s*$/i.test(lines[extensionsIndex]))
222
+ lines[extensionsIndex] = "extensions:";
213
223
  lines.splice(extensionsIndex + 1, 0, line);
214
224
  }
215
225
  }
@@ -958,6 +968,7 @@ function defaultProfile() {
958
968
  comboDefault: "off",
959
969
  cavemanDefault: "off",
960
970
  rtkDefault: false,
971
+ ponytailDefault: "off",
961
972
  };
962
973
  }
963
974
  function tty() {
@@ -965,29 +976,51 @@ function tty() {
965
976
  }
966
977
  async function resolveProfile() {
967
978
  const profile = defaultProfile();
968
- // Interactive prompt: only for a real user at a terminal, only when no
969
- // default flags were given, and never for --apply-update runs.
979
+ // Single interactive prompt: the Combo preset implies all three modes.
980
+ // Only for a real user at a terminal, only when no default flags were
981
+ // given, and never for --apply-update runs.
970
982
  if (tty() && !profileFlagsGiven && !applyUpdate && (install || reinstall)) {
971
983
  const comboAnswer = (await ask(" Default Combo preset on session start? [off/medium/balanced/max] (off): ")).trim().toLowerCase();
972
984
  if (comboAnswer && comboAnswer in COMBO_DEFAULTS)
973
985
  profile.comboDefault = comboAnswer;
974
- const cavemanAnswer = (await ask(" Default Caveman mode on session start? [off/lite/full/ultra/wenyan] (off): ")).trim().toLowerCase();
975
- if (cavemanAnswer && cavemanAnswer in CAVEMAN_DEFAULTS)
976
- profile.cavemanDefault = cavemanAnswer;
977
- const rtkAnswer = (await ask(" Default RTK state on session start? [on/off] (off): ")).trim().toLowerCase();
978
- if (rtkAnswer === "on" || rtkAnswer === "off")
979
- profile.rtkDefault = rtkAnswer === "on";
980
- }
981
- // Explicit flags always win over the prompt.
986
+ }
987
+ // Explicit flags always win. Caveman/RTK flags override the Combo preset.
982
988
  if (comboDefaultFlag !== undefined)
983
989
  profile.comboDefault = comboDefaultFlag;
990
+ const preset = COMBO_PRESET_MODES[profile.comboDefault] ?? COMBO_PRESET_MODES.off;
991
+ profile.cavemanDefault = preset.caveman;
992
+ profile.rtkDefault = preset.rtk;
993
+ profile.ponytailDefault = preset.ponytail;
984
994
  if (cavemanDefaultFlag !== undefined)
985
995
  profile.cavemanDefault = cavemanDefaultFlag;
986
996
  if (rtkDefaultFlag !== undefined)
987
997
  profile.rtkDefault = rtkDefaultFlag === "on";
988
- console.log(` Profile: combo default=${profile.comboDefault} · caveman default=${profile.cavemanDefault} · rtk default=${profile.rtkDefault ? "on" : "off"}`);
998
+ console.log(` Profile: combo default=${profile.comboDefault} (caveman=${profile.cavemanDefault} · rtk=${profile.rtkDefault ? "on" : "off"} · ponytail=${profile.ponytailDefault})`);
989
999
  return profile;
990
1000
  }
1001
+ // ponytail: post-install guard. List entries under `extensions: null` break
1002
+ // OMP launch, so fail loudly here instead of at the next OMP start.
1003
+ async function validateConfigExtensions(agentDir, options) {
1004
+ if (options.dryRun)
1005
+ return;
1006
+ const raw = await readTextIfExists(path.join(agentDir, "config.yml"));
1007
+ if (!raw)
1008
+ return;
1009
+ const lines = raw.split("\n");
1010
+ const keyIdx = lines.findIndex((l) => /^\s*extensions\s*:/i.test(l));
1011
+ if (keyIdx === -1)
1012
+ return;
1013
+ const scalarNull = /^\s*extensions\s*:\s*(null|~|\[\s*\])\s*$/i.test(lines[keyIdx]);
1014
+ const hasEntries = lines.slice(keyIdx + 1).some((l) => /^\s*-\s+\S/.test(l));
1015
+ if (scalarNull && hasEntries) {
1016
+ console.log(" [fail] config.yml lists extensions under `extensions: null` — OMP will fail to launch.");
1017
+ console.log(" [hint] Replace the `extensions: null` line with `extensions:`, then reinstall.");
1018
+ process.exitCode = 1;
1019
+ }
1020
+ else {
1021
+ console.log(" [ok] config.yml extensions key valid");
1022
+ }
1023
+ }
991
1024
  // Persist the profile as omp plugin settings so `omp plugin config get`
992
1025
  // reflects the choice and the extensions pick it up on session start.
993
1026
  async function writePluginSettings(profile, options) {
@@ -1009,6 +1042,7 @@ async function writePluginSettings(profile, options) {
1009
1042
  settings.comboDefault = profile.comboDefault;
1010
1043
  settings.cavemanDefault = profile.cavemanDefault;
1011
1044
  settings.rtkDefault = profile.rtkDefault;
1045
+ settings.ponytailDefault = profile.ponytailDefault;
1012
1046
  config.settings[PACKAGE_NAME] = settings;
1013
1047
  if (options.dryRun) {
1014
1048
  console.log(` [dry-run] would write plugin settings (${PACKAGE_NAME}) to ${lockPath}`);
@@ -1120,6 +1154,7 @@ async function main() {
1120
1154
  await stepAmanaiReward(userExtDir, options, selfPlugin);
1121
1155
  if (selfPlugin)
1122
1156
  await writePluginSettings(profile, options);
1157
+ await validateConfigExtensions(userDir, options);
1123
1158
  }
1124
1159
  if (scope === "2" || scope === "3") {
1125
1160
  console.log("\n--- Project-level install ---");