@dmmulroy/overseer 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 (46) hide show
  1. package/bin/os +99 -0
  2. package/dist/api/index.d.ts +6 -0
  3. package/dist/api/index.d.ts.map +1 -0
  4. package/dist/api/index.js +6 -0
  5. package/dist/api/index.js.map +1 -0
  6. package/dist/api/learnings.d.ts +19 -0
  7. package/dist/api/learnings.d.ts.map +1 -0
  8. package/dist/api/learnings.js +31 -0
  9. package/dist/api/learnings.js.map +1 -0
  10. package/dist/api/tasks.d.ts +69 -0
  11. package/dist/api/tasks.d.ts.map +1 -0
  12. package/dist/api/tasks.js +108 -0
  13. package/dist/api/tasks.js.map +1 -0
  14. package/dist/cli.d.ts +5 -0
  15. package/dist/cli.d.ts.map +1 -0
  16. package/dist/cli.js +52 -0
  17. package/dist/cli.js.map +1 -0
  18. package/dist/executor.d.ts +12 -0
  19. package/dist/executor.d.ts.map +1 -0
  20. package/dist/executor.js +112 -0
  21. package/dist/executor.js.map +1 -0
  22. package/dist/index.d.ts +3 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +10 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/server.d.ts +13 -0
  27. package/dist/server.d.ts.map +1 -0
  28. package/dist/server.js +193 -0
  29. package/dist/server.js.map +1 -0
  30. package/dist/tests/executor.test.d.ts +2 -0
  31. package/dist/tests/executor.test.d.ts.map +1 -0
  32. package/dist/tests/executor.test.js +169 -0
  33. package/dist/tests/executor.test.js.map +1 -0
  34. package/dist/tests/integration.test.d.ts +2 -0
  35. package/dist/tests/integration.test.d.ts.map +1 -0
  36. package/dist/tests/integration.test.js +378 -0
  37. package/dist/tests/integration.test.js.map +1 -0
  38. package/dist/tests/server.test.d.ts +2 -0
  39. package/dist/tests/server.test.d.ts.map +1 -0
  40. package/dist/tests/server.test.js +53 -0
  41. package/dist/tests/server.test.js.map +1 -0
  42. package/dist/types.d.ts +60 -0
  43. package/dist/types.d.ts.map +1 -0
  44. package/dist/types.js +42 -0
  45. package/dist/types.js.map +1 -0
  46. package/package.json +45 -0
