@prom.codes/saver 0.1.1 → 0.1.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/dist/bin.js +49 -17
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -5,7 +5,7 @@ import { resolve } from "node:path";
5
5
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
6
 
7
7
  // dist/key.js
8
- var KEY_PATTERN = /^prom_(live|test)_[A-Za-z0-9]{10,}$/;
8
+ var KEY_PATTERN = /^prom_(live|test)_[A-Za-z0-9]{6,}(?:_[A-Za-z0-9]{6,})?$/;
9
9
  var API_KEY_ENV = "PROMETHEUS_API_KEY";
10
10
  function classifyKey(raw) {
11
11
  const key = raw?.trim();
@@ -14,9 +14,6 @@ function classifyKey(raw) {
14
14
  return KEY_PATTERN.test(key) ? "valid" : "malformed";
15
15
  }
16
16
 
17
- // dist/server.js
18
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
19
-
20
17
  // dist/tools.js
21
18
  import { z } from "zod";
22
19
 
@@ -34,26 +31,26 @@ var SAVER_RUNTIMES = [
34
31
  ];
35
32
  var BLOCK_START = "<!-- prom-saver:start -->";
36
33
  var BLOCK_END = "<!-- prom-saver:end -->";
37
- var NEVER_COMPRESS = `**Never compress (all levels):**
34
+ var NEVER_COMPRESS = `**Never cut substance (all levels) \u2014 these are never "filler":**
38
35
  - Code, diffs, commit messages, CLI commands, API names, file paths and exact error strings \u2014 verbatim.
39
- - Load-bearing caveats, trade-offs, warnings and negations ("not", "only", "unless", "before"). If it changes correctness or safety, keep it.
40
- - Destructive, irreversible or multi-step sequences \u2014 spell those out in full.
41
- - **Anything you will need on a later turn \u2014 your own working context.** What you write IS your memory of this turn; condensing a recap for the reader is never a reason to drop a file path, value, decision, finding or error you may act on again. When unsure whether a detail matters later, keep it. This is the rule that prevents context loss \u2014 it overrides any urge to be brief.`;
36
+ - Load-bearing caveats, trade-offs, warnings, negations ("not"/"only"/"unless"/"before"), and \u2014 for risky or destructive work \u2014 safer alternatives, precautions, dependency/foreign-key checks and backup/rollback advice. If it changes correctness or safety, keep it.
37
+ - Destructive, irreversible or multi-step sequences \u2014 spell those out in full, including every step the task needs to actually work (e.g. a "without downtime" procedure keeps the dual-running / grace-period steps).
38
+ - **Anything you will need on a later turn \u2014 your own working context.** What you write IS your memory of this turn; condensing a recap is never a reason to drop a file path, value, decision, finding or error you may act on again. When unsure whether a detail matters later, keep it.`;
42
39
  var LEVEL_BODY = {
43
- lite: `Trim only ceremony and filler from your own prose: skip greetings, apologies, restating the question, and "I will now\u2026" preamble. Otherwise write normally.`,
44
- balanced: `Lead with the answer or the action. Skip preamble and the play-by-play narration of routine tool calls \u2014 act, then give a short result. When you recap a long tool or command output for the reader, quote the lines that matter rather than pasting all of it \u2014 but keep every detail you might act on later. Close a task with one concise summary, not running commentary. Substance over brevity \u2014 when in doubt, say the necessary thing. This is "lean", not "terse".`,
45
- aggressive: `Telegraphic prose: drop articles and filler, minimal hedging, the shortest wording that stays unambiguous; recap tool output as the essential lines only. Opt-in \u2014 more savings, more risk: the carve-outs below are hard limits, and you MUST fall back to "balanced" for any code-generation, debugging or destructive/irreversible work, where losing a single detail is costly.`
40
+ lite: `Drop ceremony and filler from your prose: no greetings, apologies, sign-offs, restating the question, or "I will now\u2026" preamble. Otherwise write normally.`,
41
+ balanced: `Lead with the answer or the action; cut preamble, sign-offs and play-by-play self-narration. Don't restate the question or pad. When several examples would be near-duplicates, give one. When recapping long tool or command output, keep the lines that carry meaning (failures, errors, the decision) and drop the noise. But include every step, caveat and precaution the answer needs to be correct and safe \u2014 if removing something would let a competent reviewer call the answer wrong, incomplete or unsafe, it stays. Lean, not terse: shorter because there is less filler, never because there is less help.`,
42
+ aggressive: `Telegraphic prose: drop articles and filler, minimal hedging, the shortest unambiguous wording; recap tool output as the load-bearing lines only. Opt-in \u2014 more savings, more risk: the carve-outs below are hard limits, and you MUST fall back to "balanced" for any code-generation, debugging or destructive/irreversible work, where losing a single detail is costly.`
46
43
  };
47
44
  function ruleBlockFor(level) {
48
45
  return `## prom.codes Saver \u2014 efficient output (level: ${level})
49
46
 
50
- Cut token cost WITHOUT cutting quality or losing context. This shapes ONLY how you PHRASE your own assistant messages \u2014 it never changes code, commands, tool inputs, what you do, or what you need to remember.
47
+ Cut token cost by writing less FILLER \u2014 without cutting quality or losing context. This shapes ONLY how you PHRASE your own messages: never code, commands, tool inputs, what you do, or what you need to remember. Trim ceremony, restating, padding and redundant examples; keep all substance.
51
48
 
52
49
  ${LEVEL_BODY[level]}
53
50
 
54
51
  ${NEVER_COMPRESS}
55
52
 
56
- Correctness, safety, completeness and your own working context come FIRST; saving tokens comes second. If the two ever conflict, do not compress.`;
53
+ Correctness, safety, completeness and your own working context come FIRST; saving tokens comes second. If the two ever conflict, do not compress \u2014 cut filler, never substance.`;
57
54
  }
58
55
  function withMarkers(block) {
59
56
  return `${BLOCK_START}
@@ -112,6 +109,7 @@ async function installRuntime(workspaceRoot, runtime, level) {
112
109
  }
113
110
 
114
111
  // dist/tools.js
112
+ var REQUIRE_KEY_ENV = "PROMETHEUS_SAVER_REQUIRE_KEY";
115
113
  function textResult(payload) {
116
114
  return { content: [{ type: "text", text: JSON.stringify(payload, null, 2) }] };
117
115
  }
@@ -122,23 +120,47 @@ var setupInput = {
122
120
  runtimes: z.array(runtimeEnum).min(1).optional()
123
121
  };
124
122
  function registerTools(server, deps) {
125
- const { workspaceRoot, apiKey } = deps;
123
+ const { workspaceRoot, apiKey, requireKey } = deps;
124
+ const keyState = deps.keyState ?? (apiKey !== void 0 ? "valid" : "absent");
126
125
  server.registerTool("setup", {
127
126
  title: "Install the prom.codes Saver efficient-output rules",
128
127
  description: "Idempotently install the prom.codes Saver efficient-output rule block into this workspace's agent runtime configs (CLAUDE.md / .cursor/rules / .augment/rules / AGENTS.md). The rules cut token cost by trimming the agent's own prose (preamble, narration, pasted tool output) while keeping code, caveats and destructive sequences verbatim. `level`: `lite` (filler only) | `balanced` (default \u2014 lean, not terse) | `aggressive` (telegraphic, opt-in, never for code/destructive). Without `runtimes` it auto-detects which are present (fallback: agents). Re-running updates the block in place. Run this once per workspace.",
129
128
  inputSchema: setupInput
130
129
  }, async (args) => {
130
+ if (requireKey === true && keyState !== "valid") {
131
+ return {
132
+ isError: true,
133
+ content: [
134
+ {
135
+ type: "text",
136
+ text: JSON.stringify({
137
+ ok: false,
138
+ installed: false,
139
+ keyState,
140
+ error: `prom.codes Saver: a valid ${API_KEY_ENV} (prom_live_\u2026 / prom_test_\u2026) is required to install because ${REQUIRE_KEY_ENV} is enabled (key is "${keyState}"). Set the key in this server's env block, or unset ${REQUIRE_KEY_ENV} to install keyless.`
141
+ }, null, 2)
142
+ }
143
+ ]
144
+ };
145
+ }
131
146
  const level = args.level ?? DEFAULT_LEVEL;
132
147
  const runtimes = args.runtimes ?? detectRuntimes(workspaceRoot);
133
148
  const results = [];
134
149
  for (const runtime of runtimes) {
135
150
  results.push(await installRuntime(workspaceRoot, runtime, level));
136
151
  }
137
- return textResult({ workspaceRoot, level, keyed: apiKey !== void 0, results });
152
+ return textResult({
153
+ workspaceRoot,
154
+ level,
155
+ keyed: apiKey !== void 0,
156
+ keyState,
157
+ results
158
+ });
138
159
  });
139
160
  }
140
161
 
141
162
  // dist/server.js
163
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
142
164
  var SERVER_IDENTITY = {
143
165
  name: "prom-codes-saver",
144
166
  version: "0.1.0",
@@ -161,14 +183,24 @@ async function main() {
161
183
  const workspaceRoot = resolve(process.env.PROMETHEUS_WORKSPACE_ROOT ?? process.cwd());
162
184
  const rawKey = process.env[API_KEY_ENV];
163
185
  const keyState = classifyKey(rawKey);
186
+ const requireKey = /^(1|true|yes|on)$/i.test(process.env[REQUIRE_KEY_ENV] ?? "");
164
187
  if (keyState === "malformed") {
165
188
  process.stderr.write(`prom-codes-saver: ${API_KEY_ENV} is malformed (expected prom_live_\u2026 / prom_test_\u2026); continuing keyless.
189
+ `);
190
+ }
191
+ if (requireKey && keyState !== "valid") {
192
+ process.stderr.write(`prom-codes-saver: ${REQUIRE_KEY_ENV} is on but ${API_KEY_ENV} is ${keyState}; setup will refuse to install until a valid prom_ key is provided.
166
193
  `);
167
194
  }
168
195
  const apiKey = keyState === "valid" ? rawKey.trim() : void 0;
169
- process.stderr.write(`prom-codes-saver: workspace=${workspaceRoot} key=${keyState}
196
+ process.stderr.write(`prom-codes-saver: workspace=${workspaceRoot} key=${keyState} requireKey=${requireKey}
170
197
  `);
171
- const server = createServer({ workspaceRoot, ...apiKey !== void 0 ? { apiKey } : {} });
198
+ const server = createServer({
199
+ workspaceRoot,
200
+ keyState,
201
+ requireKey,
202
+ ...apiKey !== void 0 ? { apiKey } : {}
203
+ });
172
204
  const transport = new StdioServerTransport();
173
205
  const shutdown = async (signal) => {
174
206
  process.stderr.write(`prom-codes-saver: received ${signal}, shutting down
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prom.codes/saver",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "prom.codes Saver — cut token cost without cutting quality, as an MCP installer.",
5
5
  "type": "module",
6
6
  "bin": {