termyte 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.
Files changed (43) hide show
  1. package/README.md +50 -0
  2. package/dist/__tests__/command-sandbox.test.d.ts +2 -0
  3. package/dist/__tests__/command-sandbox.test.d.ts.map +1 -0
  4. package/dist/__tests__/command-sandbox.test.js +18 -0
  5. package/dist/__tests__/command-sandbox.test.js.map +1 -0
  6. package/dist/__tests__/contract.test.d.ts +2 -0
  7. package/dist/__tests__/contract.test.d.ts.map +1 -0
  8. package/dist/__tests__/contract.test.js +70 -0
  9. package/dist/__tests__/contract.test.js.map +1 -0
  10. package/dist/__tests__/offline.test.d.ts +2 -0
  11. package/dist/__tests__/offline.test.d.ts.map +1 -0
  12. package/dist/__tests__/offline.test.js +22 -0
  13. package/dist/__tests__/offline.test.js.map +1 -0
  14. package/dist/cache.d.ts +26 -0
  15. package/dist/cache.d.ts.map +1 -0
  16. package/dist/cache.js +81 -0
  17. package/dist/cache.js.map +1 -0
  18. package/dist/client.d.ts +9 -0
  19. package/dist/client.d.ts.map +1 -0
  20. package/dist/client.js +32 -0
  21. package/dist/client.js.map +1 -0
  22. package/dist/cloud-client.d.ts +11 -0
  23. package/dist/cloud-client.d.ts.map +1 -0
  24. package/dist/cloud-client.js +89 -0
  25. package/dist/cloud-client.js.map +1 -0
  26. package/dist/executor.d.ts +20 -0
  27. package/dist/executor.d.ts.map +1 -0
  28. package/dist/executor.js +93 -0
  29. package/dist/executor.js.map +1 -0
  30. package/dist/index.d.ts +3 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +383 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/policy.d.ts +6 -0
  35. package/dist/policy.d.ts.map +1 -0
  36. package/dist/policy.js +24 -0
  37. package/dist/policy.js.map +1 -0
  38. package/dist/sanitizer.d.ts +28 -0
  39. package/dist/sanitizer.d.ts.map +1 -0
  40. package/dist/sanitizer.js +112 -0
  41. package/dist/sanitizer.js.map +1 -0
  42. package/package.json +49 -0
  43. package/proto/kernel.proto +101 -0
