@aspectlylabs/mikka 0.0.0-stage → 0.0.1
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/LICENSE +662 -0
- package/README.md +63 -2
- package/agents/native-container.mjs +191 -0
- package/agents/native-egress.mjs +51 -0
- package/cli.js +15433 -0
- package/client.js +3783 -0
- package/computer/driver.mjs +278 -0
- package/computer/proxy.mjs +123 -0
- package/coordinator.js +317 -0
- package/env.js +53 -0
- package/fixtures/ask.jsonl +5 -0
- package/fixtures/blocked-question.jsonl +2 -0
- package/fixtures/check-pass.jsonl +3 -0
- package/fixtures/crash.jsonl +6 -0
- package/fixtures/failure.jsonl +8 -0
- package/fixtures/long-running.jsonl +67 -0
- package/fixtures/plan.jsonl +10 -0
- package/fixtures/quota.jsonl +6 -0
- package/fixtures/run-tests.jsonl +8 -0
- package/fixtures/secret-output.jsonl +11 -0
- package/fixtures/self-verify.jsonl +5 -0
- package/fixtures/stall.jsonl +7 -0
- package/fixtures/success-edit.jsonl +19 -0
- package/fixtures/turn-ended.jsonl +18 -0
- package/fixtures/verify-fails.jsonl +7 -0
- package/http-link.js +4496 -0
- package/log.js +62 -0
- package/login.js +3883 -0
- package/main.js +14348 -0
- package/mikka-mcp.mjs +410 -0
- package/mikka.js +15433 -0
- package/package.json +46 -4
- package/paths.js +108 -0
- package/sandbox.js +133 -0
package/package.json
CHANGED
|
@@ -1,6 +1,48 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aspectlylabs/mikka",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Local Mikka daemon: runs agents through the user's own CLIs",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"private": false,
|
|
7
|
+
"license": "AGPL-3.0-only",
|
|
8
|
+
"engines": {
|
|
9
|
+
"node": ">=24"
|
|
10
|
+
},
|
|
11
|
+
"bin": {
|
|
12
|
+
"mikka": "./mikka.js"
|
|
13
|
+
},
|
|
14
|
+
"exports": {
|
|
15
|
+
".": "./main.js",
|
|
16
|
+
"./cli": "./cli.js",
|
|
17
|
+
"./client": "./client.js",
|
|
18
|
+
"./env": "./env.js",
|
|
19
|
+
"./paths": "./paths.js",
|
|
20
|
+
"./http-link": "./http-link.js",
|
|
21
|
+
"./login": "./login.js",
|
|
22
|
+
"./log": "./log.js",
|
|
23
|
+
"./sandbox": "./sandbox.js",
|
|
24
|
+
"./coordinator": "./coordinator.js"
|
|
25
|
+
},
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/alexj11324/Mikka.git",
|
|
29
|
+
"directory": "packages/daemon"
|
|
30
|
+
},
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public",
|
|
33
|
+
"provenance": true
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@agentclientprotocol/sdk": "1.9.0",
|
|
37
|
+
"@anthropic-ai/claude-agent-sdk": "^0.3.305",
|
|
38
|
+
"@anthropic-ai/sandbox-runtime": "0.0.80",
|
|
39
|
+
"ai": "7.0.142",
|
|
40
|
+
"execa": "10.1.1",
|
|
41
|
+
"pino": "10.4.0",
|
|
42
|
+
"proper-lockfile": "4.1.2",
|
|
43
|
+
"rotating-file-stream": "3.2.10",
|
|
44
|
+
"simple-git": "4.0.2",
|
|
45
|
+
"vscode-jsonrpc": "9.0.3",
|
|
46
|
+
"zod": "4.6.7"
|
|
47
|
+
}
|
|
48
|
+
}
|
package/paths.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// src/paths.ts
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
|
|
6
|
+
// package.json
|
|
7
|
+
var package_default = {
|
|
8
|
+
name: "@mikka/daemon",
|
|
9
|
+
version: "0.0.1",
|
|
10
|
+
description: "Local Mikka daemon: runs agents through the user's own CLIs",
|
|
11
|
+
type: "module",
|
|
12
|
+
private: true,
|
|
13
|
+
license: "AGPL-3.0-only",
|
|
14
|
+
bin: {
|
|
15
|
+
mikka: "./dist/mikka.js"
|
|
16
|
+
},
|
|
17
|
+
exports: {
|
|
18
|
+
".": "./src/main.ts",
|
|
19
|
+
"./cli": "./src/cli.ts",
|
|
20
|
+
"./client": "./src/rpc/client.ts",
|
|
21
|
+
"./env": "./src/env.ts",
|
|
22
|
+
"./paths": "./src/paths.ts",
|
|
23
|
+
"./http-link": "./src/server-link-http.ts",
|
|
24
|
+
"./login": "./src/login.ts",
|
|
25
|
+
"./log": "./src/log.ts",
|
|
26
|
+
"./sandbox": "./src/agents/sandbox.ts",
|
|
27
|
+
"./coordinator": "./src/coordinator/index.ts"
|
|
28
|
+
},
|
|
29
|
+
scripts: {
|
|
30
|
+
daemon: "tsx bin/mikka.ts daemon",
|
|
31
|
+
dev: "tsx watch bin/mikka.ts daemon --dev --server memory",
|
|
32
|
+
typecheck: "tsgo --noEmit -p tsconfig.json",
|
|
33
|
+
test: "vitest run && pnpm test:mailbox-cli && pnpm test:repository-identity",
|
|
34
|
+
"test:mailbox-cli": "node --import tsx --test --test-timeout=60000 test/run-mailbox.node-test.ts",
|
|
35
|
+
"codex:types": 'codex app-server generate-ts --out "${TMPDIR:-/tmp}/mikka-codex-types" && echo "Generated; compare v2/ with src/adapters/codex-protocol.ts"',
|
|
36
|
+
"test:real": "MIKKA_REAL_AGENTS=${MIKKA_REAL_AGENTS:-claude_code,codex,cursor} vitest run test/real-agents.test.ts",
|
|
37
|
+
"test:changed": "vitest run --changed origin/main --passWithNoTests",
|
|
38
|
+
build: "node scripts/build.mjs",
|
|
39
|
+
"test:package": "node --test test/package.test.mjs",
|
|
40
|
+
"test:repository-identity": "node --experimental-strip-types --test test/repository-identity-pure.node-test.ts"
|
|
41
|
+
},
|
|
42
|
+
dependencies: {
|
|
43
|
+
"@agentclientprotocol/sdk": "1.9.0",
|
|
44
|
+
"@anthropic-ai/claude-agent-sdk": "^0.3.305",
|
|
45
|
+
"@anthropic-ai/sandbox-runtime": "0.0.80",
|
|
46
|
+
"@mikka/protocol": "workspace:*",
|
|
47
|
+
ai: "7.0.142",
|
|
48
|
+
execa: "10.1.1",
|
|
49
|
+
pino: "10.4.0",
|
|
50
|
+
"proper-lockfile": "4.1.2",
|
|
51
|
+
"rotating-file-stream": "3.2.10",
|
|
52
|
+
"simple-git": "4.0.2",
|
|
53
|
+
"vscode-jsonrpc": "9.0.3",
|
|
54
|
+
zod: "4.6.7"
|
|
55
|
+
},
|
|
56
|
+
devDependencies: {
|
|
57
|
+
"@mikka/config": "workspace:*",
|
|
58
|
+
"@types/node": "24.19.2",
|
|
59
|
+
"@types/proper-lockfile": "4.1.4",
|
|
60
|
+
tsx: "4.23.15",
|
|
61
|
+
esbuild: "0.28.2",
|
|
62
|
+
vitest: "5.0.5"
|
|
63
|
+
},
|
|
64
|
+
engines: {
|
|
65
|
+
node: ">=24"
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// src/paths.ts
|
|
70
|
+
var DAEMON_VERSION = package_default.version;
|
|
71
|
+
function productName(flavor) {
|
|
72
|
+
return flavor === "dev" ? "Mikka Dev" : "Mikka";
|
|
73
|
+
}
|
|
74
|
+
function defaultDataDir(flavor, env = process.env, platform = process.platform) {
|
|
75
|
+
if (flavor === "dev" && env.MIKKA_USER_DATA_DIR) {
|
|
76
|
+
return env.MIKKA_USER_DATA_DIR;
|
|
77
|
+
}
|
|
78
|
+
const home = env.HOME || homedir();
|
|
79
|
+
const base = platform === "darwin" ? join(home, "Library", "Application Support") : platform === "win32" ? env.APPDATA || join(home, "AppData", "Roaming") : env.XDG_CONFIG_HOME || join(home, ".config");
|
|
80
|
+
const dir = join(base, productName(flavor));
|
|
81
|
+
const legacy = join(base, legacyProductName(flavor));
|
|
82
|
+
return !existsSync(dir) && existsSync(legacy) ? legacy : dir;
|
|
83
|
+
}
|
|
84
|
+
function legacyProductName(flavor) {
|
|
85
|
+
return flavor === "dev" ? "Orvilo Dev" : "Orvilo";
|
|
86
|
+
}
|
|
87
|
+
function daemonPaths(dataDir) {
|
|
88
|
+
return {
|
|
89
|
+
dataDir,
|
|
90
|
+
socket: join(dataDir, "daemon.sock"),
|
|
91
|
+
lock: join(dataDir, "daemon.lock"),
|
|
92
|
+
secret: join(dataDir, "daemon.secret"),
|
|
93
|
+
device: join(dataDir, "device.json"),
|
|
94
|
+
journal: join(dataDir, "runs.json"),
|
|
95
|
+
outbox: join(dataDir, "outbox"),
|
|
96
|
+
worktrees: join(dataDir, "worktrees"),
|
|
97
|
+
repos: join(dataDir, "repos"),
|
|
98
|
+
adapterState: join(dataDir, "adapters"),
|
|
99
|
+
logs: join(dataDir, "logs"),
|
|
100
|
+
devRepos: join(dataDir, "dev-repos.json")
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
export {
|
|
104
|
+
DAEMON_VERSION,
|
|
105
|
+
daemonPaths,
|
|
106
|
+
defaultDataDir,
|
|
107
|
+
productName
|
|
108
|
+
};
|
package/sandbox.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// src/agents/sandbox.ts
|
|
2
|
+
import { randomBytes } from "node:crypto";
|
|
3
|
+
import { SandboxManager } from "@anthropic-ai/sandbox-runtime";
|
|
4
|
+
import { execa } from "execa";
|
|
5
|
+
function shellQuote(arg) {
|
|
6
|
+
if (/^[A-Za-z0-9_@%+=:,./-]+$/.test(arg)) return arg;
|
|
7
|
+
return `'${arg.replaceAll("'", `'"'"'`)}'`;
|
|
8
|
+
}
|
|
9
|
+
function shellJoin(argv) {
|
|
10
|
+
return argv.map(shellQuote).join(" ");
|
|
11
|
+
}
|
|
12
|
+
var SandboxRuntime = class _SandboxRuntime {
|
|
13
|
+
constructor(onAsk) {
|
|
14
|
+
this.onAsk = onAsk;
|
|
15
|
+
}
|
|
16
|
+
onAsk;
|
|
17
|
+
kind = "sandbox-runtime";
|
|
18
|
+
static owner = null;
|
|
19
|
+
ready = null;
|
|
20
|
+
resetting = null;
|
|
21
|
+
/** The platform is supported and its tools (Linux: bwrap, socat, rg) exist. */
|
|
22
|
+
static supported() {
|
|
23
|
+
return SandboxManager.isSupportedPlatform() && SandboxManager.checkDependencies().errors.length === 0;
|
|
24
|
+
}
|
|
25
|
+
/** Check that the runtime can actually start isolation on this host. */
|
|
26
|
+
async probe() {
|
|
27
|
+
const wrapped = await this.wrap(["/bin/sh", "-c", ":"], {
|
|
28
|
+
allowWrite: [],
|
|
29
|
+
allowDomains: []
|
|
30
|
+
});
|
|
31
|
+
try {
|
|
32
|
+
const result = await execa("/bin/sh", ["-c", wrapped.command], {
|
|
33
|
+
reject: false,
|
|
34
|
+
timeout: 1e4
|
|
35
|
+
});
|
|
36
|
+
if (result.failed) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
`sandbox probe failed: ${result.timedOut ? "timed out" : result.stderr.trim() || `exit ${result.exitCode}`}`
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
} finally {
|
|
42
|
+
wrapped.release();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
init() {
|
|
46
|
+
if (this.resetting) return Promise.reject(new Error("sandbox runtime is stopping"));
|
|
47
|
+
if (this.ready) return this.ready;
|
|
48
|
+
if (_SandboxRuntime.owner && _SandboxRuntime.owner !== this) {
|
|
49
|
+
return Promise.reject(new Error("sandbox runtime is already in use by another instance"));
|
|
50
|
+
}
|
|
51
|
+
_SandboxRuntime.owner = this;
|
|
52
|
+
this.ready = SandboxManager.initialize(
|
|
53
|
+
{
|
|
54
|
+
// Everything is per run (`registerCommandNetworkLists`).
|
|
55
|
+
network: { allowedDomains: [], deniedDomains: [] },
|
|
56
|
+
filesystem: { denyRead: [], allowWrite: [], denyWrite: [] },
|
|
57
|
+
// Rust and Go CLIs (codex) verify TLS through trustd; without it
|
|
58
|
+
// every HTTPS request from them fails inside the sandbox.
|
|
59
|
+
enableWeakerNetworkIsolation: true
|
|
60
|
+
},
|
|
61
|
+
async ({ host, port }) => await this.onAsk?.({ host, port }) === true
|
|
62
|
+
).catch(async (error) => {
|
|
63
|
+
await SandboxManager.reset().catch(() => void 0);
|
|
64
|
+
_SandboxRuntime.owner = null;
|
|
65
|
+
this.ready = null;
|
|
66
|
+
throw error;
|
|
67
|
+
});
|
|
68
|
+
return this.ready;
|
|
69
|
+
}
|
|
70
|
+
async wrap(argv, policy) {
|
|
71
|
+
await this.init();
|
|
72
|
+
const commandId = randomBytes(16).toString("base64url");
|
|
73
|
+
const command = await SandboxManager.wrapWithSandbox(
|
|
74
|
+
shellJoin(argv),
|
|
75
|
+
"/bin/sh",
|
|
76
|
+
{
|
|
77
|
+
filesystem: {
|
|
78
|
+
denyRead: policy.denyRead ?? [],
|
|
79
|
+
allowWrite: policy.allowWrite,
|
|
80
|
+
denyWrite: policy.denyWrite ?? []
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
void 0,
|
|
84
|
+
{ commandId }
|
|
85
|
+
);
|
|
86
|
+
SandboxManager.registerCommandNetworkLists(commandId, {
|
|
87
|
+
allowedDomains: policy.allowDomains
|
|
88
|
+
});
|
|
89
|
+
let released = false;
|
|
90
|
+
return {
|
|
91
|
+
command,
|
|
92
|
+
annotate: (stderr) => SandboxManager.annotateStderrWithSandboxFailures(commandId, stderr),
|
|
93
|
+
release() {
|
|
94
|
+
if (released) return;
|
|
95
|
+
released = true;
|
|
96
|
+
SandboxManager.unregisterCommandNetworkLists(commandId);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/** Stops the proxy; the next `wrap` starts it again. */
|
|
101
|
+
reset() {
|
|
102
|
+
if (this.resetting) return this.resetting;
|
|
103
|
+
if (_SandboxRuntime.owner !== this) return Promise.resolve();
|
|
104
|
+
this.resetting = (async () => {
|
|
105
|
+
try {
|
|
106
|
+
await this.ready?.catch(() => void 0);
|
|
107
|
+
if (_SandboxRuntime.owner === this) await SandboxManager.reset();
|
|
108
|
+
} finally {
|
|
109
|
+
if (_SandboxRuntime.owner === this) _SandboxRuntime.owner = null;
|
|
110
|
+
this.ready = null;
|
|
111
|
+
this.resetting = null;
|
|
112
|
+
}
|
|
113
|
+
})();
|
|
114
|
+
return this.resetting;
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
var NoSandbox = class {
|
|
118
|
+
kind = "none";
|
|
119
|
+
async wrap(argv) {
|
|
120
|
+
return {
|
|
121
|
+
command: `exec ${shellJoin(argv)}`,
|
|
122
|
+
annotate: (stderr) => stderr,
|
|
123
|
+
release() {
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
export {
|
|
129
|
+
NoSandbox,
|
|
130
|
+
SandboxRuntime,
|
|
131
|
+
shellJoin,
|
|
132
|
+
shellQuote
|
|
133
|
+
};
|