@aspectlylabs/mikka 0.0.140 → 0.0.142
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/main.js
CHANGED
|
@@ -3780,7 +3780,7 @@ import { join as join5 } from "node:path";
|
|
|
3780
3780
|
// package.json
|
|
3781
3781
|
var package_default = {
|
|
3782
3782
|
name: "@mikka/daemon",
|
|
3783
|
-
version: "0.0.
|
|
3783
|
+
version: "0.0.142",
|
|
3784
3784
|
description: "Local Mikka daemon: runs agents through the user's own CLIs",
|
|
3785
3785
|
type: "module",
|
|
3786
3786
|
private: true,
|
|
@@ -3840,7 +3840,7 @@ var package_default = {
|
|
|
3840
3840
|
engines: {
|
|
3841
3841
|
node: ">=24"
|
|
3842
3842
|
},
|
|
3843
|
-
gitHead: "
|
|
3843
|
+
gitHead: "eba283d612639ecf9c4654327153c5118a2c27bb"
|
|
3844
3844
|
};
|
|
3845
3845
|
|
|
3846
3846
|
// src/paths.ts
|
|
@@ -4708,6 +4708,15 @@ var setupRecipeSchema = z15.object({
|
|
|
4708
4708
|
/** Approved once per repo by the user; unapproved recipes never run. */
|
|
4709
4709
|
approved: z15.boolean()
|
|
4710
4710
|
});
|
|
4711
|
+
var credentialKey = z15.string().min(1).max(4096).refine((value) => !/[\r\n\0]/.test(value));
|
|
4712
|
+
var credentialBaseUrl = z15.url().max(500).refine((value) => {
|
|
4713
|
+
const url = new URL(value);
|
|
4714
|
+
return url.protocol === "https:" && !url.username && !url.password && !url.search && !url.hash;
|
|
4715
|
+
});
|
|
4716
|
+
var runModelCredentialSchema = z15.discriminatedUnion("kind", [
|
|
4717
|
+
z15.object({ kind: z15.literal("api_key"), key: credentialKey }).strict(),
|
|
4718
|
+
z15.object({ kind: z15.literal("provider"), protocol: z15.enum(["anthropic", "openai"]), baseUrl: credentialBaseUrl, key: credentialKey }).strict()
|
|
4719
|
+
]);
|
|
4711
4720
|
var deviceRepoSchema = z15.object({
|
|
4712
4721
|
repoId: id2,
|
|
4713
4722
|
name: z15.string().max(500),
|
|
@@ -4755,6 +4764,12 @@ var runAssignmentSchema = z15.object({
|
|
|
4755
4764
|
consumerId: z15.uuid(),
|
|
4756
4765
|
route: z15.enum(["codex_cli", "claude_code_cli"])
|
|
4757
4766
|
}).strict().optional(),
|
|
4767
|
+
/**
|
|
4768
|
+
* The run's own API key, opened for this claim only. Never with
|
|
4769
|
+
* `subscriptionBinding`. The daemon keeps it in memory and hands it only
|
|
4770
|
+
* to the run's Agent process or container; it is never journaled.
|
|
4771
|
+
*/
|
|
4772
|
+
modelCredential: runModelCredentialSchema.optional(),
|
|
4758
4773
|
/** Local host authority comes only from the server's owner-bound Bot run. */
|
|
4759
4774
|
localComputer: z15.object({
|
|
4760
4775
|
botId: z15.uuid(),
|
|
@@ -4872,7 +4887,7 @@ var runAssignmentSchema = z15.object({
|
|
|
4872
4887
|
skillReceipt: skillAssignmentReceiptSchema.optional(),
|
|
4873
4888
|
/** Frozen by the server benchmark ledger; never extracted from model output. */
|
|
4874
4889
|
benchmark: runBenchmarkContext.optional()
|
|
4875
|
-
});
|
|
4890
|
+
}).refine((value) => !(value.modelCredential && value.subscriptionBinding), { message: "A run has one model credential", path: ["modelCredential"] });
|
|
4876
4891
|
var runPatchSchema = z15.object({
|
|
4877
4892
|
state: z15.enum([
|
|
4878
4893
|
"queued",
|
|
@@ -6445,15 +6460,15 @@ sandbox_mode = "read-only"
|
|
|
6445
6460
|
// src/main.ts
|
|
6446
6461
|
import { randomBytes as randomBytes4, randomUUID as randomUUID9 } from "node:crypto";
|
|
6447
6462
|
import {
|
|
6448
|
-
chmodSync as
|
|
6463
|
+
chmodSync as chmodSync6,
|
|
6449
6464
|
existsSync as existsSync9,
|
|
6450
|
-
mkdirSync as
|
|
6465
|
+
mkdirSync as mkdirSync19,
|
|
6451
6466
|
readFileSync as readFileSync12,
|
|
6452
|
-
rmSync as
|
|
6467
|
+
rmSync as rmSync21,
|
|
6453
6468
|
realpathSync as realpathSync12
|
|
6454
6469
|
} from "node:fs";
|
|
6455
6470
|
import { arch as arch2, hostname, platform as platform3 } from "node:os";
|
|
6456
|
-
import { join as
|
|
6471
|
+
import { join as join32 } from "node:path";
|
|
6457
6472
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
6458
6473
|
|
|
6459
6474
|
// src/adapters/claude.ts
|
|
@@ -7330,7 +7345,8 @@ var ClaudeAdapter = class {
|
|
|
7330
7345
|
},
|
|
7331
7346
|
...mode === "new" ? { sessionId } : { resume: sessionId },
|
|
7332
7347
|
...options.model ? { model: options.model } : {},
|
|
7333
|
-
|
|
7348
|
+
// A hosted runtime always spawns into its own container; an API-key run there holds the placeholder too.
|
|
7349
|
+
...outerLocal ? { spawnClaudeCodeProcess: spawnOuter } : this.options.spawnHosted ? { spawnClaudeCodeProcess: (options2) => this.options.spawnHosted(options2, nativeToken ?? NATIVE_AUTH_PLACEHOLDER) } : binary || externalAuth ? { spawnClaudeCodeProcess: spawnBinary(binary, nativeToken) } : {},
|
|
7334
7350
|
stderr: (data) => {
|
|
7335
7351
|
if (!externalAuth) stderr = (stderr + data).slice(-STDERR_TAIL2 * 4);
|
|
7336
7352
|
}
|
|
@@ -10538,7 +10554,10 @@ function withoutTaskEnv(assignment) {
|
|
|
10538
10554
|
|
|
10539
10555
|
// src/runs/journal.ts
|
|
10540
10556
|
function persisted(entries) {
|
|
10541
|
-
return Object.fromEntries(Object.entries(entries).map(([id4, entry]) =>
|
|
10557
|
+
return Object.fromEntries(Object.entries(entries).map(([id4, entry]) => {
|
|
10558
|
+
const { modelCredential, ...assignment } = withoutTaskEnv(entry.assignment);
|
|
10559
|
+
return [id4, { ...entry, assignment, ...modelCredential ? { credentialWithheld: true } : {} }];
|
|
10560
|
+
}));
|
|
10542
10561
|
}
|
|
10543
10562
|
var RunJournal = class {
|
|
10544
10563
|
constructor(file) {
|
|
@@ -11303,10 +11322,10 @@ var RunSupervisor = class {
|
|
|
11303
11322
|
}
|
|
11304
11323
|
const existing = this.deps.journal.get(assignment.runId);
|
|
11305
11324
|
if (existing) return this.summary(existing);
|
|
11306
|
-
const masker = createRunMasker((assignment.taskSecretNames ?? []).flatMap((name) => {
|
|
11325
|
+
const masker = createRunMasker([...(assignment.taskSecretNames ?? []).flatMap((name) => {
|
|
11307
11326
|
const value = assignment.taskEnv?.[name];
|
|
11308
11327
|
return typeof value === "string" ? [{ name, value }] : [];
|
|
11309
|
-
}));
|
|
11328
|
+
}), ...assignment.modelCredential ? [{ name: "MODEL_API_KEY", value: assignment.modelCredential.key }] : []]);
|
|
11310
11329
|
if (masker) this.maskers.set(assignment.runId, masker);
|
|
11311
11330
|
let repo;
|
|
11312
11331
|
try {
|
|
@@ -11406,6 +11425,10 @@ var RunSupervisor = class {
|
|
|
11406
11425
|
}
|
|
11407
11426
|
continue;
|
|
11408
11427
|
}
|
|
11428
|
+
if (entry.credentialWithheld && !entry.assignment.modelCredential) {
|
|
11429
|
+
this.finish(entry.assignment.runId, "error", "The run stopped with the daemon; its API key is not kept. Retry the thread.");
|
|
11430
|
+
continue;
|
|
11431
|
+
}
|
|
11409
11432
|
if (entry.assignment.leaseExpiresAt)
|
|
11410
11433
|
this.leases.set(entry.assignment.runId, Date.now() + DEFAULT_LEASE_MS);
|
|
11411
11434
|
this.launch(entry.assignment.runId, repo);
|
|
@@ -11983,7 +12006,9 @@ var RunSupervisor = class {
|
|
|
11983
12006
|
} : void 0,
|
|
11984
12007
|
fixture: assignment.fixture,
|
|
11985
12008
|
model: assignment.model,
|
|
11986
|
-
mailbox
|
|
12009
|
+
mailbox,
|
|
12010
|
+
// In memory only: the adapter hands it to the run's CLI environment.
|
|
12011
|
+
credential: assignment.modelCredential
|
|
11987
12012
|
};
|
|
11988
12013
|
const resuming = entry.sessionId !== null && adapter.capabilities.supportsResume;
|
|
11989
12014
|
const inEarlierWorktree = continued !== null || entry.worktree !== null && resolve11(entry.worktree) !== resolve11(this.deps.worktrees.pathFor(runId));
|
|
@@ -12008,8 +12033,9 @@ var RunSupervisor = class {
|
|
|
12008
12033
|
const previousExecution = entry.execution;
|
|
12009
12034
|
const previousRuntime = entry.runtime;
|
|
12010
12035
|
let session;
|
|
12036
|
+
if (assignment.subscriptionBinding && assignment.modelCredential) throw new Error("A run has one model credential");
|
|
12011
12037
|
try {
|
|
12012
|
-
session = assignment.subscriptionBinding ? this.deps.startSubscription ? await this.deps.startSubscription(assignment, { ...options, prompt: assignment.prompt }) : (() => {
|
|
12038
|
+
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 }) : (() => {
|
|
12013
12039
|
throw new Error("subscription_hosted_runtime_unavailable");
|
|
12014
12040
|
})() : resuming ? await adapter.resume(entry.sessionId, options) : await (async () => {
|
|
12015
12041
|
if (assignment.requireSessionResume)
|
|
@@ -12425,16 +12451,141 @@ import { randomUUID as randomUUID7 } from "node:crypto";
|
|
|
12425
12451
|
import {
|
|
12426
12452
|
existsSync as existsSync8,
|
|
12427
12453
|
lstatSync as lstatSync10,
|
|
12428
|
-
mkdirSync as
|
|
12429
|
-
mkdtempSync as
|
|
12454
|
+
mkdirSync as mkdirSync18,
|
|
12455
|
+
mkdtempSync as mkdtempSync9,
|
|
12430
12456
|
readdirSync as readdirSync9,
|
|
12431
12457
|
realpathSync as realpathSync11,
|
|
12432
|
-
rmSync as
|
|
12458
|
+
rmSync as rmSync20
|
|
12433
12459
|
} from "node:fs";
|
|
12434
12460
|
import { createRequire } from "node:module";
|
|
12435
|
-
import { delimiter as delimiter3, dirname as dirname15, join as
|
|
12461
|
+
import { delimiter as delimiter3, dirname as dirname15, join as join31 } from "node:path";
|
|
12436
12462
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
12437
12463
|
import { promisify as promisify6 } from "node:util";
|
|
12464
|
+
|
|
12465
|
+
// src/api-key-broker.ts
|
|
12466
|
+
import { chmodSync as chmodSync4, mkdirSync as mkdirSync17, mkdtempSync as mkdtempSync8, rmSync as rmSync19 } from "node:fs";
|
|
12467
|
+
import { createServer as createServer4 } from "node:http";
|
|
12468
|
+
import { join as join30 } from "node:path";
|
|
12469
|
+
import { once as once2 } from "node:events";
|
|
12470
|
+
var DEFAULT_BASE = { anthropic: "https://api.anthropic.com", openai: "https://api.openai.com/v1" };
|
|
12471
|
+
var PATHS = {
|
|
12472
|
+
anthropic: /* @__PURE__ */ new Set(["/v1/messages", "/v1/messages/count_tokens"]),
|
|
12473
|
+
openai: /* @__PURE__ */ new Set(["/responses", "/responses/compact"])
|
|
12474
|
+
};
|
|
12475
|
+
var FORWARD = ["content-type", "accept", "anthropic-version", "anthropic-beta", "openai-beta", "user-agent"];
|
|
12476
|
+
var RETURN = ["content-type", "retry-after", "request-id", "x-request-id"];
|
|
12477
|
+
var MAX_BODY = 32 * 1024 * 1024;
|
|
12478
|
+
async function createApiKeyBroker(host) {
|
|
12479
|
+
const { credential, protocol } = host;
|
|
12480
|
+
if (credential.kind === "provider" && credential.protocol !== protocol) throw new Error("api_key_broker_unavailable");
|
|
12481
|
+
const base = new URL(credential.kind === "provider" ? credential.baseUrl : DEFAULT_BASE[protocol]);
|
|
12482
|
+
if (base.protocol !== "https:" || base.username || base.password || !credential.key || /[\r\n\0]/.test(credential.key))
|
|
12483
|
+
throw new Error("api_key_broker_unavailable");
|
|
12484
|
+
const origin = base.href.replace(/\/+$/, "");
|
|
12485
|
+
let key2 = credential.key;
|
|
12486
|
+
const send = host.fetch ?? fetch;
|
|
12487
|
+
await host.check();
|
|
12488
|
+
mkdirSync17(host.root, { recursive: true, mode: 448 });
|
|
12489
|
+
const dir = mkdtempSync8(join30(host.root, "api-key-broker-"));
|
|
12490
|
+
chmodSync4(dir, 448);
|
|
12491
|
+
const socket = join30(dir, "broker.sock");
|
|
12492
|
+
const pending = /* @__PURE__ */ new Set();
|
|
12493
|
+
let halted = false;
|
|
12494
|
+
const server = createServer4(async (request, response) => {
|
|
12495
|
+
const abort = new AbortController();
|
|
12496
|
+
pending.add(abort);
|
|
12497
|
+
response.on("close", () => {
|
|
12498
|
+
if (!response.writableFinished) abort.abort();
|
|
12499
|
+
});
|
|
12500
|
+
try {
|
|
12501
|
+
const url = new URL(request.url ?? "/", "http://broker");
|
|
12502
|
+
if (halted || !key2 || request.method !== "POST" || (request.url ?? "").length > 256 || !PATHS[protocol].has(url.pathname) || url.search && url.search !== "?beta=true") {
|
|
12503
|
+
response.writeHead(404, { "content-type": "application/json", "cache-control": "no-store" }).end('{"error":"not_found"}');
|
|
12504
|
+
return;
|
|
12505
|
+
}
|
|
12506
|
+
const chunks = [];
|
|
12507
|
+
let length = 0;
|
|
12508
|
+
for await (const part of request) {
|
|
12509
|
+
length += part.length;
|
|
12510
|
+
if (length > MAX_BODY) throw new Error("request refused");
|
|
12511
|
+
chunks.push(part);
|
|
12512
|
+
}
|
|
12513
|
+
await host.check();
|
|
12514
|
+
if (halted || !key2 || abort.signal.aborted) throw new Error("request refused");
|
|
12515
|
+
const headers = {};
|
|
12516
|
+
for (const name of FORWARD) {
|
|
12517
|
+
const value = request.headers[name];
|
|
12518
|
+
if (typeof value === "string") headers[name] = value;
|
|
12519
|
+
}
|
|
12520
|
+
if (headers["anthropic-beta"]) {
|
|
12521
|
+
const betas = headers["anthropic-beta"].split(",").map((item) => item.trim()).filter((item) => item && !item.startsWith("oauth-"));
|
|
12522
|
+
if (betas.length) headers["anthropic-beta"] = betas.join(",");
|
|
12523
|
+
else delete headers["anthropic-beta"];
|
|
12524
|
+
}
|
|
12525
|
+
if (protocol === "anthropic") headers["x-api-key"] = key2;
|
|
12526
|
+
else headers.authorization = `Bearer ${key2}`;
|
|
12527
|
+
const upstream = await send(origin + url.pathname + url.search, {
|
|
12528
|
+
method: "POST",
|
|
12529
|
+
headers,
|
|
12530
|
+
body: Buffer.concat(chunks),
|
|
12531
|
+
redirect: "error",
|
|
12532
|
+
signal: abort.signal,
|
|
12533
|
+
cache: "no-store"
|
|
12534
|
+
});
|
|
12535
|
+
const returned = { "cache-control": "no-store" };
|
|
12536
|
+
for (const name of RETURN) {
|
|
12537
|
+
const value = upstream.headers.get(name);
|
|
12538
|
+
if (value) returned[name] = value;
|
|
12539
|
+
}
|
|
12540
|
+
response.writeHead(upstream.status, returned);
|
|
12541
|
+
if (upstream.body) {
|
|
12542
|
+
const reader = upstream.body.getReader();
|
|
12543
|
+
try {
|
|
12544
|
+
for (; ; ) {
|
|
12545
|
+
const { done, value } = await reader.read();
|
|
12546
|
+
if (done) break;
|
|
12547
|
+
if (abort.signal.aborted) throw new Error("request cancelled");
|
|
12548
|
+
if (!response.write(value)) await once2(response, "drain", { signal: abort.signal });
|
|
12549
|
+
}
|
|
12550
|
+
} finally {
|
|
12551
|
+
await reader.cancel().catch(() => void 0);
|
|
12552
|
+
reader.releaseLock();
|
|
12553
|
+
}
|
|
12554
|
+
}
|
|
12555
|
+
response.end();
|
|
12556
|
+
} catch {
|
|
12557
|
+
abort.abort();
|
|
12558
|
+
if (response.headersSent) response.destroy();
|
|
12559
|
+
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" } }));
|
|
12560
|
+
} finally {
|
|
12561
|
+
pending.delete(abort);
|
|
12562
|
+
}
|
|
12563
|
+
});
|
|
12564
|
+
try {
|
|
12565
|
+
await new Promise((resolve13, reject) => {
|
|
12566
|
+
server.once("error", reject);
|
|
12567
|
+
server.listen(socket, resolve13);
|
|
12568
|
+
});
|
|
12569
|
+
chmodSync4(socket, 384);
|
|
12570
|
+
} catch {
|
|
12571
|
+
key2 = void 0;
|
|
12572
|
+
rmSync19(dir, { recursive: true, force: true });
|
|
12573
|
+
throw new Error("api_key_broker_unavailable");
|
|
12574
|
+
}
|
|
12575
|
+
return {
|
|
12576
|
+
socket,
|
|
12577
|
+
async close() {
|
|
12578
|
+
halted = true;
|
|
12579
|
+
key2 = void 0;
|
|
12580
|
+
for (const abort of pending) abort.abort();
|
|
12581
|
+
server.closeAllConnections();
|
|
12582
|
+
await new Promise((resolve13) => server.close(() => resolve13()));
|
|
12583
|
+
rmSync19(dir, { recursive: true, force: true });
|
|
12584
|
+
}
|
|
12585
|
+
};
|
|
12586
|
+
}
|
|
12587
|
+
|
|
12588
|
+
// src/subscription-hosted-runner.ts
|
|
12438
12589
|
var exec3 = promisify6(execFile6);
|
|
12439
12590
|
var image = HOSTED_NATIVE_IMAGE;
|
|
12440
12591
|
var bootstrap = fileURLToPath3(
|
|
@@ -12459,8 +12610,8 @@ async function createHostedBotRunner(host) {
|
|
|
12459
12610
|
}).catch(() => {
|
|
12460
12611
|
throw unavailable3();
|
|
12461
12612
|
});
|
|
12462
|
-
const resources =
|
|
12463
|
-
|
|
12613
|
+
const resources = join31(host.stateDir, "native-resources");
|
|
12614
|
+
mkdirSync18(resources, { recursive: true, mode: 448 });
|
|
12464
12615
|
const removeResource = async (file, record) => {
|
|
12465
12616
|
if (!/^mikka-native-(?:verify-)?[a-f0-9-]{36}$/.test(record.name) || !/^[a-f0-9-]{36}$/.test(record.nonce))
|
|
12466
12617
|
throw unavailable3();
|
|
@@ -12480,9 +12631,9 @@ async function createHostedBotRunner(host) {
|
|
|
12480
12631
|
if (record.state === "created" && /No such (?:container|object)/i.test(
|
|
12481
12632
|
String(error.stderr)
|
|
12482
12633
|
)) {
|
|
12483
|
-
if (record.assets?.startsWith(
|
|
12484
|
-
|
|
12485
|
-
|
|
12634
|
+
if (record.assets?.startsWith(join31(host.stateDir, "native-verify-git-")))
|
|
12635
|
+
rmSync20(record.assets, { recursive: true, force: true });
|
|
12636
|
+
rmSync20(file, { force: true });
|
|
12486
12637
|
return;
|
|
12487
12638
|
}
|
|
12488
12639
|
throw new Error("native_runtime_cleanup_unconfirmed");
|
|
@@ -12491,13 +12642,13 @@ async function createHostedBotRunner(host) {
|
|
|
12491
12642
|
if (labels?.["com.mikka.native.resource"] !== record.nonce || record.id && record.id !== id4)
|
|
12492
12643
|
throw unavailable3();
|
|
12493
12644
|
await exec3("docker", ["rm", "-f", id4], { env: bareEnv, timeout: 3e4 });
|
|
12494
|
-
if (record.assets?.startsWith(
|
|
12495
|
-
|
|
12496
|
-
|
|
12645
|
+
if (record.assets?.startsWith(join31(host.stateDir, "native-verify-git-")))
|
|
12646
|
+
rmSync20(record.assets, { recursive: true, force: true });
|
|
12647
|
+
rmSync20(file, { force: true });
|
|
12497
12648
|
};
|
|
12498
12649
|
for (const name of readdirSync9(resources))
|
|
12499
12650
|
if (name.endsWith(".json")) {
|
|
12500
|
-
const file =
|
|
12651
|
+
const file = join31(resources, name);
|
|
12501
12652
|
const record = readJson(file);
|
|
12502
12653
|
if (!record) throw unavailable3();
|
|
12503
12654
|
await removeResource(file, record);
|
|
@@ -12508,7 +12659,7 @@ async function createHostedBotRunner(host) {
|
|
|
12508
12659
|
const bundled = createRequire(
|
|
12509
12660
|
require2.resolve("@anthropic-ai/claude-agent-sdk")
|
|
12510
12661
|
);
|
|
12511
|
-
claude ??=
|
|
12662
|
+
claude ??= join31(
|
|
12512
12663
|
dirname15(
|
|
12513
12664
|
bundled.resolve(
|
|
12514
12665
|
"@anthropic-ai/claude-agent-sdk-linux-x64/package.json"
|
|
@@ -12518,7 +12669,7 @@ async function createHostedBotRunner(host) {
|
|
|
12518
12669
|
);
|
|
12519
12670
|
} catch {
|
|
12520
12671
|
}
|
|
12521
|
-
const codex = host.binaries?.codex ?? (process.env.PATH ?? "").split(delimiter3).map((dir) =>
|
|
12672
|
+
const codex = host.binaries?.codex ?? (process.env.PATH ?? "").split(delimiter3).map((dir) => join31(dir, "codex")).find((path) => existsSync8(path));
|
|
12522
12673
|
const binaries = { codex, claude_code: claude };
|
|
12523
12674
|
for (const kind of ["codex", "claude_code"])
|
|
12524
12675
|
if (binaries[kind]) {
|
|
@@ -12532,12 +12683,12 @@ async function createHostedBotRunner(host) {
|
|
|
12532
12683
|
if (!binaries.codex && !binaries.claude_code) throw unavailable3();
|
|
12533
12684
|
const command = async (worktree, script, readOnly, timeoutMs, signal) => {
|
|
12534
12685
|
const name = `mikka-native-verify-${randomUUID7()}`;
|
|
12535
|
-
const file =
|
|
12686
|
+
const file = join31(resources, name + ".json");
|
|
12536
12687
|
const resource = { name, nonce: randomUUID7(), state: "creating" };
|
|
12537
12688
|
const timing = { createMs: 0, runMs: 0 };
|
|
12538
12689
|
let phase = "create";
|
|
12539
12690
|
let began = performance.now();
|
|
12540
|
-
const gitCopy =
|
|
12691
|
+
const gitCopy = mkdtempSync9(join31(host.stateDir, "native-verify-git-"));
|
|
12541
12692
|
resource.assets = gitCopy;
|
|
12542
12693
|
try {
|
|
12543
12694
|
const cwd = realpathSync11(worktree);
|
|
@@ -12553,7 +12704,7 @@ async function createHostedBotRunner(host) {
|
|
|
12553
12704
|
"--no-checkout",
|
|
12554
12705
|
"--",
|
|
12555
12706
|
cwd,
|
|
12556
|
-
|
|
12707
|
+
join31(gitCopy, "repo")
|
|
12557
12708
|
],
|
|
12558
12709
|
{
|
|
12559
12710
|
env: {
|
|
@@ -12568,8 +12719,8 @@ async function createHostedBotRunner(host) {
|
|
|
12568
12719
|
maxBuffer: 1024 * 1024
|
|
12569
12720
|
}
|
|
12570
12721
|
);
|
|
12571
|
-
const safeGit =
|
|
12572
|
-
const protectedGit = lstatSync10(
|
|
12722
|
+
const safeGit = join31(gitCopy, "repo", ".git");
|
|
12723
|
+
const protectedGit = lstatSync10(join31(cwd, ".git")).isFile() ? join31(cwd, ".git") : safeGit;
|
|
12573
12724
|
writeJsonAtomic(file, resource);
|
|
12574
12725
|
const created = await exec3(
|
|
12575
12726
|
"docker",
|
|
@@ -12657,7 +12808,7 @@ async function createHostedBotRunner(host) {
|
|
|
12657
12808
|
};
|
|
12658
12809
|
} finally {
|
|
12659
12810
|
if (existsSync8(file)) await removeResource(file, resource);
|
|
12660
|
-
else
|
|
12811
|
+
else rmSync20(gitCopy, { recursive: true, force: true });
|
|
12661
12812
|
}
|
|
12662
12813
|
};
|
|
12663
12814
|
return {
|
|
@@ -12668,12 +12819,14 @@ async function createHostedBotRunner(host) {
|
|
|
12668
12819
|
async start(assignment, options) {
|
|
12669
12820
|
const gate = requireRunToolApproval(options.runId, options.toolApproval);
|
|
12670
12821
|
const selected = assignment.subscriptionBinding;
|
|
12822
|
+
const apiKey = assignment.modelCredential;
|
|
12671
12823
|
const kind = assignment.harness;
|
|
12672
|
-
|
|
12824
|
+
const protocol = kind === "codex" ? "openai" : "anthropic";
|
|
12825
|
+
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)
|
|
12673
12826
|
throw unavailable3();
|
|
12674
12827
|
const name = `mikka-native-${randomUUID7()}`;
|
|
12675
12828
|
const nonce = randomUUID7();
|
|
12676
|
-
const resourceFile =
|
|
12829
|
+
const resourceFile = join31(resources, name + ".json");
|
|
12677
12830
|
const resource = { name, nonce, state: "creating" };
|
|
12678
12831
|
const lifetime = new AbortController();
|
|
12679
12832
|
let closed = false;
|
|
@@ -12731,25 +12884,29 @@ async function createHostedBotRunner(host) {
|
|
|
12731
12884
|
});
|
|
12732
12885
|
try {
|
|
12733
12886
|
await live();
|
|
12734
|
-
const
|
|
12735
|
-
|
|
12736
|
-
|
|
12737
|
-
if (first.route !== selected.route || first.modelId !== options.model)
|
|
12738
|
-
throw unavailable3();
|
|
12739
|
-
const revision = first.revision;
|
|
12740
|
-
const check = async () => {
|
|
12741
|
-
await live();
|
|
12742
|
-
const current = await context();
|
|
12887
|
+
const subscription = selected ? await (async () => {
|
|
12888
|
+
const context = () => host.link.nativeContext(assignment.deviceId, assignment.runId, lifetime.signal);
|
|
12889
|
+
const first = nativeBrokerContextSchema.parse(await context());
|
|
12743
12890
|
await live();
|
|
12744
|
-
if (
|
|
12891
|
+
if (first.route !== selected.route || first.modelId !== options.model)
|
|
12745
12892
|
throw unavailable3();
|
|
12746
|
-
|
|
12747
|
-
|
|
12893
|
+
const revision = first.revision;
|
|
12894
|
+
const check2 = async () => {
|
|
12895
|
+
await live();
|
|
12896
|
+
const current = await context();
|
|
12897
|
+
await live();
|
|
12898
|
+
if (current.revision !== revision || current.accountId !== first.accountId || current.route !== first.route || current.modelId !== first.modelId)
|
|
12899
|
+
throw unavailable3();
|
|
12900
|
+
return current;
|
|
12901
|
+
};
|
|
12902
|
+
return { first, revision, check: check2 };
|
|
12903
|
+
})() : void 0;
|
|
12904
|
+
const check = subscription?.check ?? live;
|
|
12748
12905
|
const paths = runPaths(host.stateDir, assignment.runId);
|
|
12749
|
-
|
|
12750
|
-
const shadow =
|
|
12751
|
-
const emptyHome =
|
|
12752
|
-
|
|
12906
|
+
mkdirSync18(paths.runDir, { recursive: true, mode: 448 });
|
|
12907
|
+
const shadow = join31(paths.runDir, "runtime-git");
|
|
12908
|
+
const emptyHome = join31(paths.runDir, "git-bootstrap-home");
|
|
12909
|
+
mkdirSync18(emptyHome, { recursive: true, mode: 448 });
|
|
12753
12910
|
if (!existsSync8(shadow))
|
|
12754
12911
|
await exec3(
|
|
12755
12912
|
"git",
|
|
@@ -12779,35 +12936,40 @@ async function createHostedBotRunner(host) {
|
|
|
12779
12936
|
}
|
|
12780
12937
|
);
|
|
12781
12938
|
await live();
|
|
12782
|
-
if (!lstatSync10(shadow).isDirectory() || !lstatSync10(
|
|
12939
|
+
if (!lstatSync10(shadow).isDirectory() || !lstatSync10(join31(shadow, ".git")).isDirectory() || !realpathSync11(shadow).startsWith(realpathSync11(paths.runDir) + "/"))
|
|
12783
12940
|
throw unavailable3();
|
|
12784
|
-
const ledger =
|
|
12941
|
+
const ledger = join31(
|
|
12785
12942
|
host.stateDir,
|
|
12786
12943
|
"native-ledgers",
|
|
12787
12944
|
assignment.runId + ".json"
|
|
12788
12945
|
);
|
|
12789
|
-
const scope = {
|
|
12946
|
+
const scope = selected && subscription ? {
|
|
12790
12947
|
runId: assignment.runId,
|
|
12791
12948
|
bindingId: selected.bindingId,
|
|
12792
12949
|
ownerId: selected.ownerId,
|
|
12793
12950
|
workspaceId: selected.workspaceId,
|
|
12794
12951
|
consumerId: selected.consumerId,
|
|
12795
12952
|
route: selected.route,
|
|
12796
|
-
revision,
|
|
12797
|
-
accountId: first.accountId,
|
|
12798
|
-
modelId: first.modelId
|
|
12799
|
-
};
|
|
12800
|
-
const previous = readJson(ledger);
|
|
12801
|
-
if (existsSync8(ledger) && (!previous || JSON.stringify(previous.scope) !== JSON.stringify(scope) || typeof previous.sessionId !== "string"))
|
|
12953
|
+
revision: subscription.revision,
|
|
12954
|
+
accountId: subscription.first.accountId,
|
|
12955
|
+
modelId: subscription.first.modelId
|
|
12956
|
+
} : void 0;
|
|
12957
|
+
const previous = scope ? readJson(ledger) : void 0;
|
|
12958
|
+
if (scope && existsSync8(ledger) && (!previous || JSON.stringify(previous.scope) !== JSON.stringify(scope) || typeof previous.sessionId !== "string"))
|
|
12802
12959
|
throw unavailable3();
|
|
12803
|
-
|
|
12960
|
+
if (scope) mkdirSync18(dirname15(ledger), { recursive: true, mode: 448 });
|
|
12804
12961
|
const record = async (sessionId) => {
|
|
12805
12962
|
assertOpen();
|
|
12806
|
-
writeJsonAtomic(ledger, { scope, sessionId });
|
|
12963
|
+
if (scope) writeJsonAtomic(ledger, { scope, sessionId });
|
|
12807
12964
|
};
|
|
12808
|
-
brokerStarting =
|
|
12809
|
-
root:
|
|
12810
|
-
|
|
12965
|
+
brokerStarting = apiKey ? createApiKeyBroker({
|
|
12966
|
+
root: join31(host.stateDir, "native-brokers"),
|
|
12967
|
+
protocol,
|
|
12968
|
+
credential: apiKey,
|
|
12969
|
+
check
|
|
12970
|
+
}) : createNativeSubscriptionBroker({
|
|
12971
|
+
root: join31(host.stateDir, "native-brokers"),
|
|
12972
|
+
revision: subscription.revision,
|
|
12811
12973
|
check,
|
|
12812
12974
|
worker: {
|
|
12813
12975
|
nativeRequest: async (_revision, payload, signal) => {
|
|
@@ -12833,7 +12995,7 @@ async function createHostedBotRunner(host) {
|
|
|
12833
12995
|
});
|
|
12834
12996
|
const readyBroker = await brokerStarting;
|
|
12835
12997
|
await live();
|
|
12836
|
-
const githubCli = options.github ? (process.env.PATH ?? "").split(delimiter3).map((dir) =>
|
|
12998
|
+
const githubCli = options.github ? (process.env.PATH ?? "").split(delimiter3).map((dir) => join31(dir, "gh")).find((file) => existsSync8(file)) : void 0;
|
|
12837
12999
|
if (options.github && !githubCli) throw new Error("Install GitHub CLI (gh) in the cloud worker image");
|
|
12838
13000
|
const githubDomains = options.github ? ["github.com", "api.github.com", new URL(options.github.endpoint).host] : [];
|
|
12839
13001
|
const egressMaximum = runDomains(runPolicy(options.policy), [...options.networkAllow ?? [], ...githubDomains]);
|
|
@@ -12850,13 +13012,13 @@ async function createHostedBotRunner(host) {
|
|
|
12850
13012
|
}
|
|
12851
13013
|
const cwd = realpathSync11(options.cwd);
|
|
12852
13014
|
const runDir = realpathSync11(paths.runDir);
|
|
12853
|
-
const protectedGit = lstatSync10(
|
|
13015
|
+
const protectedGit = lstatSync10(join31(cwd, ".git")).isFile() ? join31(cwd, ".git") : join31(shadow, ".git");
|
|
12854
13016
|
if (!lstatSync10(runDir).isDirectory() || !runDir.startsWith(realpathSync11(host.stateDir) + "/runs/")) {
|
|
12855
13017
|
await close();
|
|
12856
13018
|
throw unavailable3();
|
|
12857
13019
|
}
|
|
12858
13020
|
const computer = assignment.computer;
|
|
12859
|
-
if (computer && (!host.computerBroker || computer.ownerId !== selected.ownerId)) {
|
|
13021
|
+
if (computer && (!host.computerBroker || selected && computer.ownerId !== selected.ownerId)) {
|
|
12860
13022
|
await close();
|
|
12861
13023
|
throw unavailable3();
|
|
12862
13024
|
}
|
|
@@ -12904,7 +13066,7 @@ async function createHostedBotRunner(host) {
|
|
|
12904
13066
|
`${MCP_SERVER_SCRIPT}:${MCP_SERVER_SCRIPT}:ro`,
|
|
12905
13067
|
...githubCli ? ["-v", `${githubCli}:/usr/local/bin/mikka-gh:ro`, "-v", `${GITHUB_CREDENTIAL_SCRIPT}:${GITHUB_CREDENTIAL_SCRIPT}:ro`] : [],
|
|
12906
13068
|
"-v",
|
|
12907
|
-
`${
|
|
13069
|
+
`${join31(dirname15(MCP_SERVER_SCRIPT), "capture-copy.mjs")}:${join31(dirname15(MCP_SERVER_SCRIPT), "capture-copy.mjs")}:ro`,
|
|
12908
13070
|
"-v",
|
|
12909
13071
|
`${readyBroker.socket}:/run/mikka-native.sock:ro`,
|
|
12910
13072
|
...computerGrant ? [
|
|
@@ -12947,13 +13109,13 @@ async function createHostedBotRunner(host) {
|
|
|
12947
13109
|
}
|
|
12948
13110
|
const spawnHosted = (config) => {
|
|
12949
13111
|
assertOpen();
|
|
12950
|
-
const home =
|
|
12951
|
-
|
|
13112
|
+
const home = join31(runDir, "runtime-home");
|
|
13113
|
+
mkdirSync18(home, { recursive: true, mode: 448 });
|
|
12952
13114
|
const env = {
|
|
12953
13115
|
...config.env,
|
|
12954
13116
|
HOME: kind === "claude_code" ? config.env.HOME ?? home : home,
|
|
12955
|
-
PATH: `${options.github ?
|
|
12956
|
-
GIT_DIR:
|
|
13117
|
+
PATH: `${options.github ? join31(runDir, "github", "bin") + ":" : ""}/usr/local/bin:/usr/bin:/bin`,
|
|
13118
|
+
GIT_DIR: join31(shadow, ".git"),
|
|
12957
13119
|
GIT_WORK_TREE: cwd,
|
|
12958
13120
|
GIT_CONFIG_GLOBAL: "/dev/null",
|
|
12959
13121
|
GIT_CONFIG_SYSTEM: "/dev/null",
|
|
@@ -12962,7 +13124,7 @@ async function createHostedBotRunner(host) {
|
|
|
12962
13124
|
for (const [key2, value] of Object.entries(env))
|
|
12963
13125
|
if (value !== void 0 && (/INFISICAL|E2B_API_KEY|REFRESH_TOKEN|^AWS_|^GOOGLE_|^OPENAI_|^ANTHROPIC_.*(?:KEY|TOKEN)|SECRET|PASSWORD/.test(
|
|
12964
13126
|
key2
|
|
12965
|
-
) || key2 === "CLAUDE_CODE_OAUTH_TOKEN" && value !== placeholder))
|
|
13127
|
+
) || (key2 === "CLAUDE_CODE_OAUTH_TOKEN" || key2 === "MIKKA_MODEL_API_KEY") && value !== placeholder))
|
|
12966
13128
|
throw unavailable3();
|
|
12967
13129
|
const task = withTaskEnv(env, assignment.taskEnv);
|
|
12968
13130
|
if (task.dropped.length) console.warn(`run ${assignment.runId}: skipped reserved task variables ${task.dropped.join(", ")}`);
|
|
@@ -12972,7 +13134,7 @@ async function createHostedBotRunner(host) {
|
|
|
12972
13134
|
signal: AbortSignal.any([lifetime.signal, ...config.signal ? [config.signal] : []])
|
|
12973
13135
|
});
|
|
12974
13136
|
child.stdin.write(
|
|
12975
|
-
JSON.stringify({ kind, args: config.args, cwd, env: task.env, publicEgress: Boolean(egress), ...options.github ? { githubBin:
|
|
13137
|
+
JSON.stringify({ kind, args: config.args, cwd, env: task.env, publicEgress: Boolean(egress), ...options.github ? { githubBin: join31(runDir, "github", "bin") } : {} }) + "\n"
|
|
12976
13138
|
);
|
|
12977
13139
|
return child;
|
|
12978
13140
|
};
|
|
@@ -13001,19 +13163,27 @@ async function createHostedBotRunner(host) {
|
|
|
13001
13163
|
};
|
|
13002
13164
|
};
|
|
13003
13165
|
try {
|
|
13004
|
-
const
|
|
13166
|
+
const placeholderCredential = apiKey && kind === "codex" ? { kind: "provider", protocol: "openai", baseUrl: apiKey.kind === "provider" ? apiKey.baseUrl : "https://api.openai.com/v1", key: placeholder } : void 0;
|
|
13167
|
+
const adapter = apiKey ? kind === "codex" ? new CodexAdapter({ stateDir: host.stateDir, sandbox: blockedSandbox, spawnCli: codexSpawn, computerMcp }) : new ClaudeAdapter({
|
|
13168
|
+
stateDir: host.stateDir,
|
|
13169
|
+
computerMcp,
|
|
13170
|
+
spawnHosted: (config, token) => {
|
|
13171
|
+
if (token !== placeholder) throw unavailable3();
|
|
13172
|
+
return spawnHosted(config);
|
|
13173
|
+
}
|
|
13174
|
+
}) : kind === "codex" ? new CodexAdapter({
|
|
13005
13175
|
stateDir: host.stateDir,
|
|
13006
13176
|
sandbox: blockedSandbox,
|
|
13007
13177
|
spawnCli: codexSpawn,
|
|
13008
13178
|
onHostedSession: record,
|
|
13009
13179
|
computerMcp,
|
|
13010
13180
|
subscriptionAuth: {
|
|
13011
|
-
accountId: first.accountId,
|
|
13181
|
+
accountId: subscription.first.accountId,
|
|
13012
13182
|
verify: async () => {
|
|
13013
13183
|
await check();
|
|
13014
13184
|
},
|
|
13015
13185
|
token: async () => {
|
|
13016
|
-
const current = await check();
|
|
13186
|
+
const current = await subscription.check();
|
|
13017
13187
|
return {
|
|
13018
13188
|
accessToken: placeholder,
|
|
13019
13189
|
chatgptAccountId: current.accountId,
|
|
@@ -13031,12 +13201,12 @@ async function createHostedBotRunner(host) {
|
|
|
13031
13201
|
},
|
|
13032
13202
|
subscriptionAuth: {
|
|
13033
13203
|
brokered: true,
|
|
13034
|
-
accountId: first.accountId,
|
|
13204
|
+
accountId: subscription.first.accountId,
|
|
13035
13205
|
verify: async () => {
|
|
13036
13206
|
await check();
|
|
13037
13207
|
},
|
|
13038
13208
|
token: async () => {
|
|
13039
|
-
const current = await check();
|
|
13209
|
+
const current = await subscription.check();
|
|
13040
13210
|
return {
|
|
13041
13211
|
accessToken: placeholder,
|
|
13042
13212
|
accountId: current.accountId,
|
|
@@ -13045,7 +13215,7 @@ async function createHostedBotRunner(host) {
|
|
|
13045
13215
|
}
|
|
13046
13216
|
}
|
|
13047
13217
|
});
|
|
13048
|
-
const runtimeOptions = { ...options, ...options.github ? { githubRuntime: { nodeBinary: "/usr/local/bin/node", ghBinary: "/usr/local/bin/mikka-gh" } } : {} };
|
|
13218
|
+
const runtimeOptions = { ...options, credential: placeholderCredential, ...options.github ? { githubRuntime: { nodeBinary: "/usr/local/bin/node", ghBinary: "/usr/local/bin/mikka-gh" } } : {} };
|
|
13049
13219
|
const session = previous ? await adapter.resume(previous.sessionId, runtimeOptions) : await adapter.start(runtimeOptions);
|
|
13050
13220
|
let checking = false;
|
|
13051
13221
|
if (!closed) timer = setInterval(() => {
|
|
@@ -13107,8 +13277,8 @@ import {
|
|
|
13107
13277
|
createHash as createHash9,
|
|
13108
13278
|
timingSafeEqual as timingSafeEqual2
|
|
13109
13279
|
} from "node:crypto";
|
|
13110
|
-
import { chmodSync as
|
|
13111
|
-
import { createServer as
|
|
13280
|
+
import { chmodSync as chmodSync5 } from "node:fs";
|
|
13281
|
+
import { createServer as createServer5 } from "node:net";
|
|
13112
13282
|
|
|
13113
13283
|
// src/computer/driver.mjs
|
|
13114
13284
|
import { spawn as spawn6 } from "node:child_process";
|
|
@@ -13328,7 +13498,7 @@ var ComputerBroker = class {
|
|
|
13328
13498
|
}
|
|
13329
13499
|
async listen() {
|
|
13330
13500
|
if (this.suspended) throw new Error("Broker suspended");
|
|
13331
|
-
this.server =
|
|
13501
|
+
this.server = createServer5((socket) => {
|
|
13332
13502
|
this.sockets.add(socket);
|
|
13333
13503
|
socket.on("close", () => this.sockets.delete(socket));
|
|
13334
13504
|
let text3 = "", submitted = false;
|
|
@@ -13371,7 +13541,7 @@ var ComputerBroker = class {
|
|
|
13371
13541
|
else this.server.listen(this.socketPath, resolve13);
|
|
13372
13542
|
});
|
|
13373
13543
|
if (this.transport === "tcp") this.socketPath = `tcp://127.0.0.1:${this.server.address().port}`;
|
|
13374
|
-
else
|
|
13544
|
+
else chmodSync5(this.socketPath, 384);
|
|
13375
13545
|
}
|
|
13376
13546
|
request(token, value, signal) {
|
|
13377
13547
|
const grant = this.grants.get(token);
|
|
@@ -13617,6 +13787,9 @@ function loadDeviceFile(raw) {
|
|
|
13617
13787
|
return file;
|
|
13618
13788
|
}
|
|
13619
13789
|
var HARNESS_RESCAN_MS = 5 * 6e4;
|
|
13790
|
+
function credentialOwner(assignment) {
|
|
13791
|
+
return assignment.subscriptionBinding?.ownerId ?? (assignment.modelCredential ? assignment.computer?.ownerId : void 0);
|
|
13792
|
+
}
|
|
13620
13793
|
var SANDBOX_REPAIR_RETRY_MS = 60 * 6e4;
|
|
13621
13794
|
function missingToolsUnchanged(issue) {
|
|
13622
13795
|
return !issue?.missing.length || missingSandboxTools().length === issue.missing.length;
|
|
@@ -13692,8 +13865,8 @@ var Daemon = class {
|
|
|
13692
13865
|
}
|
|
13693
13866
|
async startInternal() {
|
|
13694
13867
|
const { paths } = this;
|
|
13695
|
-
|
|
13696
|
-
if (process.platform !== "win32")
|
|
13868
|
+
mkdirSync19(paths.dataDir, { recursive: true, mode: 448 });
|
|
13869
|
+
if (process.platform !== "win32") chmodSync6(paths.dataDir, 448);
|
|
13697
13870
|
this.releaseLock = await acquireLock(
|
|
13698
13871
|
paths.dataDir,
|
|
13699
13872
|
paths.lock,
|
|
@@ -13706,7 +13879,7 @@ var Daemon = class {
|
|
|
13706
13879
|
if (this.options.credential)
|
|
13707
13880
|
this.saveDevice({ credential: this.options.credential });
|
|
13708
13881
|
this.journal = new RunJournal(paths.journal);
|
|
13709
|
-
this.captureUploader = new CaptureUploader((runId) =>
|
|
13882
|
+
this.captureUploader = new CaptureUploader((runId) => join32(runPaths(paths.adapterState, runId).runDir, CAPTURES_DIR), this.options.link, this.log, join32(paths.dataDir, "capture-pending"));
|
|
13710
13883
|
this.outbox = new Outbox(
|
|
13711
13884
|
paths.outbox,
|
|
13712
13885
|
this.options.link,
|
|
@@ -13723,7 +13896,7 @@ var Daemon = class {
|
|
|
13723
13896
|
if (this.localComputerDriver && this.options.link.syncComputerReviews && this.options.link.localComputerAuthority) {
|
|
13724
13897
|
this.localComputerBroker = new ComputerBroker({
|
|
13725
13898
|
driver: this.localComputerDriver,
|
|
13726
|
-
socketPath:
|
|
13899
|
+
socketPath: join32(paths.dataDir, "local-computer.sock"),
|
|
13727
13900
|
transport: "tcp",
|
|
13728
13901
|
permitted: (runId) => {
|
|
13729
13902
|
const assignment = this.journal.get(runId)?.assignment;
|
|
@@ -13756,7 +13929,7 @@ var Daemon = class {
|
|
|
13756
13929
|
const liveComputer = (runId, display) => {
|
|
13757
13930
|
const entry = this.journal.get(runId);
|
|
13758
13931
|
const computer = entry?.assignment.computer;
|
|
13759
|
-
if (this.stopped || !this.registered || !computer || computer.display !== display || computer.ownerId !== entry
|
|
13932
|
+
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");
|
|
13760
13933
|
return computer;
|
|
13761
13934
|
};
|
|
13762
13935
|
const executeOrdinary = async (current, call, display, runId, assertLive) => {
|
|
@@ -13765,7 +13938,7 @@ var Daemon = class {
|
|
|
13765
13938
|
};
|
|
13766
13939
|
this.cloudComputerBroker = new ComputerBroker({
|
|
13767
13940
|
driver,
|
|
13768
|
-
socketPath:
|
|
13941
|
+
socketPath: join32(paths.dataDir, "computer.sock"),
|
|
13769
13942
|
permitted: (runId) => {
|
|
13770
13943
|
const entry = this.journal.get(runId);
|
|
13771
13944
|
return Boolean(!this.stopped && this.registered && entry?.assignment.computer && this.supervisor?.computerRunAllowed(runId));
|
|
@@ -13833,6 +14006,7 @@ var Daemon = class {
|
|
|
13833
14006
|
worktrees: this.worktrees,
|
|
13834
14007
|
adapters,
|
|
13835
14008
|
startSubscription: hosted?.start ?? this.localSubscriptions()?.start,
|
|
14009
|
+
startCredential: hosted?.start,
|
|
13836
14010
|
prepareRunMailbox: this.options.link.prepareRunMailbox?.bind(this.options.link),
|
|
13837
14011
|
prepareRunToolApproval: this.options.link.prepareRunToolApproval?.bind(this.options.link),
|
|
13838
14012
|
verifyRunPolicy: this.options.link.verifyRunPolicy ? async (assignment, signal) => {
|
|
@@ -13892,7 +14066,7 @@ var Daemon = class {
|
|
|
13892
14066
|
worktree,
|
|
13893
14067
|
tree,
|
|
13894
14068
|
github: { ...assignment.github, runToken: assignment.mcp.token, issueId: assignment.issueId },
|
|
13895
|
-
privateDir:
|
|
14069
|
+
privateDir: join32(paths.adapterState, "pids"),
|
|
13896
14070
|
...hosted ? { hosted: true } : {},
|
|
13897
14071
|
env: githubReceiptEnvironment()
|
|
13898
14072
|
}) : publishRun({
|
|
@@ -14252,11 +14426,11 @@ var Daemon = class {
|
|
|
14252
14426
|
return runVerify(sandbox, {
|
|
14253
14427
|
command,
|
|
14254
14428
|
worktree: realpathSync12(worktree),
|
|
14255
|
-
tmpRoot:
|
|
14429
|
+
tmpRoot: join32(this.paths.adapterState, "verify", runId),
|
|
14256
14430
|
privateDir: paths.privateDir,
|
|
14257
14431
|
pidFile: paths.pidFile.replace(/\.pgid$/, ".verify.pgid"),
|
|
14258
14432
|
networkAllow: repo.networkAllow,
|
|
14259
|
-
env: { ...buildChildEnv(), MIKKA_HANDOFF_FILE:
|
|
14433
|
+
env: { ...buildChildEnv(), MIKKA_HANDOFF_FILE: join32(paths.runDir, "handoff.json") },
|
|
14260
14434
|
timeoutMs,
|
|
14261
14435
|
signal,
|
|
14262
14436
|
readOnly
|
|
@@ -14441,7 +14615,7 @@ var Daemon = class {
|
|
|
14441
14615
|
setImmediate(() => {
|
|
14442
14616
|
void this.stop().then(() => uninstallService(() => {
|
|
14443
14617
|
this.saveDevice({ credential: void 0 });
|
|
14444
|
-
|
|
14618
|
+
rmSync21(this.paths.secret, { force: true });
|
|
14445
14619
|
})).catch(() => {
|
|
14446
14620
|
this.options.onDrained?.();
|
|
14447
14621
|
});
|
|
@@ -14559,7 +14733,7 @@ var Daemon = class {
|
|
|
14559
14733
|
throw new DaemonError(DAEMON_RPC_ERRORS.unauthorized, message);
|
|
14560
14734
|
}
|
|
14561
14735
|
}
|
|
14562
|
-
if (assignment.computer && (!this.cloudComputerBroker ||
|
|
14736
|
+
if (assignment.computer && (!this.cloudComputerBroker || assignment.computer.ownerId !== credentialOwner(assignment))) throw new Error("Cloud computer runtime unavailable");
|
|
14563
14737
|
return await this.supervisor.start(assignment);
|
|
14564
14738
|
}
|
|
14565
14739
|
/**
|
|
@@ -14766,7 +14940,7 @@ var Daemon = class {
|
|
|
14766
14940
|
if (!job || controller.signal.aborted) return;
|
|
14767
14941
|
await runNativeCoordinatorJob(job, {
|
|
14768
14942
|
deviceId,
|
|
14769
|
-
stateDir:
|
|
14943
|
+
stateDir: join32(this.paths.dataDir, "coordinator"),
|
|
14770
14944
|
link,
|
|
14771
14945
|
signal: controller.signal,
|
|
14772
14946
|
sandbox,
|
|
@@ -14809,7 +14983,7 @@ var Daemon = class {
|
|
|
14809
14983
|
}, void 0, () => !this.stopped);
|
|
14810
14984
|
});
|
|
14811
14985
|
} else if (!this.updateCheck && !this.updateVersion) {
|
|
14812
|
-
this.updateCheck = checkLatestVersion(
|
|
14986
|
+
this.updateCheck = checkLatestVersion(join32(this.paths.dataDir, "auto-update.json"), DAEMON_VERSION, runtime).then((version) => {
|
|
14813
14987
|
this.updateVersion = version;
|
|
14814
14988
|
}).catch(() => {
|
|
14815
14989
|
this.log.warn("Daemon automatic update check failed");
|