@prom.codes/saver 0.1.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 +32 -0
- package/dist/bin.js +173 -0
- package/package.json +32 -0
package/README.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# @prom.codes/saver
|
|
2
|
+
|
|
3
|
+
**prom.codes Saver** — cut token cost without cutting quality. A tiny, pure-JS
|
|
4
|
+
MCP installer (stdio): one `setup` tool writes an *efficient-output* rule block
|
|
5
|
+
into your agent's runtime configs so it spends fewer tokens on its own prose —
|
|
6
|
+
preamble, play-by-play narration, pasted tool output — while keeping code,
|
|
7
|
+
caveats and destructive sequences **verbatim**.
|
|
8
|
+
|
|
9
|
+
It is the third prom.codes tool, alongside **prom.codes Context** (code retrieval)
|
|
10
|
+
and **prom.codes Memory** (agent memory).
|
|
11
|
+
|
|
12
|
+
## Quick start
|
|
13
|
+
|
|
14
|
+
```jsonc
|
|
15
|
+
// Claude Desktop / Cursor MCP config
|
|
16
|
+
{
|
|
17
|
+
"mcpServers": {
|
|
18
|
+
"saver": {
|
|
19
|
+
"command": "npx",
|
|
20
|
+
"args": ["-y", "@prom.codes/saver@latest"],
|
|
21
|
+
"env": { "PROMETHEUS_WORKSPACE_ROOT": "/absolute/path/to/your/repo" }
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Then ask your agent to run `setup` once per workspace. Levels: `lite` (filler
|
|
28
|
+
only), `balanced` (default — lean, not terse), `aggressive` (telegraphic, opt-in,
|
|
29
|
+
never for code/destructive work). No API key, no database, no native modules —
|
|
30
|
+
`npx` works turnkey everywhere. Requires Node ≥ 20.10.
|
|
31
|
+
|
|
32
|
+
Docs: https://prom.codes/docs
|
package/dist/bin.js
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// dist/bin.js
|
|
4
|
+
import { resolve } from "node:path";
|
|
5
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
|
+
|
|
7
|
+
// dist/server.js
|
|
8
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
9
|
+
|
|
10
|
+
// dist/tools.js
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
|
|
13
|
+
// dist/setup.js
|
|
14
|
+
import { existsSync } from "node:fs";
|
|
15
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
16
|
+
import { dirname, join } from "node:path";
|
|
17
|
+
var SAVER_LEVELS = ["lite", "balanced", "aggressive"];
|
|
18
|
+
var DEFAULT_LEVEL = "balanced";
|
|
19
|
+
var SAVER_RUNTIMES = [
|
|
20
|
+
"claude-code",
|
|
21
|
+
"cursor",
|
|
22
|
+
"augment",
|
|
23
|
+
"agents"
|
|
24
|
+
];
|
|
25
|
+
var BLOCK_START = "<!-- prom-saver:start -->";
|
|
26
|
+
var BLOCK_END = "<!-- prom-saver:end -->";
|
|
27
|
+
var NEVER_COMPRESS = `**Never compress (all levels):**
|
|
28
|
+
- Code, diffs, commit messages, CLI commands, API names, file paths and exact error strings \u2014 verbatim.
|
|
29
|
+
- Load-bearing caveats, trade-offs, warnings and negations ("not", "only", "unless", "before"). If it changes correctness or safety, keep it.
|
|
30
|
+
- Destructive, irreversible or multi-step sequences \u2014 spell those out in full.`;
|
|
31
|
+
var LEVEL_BODY = {
|
|
32
|
+
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.`,
|
|
33
|
+
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. Summarize long tool/command output instead of pasting it verbatim; quote only the lines that matter. Close a task with one concise summary, not running commentary. Keep substance over brevity \u2014 when in doubt, say the necessary thing. This is "lean", not "terse".`,
|
|
34
|
+
aggressive: `Telegraphic prose: drop articles and filler, minimal hedging, the shortest wording that stays unambiguous; summarize all tool output to the essential lines. 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 or destructive/irreversible work.`
|
|
35
|
+
};
|
|
36
|
+
function ruleBlockFor(level) {
|
|
37
|
+
return `## prom.codes Saver \u2014 efficient output (level: ${level})
|
|
38
|
+
|
|
39
|
+
Cut token cost WITHOUT cutting quality. This shapes ONLY your own assistant prose \u2014 it never changes code, commands, tool inputs, or what you actually do.
|
|
40
|
+
|
|
41
|
+
${LEVEL_BODY[level]}
|
|
42
|
+
|
|
43
|
+
${NEVER_COMPRESS}
|
|
44
|
+
|
|
45
|
+
The user asked for fewer wasted tokens, not a worse answer: preserve correctness, safety and completeness first, save tokens second.`;
|
|
46
|
+
}
|
|
47
|
+
function withMarkers(block) {
|
|
48
|
+
return `${BLOCK_START}
|
|
49
|
+
${block}
|
|
50
|
+
${BLOCK_END}`;
|
|
51
|
+
}
|
|
52
|
+
var CURSOR_FRONTMATTER = `---
|
|
53
|
+
description: prom.codes Saver \u2014 efficient-output protocol
|
|
54
|
+
alwaysApply: true
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
`;
|
|
58
|
+
var TARGETS = {
|
|
59
|
+
"claude-code": { relPath: "CLAUDE.md", mode: "block", detect: "CLAUDE.md" },
|
|
60
|
+
cursor: {
|
|
61
|
+
relPath: join(".cursor", "rules", "prom-saver.mdc"),
|
|
62
|
+
mode: "file",
|
|
63
|
+
fileContent: (b) => CURSOR_FRONTMATTER + withMarkers(b) + "\n",
|
|
64
|
+
detect: ".cursor"
|
|
65
|
+
},
|
|
66
|
+
augment: {
|
|
67
|
+
relPath: join(".augment", "rules", "prom-saver.md"),
|
|
68
|
+
mode: "file",
|
|
69
|
+
fileContent: (b) => withMarkers(b) + "\n",
|
|
70
|
+
detect: ".augment"
|
|
71
|
+
},
|
|
72
|
+
agents: { relPath: "AGENTS.md", mode: "block", detect: "AGENTS.md" }
|
|
73
|
+
};
|
|
74
|
+
function detectRuntimes(workspaceRoot) {
|
|
75
|
+
const found = SAVER_RUNTIMES.filter((rt) => existsSync(join(workspaceRoot, TARGETS[rt].detect)));
|
|
76
|
+
return found.length > 0 ? found : ["agents"];
|
|
77
|
+
}
|
|
78
|
+
function upsertBlock(existing, block) {
|
|
79
|
+
const marked = withMarkers(block);
|
|
80
|
+
const start = existing.indexOf(BLOCK_START);
|
|
81
|
+
const end = existing.indexOf(BLOCK_END);
|
|
82
|
+
if (start !== -1 && end !== -1 && end > start) {
|
|
83
|
+
return existing.slice(0, start) + marked + existing.slice(end + BLOCK_END.length);
|
|
84
|
+
}
|
|
85
|
+
const sep = existing.length === 0 || existing.endsWith("\n\n") ? "" : existing.endsWith("\n") ? "\n" : "\n\n";
|
|
86
|
+
return existing + sep + marked + "\n";
|
|
87
|
+
}
|
|
88
|
+
async function installRuntime(workspaceRoot, runtime, level) {
|
|
89
|
+
const target = TARGETS[runtime];
|
|
90
|
+
const block = ruleBlockFor(level);
|
|
91
|
+
const absPath = join(workspaceRoot, target.relPath);
|
|
92
|
+
const exists = existsSync(absPath);
|
|
93
|
+
const before = exists ? await readFile(absPath, "utf-8") : "";
|
|
94
|
+
const after = target.mode === "file" ? target.fileContent(block) : upsertBlock(before, block);
|
|
95
|
+
if (exists && before === after) {
|
|
96
|
+
return { runtime, path: absPath, action: "unchanged" };
|
|
97
|
+
}
|
|
98
|
+
await mkdir(dirname(absPath), { recursive: true });
|
|
99
|
+
await writeFile(absPath, after, "utf-8");
|
|
100
|
+
return { runtime, path: absPath, action: exists ? "updated" : "created" };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// dist/tools.js
|
|
104
|
+
function textResult(payload) {
|
|
105
|
+
return { content: [{ type: "text", text: JSON.stringify(payload, null, 2) }] };
|
|
106
|
+
}
|
|
107
|
+
var levelEnum = z.enum(SAVER_LEVELS);
|
|
108
|
+
var runtimeEnum = z.enum(SAVER_RUNTIMES);
|
|
109
|
+
var setupInput = {
|
|
110
|
+
level: levelEnum.optional(),
|
|
111
|
+
runtimes: z.array(runtimeEnum).min(1).optional()
|
|
112
|
+
};
|
|
113
|
+
function registerTools(server, deps) {
|
|
114
|
+
const { workspaceRoot } = deps;
|
|
115
|
+
server.registerTool("setup", {
|
|
116
|
+
title: "Install the prom.codes Saver efficient-output rules",
|
|
117
|
+
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.",
|
|
118
|
+
inputSchema: setupInput
|
|
119
|
+
}, async (args) => {
|
|
120
|
+
const level = args.level ?? DEFAULT_LEVEL;
|
|
121
|
+
const runtimes = args.runtimes ?? detectRuntimes(workspaceRoot);
|
|
122
|
+
const results = [];
|
|
123
|
+
for (const runtime of runtimes) {
|
|
124
|
+
results.push(await installRuntime(workspaceRoot, runtime, level));
|
|
125
|
+
}
|
|
126
|
+
return textResult({ workspaceRoot, level, results });
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// dist/server.js
|
|
131
|
+
var SERVER_IDENTITY = {
|
|
132
|
+
name: "prom-codes-saver",
|
|
133
|
+
version: "0.1.0",
|
|
134
|
+
title: "prom.codes Saver"
|
|
135
|
+
};
|
|
136
|
+
var SERVER_INSTRUCTIONS = "prom.codes Saver cuts token cost by trimming the agent's own prose \u2014 preamble, play-by-play narration and pasted tool output \u2014 while keeping code, caveats and destructive sequences verbatim. Run `setup` once per workspace to install the efficient-output protocol into the runtime rule files. Default level is `balanced` (lean, not terse): lead with the answer, summarize long output, one end-of-task summary. Never sacrifice correctness, safety or completeness to save tokens.";
|
|
137
|
+
function createServer(deps, options = {}) {
|
|
138
|
+
const identity = { ...SERVER_IDENTITY, ...options.identity ?? {} };
|
|
139
|
+
const capabilities = options.capabilities ?? { tools: {} };
|
|
140
|
+
const server = new McpServer(identity, {
|
|
141
|
+
capabilities,
|
|
142
|
+
instructions: SERVER_INSTRUCTIONS
|
|
143
|
+
});
|
|
144
|
+
registerTools(server, deps);
|
|
145
|
+
return server;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// dist/bin.js
|
|
149
|
+
async function main() {
|
|
150
|
+
const workspaceRoot = resolve(process.env.PROMETHEUS_WORKSPACE_ROOT ?? process.cwd());
|
|
151
|
+
process.stderr.write(`prom-codes-saver: workspace=${workspaceRoot}
|
|
152
|
+
`);
|
|
153
|
+
const server = createServer({ workspaceRoot });
|
|
154
|
+
const transport = new StdioServerTransport();
|
|
155
|
+
const shutdown = async (signal) => {
|
|
156
|
+
process.stderr.write(`prom-codes-saver: received ${signal}, shutting down
|
|
157
|
+
`);
|
|
158
|
+
try {
|
|
159
|
+
await server.close();
|
|
160
|
+
} finally {
|
|
161
|
+
process.exit(0);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
process.once("SIGINT", shutdown);
|
|
165
|
+
process.once("SIGTERM", shutdown);
|
|
166
|
+
await server.connect(transport);
|
|
167
|
+
}
|
|
168
|
+
main().catch((err) => {
|
|
169
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
170
|
+
process.stderr.write(`prom-codes-saver: fatal: ${message}
|
|
171
|
+
`);
|
|
172
|
+
process.exit(1);
|
|
173
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@prom.codes/saver",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "prom.codes Saver — cut token cost without cutting quality, as an MCP installer.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"prom-codes-saver": "dist/bin.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=20.10"
|
|
14
|
+
},
|
|
15
|
+
"license": "UNLICENSED",
|
|
16
|
+
"homepage": "https://prom.codes",
|
|
17
|
+
"keywords": [
|
|
18
|
+
"mcp",
|
|
19
|
+
"model-context-protocol",
|
|
20
|
+
"tokens",
|
|
21
|
+
"cost",
|
|
22
|
+
"efficiency",
|
|
23
|
+
"ai-agents"
|
|
24
|
+
],
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
30
|
+
"zod": "^4.4.3"
|
|
31
|
+
}
|
|
32
|
+
}
|