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