@aspectlylabs/mikka 0.0.141 → 0.0.143
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/agents/native-container.mjs +4 -1
- package/cli.js +275 -99
- package/client.js +18 -3
- package/http-link.js +20 -3
- package/login.js +18 -3
- package/main.js +273 -99
- package/mikka-release-manifest.json +21 -21
- package/mikka.js +275 -99
- package/npm-shrinkwrap.json +2 -2
- package/package.json +2 -2
- package/paths.js +2 -2
- package/sbom.cdx.json +7 -7
package/mikka.js
CHANGED
|
@@ -3561,6 +3561,16 @@ var setupRecipeSchema = z14.object({
|
|
|
3561
3561
|
approved: z14.boolean()
|
|
3562
3562
|
});
|
|
3563
3563
|
var REPO_ORIGIN_HEADER = "x-mikka-repo-origin-check";
|
|
3564
|
+
var MODEL_CREDENTIAL_HEADER = "x-mikka-model-credential";
|
|
3565
|
+
var credentialKey = z14.string().min(1).max(4096).refine((value) => !/[\r\n\0]/.test(value));
|
|
3566
|
+
var credentialBaseUrl = z14.url().max(500).refine((value) => {
|
|
3567
|
+
const url = new URL(value);
|
|
3568
|
+
return url.protocol === "https:" && !url.username && !url.password && !url.search && !url.hash;
|
|
3569
|
+
});
|
|
3570
|
+
var runModelCredentialSchema = z14.discriminatedUnion("kind", [
|
|
3571
|
+
z14.object({ kind: z14.literal("api_key"), key: credentialKey }).strict(),
|
|
3572
|
+
z14.object({ kind: z14.literal("provider"), protocol: z14.enum(["anthropic", "openai"]), baseUrl: credentialBaseUrl, key: credentialKey }).strict()
|
|
3573
|
+
]);
|
|
3564
3574
|
var deviceRepoSchema = z14.object({
|
|
3565
3575
|
repoId: id2,
|
|
3566
3576
|
name: z14.string().max(500),
|
|
@@ -3608,6 +3618,12 @@ var runAssignmentSchema = z14.object({
|
|
|
3608
3618
|
consumerId: z14.uuid(),
|
|
3609
3619
|
route: z14.enum(["codex_cli", "claude_code_cli"])
|
|
3610
3620
|
}).strict().optional(),
|
|
3621
|
+
/**
|
|
3622
|
+
* The run's own API key, opened for this claim only. Never with
|
|
3623
|
+
* `subscriptionBinding`. The daemon keeps it in memory and hands it only
|
|
3624
|
+
* to the run's Agent process or container; it is never journaled.
|
|
3625
|
+
*/
|
|
3626
|
+
modelCredential: runModelCredentialSchema.optional(),
|
|
3611
3627
|
/** Local host authority comes only from the server's owner-bound Bot run. */
|
|
3612
3628
|
localComputer: z14.object({
|
|
3613
3629
|
botId: z14.uuid(),
|
|
@@ -3725,7 +3741,7 @@ var runAssignmentSchema = z14.object({
|
|
|
3725
3741
|
skillReceipt: skillAssignmentReceiptSchema.optional(),
|
|
3726
3742
|
/** Frozen by the server benchmark ledger; never extracted from model output. */
|
|
3727
3743
|
benchmark: runBenchmarkContext.optional()
|
|
3728
|
-
});
|
|
3744
|
+
}).refine((value) => !(value.modelCredential && value.subscriptionBinding), { message: "A run has one model credential", path: ["modelCredential"] });
|
|
3729
3745
|
var runPatchSchema = z14.object({
|
|
3730
3746
|
state: z14.enum([
|
|
3731
3747
|
"queued",
|
|
@@ -4458,7 +4474,7 @@ import { join as join4 } from "node:path";
|
|
|
4458
4474
|
// package.json
|
|
4459
4475
|
var package_default = {
|
|
4460
4476
|
name: "@mikka/daemon",
|
|
4461
|
-
version: "0.0.
|
|
4477
|
+
version: "0.0.143",
|
|
4462
4478
|
description: "Local Mikka daemon: runs agents through the user's own CLIs",
|
|
4463
4479
|
type: "module",
|
|
4464
4480
|
private: true,
|
|
@@ -4518,7 +4534,7 @@ var package_default = {
|
|
|
4518
4534
|
engines: {
|
|
4519
4535
|
node: ">=24"
|
|
4520
4536
|
},
|
|
4521
|
-
gitHead: "
|
|
4537
|
+
gitHead: "1a7ea7ffcdb44a8228f84d936a7a395f33f13355"
|
|
4522
4538
|
};
|
|
4523
4539
|
|
|
4524
4540
|
// src/paths.ts
|
|
@@ -5359,6 +5375,7 @@ var HttpServerLink = class {
|
|
|
5359
5375
|
[TEAM_SKILL_HEADER]: "1",
|
|
5360
5376
|
[REPO_ORIGIN_HEADER]: "1",
|
|
5361
5377
|
[RECOVERY_WORKTREE_HEADER]: "1",
|
|
5378
|
+
[MODEL_CREDENTIAL_HEADER]: "1",
|
|
5362
5379
|
...token ? { authorization: `Bearer ${token}` } : {},
|
|
5363
5380
|
...this.protectionBypass ? { "x-vercel-protection-bypass": this.protectionBypass } : {}
|
|
5364
5381
|
},
|
|
@@ -7659,15 +7676,15 @@ sandbox_mode = "read-only"
|
|
|
7659
7676
|
// src/main.ts
|
|
7660
7677
|
import { randomBytes as randomBytes4, randomUUID as randomUUID10 } from "node:crypto";
|
|
7661
7678
|
import {
|
|
7662
|
-
chmodSync as
|
|
7679
|
+
chmodSync as chmodSync6,
|
|
7663
7680
|
existsSync as existsSync9,
|
|
7664
|
-
mkdirSync as
|
|
7681
|
+
mkdirSync as mkdirSync19,
|
|
7665
7682
|
readFileSync as readFileSync12,
|
|
7666
|
-
rmSync as
|
|
7683
|
+
rmSync as rmSync21,
|
|
7667
7684
|
realpathSync as realpathSync12
|
|
7668
7685
|
} from "node:fs";
|
|
7669
7686
|
import { arch as arch2, hostname, platform as platform3 } from "node:os";
|
|
7670
|
-
import { join as
|
|
7687
|
+
import { join as join32 } from "node:path";
|
|
7671
7688
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
7672
7689
|
|
|
7673
7690
|
// src/adapters/claude.ts
|
|
@@ -8509,7 +8526,8 @@ var ClaudeAdapter = class {
|
|
|
8509
8526
|
},
|
|
8510
8527
|
...mode === "new" ? { sessionId } : { resume: sessionId },
|
|
8511
8528
|
...options.model ? { model: options.model } : {},
|
|
8512
|
-
|
|
8529
|
+
// A hosted runtime always spawns into its own container; an API-key run there holds the placeholder too.
|
|
8530
|
+
...outerLocal ? { spawnClaudeCodeProcess: spawnOuter } : this.options.spawnHosted ? { spawnClaudeCodeProcess: (options2) => this.options.spawnHosted(options2, nativeToken ?? NATIVE_AUTH_PLACEHOLDER) } : binary || externalAuth ? { spawnClaudeCodeProcess: spawnBinary(binary, nativeToken) } : {},
|
|
8513
8531
|
stderr: (data) => {
|
|
8514
8532
|
if (!externalAuth) stderr = (stderr + data).slice(-STDERR_TAIL2 * 4);
|
|
8515
8533
|
}
|
|
@@ -11476,7 +11494,10 @@ function withoutTaskEnv(assignment) {
|
|
|
11476
11494
|
|
|
11477
11495
|
// src/runs/journal.ts
|
|
11478
11496
|
function persisted(entries) {
|
|
11479
|
-
return Object.fromEntries(Object.entries(entries).map(([id4, entry]) =>
|
|
11497
|
+
return Object.fromEntries(Object.entries(entries).map(([id4, entry]) => {
|
|
11498
|
+
const { modelCredential, ...assignment } = withoutTaskEnv(entry.assignment);
|
|
11499
|
+
return [id4, { ...entry, assignment, ...modelCredential ? { credentialWithheld: true } : {} }];
|
|
11500
|
+
}));
|
|
11480
11501
|
}
|
|
11481
11502
|
var RunJournal = class {
|
|
11482
11503
|
constructor(file) {
|
|
@@ -12241,10 +12262,10 @@ var RunSupervisor = class {
|
|
|
12241
12262
|
}
|
|
12242
12263
|
const existing = this.deps.journal.get(assignment.runId);
|
|
12243
12264
|
if (existing) return this.summary(existing);
|
|
12244
|
-
const masker = createRunMasker((assignment.taskSecretNames ?? []).flatMap((name) => {
|
|
12265
|
+
const masker = createRunMasker([...(assignment.taskSecretNames ?? []).flatMap((name) => {
|
|
12245
12266
|
const value = assignment.taskEnv?.[name];
|
|
12246
12267
|
return typeof value === "string" ? [{ name, value }] : [];
|
|
12247
|
-
}));
|
|
12268
|
+
}), ...assignment.modelCredential ? [{ name: "MODEL_API_KEY", value: assignment.modelCredential.key }] : []]);
|
|
12248
12269
|
if (masker) this.maskers.set(assignment.runId, masker);
|
|
12249
12270
|
let repo;
|
|
12250
12271
|
try {
|
|
@@ -12344,6 +12365,10 @@ var RunSupervisor = class {
|
|
|
12344
12365
|
}
|
|
12345
12366
|
continue;
|
|
12346
12367
|
}
|
|
12368
|
+
if (entry.credentialWithheld && !entry.assignment.modelCredential) {
|
|
12369
|
+
this.finish(entry.assignment.runId, "error", "The run stopped with the daemon; its API key is not kept. Retry the thread.");
|
|
12370
|
+
continue;
|
|
12371
|
+
}
|
|
12347
12372
|
if (entry.assignment.leaseExpiresAt)
|
|
12348
12373
|
this.leases.set(entry.assignment.runId, Date.now() + DEFAULT_LEASE_MS);
|
|
12349
12374
|
this.launch(entry.assignment.runId, repo);
|
|
@@ -12921,7 +12946,9 @@ var RunSupervisor = class {
|
|
|
12921
12946
|
} : void 0,
|
|
12922
12947
|
fixture: assignment.fixture,
|
|
12923
12948
|
model: assignment.model,
|
|
12924
|
-
mailbox
|
|
12949
|
+
mailbox,
|
|
12950
|
+
// In memory only: the adapter hands it to the run's CLI environment.
|
|
12951
|
+
credential: assignment.modelCredential
|
|
12925
12952
|
};
|
|
12926
12953
|
const resuming = entry.sessionId !== null && adapter.capabilities.supportsResume;
|
|
12927
12954
|
const inEarlierWorktree = continued !== null || entry.worktree !== null && resolve11(entry.worktree) !== resolve11(this.deps.worktrees.pathFor(runId));
|
|
@@ -12946,8 +12973,9 @@ var RunSupervisor = class {
|
|
|
12946
12973
|
const previousExecution = entry.execution;
|
|
12947
12974
|
const previousRuntime = entry.runtime;
|
|
12948
12975
|
let session;
|
|
12976
|
+
if (assignment.subscriptionBinding && assignment.modelCredential) throw new Error("A run has one model credential");
|
|
12949
12977
|
try {
|
|
12950
|
-
session = assignment.subscriptionBinding ? this.deps.startSubscription ? await this.deps.startSubscription(assignment, { ...options, prompt: assignment.prompt }) : (() => {
|
|
12978
|
+
session = assignment.modelCredential && this.deps.startCredential ? await this.deps.startCredential(assignment, { ...options, prompt: assignment.prompt }) : assignment.subscriptionBinding ? this.deps.startSubscription ? await this.deps.startSubscription(assignment, { ...options, prompt: assignment.prompt }) : (() => {
|
|
12951
12979
|
throw new Error("subscription_hosted_runtime_unavailable");
|
|
12952
12980
|
})() : resuming ? await adapter.resume(entry.sessionId, options) : await (async () => {
|
|
12953
12981
|
if (assignment.requireSessionResume)
|
|
@@ -13351,16 +13379,141 @@ import { randomUUID as randomUUID8 } from "node:crypto";
|
|
|
13351
13379
|
import {
|
|
13352
13380
|
existsSync as existsSync8,
|
|
13353
13381
|
lstatSync as lstatSync10,
|
|
13354
|
-
mkdirSync as
|
|
13355
|
-
mkdtempSync as
|
|
13382
|
+
mkdirSync as mkdirSync18,
|
|
13383
|
+
mkdtempSync as mkdtempSync9,
|
|
13356
13384
|
readdirSync as readdirSync9,
|
|
13357
13385
|
realpathSync as realpathSync11,
|
|
13358
|
-
rmSync as
|
|
13386
|
+
rmSync as rmSync20
|
|
13359
13387
|
} from "node:fs";
|
|
13360
13388
|
import { createRequire } from "node:module";
|
|
13361
|
-
import { delimiter as delimiter3, dirname as dirname15, join as
|
|
13389
|
+
import { delimiter as delimiter3, dirname as dirname15, join as join31 } from "node:path";
|
|
13362
13390
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
13363
13391
|
import { promisify as promisify6 } from "node:util";
|
|
13392
|
+
|
|
13393
|
+
// src/api-key-broker.ts
|
|
13394
|
+
import { chmodSync as chmodSync4, mkdirSync as mkdirSync17, mkdtempSync as mkdtempSync8, rmSync as rmSync19 } from "node:fs";
|
|
13395
|
+
import { createServer as createServer4 } from "node:http";
|
|
13396
|
+
import { join as join30 } from "node:path";
|
|
13397
|
+
import { once as once2 } from "node:events";
|
|
13398
|
+
var DEFAULT_BASE = { anthropic: "https://api.anthropic.com", openai: "https://api.openai.com/v1" };
|
|
13399
|
+
var PATHS = {
|
|
13400
|
+
anthropic: /* @__PURE__ */ new Set(["/v1/messages", "/v1/messages/count_tokens"]),
|
|
13401
|
+
openai: /* @__PURE__ */ new Set(["/responses", "/responses/compact"])
|
|
13402
|
+
};
|
|
13403
|
+
var FORWARD = ["content-type", "accept", "anthropic-version", "anthropic-beta", "openai-beta", "user-agent"];
|
|
13404
|
+
var RETURN = ["content-type", "retry-after", "request-id", "x-request-id"];
|
|
13405
|
+
var MAX_BODY = 32 * 1024 * 1024;
|
|
13406
|
+
async function createApiKeyBroker(host) {
|
|
13407
|
+
const { credential, protocol } = host;
|
|
13408
|
+
if (credential.kind === "provider" && credential.protocol !== protocol) throw new Error("api_key_broker_unavailable");
|
|
13409
|
+
const base = new URL(credential.kind === "provider" ? credential.baseUrl : DEFAULT_BASE[protocol]);
|
|
13410
|
+
if (base.protocol !== "https:" || base.username || base.password || !credential.key || /[\r\n\0]/.test(credential.key))
|
|
13411
|
+
throw new Error("api_key_broker_unavailable");
|
|
13412
|
+
const origin = base.href.replace(/\/+$/, "");
|
|
13413
|
+
let key2 = credential.key;
|
|
13414
|
+
const send = host.fetch ?? fetch;
|
|
13415
|
+
await host.check();
|
|
13416
|
+
mkdirSync17(host.root, { recursive: true, mode: 448 });
|
|
13417
|
+
const dir = mkdtempSync8(join30(host.root, "api-key-broker-"));
|
|
13418
|
+
chmodSync4(dir, 448);
|
|
13419
|
+
const socket = join30(dir, "broker.sock");
|
|
13420
|
+
const pending = /* @__PURE__ */ new Set();
|
|
13421
|
+
let halted = false;
|
|
13422
|
+
const server = createServer4(async (request, response) => {
|
|
13423
|
+
const abort = new AbortController();
|
|
13424
|
+
pending.add(abort);
|
|
13425
|
+
response.on("close", () => {
|
|
13426
|
+
if (!response.writableFinished) abort.abort();
|
|
13427
|
+
});
|
|
13428
|
+
try {
|
|
13429
|
+
const url = new URL(request.url ?? "/", "http://broker");
|
|
13430
|
+
if (halted || !key2 || request.method !== "POST" || (request.url ?? "").length > 256 || !PATHS[protocol].has(url.pathname) || url.search && url.search !== "?beta=true") {
|
|
13431
|
+
response.writeHead(404, { "content-type": "application/json", "cache-control": "no-store" }).end('{"error":"not_found"}');
|
|
13432
|
+
return;
|
|
13433
|
+
}
|
|
13434
|
+
const chunks = [];
|
|
13435
|
+
let length = 0;
|
|
13436
|
+
for await (const part of request) {
|
|
13437
|
+
length += part.length;
|
|
13438
|
+
if (length > MAX_BODY) throw new Error("request refused");
|
|
13439
|
+
chunks.push(part);
|
|
13440
|
+
}
|
|
13441
|
+
await host.check();
|
|
13442
|
+
if (halted || !key2 || abort.signal.aborted) throw new Error("request refused");
|
|
13443
|
+
const headers = {};
|
|
13444
|
+
for (const name of FORWARD) {
|
|
13445
|
+
const value = request.headers[name];
|
|
13446
|
+
if (typeof value === "string") headers[name] = value;
|
|
13447
|
+
}
|
|
13448
|
+
if (headers["anthropic-beta"]) {
|
|
13449
|
+
const betas = headers["anthropic-beta"].split(",").map((item) => item.trim()).filter((item) => item && !item.startsWith("oauth-"));
|
|
13450
|
+
if (betas.length) headers["anthropic-beta"] = betas.join(",");
|
|
13451
|
+
else delete headers["anthropic-beta"];
|
|
13452
|
+
}
|
|
13453
|
+
if (protocol === "anthropic") headers["x-api-key"] = key2;
|
|
13454
|
+
else headers.authorization = `Bearer ${key2}`;
|
|
13455
|
+
const upstream = await send(origin + url.pathname + url.search, {
|
|
13456
|
+
method: "POST",
|
|
13457
|
+
headers,
|
|
13458
|
+
body: Buffer.concat(chunks),
|
|
13459
|
+
redirect: "error",
|
|
13460
|
+
signal: abort.signal,
|
|
13461
|
+
cache: "no-store"
|
|
13462
|
+
});
|
|
13463
|
+
const returned = { "cache-control": "no-store" };
|
|
13464
|
+
for (const name of RETURN) {
|
|
13465
|
+
const value = upstream.headers.get(name);
|
|
13466
|
+
if (value) returned[name] = value;
|
|
13467
|
+
}
|
|
13468
|
+
response.writeHead(upstream.status, returned);
|
|
13469
|
+
if (upstream.body) {
|
|
13470
|
+
const reader = upstream.body.getReader();
|
|
13471
|
+
try {
|
|
13472
|
+
for (; ; ) {
|
|
13473
|
+
const { done, value } = await reader.read();
|
|
13474
|
+
if (done) break;
|
|
13475
|
+
if (abort.signal.aborted) throw new Error("request cancelled");
|
|
13476
|
+
if (!response.write(value)) await once2(response, "drain", { signal: abort.signal });
|
|
13477
|
+
}
|
|
13478
|
+
} finally {
|
|
13479
|
+
await reader.cancel().catch(() => void 0);
|
|
13480
|
+
reader.releaseLock();
|
|
13481
|
+
}
|
|
13482
|
+
}
|
|
13483
|
+
response.end();
|
|
13484
|
+
} catch {
|
|
13485
|
+
abort.abort();
|
|
13486
|
+
if (response.headersSent) response.destroy();
|
|
13487
|
+
else response.writeHead(502, { "content-type": "application/json", "cache-control": "no-store" }).end(JSON.stringify({ type: "error", error: { type: "api_key_unavailable", message: "API key unavailable" } }));
|
|
13488
|
+
} finally {
|
|
13489
|
+
pending.delete(abort);
|
|
13490
|
+
}
|
|
13491
|
+
});
|
|
13492
|
+
try {
|
|
13493
|
+
await new Promise((resolve13, reject) => {
|
|
13494
|
+
server.once("error", reject);
|
|
13495
|
+
server.listen(socket, resolve13);
|
|
13496
|
+
});
|
|
13497
|
+
chmodSync4(socket, 384);
|
|
13498
|
+
} catch {
|
|
13499
|
+
key2 = void 0;
|
|
13500
|
+
rmSync19(dir, { recursive: true, force: true });
|
|
13501
|
+
throw new Error("api_key_broker_unavailable");
|
|
13502
|
+
}
|
|
13503
|
+
return {
|
|
13504
|
+
socket,
|
|
13505
|
+
async close() {
|
|
13506
|
+
halted = true;
|
|
13507
|
+
key2 = void 0;
|
|
13508
|
+
for (const abort of pending) abort.abort();
|
|
13509
|
+
server.closeAllConnections();
|
|
13510
|
+
await new Promise((resolve13) => server.close(() => resolve13()));
|
|
13511
|
+
rmSync19(dir, { recursive: true, force: true });
|
|
13512
|
+
}
|
|
13513
|
+
};
|
|
13514
|
+
}
|
|
13515
|
+
|
|
13516
|
+
// src/subscription-hosted-runner.ts
|
|
13364
13517
|
var exec3 = promisify6(execFile6);
|
|
13365
13518
|
var image = HOSTED_NATIVE_IMAGE;
|
|
13366
13519
|
var bootstrap = fileURLToPath3(
|
|
@@ -13385,8 +13538,8 @@ async function createHostedBotRunner(host) {
|
|
|
13385
13538
|
}).catch(() => {
|
|
13386
13539
|
throw unavailable3();
|
|
13387
13540
|
});
|
|
13388
|
-
const resources =
|
|
13389
|
-
|
|
13541
|
+
const resources = join31(host.stateDir, "native-resources");
|
|
13542
|
+
mkdirSync18(resources, { recursive: true, mode: 448 });
|
|
13390
13543
|
const removeResource = async (file, record) => {
|
|
13391
13544
|
if (!/^mikka-native-(?:verify-)?[a-f0-9-]{36}$/.test(record.name) || !/^[a-f0-9-]{36}$/.test(record.nonce))
|
|
13392
13545
|
throw unavailable3();
|
|
@@ -13406,9 +13559,9 @@ async function createHostedBotRunner(host) {
|
|
|
13406
13559
|
if (record.state === "created" && /No such (?:container|object)/i.test(
|
|
13407
13560
|
String(error.stderr)
|
|
13408
13561
|
)) {
|
|
13409
|
-
if (record.assets?.startsWith(
|
|
13410
|
-
|
|
13411
|
-
|
|
13562
|
+
if (record.assets?.startsWith(join31(host.stateDir, "native-verify-git-")))
|
|
13563
|
+
rmSync20(record.assets, { recursive: true, force: true });
|
|
13564
|
+
rmSync20(file, { force: true });
|
|
13412
13565
|
return;
|
|
13413
13566
|
}
|
|
13414
13567
|
throw new Error("native_runtime_cleanup_unconfirmed");
|
|
@@ -13417,13 +13570,13 @@ async function createHostedBotRunner(host) {
|
|
|
13417
13570
|
if (labels?.["com.mikka.native.resource"] !== record.nonce || record.id && record.id !== id4)
|
|
13418
13571
|
throw unavailable3();
|
|
13419
13572
|
await exec3("docker", ["rm", "-f", id4], { env: bareEnv, timeout: 3e4 });
|
|
13420
|
-
if (record.assets?.startsWith(
|
|
13421
|
-
|
|
13422
|
-
|
|
13573
|
+
if (record.assets?.startsWith(join31(host.stateDir, "native-verify-git-")))
|
|
13574
|
+
rmSync20(record.assets, { recursive: true, force: true });
|
|
13575
|
+
rmSync20(file, { force: true });
|
|
13423
13576
|
};
|
|
13424
13577
|
for (const name of readdirSync9(resources))
|
|
13425
13578
|
if (name.endsWith(".json")) {
|
|
13426
|
-
const file =
|
|
13579
|
+
const file = join31(resources, name);
|
|
13427
13580
|
const record = readJson(file);
|
|
13428
13581
|
if (!record) throw unavailable3();
|
|
13429
13582
|
await removeResource(file, record);
|
|
@@ -13434,7 +13587,7 @@ async function createHostedBotRunner(host) {
|
|
|
13434
13587
|
const bundled = createRequire(
|
|
13435
13588
|
require2.resolve("@anthropic-ai/claude-agent-sdk")
|
|
13436
13589
|
);
|
|
13437
|
-
claude ??=
|
|
13590
|
+
claude ??= join31(
|
|
13438
13591
|
dirname15(
|
|
13439
13592
|
bundled.resolve(
|
|
13440
13593
|
"@anthropic-ai/claude-agent-sdk-linux-x64/package.json"
|
|
@@ -13444,7 +13597,7 @@ async function createHostedBotRunner(host) {
|
|
|
13444
13597
|
);
|
|
13445
13598
|
} catch {
|
|
13446
13599
|
}
|
|
13447
|
-
const codex = host.binaries?.codex ?? (process.env.PATH ?? "").split(delimiter3).map((dir) =>
|
|
13600
|
+
const codex = host.binaries?.codex ?? (process.env.PATH ?? "").split(delimiter3).map((dir) => join31(dir, "codex")).find((path) => existsSync8(path));
|
|
13448
13601
|
const binaries = { codex, claude_code: claude };
|
|
13449
13602
|
for (const kind of ["codex", "claude_code"])
|
|
13450
13603
|
if (binaries[kind]) {
|
|
@@ -13458,12 +13611,12 @@ async function createHostedBotRunner(host) {
|
|
|
13458
13611
|
if (!binaries.codex && !binaries.claude_code) throw unavailable3();
|
|
13459
13612
|
const command = async (worktree, script, readOnly, timeoutMs, signal) => {
|
|
13460
13613
|
const name = `mikka-native-verify-${randomUUID8()}`;
|
|
13461
|
-
const file =
|
|
13614
|
+
const file = join31(resources, name + ".json");
|
|
13462
13615
|
const resource = { name, nonce: randomUUID8(), state: "creating" };
|
|
13463
13616
|
const timing = { createMs: 0, runMs: 0 };
|
|
13464
13617
|
let phase = "create";
|
|
13465
13618
|
let began = performance.now();
|
|
13466
|
-
const gitCopy =
|
|
13619
|
+
const gitCopy = mkdtempSync9(join31(host.stateDir, "native-verify-git-"));
|
|
13467
13620
|
resource.assets = gitCopy;
|
|
13468
13621
|
try {
|
|
13469
13622
|
const cwd = realpathSync11(worktree);
|
|
@@ -13479,7 +13632,7 @@ async function createHostedBotRunner(host) {
|
|
|
13479
13632
|
"--no-checkout",
|
|
13480
13633
|
"--",
|
|
13481
13634
|
cwd,
|
|
13482
|
-
|
|
13635
|
+
join31(gitCopy, "repo")
|
|
13483
13636
|
],
|
|
13484
13637
|
{
|
|
13485
13638
|
env: {
|
|
@@ -13494,8 +13647,8 @@ async function createHostedBotRunner(host) {
|
|
|
13494
13647
|
maxBuffer: 1024 * 1024
|
|
13495
13648
|
}
|
|
13496
13649
|
);
|
|
13497
|
-
const safeGit =
|
|
13498
|
-
const protectedGit = lstatSync10(
|
|
13650
|
+
const safeGit = join31(gitCopy, "repo", ".git");
|
|
13651
|
+
const protectedGit = lstatSync10(join31(cwd, ".git")).isFile() ? join31(cwd, ".git") : safeGit;
|
|
13499
13652
|
writeJsonAtomic(file, resource);
|
|
13500
13653
|
const created = await exec3(
|
|
13501
13654
|
"docker",
|
|
@@ -13583,7 +13736,7 @@ async function createHostedBotRunner(host) {
|
|
|
13583
13736
|
};
|
|
13584
13737
|
} finally {
|
|
13585
13738
|
if (existsSync8(file)) await removeResource(file, resource);
|
|
13586
|
-
else
|
|
13739
|
+
else rmSync20(gitCopy, { recursive: true, force: true });
|
|
13587
13740
|
}
|
|
13588
13741
|
};
|
|
13589
13742
|
return {
|
|
@@ -13594,12 +13747,14 @@ async function createHostedBotRunner(host) {
|
|
|
13594
13747
|
async start(assignment, options) {
|
|
13595
13748
|
const gate = requireRunToolApproval(options.runId, options.toolApproval);
|
|
13596
13749
|
const selected = assignment.subscriptionBinding;
|
|
13750
|
+
const apiKey = assignment.modelCredential;
|
|
13597
13751
|
const kind = assignment.harness;
|
|
13598
|
-
|
|
13752
|
+
const protocol = kind === "codex" ? "openai" : "anthropic";
|
|
13753
|
+
if (Boolean(selected) === Boolean(apiKey) || options.runId !== assignment.runId || kind !== "codex" && kind !== "claude_code" || !binaries[kind] || selected && (selected.consumerId.length !== 36 || selected.route !== (kind === "codex" ? "codex_cli" : "claude_code_cli")) || apiKey?.kind === "provider" && apiKey.protocol !== protocol || options.continueSession)
|
|
13599
13754
|
throw unavailable3();
|
|
13600
13755
|
const name = `mikka-native-${randomUUID8()}`;
|
|
13601
13756
|
const nonce = randomUUID8();
|
|
13602
|
-
const resourceFile =
|
|
13757
|
+
const resourceFile = join31(resources, name + ".json");
|
|
13603
13758
|
const resource = { name, nonce, state: "creating" };
|
|
13604
13759
|
const lifetime = new AbortController();
|
|
13605
13760
|
let closed = false;
|
|
@@ -13657,25 +13812,29 @@ async function createHostedBotRunner(host) {
|
|
|
13657
13812
|
});
|
|
13658
13813
|
try {
|
|
13659
13814
|
await live();
|
|
13660
|
-
const
|
|
13661
|
-
|
|
13662
|
-
|
|
13663
|
-
if (first.route !== selected.route || first.modelId !== options.model)
|
|
13664
|
-
throw unavailable3();
|
|
13665
|
-
const revision = first.revision;
|
|
13666
|
-
const check = async () => {
|
|
13667
|
-
await live();
|
|
13668
|
-
const current = await context();
|
|
13815
|
+
const subscription = selected ? await (async () => {
|
|
13816
|
+
const context = () => host.link.nativeContext(assignment.deviceId, assignment.runId, lifetime.signal);
|
|
13817
|
+
const first = nativeBrokerContextSchema.parse(await context());
|
|
13669
13818
|
await live();
|
|
13670
|
-
if (
|
|
13819
|
+
if (first.route !== selected.route || first.modelId !== options.model)
|
|
13671
13820
|
throw unavailable3();
|
|
13672
|
-
|
|
13673
|
-
|
|
13821
|
+
const revision = first.revision;
|
|
13822
|
+
const check2 = async () => {
|
|
13823
|
+
await live();
|
|
13824
|
+
const current = await context();
|
|
13825
|
+
await live();
|
|
13826
|
+
if (current.revision !== revision || current.accountId !== first.accountId || current.route !== first.route || current.modelId !== first.modelId)
|
|
13827
|
+
throw unavailable3();
|
|
13828
|
+
return current;
|
|
13829
|
+
};
|
|
13830
|
+
return { first, revision, check: check2 };
|
|
13831
|
+
})() : void 0;
|
|
13832
|
+
const check = subscription?.check ?? live;
|
|
13674
13833
|
const paths = runPaths(host.stateDir, assignment.runId);
|
|
13675
|
-
|
|
13676
|
-
const shadow =
|
|
13677
|
-
const emptyHome =
|
|
13678
|
-
|
|
13834
|
+
mkdirSync18(paths.runDir, { recursive: true, mode: 448 });
|
|
13835
|
+
const shadow = join31(paths.runDir, "runtime-git");
|
|
13836
|
+
const emptyHome = join31(paths.runDir, "git-bootstrap-home");
|
|
13837
|
+
mkdirSync18(emptyHome, { recursive: true, mode: 448 });
|
|
13679
13838
|
if (!existsSync8(shadow))
|
|
13680
13839
|
await exec3(
|
|
13681
13840
|
"git",
|
|
@@ -13705,35 +13864,40 @@ async function createHostedBotRunner(host) {
|
|
|
13705
13864
|
}
|
|
13706
13865
|
);
|
|
13707
13866
|
await live();
|
|
13708
|
-
if (!lstatSync10(shadow).isDirectory() || !lstatSync10(
|
|
13867
|
+
if (!lstatSync10(shadow).isDirectory() || !lstatSync10(join31(shadow, ".git")).isDirectory() || !realpathSync11(shadow).startsWith(realpathSync11(paths.runDir) + "/"))
|
|
13709
13868
|
throw unavailable3();
|
|
13710
|
-
const ledger =
|
|
13869
|
+
const ledger = join31(
|
|
13711
13870
|
host.stateDir,
|
|
13712
13871
|
"native-ledgers",
|
|
13713
13872
|
assignment.runId + ".json"
|
|
13714
13873
|
);
|
|
13715
|
-
const scope = {
|
|
13874
|
+
const scope = selected && subscription ? {
|
|
13716
13875
|
runId: assignment.runId,
|
|
13717
13876
|
bindingId: selected.bindingId,
|
|
13718
13877
|
ownerId: selected.ownerId,
|
|
13719
13878
|
workspaceId: selected.workspaceId,
|
|
13720
13879
|
consumerId: selected.consumerId,
|
|
13721
13880
|
route: selected.route,
|
|
13722
|
-
revision,
|
|
13723
|
-
accountId: first.accountId,
|
|
13724
|
-
modelId: first.modelId
|
|
13725
|
-
};
|
|
13726
|
-
const previous = readJson(ledger);
|
|
13727
|
-
if (existsSync8(ledger) && (!previous || JSON.stringify(previous.scope) !== JSON.stringify(scope) || typeof previous.sessionId !== "string"))
|
|
13881
|
+
revision: subscription.revision,
|
|
13882
|
+
accountId: subscription.first.accountId,
|
|
13883
|
+
modelId: subscription.first.modelId
|
|
13884
|
+
} : void 0;
|
|
13885
|
+
const previous = scope ? readJson(ledger) : void 0;
|
|
13886
|
+
if (scope && existsSync8(ledger) && (!previous || JSON.stringify(previous.scope) !== JSON.stringify(scope) || typeof previous.sessionId !== "string"))
|
|
13728
13887
|
throw unavailable3();
|
|
13729
|
-
|
|
13888
|
+
if (scope) mkdirSync18(dirname15(ledger), { recursive: true, mode: 448 });
|
|
13730
13889
|
const record = async (sessionId) => {
|
|
13731
13890
|
assertOpen();
|
|
13732
|
-
writeJsonAtomic(ledger, { scope, sessionId });
|
|
13891
|
+
if (scope) writeJsonAtomic(ledger, { scope, sessionId });
|
|
13733
13892
|
};
|
|
13734
|
-
brokerStarting =
|
|
13735
|
-
root:
|
|
13736
|
-
|
|
13893
|
+
brokerStarting = apiKey ? createApiKeyBroker({
|
|
13894
|
+
root: join31(host.stateDir, "native-brokers"),
|
|
13895
|
+
protocol,
|
|
13896
|
+
credential: apiKey,
|
|
13897
|
+
check
|
|
13898
|
+
}) : createNativeSubscriptionBroker({
|
|
13899
|
+
root: join31(host.stateDir, "native-brokers"),
|
|
13900
|
+
revision: subscription.revision,
|
|
13737
13901
|
check,
|
|
13738
13902
|
worker: {
|
|
13739
13903
|
nativeRequest: async (_revision, payload, signal) => {
|
|
@@ -13759,7 +13923,7 @@ async function createHostedBotRunner(host) {
|
|
|
13759
13923
|
});
|
|
13760
13924
|
const readyBroker = await brokerStarting;
|
|
13761
13925
|
await live();
|
|
13762
|
-
const githubCli = options.github ? (process.env.PATH ?? "").split(delimiter3).map((dir) =>
|
|
13926
|
+
const githubCli = options.github ? (process.env.PATH ?? "").split(delimiter3).map((dir) => join31(dir, "gh")).find((file) => existsSync8(file)) : void 0;
|
|
13763
13927
|
if (options.github && !githubCli) throw new Error("Install GitHub CLI (gh) in the cloud worker image");
|
|
13764
13928
|
const githubDomains = options.github ? ["github.com", "api.github.com", new URL(options.github.endpoint).host] : [];
|
|
13765
13929
|
const egressMaximum = runDomains(runPolicy(options.policy), [...options.networkAllow ?? [], ...githubDomains]);
|
|
@@ -13776,13 +13940,13 @@ async function createHostedBotRunner(host) {
|
|
|
13776
13940
|
}
|
|
13777
13941
|
const cwd = realpathSync11(options.cwd);
|
|
13778
13942
|
const runDir = realpathSync11(paths.runDir);
|
|
13779
|
-
const protectedGit = lstatSync10(
|
|
13943
|
+
const protectedGit = lstatSync10(join31(cwd, ".git")).isFile() ? join31(cwd, ".git") : join31(shadow, ".git");
|
|
13780
13944
|
if (!lstatSync10(runDir).isDirectory() || !runDir.startsWith(realpathSync11(host.stateDir) + "/runs/")) {
|
|
13781
13945
|
await close();
|
|
13782
13946
|
throw unavailable3();
|
|
13783
13947
|
}
|
|
13784
13948
|
const computer = assignment.computer;
|
|
13785
|
-
if (computer && (!host.computerBroker || computer.ownerId !== selected.ownerId)) {
|
|
13949
|
+
if (computer && (!host.computerBroker || selected && computer.ownerId !== selected.ownerId)) {
|
|
13786
13950
|
await close();
|
|
13787
13951
|
throw unavailable3();
|
|
13788
13952
|
}
|
|
@@ -13830,7 +13994,7 @@ async function createHostedBotRunner(host) {
|
|
|
13830
13994
|
`${MCP_SERVER_SCRIPT}:${MCP_SERVER_SCRIPT}:ro`,
|
|
13831
13995
|
...githubCli ? ["-v", `${githubCli}:/usr/local/bin/mikka-gh:ro`, "-v", `${GITHUB_CREDENTIAL_SCRIPT}:${GITHUB_CREDENTIAL_SCRIPT}:ro`] : [],
|
|
13832
13996
|
"-v",
|
|
13833
|
-
`${
|
|
13997
|
+
`${join31(dirname15(MCP_SERVER_SCRIPT), "capture-copy.mjs")}:${join31(dirname15(MCP_SERVER_SCRIPT), "capture-copy.mjs")}:ro`,
|
|
13834
13998
|
"-v",
|
|
13835
13999
|
`${readyBroker.socket}:/run/mikka-native.sock:ro`,
|
|
13836
14000
|
...computerGrant ? [
|
|
@@ -13873,13 +14037,13 @@ async function createHostedBotRunner(host) {
|
|
|
13873
14037
|
}
|
|
13874
14038
|
const spawnHosted = (config) => {
|
|
13875
14039
|
assertOpen();
|
|
13876
|
-
const home =
|
|
13877
|
-
|
|
14040
|
+
const home = join31(runDir, "runtime-home");
|
|
14041
|
+
mkdirSync18(home, { recursive: true, mode: 448 });
|
|
13878
14042
|
const env = {
|
|
13879
14043
|
...config.env,
|
|
13880
14044
|
HOME: kind === "claude_code" ? config.env.HOME ?? home : home,
|
|
13881
|
-
PATH: `${options.github ?
|
|
13882
|
-
GIT_DIR:
|
|
14045
|
+
PATH: `${options.github ? join31(runDir, "github", "bin") + ":" : ""}/usr/local/bin:/usr/bin:/bin`,
|
|
14046
|
+
GIT_DIR: join31(shadow, ".git"),
|
|
13883
14047
|
GIT_WORK_TREE: cwd,
|
|
13884
14048
|
GIT_CONFIG_GLOBAL: "/dev/null",
|
|
13885
14049
|
GIT_CONFIG_SYSTEM: "/dev/null",
|
|
@@ -13888,7 +14052,7 @@ async function createHostedBotRunner(host) {
|
|
|
13888
14052
|
for (const [key2, value] of Object.entries(env))
|
|
13889
14053
|
if (value !== void 0 && (/INFISICAL|E2B_API_KEY|REFRESH_TOKEN|^AWS_|^GOOGLE_|^OPENAI_|^ANTHROPIC_.*(?:KEY|TOKEN)|SECRET|PASSWORD/.test(
|
|
13890
14054
|
key2
|
|
13891
|
-
) || key2 === "CLAUDE_CODE_OAUTH_TOKEN" && value !== placeholder))
|
|
14055
|
+
) || (key2 === "CLAUDE_CODE_OAUTH_TOKEN" || key2 === "MIKKA_MODEL_API_KEY") && value !== placeholder))
|
|
13892
14056
|
throw unavailable3();
|
|
13893
14057
|
const task = withTaskEnv(env, assignment.taskEnv);
|
|
13894
14058
|
if (task.dropped.length) console.warn(`run ${assignment.runId}: skipped reserved task variables ${task.dropped.join(", ")}`);
|
|
@@ -13898,7 +14062,7 @@ async function createHostedBotRunner(host) {
|
|
|
13898
14062
|
signal: AbortSignal.any([lifetime.signal, ...config.signal ? [config.signal] : []])
|
|
13899
14063
|
});
|
|
13900
14064
|
child.stdin.write(
|
|
13901
|
-
JSON.stringify({ kind, args: config.args, cwd, env: task.env, publicEgress: Boolean(egress), ...options.github ? { githubBin:
|
|
14065
|
+
JSON.stringify({ kind, args: config.args, cwd, env: task.env, publicEgress: Boolean(egress), ...options.github ? { githubBin: join31(runDir, "github", "bin") } : {} }) + "\n"
|
|
13902
14066
|
);
|
|
13903
14067
|
return child;
|
|
13904
14068
|
};
|
|
@@ -13927,19 +14091,27 @@ async function createHostedBotRunner(host) {
|
|
|
13927
14091
|
};
|
|
13928
14092
|
};
|
|
13929
14093
|
try {
|
|
13930
|
-
const
|
|
14094
|
+
const placeholderCredential = apiKey && kind === "codex" ? { kind: "provider", protocol: "openai", baseUrl: apiKey.kind === "provider" ? apiKey.baseUrl : "https://api.openai.com/v1", key: placeholder } : void 0;
|
|
14095
|
+
const adapter = apiKey ? kind === "codex" ? new CodexAdapter({ stateDir: host.stateDir, sandbox: blockedSandbox, spawnCli: codexSpawn, computerMcp }) : new ClaudeAdapter({
|
|
14096
|
+
stateDir: host.stateDir,
|
|
14097
|
+
computerMcp,
|
|
14098
|
+
spawnHosted: (config, token) => {
|
|
14099
|
+
if (token !== placeholder) throw unavailable3();
|
|
14100
|
+
return spawnHosted(config);
|
|
14101
|
+
}
|
|
14102
|
+
}) : kind === "codex" ? new CodexAdapter({
|
|
13931
14103
|
stateDir: host.stateDir,
|
|
13932
14104
|
sandbox: blockedSandbox,
|
|
13933
14105
|
spawnCli: codexSpawn,
|
|
13934
14106
|
onHostedSession: record,
|
|
13935
14107
|
computerMcp,
|
|
13936
14108
|
subscriptionAuth: {
|
|
13937
|
-
accountId: first.accountId,
|
|
14109
|
+
accountId: subscription.first.accountId,
|
|
13938
14110
|
verify: async () => {
|
|
13939
14111
|
await check();
|
|
13940
14112
|
},
|
|
13941
14113
|
token: async () => {
|
|
13942
|
-
const current = await check();
|
|
14114
|
+
const current = await subscription.check();
|
|
13943
14115
|
return {
|
|
13944
14116
|
accessToken: placeholder,
|
|
13945
14117
|
chatgptAccountId: current.accountId,
|
|
@@ -13957,12 +14129,12 @@ async function createHostedBotRunner(host) {
|
|
|
13957
14129
|
},
|
|
13958
14130
|
subscriptionAuth: {
|
|
13959
14131
|
brokered: true,
|
|
13960
|
-
accountId: first.accountId,
|
|
14132
|
+
accountId: subscription.first.accountId,
|
|
13961
14133
|
verify: async () => {
|
|
13962
14134
|
await check();
|
|
13963
14135
|
},
|
|
13964
14136
|
token: async () => {
|
|
13965
|
-
const current = await check();
|
|
14137
|
+
const current = await subscription.check();
|
|
13966
14138
|
return {
|
|
13967
14139
|
accessToken: placeholder,
|
|
13968
14140
|
accountId: current.accountId,
|
|
@@ -13971,7 +14143,7 @@ async function createHostedBotRunner(host) {
|
|
|
13971
14143
|
}
|
|
13972
14144
|
}
|
|
13973
14145
|
});
|
|
13974
|
-
const runtimeOptions = { ...options, ...options.github ? { githubRuntime: { nodeBinary: "/usr/local/bin/node", ghBinary: "/usr/local/bin/mikka-gh" } } : {} };
|
|
14146
|
+
const runtimeOptions = { ...options, credential: placeholderCredential, ...options.github ? { githubRuntime: { nodeBinary: "/usr/local/bin/node", ghBinary: "/usr/local/bin/mikka-gh" } } : {} };
|
|
13975
14147
|
const session = previous ? await adapter.resume(previous.sessionId, runtimeOptions) : await adapter.start(runtimeOptions);
|
|
13976
14148
|
let checking = false;
|
|
13977
14149
|
if (!closed) timer = setInterval(() => {
|
|
@@ -14033,8 +14205,8 @@ import {
|
|
|
14033
14205
|
createHash as createHash9,
|
|
14034
14206
|
timingSafeEqual as timingSafeEqual2
|
|
14035
14207
|
} from "node:crypto";
|
|
14036
|
-
import { chmodSync as
|
|
14037
|
-
import { createServer as
|
|
14208
|
+
import { chmodSync as chmodSync5 } from "node:fs";
|
|
14209
|
+
import { createServer as createServer5 } from "node:net";
|
|
14038
14210
|
|
|
14039
14211
|
// src/computer/driver.mjs
|
|
14040
14212
|
import { spawn as spawn6 } from "node:child_process";
|
|
@@ -14254,7 +14426,7 @@ var ComputerBroker = class {
|
|
|
14254
14426
|
}
|
|
14255
14427
|
async listen() {
|
|
14256
14428
|
if (this.suspended) throw new Error("Broker suspended");
|
|
14257
|
-
this.server =
|
|
14429
|
+
this.server = createServer5((socket) => {
|
|
14258
14430
|
this.sockets.add(socket);
|
|
14259
14431
|
socket.on("close", () => this.sockets.delete(socket));
|
|
14260
14432
|
let text3 = "", submitted = false;
|
|
@@ -14297,7 +14469,7 @@ var ComputerBroker = class {
|
|
|
14297
14469
|
else this.server.listen(this.socketPath, resolve13);
|
|
14298
14470
|
});
|
|
14299
14471
|
if (this.transport === "tcp") this.socketPath = `tcp://127.0.0.1:${this.server.address().port}`;
|
|
14300
|
-
else
|
|
14472
|
+
else chmodSync5(this.socketPath, 384);
|
|
14301
14473
|
}
|
|
14302
14474
|
request(token, value, signal) {
|
|
14303
14475
|
const grant = this.grants.get(token);
|
|
@@ -14543,6 +14715,9 @@ function loadDeviceFile(raw) {
|
|
|
14543
14715
|
return file;
|
|
14544
14716
|
}
|
|
14545
14717
|
var HARNESS_RESCAN_MS = 5 * 6e4;
|
|
14718
|
+
function credentialOwner(assignment) {
|
|
14719
|
+
return assignment.subscriptionBinding?.ownerId ?? (assignment.modelCredential ? assignment.computer?.ownerId : void 0);
|
|
14720
|
+
}
|
|
14546
14721
|
var SANDBOX_REPAIR_RETRY_MS = 60 * 6e4;
|
|
14547
14722
|
function missingToolsUnchanged(issue) {
|
|
14548
14723
|
return !issue?.missing.length || missingSandboxTools().length === issue.missing.length;
|
|
@@ -14618,8 +14793,8 @@ var Daemon = class {
|
|
|
14618
14793
|
}
|
|
14619
14794
|
async startInternal() {
|
|
14620
14795
|
const { paths } = this;
|
|
14621
|
-
|
|
14622
|
-
if (process.platform !== "win32")
|
|
14796
|
+
mkdirSync19(paths.dataDir, { recursive: true, mode: 448 });
|
|
14797
|
+
if (process.platform !== "win32") chmodSync6(paths.dataDir, 448);
|
|
14623
14798
|
this.releaseLock = await acquireLock(
|
|
14624
14799
|
paths.dataDir,
|
|
14625
14800
|
paths.lock,
|
|
@@ -14632,7 +14807,7 @@ var Daemon = class {
|
|
|
14632
14807
|
if (this.options.credential)
|
|
14633
14808
|
this.saveDevice({ credential: this.options.credential });
|
|
14634
14809
|
this.journal = new RunJournal(paths.journal);
|
|
14635
|
-
this.captureUploader = new CaptureUploader((runId) =>
|
|
14810
|
+
this.captureUploader = new CaptureUploader((runId) => join32(runPaths(paths.adapterState, runId).runDir, CAPTURES_DIR), this.options.link, this.log, join32(paths.dataDir, "capture-pending"));
|
|
14636
14811
|
this.outbox = new Outbox(
|
|
14637
14812
|
paths.outbox,
|
|
14638
14813
|
this.options.link,
|
|
@@ -14649,7 +14824,7 @@ var Daemon = class {
|
|
|
14649
14824
|
if (this.localComputerDriver && this.options.link.syncComputerReviews && this.options.link.localComputerAuthority) {
|
|
14650
14825
|
this.localComputerBroker = new ComputerBroker({
|
|
14651
14826
|
driver: this.localComputerDriver,
|
|
14652
|
-
socketPath:
|
|
14827
|
+
socketPath: join32(paths.dataDir, "local-computer.sock"),
|
|
14653
14828
|
transport: "tcp",
|
|
14654
14829
|
permitted: (runId) => {
|
|
14655
14830
|
const assignment = this.journal.get(runId)?.assignment;
|
|
@@ -14682,7 +14857,7 @@ var Daemon = class {
|
|
|
14682
14857
|
const liveComputer = (runId, display) => {
|
|
14683
14858
|
const entry = this.journal.get(runId);
|
|
14684
14859
|
const computer = entry?.assignment.computer;
|
|
14685
|
-
if (this.stopped || !this.registered || !computer || computer.display !== display || computer.ownerId !== entry
|
|
14860
|
+
if (this.stopped || !this.registered || !computer || computer.display !== display || !entry || computer.ownerId !== credentialOwner(entry.assignment) || !this.supervisor.computerRunAllowed(runId)) throw new Error("Cloud computer run unavailable");
|
|
14686
14861
|
return computer;
|
|
14687
14862
|
};
|
|
14688
14863
|
const executeOrdinary = async (current, call, display, runId, assertLive) => {
|
|
@@ -14691,7 +14866,7 @@ var Daemon = class {
|
|
|
14691
14866
|
};
|
|
14692
14867
|
this.cloudComputerBroker = new ComputerBroker({
|
|
14693
14868
|
driver,
|
|
14694
|
-
socketPath:
|
|
14869
|
+
socketPath: join32(paths.dataDir, "computer.sock"),
|
|
14695
14870
|
permitted: (runId) => {
|
|
14696
14871
|
const entry = this.journal.get(runId);
|
|
14697
14872
|
return Boolean(!this.stopped && this.registered && entry?.assignment.computer && this.supervisor?.computerRunAllowed(runId));
|
|
@@ -14759,6 +14934,7 @@ var Daemon = class {
|
|
|
14759
14934
|
worktrees: this.worktrees,
|
|
14760
14935
|
adapters,
|
|
14761
14936
|
startSubscription: hosted?.start ?? this.localSubscriptions()?.start,
|
|
14937
|
+
startCredential: hosted?.start,
|
|
14762
14938
|
prepareRunMailbox: this.options.link.prepareRunMailbox?.bind(this.options.link),
|
|
14763
14939
|
prepareRunToolApproval: this.options.link.prepareRunToolApproval?.bind(this.options.link),
|
|
14764
14940
|
verifyRunPolicy: this.options.link.verifyRunPolicy ? async (assignment, signal) => {
|
|
@@ -14818,7 +14994,7 @@ var Daemon = class {
|
|
|
14818
14994
|
worktree,
|
|
14819
14995
|
tree,
|
|
14820
14996
|
github: { ...assignment.github, runToken: assignment.mcp.token, issueId: assignment.issueId },
|
|
14821
|
-
privateDir:
|
|
14997
|
+
privateDir: join32(paths.adapterState, "pids"),
|
|
14822
14998
|
...hosted ? { hosted: true } : {},
|
|
14823
14999
|
env: githubReceiptEnvironment()
|
|
14824
15000
|
}) : publishRun({
|
|
@@ -15178,11 +15354,11 @@ var Daemon = class {
|
|
|
15178
15354
|
return runVerify(sandbox, {
|
|
15179
15355
|
command,
|
|
15180
15356
|
worktree: realpathSync12(worktree),
|
|
15181
|
-
tmpRoot:
|
|
15357
|
+
tmpRoot: join32(this.paths.adapterState, "verify", runId),
|
|
15182
15358
|
privateDir: paths.privateDir,
|
|
15183
15359
|
pidFile: paths.pidFile.replace(/\.pgid$/, ".verify.pgid"),
|
|
15184
15360
|
networkAllow: repo.networkAllow,
|
|
15185
|
-
env: { ...buildChildEnv(), MIKKA_HANDOFF_FILE:
|
|
15361
|
+
env: { ...buildChildEnv(), MIKKA_HANDOFF_FILE: join32(paths.runDir, "handoff.json") },
|
|
15186
15362
|
timeoutMs,
|
|
15187
15363
|
signal,
|
|
15188
15364
|
readOnly
|
|
@@ -15367,7 +15543,7 @@ var Daemon = class {
|
|
|
15367
15543
|
setImmediate(() => {
|
|
15368
15544
|
void this.stop().then(() => uninstallService(() => {
|
|
15369
15545
|
this.saveDevice({ credential: void 0 });
|
|
15370
|
-
|
|
15546
|
+
rmSync21(this.paths.secret, { force: true });
|
|
15371
15547
|
})).catch(() => {
|
|
15372
15548
|
this.options.onDrained?.();
|
|
15373
15549
|
});
|
|
@@ -15485,7 +15661,7 @@ var Daemon = class {
|
|
|
15485
15661
|
throw new DaemonError(DAEMON_RPC_ERRORS.unauthorized, message);
|
|
15486
15662
|
}
|
|
15487
15663
|
}
|
|
15488
|
-
if (assignment.computer && (!this.cloudComputerBroker ||
|
|
15664
|
+
if (assignment.computer && (!this.cloudComputerBroker || assignment.computer.ownerId !== credentialOwner(assignment))) throw new Error("Cloud computer runtime unavailable");
|
|
15489
15665
|
return await this.supervisor.start(assignment);
|
|
15490
15666
|
}
|
|
15491
15667
|
/**
|
|
@@ -15692,7 +15868,7 @@ var Daemon = class {
|
|
|
15692
15868
|
if (!job || controller.signal.aborted) return;
|
|
15693
15869
|
await runNativeCoordinatorJob(job, {
|
|
15694
15870
|
deviceId,
|
|
15695
|
-
stateDir:
|
|
15871
|
+
stateDir: join32(this.paths.dataDir, "coordinator"),
|
|
15696
15872
|
link,
|
|
15697
15873
|
signal: controller.signal,
|
|
15698
15874
|
sandbox,
|
|
@@ -15735,7 +15911,7 @@ var Daemon = class {
|
|
|
15735
15911
|
}, void 0, () => !this.stopped);
|
|
15736
15912
|
});
|
|
15737
15913
|
} else if (!this.updateCheck && !this.updateVersion) {
|
|
15738
|
-
this.updateCheck = checkLatestVersion(
|
|
15914
|
+
this.updateCheck = checkLatestVersion(join32(this.paths.dataDir, "auto-update.json"), DAEMON_VERSION, runtime).then((version) => {
|
|
15739
15915
|
this.updateVersion = version;
|
|
15740
15916
|
}).catch(() => {
|
|
15741
15917
|
this.log.warn("Daemon automatic update check failed");
|