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.
- package/README.md +50 -0
- package/dist/__tests__/command-sandbox.test.d.ts +2 -0
- package/dist/__tests__/command-sandbox.test.d.ts.map +1 -0
- package/dist/__tests__/command-sandbox.test.js +18 -0
- package/dist/__tests__/command-sandbox.test.js.map +1 -0
- package/dist/__tests__/contract.test.d.ts +2 -0
- package/dist/__tests__/contract.test.d.ts.map +1 -0
- package/dist/__tests__/contract.test.js +70 -0
- package/dist/__tests__/contract.test.js.map +1 -0
- package/dist/__tests__/offline.test.d.ts +2 -0
- package/dist/__tests__/offline.test.d.ts.map +1 -0
- package/dist/__tests__/offline.test.js +22 -0
- package/dist/__tests__/offline.test.js.map +1 -0
- package/dist/cache.d.ts +26 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +81 -0
- package/dist/cache.js.map +1 -0
- package/dist/client.d.ts +9 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +32 -0
- package/dist/client.js.map +1 -0
- package/dist/cloud-client.d.ts +11 -0
- package/dist/cloud-client.d.ts.map +1 -0
- package/dist/cloud-client.js +89 -0
- package/dist/cloud-client.js.map +1 -0
- package/dist/executor.d.ts +20 -0
- package/dist/executor.d.ts.map +1 -0
- package/dist/executor.js +93 -0
- package/dist/executor.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +383 -0
- package/dist/index.js.map +1 -0
- package/dist/policy.d.ts +6 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +24 -0
- package/dist/policy.js.map +1 -0
- package/dist/sanitizer.d.ts +28 -0
- package/dist/sanitizer.d.ts.map +1 -0
- package/dist/sanitizer.js +112 -0
- package/dist/sanitizer.js.map +1 -0
- package/package.json +49 -0
- 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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"}
|
package/dist/policy.d.ts
ADDED
|
@@ -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
|
+
}
|