package/dist/index.js ADDED
@@ -0,0 +1,383 @@
1
+ #!/usr/bin/env node
2
+ import pc from "picocolors";
3
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
+ import { z } from "zod";
6
+ import { kernel } from "./client.js";
7
+ import * as fs from "fs";
8
+ import * as path from "path";
9
+ import * as os from "os";
10
+ import * as https from "https";
11
+ import { v4 as uuidv4 } from "uuid";
12
+ const CONFIG_DIR = path.join(os.homedir(), ".termyte");
13
+ const CONFIG_PATH = path.join(CONFIG_DIR, "config.json");
14
+ // ─── CLI Command Dispatcher ───────────────────────────────────────────────────
15
+ const arg = process.argv[2];
16
+ if (arg === "init") {
17
+ init().catch(err => {
18
+ console.error(pc.red(`Init failed: ${err.message}`));
19
+ process.exit(1);
20
+ });
21
+ }
22
+ else if (arg === "log" || arg === "logs") {
23
+ showLogs();
24
+ }
25
+ else if (arg === "status") {
26
+ checkStatus();
27
+ }
28
+ else if (arg === "--version" || arg === "-v") {
29
+ console.log("Termyte v0.2.0");
30
+ process.exit(0);
31
+ }
32
+ else if (arg === "--help" || arg === "-h") {
33
+ showHelp();
34
+ }
35
+ else {
36
+ startMcpServer();
37
+ }
38
+ // ─── Interactive CLI Helpers ──────────────────────────────────────────────────
39
+ function syncPrompt(question) {
40
+ process.stdout.write(question);
41
+ const buffer = Buffer.alloc(1024);
42
+ const bytesRead = fs.readSync(0, buffer, 0, 1024, null);
43
+ return buffer.toString('utf8', 0, bytesRead).trim();
44
+ }
45
+ async function init() {
46
+ console.log(`\n${pc.bold(pc.cyan("Initializing Termyte Governance..."))}\n`);
47
+ const home = os.homedir();
48
+ const agents = [
49
+ {
50
+ name: "Claude Code",
51
+ key: "claude",
52
+ paths: [path.join(home, ".claude", "settings.json")],
53
+ type: "json",
54
+ restart: "Restart Claude Code (close and reopen the app)"
55
+ },
56
+ {
57
+ name: "Cursor",
58
+ key: "cursor",
59
+ paths: [path.join(home, ".cursor", "mcp.json"), path.join(home, ".cursor", "config", "mcp.json")],
60
+ type: "json",
61
+ restart: "Restart Cursor to activate MCP server"
62
+ },
63
+ {
64
+ name: "Antigravity",
65
+ key: "antigravity",
66
+ paths: [path.join(home, ".gemini", "antigravity", "mcp_config.json")],
67
+ type: "json",
68
+ restart: "In Antigravity, open ... > Manage MCP Servers and click the refresh button"
69
+ },
70
+ {
71
+ name: "Codex",
72
+ key: "codex",
73
+ paths: [path.join(home, ".codex", "config.toml")],
74
+ type: "toml",
75
+ restart: "Restart Codex and run /mcp to confirm termyte tools are loaded"
76
+ },
77
+ ];
78
+ const detected = agents.filter(a => a.paths.some(p => fs.existsSync(p)));
79
+ let selectedAgent = null;
80
+ if (detected.length > 1) {
81
+ console.log("Multiple coding agents detected:");
82
+ detected.forEach((a, i) => console.log(` ${i + 1}. ${a.name}`));
83
+ const choice = parseInt(syncPrompt(`Select agent (1-${detected.length}): `));
84
+ selectedAgent = detected[choice - 1];
85
+ }
86
+ else if (detected.length === 1) {
87
+ selectedAgent = detected[0];
88
+ console.log(`Detected ${pc.bold(selectedAgent.name)}`);
89
+ }
90
+ else {
91
+ console.log("No coding agent detected. Which agent are you using?");
92
+ agents.forEach((a, i) => console.log(` ${i + 1}. ${a.name}`));
93
+ console.log(` ${agents.length + 1}. Other (manual setup)`);
94
+ const choice = parseInt(syncPrompt(`Select agent (1-${agents.length + 1}): `));
95
+ if (choice > agents.length) {
96
+ console.log(`\n${pc.yellow("Manual setup required.")}`);
97
+ console.log("\nAdd this to your MCP config under mcpServers:");
98
+ console.log(`
99
+ "termyte": {
100
+ "command": "npx",
101
+ "args": ["-y", "termyte-mcp"],
102
+ "env": {
103
+ "TERMYTE_DEVICE_ID": "<device_id>",
104
+ "TERMYTE_API_URL": "https://mcp.causalos.xyz"
105
+ }
106
+ }
107
+
108
+ For TOML-based configs (e.g. Codex):
109
+
110
+ [mcp_servers.termyte]
111
+ command = "npx"
112
+ args = ["-y", "termyte-mcp"]
113
+
114
+ [mcp_servers.termyte.env]
115
+ TERMYTE_DEVICE_ID = "<device_id>"
116
+ TERMYTE_API_URL = "https://mcp.causalos.xyz"
117
+ `);
118
+ process.exit(0);
119
+ }
120
+ selectedAgent = agents[choice - 1];
121
+ }
122
+ if (!selectedAgent) {
123
+ console.error(pc.red("Invalid selection."));
124
+ process.exit(1);
125
+ }
126
+ // 2. Device ID Management
127
+ if (!fs.existsSync(CONFIG_DIR))
128
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
129
+ let termyteConfig = {};
130
+ if (fs.existsSync(CONFIG_PATH)) {
131
+ try {
132
+ termyteConfig = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8"));
133
+ }
134
+ catch (e) { }
135
+ }
136
+ if (!termyteConfig.device_id) {
137
+ termyteConfig.device_id = uuidv4();
138
+ termyteConfig.agent = selectedAgent.key;
139
+ termyteConfig.created_at = new Date().toISOString();
140
+ fs.writeFileSync(CONFIG_PATH, JSON.stringify(termyteConfig, null, 2));
141
+ console.log(`Generated Device ID: ${pc.green(termyteConfig.device_id)}`);
142
+ }
143
+ else {
144
+ console.log(`Using existing Device ID: ${pc.green(termyteConfig.device_id)}`);
145
+ }
146
+ // 3. Write MCP Config
147
+ const targetPath = selectedAgent.paths.find((p) => fs.existsSync(p)) || selectedAgent.paths[0];
148
+ const targetDir = path.dirname(targetPath);
149
+ if (!fs.existsSync(targetDir)) {
150
+ fs.mkdirSync(targetDir, { recursive: true });
151
+ }
152
+ // Backup if exists
153
+ if (fs.existsSync(targetPath)) {
154
+ fs.copyFileSync(targetPath, `${targetPath}.termyte.bak`);
155
+ console.log(`📦 Backup created: ${path.basename(targetPath)}.termyte.bak`);
156
+ }
157
+ if (selectedAgent.type === "json") {
158
+ let agentConfig = { mcpServers: {} };
159
+ if (fs.existsSync(targetPath)) {
160
+ try {
161
+ agentConfig = JSON.parse(fs.readFileSync(targetPath, "utf-8"));
162
+ }
163
+ catch (e) {
164
+ console.warn(pc.yellow(`Warning: Malformed JSON at ${targetPath}. Starting fresh.`));
165
+ }
166
+ }
167
+ if (!agentConfig.mcpServers)
168
+ agentConfig.mcpServers = {};
169
+ agentConfig.mcpServers.termyte = {
170
+ command: "npx",
171
+ args: ["-y", "termyte-mcp"],
172
+ env: {
173
+ TERMYTE_DEVICE_ID: termyteConfig.device_id,
174
+ TERMYTE_API_URL: "https://mcp.causalos.xyz"
175
+ }
176
+ };
177
+ fs.writeFileSync(targetPath, JSON.stringify(agentConfig, null, 2));
178
+ }
179
+ else if (selectedAgent.type === "toml") {
180
+ let content = "";
181
+ if (fs.existsSync(targetPath)) {
182
+ content = fs.readFileSync(targetPath, "utf-8");
183
+ }
184
+ if (content.includes("[mcp_servers.termyte]")) {
185
+ console.log(`\n${pc.yellow(`Termyte already configured in ${path.basename(targetPath)}.`)}`);
186
+ }
187
+ else {
188
+ let newContent = content;
189
+ if (!content.includes("rmcp_client = true")) {
190
+ newContent = "# Required for MCP support\nrmcp_client = true\n\n" + newContent;
191
+ }
192
+ newContent += `\n[mcp_servers.termyte]\ncommand = "npx"\nargs = ["-y", "termyte-mcp"]\n\n[mcp_servers.termyte.env]\nTERMYTE_DEVICE_ID = "${termyteConfig.device_id}"\nTERMYTE_API_URL = "https://mcp.causalos.xyz"\n`;
193
+ fs.writeFileSync(targetPath, newContent);
194
+ }
195
+ }
196
+ // 4. Verification Step
197
+ const finalContent = fs.readFileSync(targetPath, "utf-8");
198
+ const verified = selectedAgent.type === "json"
199
+ ? finalContent.includes('"termyte"')
200
+ : finalContent.includes("[mcp_servers.termyte]");
201
+ console.log(pc.green(`MCP entry verified in ${pc.bold(targetPath)}`));
202
+ // 5. Verify API Connection
203
+ console.log(`\nVerifying connection to ${pc.cyan("mcp.causalos.xyz")}...`);
204
+ try {
205
+ await new Promise((resolve, reject) => {
206
+ const req = https.get("https://mcp.causalos.xyz/v1/health", {
207
+ headers: { "x-termyte-device-id": termyteConfig.device_id },
208
+ timeout: 5000
209
+ }, (res) => {
210
+ if (res.statusCode === 200)
211
+ resolve(true);
212
+ else
213
+ reject(new Error(`Server returned status ${res.statusCode}`));
214
+ });
215
+ req.on('error', reject);
216
+ req.on('timeout', () => { req.destroy(); reject(new Error("Timeout (5s)")); });
217
+ });
218
+ console.log(pc.green("v API Connection Verified"));
219
+ }
220
+ catch (err) {
221
+ console.error(pc.red(`Connection failed: ${err.message}`));
222
+ console.error("The Termyte sidecar might be down. Please check status later.");
223
+ process.exit(1);
224
+ }
225
+ // 6. Print Success
226
+ console.log(`\n${pc.green(pc.bold("Termyte active for " + selectedAgent.name))}\n`);
227
+ console.log(` Device: ${pc.cyan(termyteConfig.device_id)}`);
228
+ console.log(` API: https://mcp.causalos.xyz ${pc.green("v")}\n`);
229
+ console.log(` ${pc.bold(selectedAgent.restart)}\n`);
230
+ console.log(` ${pc.bold("npx termyte log")} -> see what your agent did`);
231
+ console.log(` ${pc.bold("npx termyte status")} -> check connection\n`);
232
+ process.exit(0);
233
+ }
234
+ function showLogs() {
235
+ const config = fs.existsSync(CONFIG_PATH) ? JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8")) : null;
236
+ if (!config) {
237
+ console.error(pc.red("Termyte not initialized. Run 'npx termyte init' first."));
238
+ process.exit(1);
239
+ }
240
+ const deviceId = config.device_id;
241
+ const apiUrl = process.env.TERMYTE_API_URL || "https://mcp.causalos.xyz";
242
+ console.log(pc.bold(pc.cyan(`\n📋 Termyte Governance Logs [${deviceId}]\n`)));
243
+ const url = new URL(`${apiUrl}/v1/governance/logs`);
244
+ const req = https.get({
245
+ hostname: url.hostname,
246
+ path: url.pathname,
247
+ headers: { "x-termyte-device-id": deviceId }
248
+ }, (res) => {
249
+ let data = "";
250
+ res.on("data", chunk => data += chunk);
251
+ res.on("end", () => {
252
+ const logs = JSON.parse(data);
253
+ if (logs.length === 0) {
254
+ console.log(pc.gray("No events recorded yet."));
255
+ }
256
+ else {
257
+ logs.forEach((l) => {
258
+ const verdictColor = l.verdict === "ALLOW" ? pc.green : l.verdict === "BLOCK" ? pc.red : pc.yellow;
259
+ const time = new Date(l.timestamp).toLocaleTimeString();
260
+ const outcomeIcon = l.success === true ? pc.green("(v)") : l.success === false ? pc.red("(x)") : pc.gray("(-)");
261
+ console.log(`${verdictColor(`[${l.verdict}]`)} ${pc.gray(time)} ${pc.bold(l.tool_name)} ${outcomeIcon}`);
262
+ if (l.verdict === "BLOCK" && l.reason) {
263
+ console.log(pc.red(` Reason: ${l.reason}`));
264
+ }
265
+ else if (l.reason && l.verdict !== "ALLOW") {
266
+ console.log(pc.gray(` Note: ${l.reason}`));
267
+ }
268
+ });
269
+ }
270
+ process.exit(0);
271
+ });
272
+ });
273
+ req.on("error", err => {
274
+ console.error(pc.red(`Failed to fetch logs: ${err.message}`));
275
+ process.exit(1);
276
+ });
277
+ }
278
+ function checkStatus() {
279
+ if (!fs.existsSync(CONFIG_PATH)) {
280
+ console.log(pc.red("Status: Not Initialized"));
281
+ process.exit(1);
282
+ }
283
+ const config = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8"));
284
+ console.log(`\n${pc.bold("Termyte Status")}`);
285
+ console.log(` Device ID: ${pc.cyan(config.device_id)}`);
286
+ console.log(` Agent: ${pc.cyan(config.agent || "Unknown")}`);
287
+ https.get("https://mcp.causalos.xyz/v1/health", {
288
+ headers: { "x-termyte-device-id": config.device_id },
289
+ timeout: 3000
290
+ }, (res) => {
291
+ if (res.statusCode === 200) {
292
+ console.log(` API: ${pc.green("Online")}`);
293
+ process.exit(0);
294
+ }
295
+ else {
296
+ console.log(` API: ${pc.red(`Error (${res.statusCode})`)}`);
297
+ process.exit(1);
298
+ }
299
+ }).on('error', () => {
300
+ console.log(` API: ${pc.red("Offline")}`);
301
+ process.exit(1);
302
+ });
303
+ }
304
+ function showHelp() {
305
+ console.log(`
306
+ ${pc.bold("Termyte — Terminal Governance for Coding Agents")}
307
+
308
+ Usage:
309
+ npx termyte init Setup local device-id and auto-configure agent
310
+ npx termyte log Show recent governance events
311
+ npx termyte status Check connection to the sidecar
312
+ npx termyte Start MCP Server (Standard IO)
313
+
314
+ Governance:
315
+ Termyte intercepts agent actions, evaluates them against a deterministic
316
+ sandbox and LLM judge, and records everything in a secure ledger.
317
+ `);
318
+ process.exit(0);
319
+ }
320
+ // ─── MCP Server ──────────────────────────────────────────────────────────────
321
+ async function startMcpServer() {
322
+ const server = new McpServer({
323
+ name: "termyte",
324
+ version: "0.1.0",
325
+ });
326
+ let currentSessionId = uuidv4(); // One session ID per MCP server process startup
327
+ server.tool("execute", "Execute a shell command.", {
328
+ command: z.string(),
329
+ args: z.array(z.string()).default([]),
330
+ cwd: z.string().optional(),
331
+ }, async ({ command, args, cwd }) => {
332
+ const action_payload = { command, args, cwd };
333
+ const session_id = currentSessionId;
334
+ // 1. Call prepare — invisible to agent
335
+ const verdict = await kernel.prepareToolCall(session_id, "execute", action_payload);
336
+ // 2. If blocked, return structured alternative
337
+ if (verdict.verdict === "BLOCK") {
338
+ return {
339
+ content: [{
340
+ type: "text",
341
+ text: `Action blocked by Termyte.\n` +
342
+ `Reason: ${verdict.reason}\n` +
343
+ `Alternative: ${verdict.alternative || "No alternative provided."}`
344
+ }],
345
+ isError: true
346
+ };
347
+ }
348
+ // 3. Execute via command sandbox
349
+ // We use nativeExec from executor.ts as it implements the OS-level sandbox
350
+ const { nativeExec } = await import("./executor.js");
351
+ // reconstruct command line string for nativeExec
352
+ const cmdString = args.length > 0 ? `${command} ${args.map((a) => `"${a.replace(/"/g, '\\"')}"`).join(" ")}` : command;
353
+ let result;
354
+ if (cwd) {
355
+ const originalCwd = process.cwd();
356
+ try {
357
+ process.chdir(cwd);
358
+ result = await nativeExec(cmdString);
359
+ }
360
+ finally {
361
+ process.chdir(originalCwd);
362
+ }
363
+ }
364
+ else {
365
+ result = await nativeExec(cmdString);
366
+ }
367
+ // 4. Call commit — invisible to agent
368
+ await kernel.commitToolCall(verdict.tool_call_id || uuidv4(), { stdout: result.stdout, stderr: result.stderr }, result.exit_code === 0, result.exit_code);
369
+ const combinedOutput = (result.stdout + "\n" + result.stderr).trim();
370
+ return {
371
+ content: [{ type: "text", text: combinedOutput || "Command completed with no output." }],
372
+ isError: result.exit_code !== 0
373
+ };
374
+ });
375
+ try {
376
+ const transport = new StdioServerTransport();
377
+ await server.connect(transport);
378
+ }
379
+ catch (err) {
380
+ console.error("MCP Server Error:", err);
381
+ }
382
+ }
383
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export type GovernanceAction = "ALLOW" | "BLOCK" | "UNCERTAIN";
2
+ export declare function getTermyteEnv(): "production" | "development";
3
+ export declare function normalizeVerdict(action: GovernanceAction): GovernanceAction;
4
+ export declare function applyUnifiedPolicy(action: GovernanceAction): GovernanceAction;
5
+ export declare function recommendationFor(action: GovernanceAction): "PROCEED" | "ABORT" | "ESCALATE";
6
+ //# sourceMappingURL=policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,OAAO,GAAG,WAAW,CAAC;AAE/D,wBAAgB,aAAa,IAAI,YAAY,GAAG,aAAa,CAE5D;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,gBAAgB,GACvB,gBAAgB,CAKlB;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,gBAAgB,GAAG,gBAAgB,CAM7E;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,CAI5F"}
package/dist/policy.js ADDED
@@ -0,0 +1,24 @@
1
+ export function getTermyteEnv() {
2
+ return process.env.TERMYTE_ENV === "production" ? "production" : "development";
3
+ }
4
+ export function normalizeVerdict(action) {
5
+ if (action === "ALLOW" || action === "BLOCK" || action === "UNCERTAIN") {
6
+ return action;
7
+ }
8
+ return "UNCERTAIN";
9
+ }
10
+ export function applyUnifiedPolicy(action) {
11
+ const env = getTermyteEnv();
12
+ if (env === "production") {
13
+ return action === "ALLOW" ? "ALLOW" : "BLOCK";
14
+ }
15
+ return action === "ALLOW" ? "ALLOW" : "UNCERTAIN";
16
+ }
17
+ export function recommendationFor(action) {
18
+ if (action === "ALLOW")
19
+ return "PROCEED";
20
+ if (action === "BLOCK")
21
+ return "ABORT";
22
+ return "ESCALATE";
23
+ }
24
+ //# sourceMappingURL=policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,aAAa;IAC3B,OAAO,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,CAAC;AACjF,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,MAAwB;IAExB,IAAI,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;QACvE,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAwB;IACzD,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;IAC5B,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;QACzB,OAAO,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;IAChD,CAAC;IACD,OAAO,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAwB;IACxD,IAAI,MAAM,KAAK,OAAO;QAAE,OAAO,SAAS,CAAC;IACzC,IAAI,MAAM,KAAK,OAAO;QAAE,OAAO,OAAO,CAAC;IACvC,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Sanitizer: Privacy-First Data Redaction for Termyte
3
+ *
4
+ * This utility ensures that sensitive data (API keys, secrets, PII) is redacted
5
+ * locally within the MCP sidecar before any trajectory data is streamed to the Cloud Runtime.
6
+ */
7
+ export declare class Sanitizer {
8
+ private static SECRET_PATTERNS;
9
+ /**
10
+ * Redacts sensitive information from a string or JSON object.
11
+ */
12
+ static redact(input: any): any;
13
+ private static redactString;
14
+ private static redactObject;
15
+ /**
16
+ * Generates a stable fingerprint of an action for caching.
17
+ * Matches the format used in the Cloud Runtime: tool_name:sanitized_args_json
18
+ */
19
+ static getFingerprint(toolName: string, args: any): string;
20
+ private static normalizeShellArgs;
21
+ /**
22
+ * Normalizes volatile tokens in a command string so that the fingerprint
23
+ * matches the one produced by the Rust kernel's Normalizer::normalize_shell().
24
+ * Must stay in sync with cloud-runtime/src/normalizer.rs.
25
+ */
26
+ private static normalizeCommandString;
27
+ }
28
+ //# sourceMappingURL=sanitizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitizer.d.ts","sourceRoot":"","sources":["../src/sanitizer.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAC,eAAe,CAe5B;IAEF;;OAEG;WACW,MAAM,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG;IAYrC,OAAO,CAAC,MAAM,CAAC,YAAY;IAe3B,OAAO,CAAC,MAAM,CAAC,YAAY;IAU3B;;;OAGG;WACW,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,MAAM;IAajE,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAUjC;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,sBAAsB;CAyBtC"}
@@ -0,0 +1,112 @@
1
+ import { createHash } from 'crypto';
2
+ /**
3
+ * Sanitizer: Privacy-First Data Redaction for Termyte
4
+ *
5
+ * This utility ensures that sensitive data (API keys, secrets, PII) is redacted
6
+ * locally within the MCP sidecar before any trajectory data is streamed to the Cloud Runtime.
7
+ */
8
+ export class Sanitizer {
9
+ static SECRET_PATTERNS = {
10
+ // Standard cloud/service tokens
11
+ AWS_KEY: /(?:ASIA|AKIA|AROA|AIDA)[A-Z0-9]{16}/g,
12
+ AWS_SECRET: /(?:aws_secret_access_key|aws_secret)\s*[:=]\s*(?:"|')?[A-Za-z0-9/+=]{40}(?:"|')?/gi,
13
+ STRIPE_KEY: /sk_live_[0-9a-zA-Z]{24}/g,
14
+ GITHUB_TOKEN: /(?:ghp|gho|ghu|ghs|ghr)_[a-zA-Z0-9]{36}/g,
15
+ SLACK_TOKEN: /xox[baprs]-[0-9a-zA-Z]{10,48}/g,
16
+ // Generic authentication
17
+ BEARER_TOKEN: /Bearer\s+[a-zA-Z0-9\-._~+/]+=*/gi,
18
+ BASIC_AUTH: /Basic\s+[a-zA-Z0-9+/]+=*/gi,
19
+ PRIVATE_KEY: /-----BEGIN (?:RSA|OPENSSH|EC|PGP) PRIVATE KEY-----[\s\S]+?-----END (?:RSA|OPENSSH|EC|PGP) PRIVATE KEY-----/g,
20
+ // Common sensitive field names in JSON
21
+ JSON_SECRET_KEY: /"(?:password|secret|token|key|pwd|auth|credential|api_key)":\s*"[^"]+"/gi,
22
+ };
23
+ /**
24
+ * Redacts sensitive information from a string or JSON object.
25
+ */
26
+ static redact(input) {
27
+ if (typeof input === 'string') {
28
+ return this.redactString(input);
29
+ }
30
+ if (typeof input === 'object' && input !== null) {
31
+ return this.redactObject(input);
32
+ }
33
+ return input;
34
+ }
35
+ static redactString(str) {
36
+ let result = str;
37
+ for (const [label, pattern] of Object.entries(this.SECRET_PATTERNS)) {
38
+ if (label === 'JSON_SECRET_KEY') {
39
+ result = result.replace(pattern, (match) => {
40
+ const parts = match.split(':');
41
+ return `${parts[0]}: "[REDACTED]"`;
42
+ });
43
+ }
44
+ else {
45
+ result = result.replace(pattern, `[REDACTED_${label}]`);
46
+ }
47
+ }
48
+ return result;
49
+ }
50
+ static redactObject(obj) {
51
+ const jsonStr = JSON.stringify(obj);
52
+ const redactedStr = this.redactString(jsonStr);
53
+ try {
54
+ return JSON.parse(redactedStr);
55
+ }
56
+ catch (e) {
57
+ return redactedStr;
58
+ }
59
+ }
60
+ /**
61
+ * Generates a stable fingerprint of an action for caching.
62
+ * Matches the format used in the Cloud Runtime: tool_name:sanitized_args_json
63
+ */
64
+ static getFingerprint(toolName, args) {
65
+ let sanitizedArgs = this.redact(args);
66
+ // Phase 3: Command Normalization for shell tools
67
+ if (["run_command", "shell", "run_shell_command"].includes(toolName)) {
68
+ sanitizedArgs = this.normalizeShellArgs(sanitizedArgs);
69
+ }
70
+ const argsJson = JSON.stringify(sanitizedArgs);
71
+ const canonical = `${toolName}:${argsJson}`;
72
+ return createHash('sha256').update(canonical).digest('hex');
73
+ }
74
+ static normalizeShellArgs(args) {
75
+ if (typeof args === 'string')
76
+ return this.normalizeCommandString(args);
77
+ if (typeof args === 'object' && args !== null) {
78
+ if (args.command) {
79
+ return { ...args, command: this.normalizeCommandString(args.command) };
80
+ }
81
+ }
82
+ return args;
83
+ }
84
+ /**
85
+ * Normalizes volatile tokens in a command string so that the fingerprint
86
+ * matches the one produced by the Rust kernel's Normalizer::normalize_shell().
87
+ * Must stay in sync with cloud-runtime/src/normalizer.rs.
88
+ */
89
+ static normalizeCommandString(cmd) {
90
+ const trimmed = cmd.trim();
91
+ if (!trimmed)
92
+ return cmd;
93
+ // Mirror Rust RE_TEMP_PATH / RE_ABS_PATH / RE_REL_PATH / RE_SESSION_ID / RE_PORT
94
+ let result = trimmed
95
+ .replace(/(?:\/tmp\/|\/var\/tmp\/|\/var\/folders\/|%TEMP%)\S*/gi, '[TEMP_PATH]')
96
+ .replace(/\/(?:[\w.-]+\/)*[\w.-]+/g, '[ABS_PATH]')
97
+ .replace(/\.\.?\/(?:[\w.-]+\/)*[\w.-]+/g, '[REL_PATH]')
98
+ .replace(/session-[a-z0-9]+/gi, '[SESSION_ID]')
99
+ .replace(/port\s+\d{4,5}/gi, 'port [EPHEMERAL_PORT]');
100
+ const parts = result.split(/\s+/).filter(Boolean);
101
+ if (parts.length <= 1)
102
+ return result;
103
+ const verb = parts[0];
104
+ const rest = parts.slice(1);
105
+ // Separate flags (start with -) from positional arguments and sort flags for
106
+ // canonical ordering — same logic as Rust: flags.sort() then non_flags.
107
+ const flags = rest.filter(p => p.startsWith('-')).sort();
108
+ const nonFlags = rest.filter(p => !p.startsWith('-'));
109
+ return [verb, ...flags, ...nonFlags].join(' ');
110
+ }
111
+ }
112
+ //# sourceMappingURL=sanitizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitizer.js","sourceRoot":"","sources":["../src/sanitizer.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "termyte",
3
+ "version": "0.1.0",
4
+ "description": "Termyte eats dangerous agent actions before they eat your codebase",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "termyte": "dist/index.js"
8
+ },
9
+ "type": "module",
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "start": "node dist/index.js",
13
+ "dev": "tsc --watch",
14
+ "test": "vitest run",
15
+ "prepublishOnly": "npm run build"
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "proto",
20
+ "README.md",
21
+ "LICENSE",
22
+ "package.json"
23
+ ],
24
+ "keywords": [
25
+ "mcp",
26
+ "ai-agents",
27
+ "causal-memory",
28
+ "deterministic-governance",
29
+ "split-plane-architecture",
30
+ "agent-governance",
31
+ "high-performance-ai"
32
+ ],
33
+ "author": "",
34
+ "license": "ISC",
35
+ "devDependencies": {
36
+ "@types/node": "^25.6.0",
37
+ "ts-node": "^10.9.2",
38
+ "typescript": "^6.0.2",
39
+ "vitest": "^4.1.4"
40
+ },
41
+ "dependencies": {
42
+ "@modelcontextprotocol/sdk": "^1.29.0",
43
+ "@types/uuid": "^10.0.0",
44
+ "lru-cache": "^11.3.5",
45
+ "picocolors": "^1.1.1",
46
+ "uuid": "^14.0.0",
47
+ "zod": "^4.3.6"
48
+ }
49
+ }