package/bin/os ADDED
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Unified CLI entry point
4
+ * - `os mcp` → starts MCP server (Node, codemode)
5
+ * - `os <cmd>` → forwards to native binary
6
+ */
7
+ import { existsSync, readFileSync } from "node:fs";
8
+ import { execSync, spawn } from "node:child_process";
9
+ import { platform, arch } from "node:process";
10
+ import { createRequire } from "node:module";
11
+ import { fileURLToPath } from "node:url";
12
+ import { dirname, join } from "node:path";
13
+
14
+ const require = createRequire(import.meta.url);
15
+ const __dirname = dirname(fileURLToPath(import.meta.url));
16
+
17
+ const PLATFORMS = {
18
+ "darwin-arm64": "@dmmulroy/overseer-darwin-arm64",
19
+ "darwin-x64": "@dmmulroy/overseer-darwin-x64",
20
+ "linux-arm64": "@dmmulroy/overseer-linux-arm64",
21
+ "linux-x64": "@dmmulroy/overseer-linux-x64",
22
+ "linux-arm64-musl": "@dmmulroy/overseer-linux-arm64-musl",
23
+ "linux-x64-musl": "@dmmulroy/overseer-linux-x64-musl",
24
+ };
25
+
26
+ function isMusl() {
27
+ if (platform !== "linux") return false;
28
+ if (existsSync("/etc/alpine-release")) return true;
29
+ try {
30
+ const maps = readFileSync("/proc/self/maps", "utf8");
31
+ if (maps.includes("musl")) return true;
32
+ } catch {}
33
+ try {
34
+ const output = execSync("ldd --version 2>&1", { encoding: "utf8" });
35
+ return output.toLowerCase().includes("musl");
36
+ } catch (err) {
37
+ const stderr = err.stderr?.toString() || err.message || "";
38
+ return stderr.toLowerCase().includes("musl");
39
+ }
40
+ }
41
+
42
+ function getBinaryPath() {
43
+ if (process.env.OVERSEER_CLI_PATH) {
44
+ return process.env.OVERSEER_CLI_PATH;
45
+ }
46
+
47
+ const cpuArch = arch === "arm64" ? "arm64" : "x64";
48
+ const libc = isMusl() ? "-musl" : "";
49
+ const key = `${platform}-${cpuArch}${libc}`;
50
+ const pkg = PLATFORMS[key];
51
+
52
+ if (!pkg) {
53
+ console.error(`Unsupported platform: ${key}`);
54
+ console.error("Install via cargo: cargo install overseer");
55
+ process.exit(1);
56
+ }
57
+
58
+ try {
59
+ const pkgPath = require.resolve(`${pkg}/package.json`);
60
+ return join(dirname(pkgPath), "os");
61
+ } catch {
62
+ console.error(`Platform package not installed: ${pkg}`);
63
+ console.error("Try: npm install -g @dmmulroy/overseer");
64
+ process.exit(1);
65
+ }
66
+ }
67
+
68
+ const args = process.argv.slice(2);
69
+ const command = args[0];
70
+
71
+ // Handle `os mcp` - start MCP server
72
+ if (command === "mcp") {
73
+ const binaryPath = getBinaryPath();
74
+ process.env.OVERSEER_CLI_PATH = binaryPath;
75
+
76
+ const serverPath = join(__dirname, "..", "dist", "index.js");
77
+ import(serverPath).catch((err) => {
78
+ console.error("Failed to start MCP server:", err.message);
79
+ process.exit(1);
80
+ });
81
+ } else {
82
+ // All other commands - passthrough to native binary
83
+ const child = spawn(getBinaryPath(), args, {
84
+ stdio: "inherit",
85
+ });
86
+
87
+ child.on("error", (err) => {
88
+ console.error(`Failed to run os: ${err.message}`);
89
+ process.exit(1);
90
+ });
91
+
92
+ child.on("exit", (code, signal) => {
93
+ if (signal) {
94
+ process.kill(process.pid, signal);
95
+ } else {
96
+ process.exit(code ?? 0);
97
+ }
98
+ });
99
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * API exports
3
+ */
4
+ export { tasks } from "./tasks.js";
5
+ export { learnings } from "./learnings.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * API exports
3
+ */
4
+ export { tasks } from "./tasks.js";
5
+ export { learnings } from "./learnings.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { Learning } from "../types.js";
2
+ /**
3
+ * Learnings API exposed to VM sandbox
4
+ */
5
+ export declare const learnings: {
6
+ /**
7
+ * Add learning to a task
8
+ */
9
+ add(taskId: string, content: string, sourceTaskId?: string): Promise<Learning>;
10
+ /**
11
+ * List all learnings for a task
12
+ */
13
+ list(taskId: string): Promise<Learning[]>;
14
+ /**
15
+ * Delete a learning
16
+ */
17
+ delete(id: string): Promise<void>;
18
+ };
19
+ //# sourceMappingURL=learnings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learnings.d.ts","sourceRoot":"","sources":["../../src/api/learnings.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C;;GAEG;AACH,eAAO,MAAM,SAAS;IACpB;;OAEG;gBAEO,MAAM,WACL,MAAM,iBACA,MAAM,GACpB,OAAO,CAAC,QAAQ,CAAC;IAMpB;;OAEG;iBACgB,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAI/C;;OAEG;eACc,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGxC,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Learnings API - typed wrapper around os learning commands
3
+ */
4
+ import { callCli } from "../cli.js";
5
+ /**
6
+ * Learnings API exposed to VM sandbox
7
+ */
8
+ export const learnings = {
9
+ /**
10
+ * Add learning to a task
11
+ */
12
+ async add(taskId, content, sourceTaskId) {
13
+ const args = ["learning", "add", taskId, content];
14
+ if (sourceTaskId)
15
+ args.push("--source", sourceTaskId);
16
+ return (await callCli(args));
17
+ },
18
+ /**
19
+ * List all learnings for a task
20
+ */
21
+ async list(taskId) {
22
+ return (await callCli(["learning", "list", taskId]));
23
+ },
24
+ /**
25
+ * Delete a learning
26
+ */
27
+ async delete(id) {
28
+ await callCli(["learning", "delete", id]);
29
+ },
30
+ };
31
+ //# sourceMappingURL=learnings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learnings.js","sourceRoot":"","sources":["../../src/api/learnings.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC;;GAEG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB;;OAEG;IACH,KAAK,CAAC,GAAG,CACP,MAAc,EACd,OAAe,EACf,YAAqB;QAErB,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;QAClD,IAAI,YAAY;YAAE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;QACtD,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAa,CAAC;IAC3C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,IAAI,CAAC,MAAc;QACvB,OAAO,CAAC,MAAM,OAAO,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAe,CAAC;IACrE,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,MAAM,OAAO,CAAC,CAAC,UAAU,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;IAC5C,CAAC;CACF,CAAC"}
@@ -0,0 +1,69 @@
1
+ import type { Task } from "../types.js";
2
+ export interface TaskFilter {
3
+ parentId?: string;
4
+ ready?: boolean;
5
+ completed?: boolean;
6
+ }
7
+ export interface CreateTaskInput {
8
+ description: string;
9
+ context?: string;
10
+ parentId?: string;
11
+ priority?: 1 | 2 | 3 | 4 | 5;
12
+ blockedBy?: string[];
13
+ }
14
+ export interface UpdateTaskInput {
15
+ description?: string;
16
+ context?: string;
17
+ priority?: 1 | 2 | 3 | 4 | 5;
18
+ parentId?: string;
19
+ }
20
+ /**
21
+ * Tasks API exposed to VM sandbox
22
+ */
23
+ export declare const tasks: {
24
+ /**
25
+ * List tasks with optional filters
26
+ */
27
+ list(filter?: TaskFilter): Promise<Task[]>;
28
+ /**
29
+ * Get single task with full context and learnings
30
+ */
31
+ get(id: string): Promise<Task>;
32
+ /**
33
+ * Create new task
34
+ */
35
+ create(input: CreateTaskInput): Promise<Task>;
36
+ /**
37
+ * Update existing task
38
+ */
39
+ update(id: string, input: UpdateTaskInput): Promise<Task>;
40
+ /**
41
+ * Mark task as started
42
+ */
43
+ start(id: string): Promise<Task>;
44
+ /**
45
+ * Complete task with optional result
46
+ */
47
+ complete(id: string, result?: string): Promise<Task>;
48
+ /**
49
+ * Reopen completed task
50
+ */
51
+ reopen(id: string): Promise<Task>;
52
+ /**
53
+ * Delete task (cascades to children)
54
+ */
55
+ delete(id: string): Promise<void>;
56
+ /**
57
+ * Add blocker relationship
58
+ */
59
+ block(taskId: string, blockerId: string): Promise<void>;
60
+ /**
61
+ * Remove blocker relationship
62
+ */
63
+ unblock(taskId: string, blockerId: string): Promise<void>;
64
+ /**
65
+ * Get next ready task
66
+ */
67
+ nextReady(milestoneId?: string): Promise<Task | null>;
68
+ };
69
+ //# sourceMappingURL=tasks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../../src/api/tasks.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,eAAO,MAAM,KAAK;IAChB;;OAEG;kBACiB,UAAU,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAQhD;;OAEG;YACW,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpC;;OAEG;kBACiB,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAWnD;;OAEG;eACc,MAAM,SAAS,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAS/D;;OAEG;cACa,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAItC;;OAEG;iBACgB,MAAM,WAAW,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM1D;;OAEG;eACc,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC;;OAEG;eACc,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC;;OAEG;kBACiB,MAAM,aAAa,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7D;;OAEG;oBACmB,MAAM,aAAa,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/D;;OAEG;4BAC2B,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;CAK5D,CAAC"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Tasks API - typed wrapper around os task commands
3
+ */
4
+ import { callCli } from "../cli.js";
5
+ /**
6
+ * Tasks API exposed to VM sandbox
7
+ */
8
+ export const tasks = {
9
+ /**
10
+ * List tasks with optional filters
11
+ */
12
+ async list(filter) {
13
+ const args = ["task", "list"];
14
+ if (filter?.parentId)
15
+ args.push("--parent", filter.parentId);
16
+ if (filter?.ready)
17
+ args.push("--ready");
18
+ if (filter?.completed)
19
+ args.push("--completed");
20
+ return (await callCli(args));
21
+ },
22
+ /**
23
+ * Get single task with full context and learnings
24
+ */
25
+ async get(id) {
26
+ return (await callCli(["task", "get", id]));
27
+ },
28
+ /**
29
+ * Create new task
30
+ */
31
+ async create(input) {
32
+ const args = ["task", "create", "-d", input.description];
33
+ if (input.context)
34
+ args.push("--context", input.context);
35
+ if (input.parentId)
36
+ args.push("--parent", input.parentId);
37
+ if (input.priority)
38
+ args.push("--priority", String(input.priority));
39
+ if (input.blockedBy && input.blockedBy.length > 0) {
40
+ args.push("--blocked-by", input.blockedBy.join(","));
41
+ }
42
+ return (await callCli(args));
43
+ },
44
+ /**
45
+ * Update existing task
46
+ */
47
+ async update(id, input) {
48
+ const args = ["task", "update", id];
49
+ if (input.description)
50
+ args.push("-d", input.description);
51
+ if (input.context)
52
+ args.push("--context", input.context);
53
+ if (input.priority)
54
+ args.push("--priority", String(input.priority));
55
+ if (input.parentId)
56
+ args.push("--parent", input.parentId);
57
+ return (await callCli(args));
58
+ },
59
+ /**
60
+ * Mark task as started
61
+ */
62
+ async start(id) {
63
+ return (await callCli(["task", "start", id]));
64
+ },
65
+ /**
66
+ * Complete task with optional result
67
+ */
68
+ async complete(id, result) {
69
+ const args = ["task", "complete", id];
70
+ if (result)
71
+ args.push("--result", result);
72
+ return (await callCli(args));
73
+ },
74
+ /**
75
+ * Reopen completed task
76
+ */
77
+ async reopen(id) {
78
+ return (await callCli(["task", "reopen", id]));
79
+ },
80
+ /**
81
+ * Delete task (cascades to children)
82
+ */
83
+ async delete(id) {
84
+ await callCli(["task", "delete", id]);
85
+ },
86
+ /**
87
+ * Add blocker relationship
88
+ */
89
+ async block(taskId, blockerId) {
90
+ await callCli(["task", "block", taskId, "--by", blockerId]);
91
+ },
92
+ /**
93
+ * Remove blocker relationship
94
+ */
95
+ async unblock(taskId, blockerId) {
96
+ await callCli(["task", "unblock", taskId, "--by", blockerId]);
97
+ },
98
+ /**
99
+ * Get next ready task
100
+ */
101
+ async nextReady(milestoneId) {
102
+ const args = ["task", "next-ready"];
103
+ if (milestoneId)
104
+ args.push("--milestone", milestoneId);
105
+ return (await callCli(args));
106
+ },
107
+ };
108
+ //# sourceMappingURL=tasks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/api/tasks.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Execute os CLI command with --json flag
3
+ */
4
+ export declare function callCli(args: string[]): Promise<unknown>;
5
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAYA;;GAEG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAmD9D"}
package/dist/cli.js ADDED
@@ -0,0 +1,52 @@
1
+ /**
2
+ * CLI bridge - spawns `os` binary and parses JSON output
3
+ */
4
+ import { spawn } from "node:child_process";
5
+ import { CliError, CliTimeoutError } from "./types.js";
6
+ const CLI_TIMEOUT_MS = 30_000;
7
+ // Allow override via env var (useful for tests)
8
+ const CLI_PATH = process.env.OVERSEER_CLI_PATH || "os";
9
+ const CLI_CWD = process.env.OVERSEER_CLI_CWD || process.cwd();
10
+ /**
11
+ * Execute os CLI command with --json flag
12
+ */
13
+ export async function callCli(args) {
14
+ return new Promise((resolve, reject) => {
15
+ const proc = spawn(CLI_PATH, [...args, "--json"], {
16
+ cwd: CLI_CWD,
17
+ stdio: ["ignore", "pipe", "pipe"],
18
+ });
19
+ const timeout = setTimeout(() => {
20
+ proc.kill("SIGTERM");
21
+ reject(new CliTimeoutError());
22
+ }, CLI_TIMEOUT_MS);
23
+ let stdout = "";
24
+ let stderr = "";
25
+ proc.stdout.on("data", (chunk) => {
26
+ stdout += chunk.toString();
27
+ });
28
+ proc.stderr.on("data", (chunk) => {
29
+ stderr += chunk.toString();
30
+ });
31
+ proc.on("error", (err) => {
32
+ clearTimeout(timeout);
33
+ reject(new CliError(`Failed to spawn os: ${err.message}`, -1, ""));
34
+ });
35
+ proc.on("close", (code) => {
36
+ clearTimeout(timeout);
37
+ if (code !== 0) {
38
+ const message = stderr.trim() || `os exited with code ${code}`;
39
+ reject(new CliError(message, code ?? -1, stderr));
40
+ return;
41
+ }
42
+ try {
43
+ const result = JSON.parse(stdout);
44
+ resolve(result);
45
+ }
46
+ catch (err) {
47
+ reject(new CliError(`Invalid JSON from os: ${err instanceof Error ? err.message : String(err)}`, 0, stdout));
48
+ }
49
+ });
50
+ });
51
+ }
52
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEvD,MAAM,cAAc,GAAG,MAAM,CAAC;AAE9B,gDAAgD;AAChD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,IAAI,CAAC;AACvD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;AAE9D;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAc;IAC1C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,QAAQ,CAAC,EAAE;YAChD,GAAG,EAAE,OAAO;YACZ,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;SAClC,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACrB,MAAM,CAAC,IAAI,eAAe,EAAE,CAAC,CAAC;QAChC,CAAC,EAAE,cAAc,CAAC,CAAC;QAEnB,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YAC/B,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YAC/B,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACvB,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,MAAM,CAAC,IAAI,QAAQ,CAAC,uBAAuB,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QACrE,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACxB,YAAY,CAAC,OAAO,CAAC,CAAC;YAEtB,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBACf,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,uBAAuB,IAAI,EAAE,CAAC;gBAC/D,MAAM,CAAC,IAAI,QAAQ,CAAC,OAAO,EAAE,IAAI,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;gBAClD,OAAO;YACT,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBAClC,OAAO,CAAC,MAAM,CAAC,CAAC;YAClB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,CACJ,IAAI,QAAQ,CACV,yBAAyB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAC3E,CAAC,EACD,MAAM,CACP,CACF,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Execute agent-provided code in VM sandbox
3
+ */
4
+ export declare function execute(code: string): Promise<unknown>;
5
+ /**
6
+ * Execution error wrapper
7
+ */
8
+ export declare class ExecutionError extends Error {
9
+ readonly stackTrace?: string | undefined;
10
+ constructor(message: string, stackTrace?: string | undefined);
11
+ }
12
+ //# sourceMappingURL=executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"AASA;;GAEG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CA6E5D;AAmBD;;GAEG;AACH,qBAAa,cAAe,SAAQ,KAAK;aAGrB,UAAU,CAAC,EAAE,MAAM;gBADnC,OAAO,EAAE,MAAM,EACC,UAAU,CAAC,EAAE,MAAM,YAAA;CAKtC"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * VM sandbox executor - runs agent code with exposed APIs
3
+ */
4
+ import vm from "node:vm";
5
+ import { tasks } from "./api/tasks.js";
6
+ import { learnings } from "./api/learnings.js";
7
+ const MAX_OUTPUT_SIZE = 50_000; // chars
8
+ /**
9
+ * Execute agent-provided code in VM sandbox
10
+ */
11
+ export async function execute(code) {
12
+ // Track timers to prevent resource leaks
13
+ const timers = new Set();
14
+ const MAX_TIMERS = 100;
15
+ // Create sandbox context with exposed APIs
16
+ // Note: VCS operations are now integrated into task start/complete, not exposed directly
17
+ const sandbox = {
18
+ tasks,
19
+ learnings,
20
+ console: {
21
+ log: (...args) => console.log("[sandbox]", ...args),
22
+ error: (...args) => console.error("[sandbox]", ...args),
23
+ },
24
+ // Wrap setTimeout to track and limit timers
25
+ setTimeout: (handler, timeout) => {
26
+ if (timers.size >= MAX_TIMERS) {
27
+ throw new Error(`Timer limit exceeded (max ${MAX_TIMERS})`);
28
+ }
29
+ const id = setTimeout(() => {
30
+ timers.delete(id);
31
+ handler();
32
+ }, timeout);
33
+ timers.add(id);
34
+ return id;
35
+ },
36
+ // Wrap setInterval to track and limit timers
37
+ setInterval: (handler, timeout) => {
38
+ if (timers.size >= MAX_TIMERS) {
39
+ throw new Error(`Timer limit exceeded (max ${MAX_TIMERS})`);
40
+ }
41
+ const id = setInterval(handler, timeout);
42
+ timers.add(id);
43
+ return id;
44
+ },
45
+ clearTimeout: (id) => {
46
+ timers.delete(id);
47
+ clearTimeout(id);
48
+ },
49
+ clearInterval: (id) => {
50
+ timers.delete(id);
51
+ clearInterval(id);
52
+ },
53
+ Promise,
54
+ };
55
+ // Wrap code in async IIFE to handle await
56
+ const wrappedCode = `
57
+ (async () => {
58
+ ${code}
59
+ })()
60
+ `;
61
+ try {
62
+ const script = new vm.Script(wrappedCode, {
63
+ filename: "agent-code.js",
64
+ });
65
+ const context = vm.createContext(sandbox);
66
+ const result = await script.runInContext(context, {
67
+ timeout: 30_000, // 30s max execution
68
+ });
69
+ return truncateOutput(result);
70
+ }
71
+ catch (err) {
72
+ if (err instanceof Error) {
73
+ throw new ExecutionError(err.message, err.stack);
74
+ }
75
+ throw new ExecutionError(String(err));
76
+ }
77
+ finally {
78
+ // Clean up any remaining timers to prevent resource leaks
79
+ timers.forEach((id) => {
80
+ clearTimeout(id);
81
+ clearInterval(id);
82
+ });
83
+ timers.clear();
84
+ }
85
+ }
86
+ /**
87
+ * Truncate large outputs to prevent response overflow
88
+ */
89
+ function truncateOutput(result) {
90
+ const json = JSON.stringify(result, null, 2);
91
+ if (json.length <= MAX_OUTPUT_SIZE) {
92
+ return result;
93
+ }
94
+ return {
95
+ _truncated: true,
96
+ size: json.length,
97
+ preview: json.slice(0, MAX_OUTPUT_SIZE),
98
+ message: `Output truncated (${json.length} chars, showing first ${MAX_OUTPUT_SIZE})`,
99
+ };
100
+ }
101
+ /**
102
+ * Execution error wrapper
103
+ */
104
+ export class ExecutionError extends Error {
105
+ stackTrace;
106
+ constructor(message, stackTrace) {
107
+ super(message);
108
+ this.stackTrace = stackTrace;
109
+ this.name = "ExecutionError";
110
+ }
111
+ }
112
+ //# sourceMappingURL=executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Overseer MCP Server entry point
4
+ */
5
+ import { startServer } from "./server.js";
6
+ startServer().catch((err) => {
7
+ console.error("Fatal error:", err);
8
+ process.exit(1);
9
+ });
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;GAEG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC1B,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;IACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * MCP Server - registers execute tool with type definitions
3
+ */
4
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
5
+ /**
6
+ * Create and configure MCP server
7
+ */
8
+ export declare function createServer(): Server;
9
+ /**
10
+ * Start MCP server with stdio transport
11
+ */
12
+ export declare function startServer(): Promise<void>;
13
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAwGnE;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAiFrC;AAED;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAKjD"}