@aspectlylabs/mikka 0.0.86 → 0.0.89
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/README.md +6 -0
- package/cli.js +520 -178
- package/client.js +8 -2
- package/http-link.js +8 -2
- package/login.js +8 -2
- package/main.js +530 -188
- package/mikka-release-manifest.json +22 -22
- package/mikka.js +520 -178
- 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
|
@@ -878,10 +878,10 @@ var require_truncate = __commonJS({
|
|
|
878
878
|
"../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/truncate.js"(exports, module) {
|
|
879
879
|
"use strict";
|
|
880
880
|
var parse2 = require_parse();
|
|
881
|
-
var
|
|
881
|
+
var constants4 = require_constants();
|
|
882
882
|
var SemVer = require_semver();
|
|
883
883
|
var truncate = (version, truncation, options) => {
|
|
884
|
-
if (!
|
|
884
|
+
if (!constants4.RELEASE_TYPES.includes(truncation)) {
|
|
885
885
|
return null;
|
|
886
886
|
}
|
|
887
887
|
const clonedVersion = cloneInputVersion(version, options);
|
|
@@ -1930,7 +1930,7 @@ var require_semver2 = __commonJS({
|
|
|
1930
1930
|
"../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/index.js"(exports, module) {
|
|
1931
1931
|
"use strict";
|
|
1932
1932
|
var internalRe = require_re();
|
|
1933
|
-
var
|
|
1933
|
+
var constants4 = require_constants();
|
|
1934
1934
|
var SemVer = require_semver();
|
|
1935
1935
|
var identifiers = require_identifiers();
|
|
1936
1936
|
var parse2 = require_parse();
|
|
@@ -2014,8 +2014,8 @@ var require_semver2 = __commonJS({
|
|
|
2014
2014
|
re: internalRe.re,
|
|
2015
2015
|
src: internalRe.src,
|
|
2016
2016
|
tokens: internalRe.t,
|
|
2017
|
-
SEMVER_SPEC_VERSION:
|
|
2018
|
-
RELEASE_TYPES:
|
|
2017
|
+
SEMVER_SPEC_VERSION: constants4.SEMVER_SPEC_VERSION,
|
|
2018
|
+
RELEASE_TYPES: constants4.RELEASE_TYPES,
|
|
2019
2019
|
compareIdentifiers: identifiers.compareIdentifiers,
|
|
2020
2020
|
rcompareIdentifiers: identifiers.rcompareIdentifiers
|
|
2021
2021
|
};
|
|
@@ -2804,6 +2804,12 @@ var harnessInfoSchema = z6.object({
|
|
|
2804
2804
|
computerBroker: z6.literal(true).optional(),
|
|
2805
2805
|
/** Run-scoped CLI approvals and policy-version checks are supported. */
|
|
2806
2806
|
toolApproval: z6.literal(true).optional(),
|
|
2807
|
+
/**
|
|
2808
|
+
* The CLI exists but `installed` stays false because the daemon cannot run it
|
|
2809
|
+
* in a sandbox. `missing` names the absent packages; empty means the machine
|
|
2810
|
+
* itself refused isolation.
|
|
2811
|
+
*/
|
|
2812
|
+
sandboxBlocked: z6.object({ missing: z6.array(z6.string().trim().min(1).max(64)).max(8) }).optional(),
|
|
2807
2813
|
/** Version string reported by the CLI, null when not installed. */
|
|
2808
2814
|
version: z6.string().nullable()
|
|
2809
2815
|
});
|
|
@@ -4431,7 +4437,7 @@ import { join as join4 } from "node:path";
|
|
|
4431
4437
|
// package.json
|
|
4432
4438
|
var package_default = {
|
|
4433
4439
|
name: "@mikka/daemon",
|
|
4434
|
-
version: "0.0.
|
|
4440
|
+
version: "0.0.89",
|
|
4435
4441
|
description: "Local Mikka daemon: runs agents through the user's own CLIs",
|
|
4436
4442
|
type: "module",
|
|
4437
4443
|
private: true,
|
|
@@ -4490,7 +4496,7 @@ var package_default = {
|
|
|
4490
4496
|
engines: {
|
|
4491
4497
|
node: ">=24"
|
|
4492
4498
|
},
|
|
4493
|
-
gitHead: "
|
|
4499
|
+
gitHead: "16b71d6c5aa7e0122cafab65524823236ecbad64"
|
|
4494
4500
|
};
|
|
4495
4501
|
|
|
4496
4502
|
// src/paths.ts
|
|
@@ -7072,6 +7078,7 @@ var RunContext = class {
|
|
|
7072
7078
|
],
|
|
7073
7079
|
allowDomains: [
|
|
7074
7080
|
...HARNESS_DOMAINS[this.options.harness],
|
|
7081
|
+
...this.options.harnessDomains ?? [],
|
|
7075
7082
|
...runAppsHost(this.options.apps) ? [runAppsHost(this.options.apps)] : [],
|
|
7076
7083
|
...runDomains(
|
|
7077
7084
|
runPolicy(this.options.policy),
|
|
@@ -7595,15 +7602,15 @@ sandbox_mode = "read-only"
|
|
|
7595
7602
|
// src/main.ts
|
|
7596
7603
|
import { randomBytes as randomBytes3, randomUUID as randomUUID10 } from "node:crypto";
|
|
7597
7604
|
import {
|
|
7598
|
-
chmodSync as
|
|
7599
|
-
existsSync as
|
|
7600
|
-
mkdirSync as
|
|
7601
|
-
readFileSync as
|
|
7602
|
-
rmSync as
|
|
7605
|
+
chmodSync as chmodSync5,
|
|
7606
|
+
existsSync as existsSync8,
|
|
7607
|
+
mkdirSync as mkdirSync17,
|
|
7608
|
+
readFileSync as readFileSync12,
|
|
7609
|
+
rmSync as rmSync18,
|
|
7603
7610
|
realpathSync as realpathSync13
|
|
7604
7611
|
} from "node:fs";
|
|
7605
7612
|
import { arch, hostname, platform as platform2 } from "node:os";
|
|
7606
|
-
import { join as
|
|
7613
|
+
import { join as join32 } from "node:path";
|
|
7607
7614
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
7608
7615
|
|
|
7609
7616
|
// src/adapters/claude.ts
|
|
@@ -7629,7 +7636,52 @@ function computerSandboxPolicy(policy, spec) {
|
|
|
7629
7636
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
7630
7637
|
import { realpathSync as realpathSync9 } from "node:fs";
|
|
7631
7638
|
import { homedir as homedir6 } from "node:os";
|
|
7632
|
-
|
|
7639
|
+
|
|
7640
|
+
// src/adapters/claude-gateway.ts
|
|
7641
|
+
import { readFileSync as readFileSync9 } from "node:fs";
|
|
7642
|
+
import { join as join13 } from "node:path";
|
|
7643
|
+
var GATEWAY_ENV = [
|
|
7644
|
+
"ANTHROPIC_BASE_URL",
|
|
7645
|
+
"ANTHROPIC_AUTH_TOKEN",
|
|
7646
|
+
"ANTHROPIC_API_KEY",
|
|
7647
|
+
"ANTHROPIC_MODEL",
|
|
7648
|
+
"ANTHROPIC_DEFAULT_FABLE_MODEL",
|
|
7649
|
+
"ANTHROPIC_DEFAULT_OPUS_MODEL",
|
|
7650
|
+
"ANTHROPIC_DEFAULT_SONNET_MODEL",
|
|
7651
|
+
"ANTHROPIC_DEFAULT_HAIKU_MODEL",
|
|
7652
|
+
"CLAUDE_CODE_SUBAGENT_MODEL"
|
|
7653
|
+
];
|
|
7654
|
+
function readClaudeGateway(configDir) {
|
|
7655
|
+
let settings;
|
|
7656
|
+
try {
|
|
7657
|
+
settings = JSON.parse(readFileSync9(join13(configDir, "settings.json"), "utf8"));
|
|
7658
|
+
} catch {
|
|
7659
|
+
return null;
|
|
7660
|
+
}
|
|
7661
|
+
const declared = settings?.env;
|
|
7662
|
+
if (!declared || typeof declared !== "object") return null;
|
|
7663
|
+
const values = declared;
|
|
7664
|
+
const domain = gatewayDomain(values.ANTHROPIC_BASE_URL);
|
|
7665
|
+
if (!domain) return null;
|
|
7666
|
+
const env = {};
|
|
7667
|
+
for (const name of GATEWAY_ENV) {
|
|
7668
|
+
const value = values[name];
|
|
7669
|
+
if (typeof value === "string" && value) env[name] = value;
|
|
7670
|
+
}
|
|
7671
|
+
return { env, domain };
|
|
7672
|
+
}
|
|
7673
|
+
function gatewayDomain(baseUrl) {
|
|
7674
|
+
if (typeof baseUrl !== "string") return null;
|
|
7675
|
+
try {
|
|
7676
|
+
const url = new URL(baseUrl);
|
|
7677
|
+
return url.protocol === "https:" || url.protocol === "http:" ? url.hostname : null;
|
|
7678
|
+
} catch {
|
|
7679
|
+
return null;
|
|
7680
|
+
}
|
|
7681
|
+
}
|
|
7682
|
+
|
|
7683
|
+
// src/adapters/claude.ts
|
|
7684
|
+
import { join as join15 } from "node:path";
|
|
7633
7685
|
import {
|
|
7634
7686
|
query as query2,
|
|
7635
7687
|
createSdkMcpServer as createSdkMcpServer2
|
|
@@ -7890,15 +7942,15 @@ function runNetworkApproval(runId, harness, gate, maximum, localComputerEndpoint
|
|
|
7890
7942
|
// src/subscription-native-broker.ts
|
|
7891
7943
|
import { chmodSync, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync4, rmSync as rmSync10 } from "node:fs";
|
|
7892
7944
|
import { createServer } from "node:http";
|
|
7893
|
-
import { join as
|
|
7945
|
+
import { join as join14 } from "node:path";
|
|
7894
7946
|
import { once } from "node:events";
|
|
7895
7947
|
var NATIVE_AUTH_PLACEHOLDER = "mikka-native-broker-placeholder";
|
|
7896
7948
|
async function createNativeSubscriptionBroker(host) {
|
|
7897
7949
|
await host.check();
|
|
7898
7950
|
mkdirSync10(host.root, { recursive: true, mode: 448 });
|
|
7899
|
-
const dir = mkdtempSync4(
|
|
7951
|
+
const dir = mkdtempSync4(join14(host.root, "native-broker-"));
|
|
7900
7952
|
chmodSync(dir, 448);
|
|
7901
|
-
const socket =
|
|
7953
|
+
const socket = join14(dir, "broker.sock");
|
|
7902
7954
|
const pending = /* @__PURE__ */ new Set();
|
|
7903
7955
|
let halted = false;
|
|
7904
7956
|
const server = createServer(async (request, response) => {
|
|
@@ -8252,10 +8304,12 @@ var ClaudeAdapter = class {
|
|
|
8252
8304
|
throw new Error(SUBSCRIPTION_ERROR);
|
|
8253
8305
|
}
|
|
8254
8306
|
}
|
|
8255
|
-
const nativeHome = externalAuth ?
|
|
8256
|
-
const configDir = nativeHome ?
|
|
8307
|
+
const nativeHome = externalAuth ? join15(runDir, "native-home") : void 0;
|
|
8308
|
+
const configDir = nativeHome ? join15(nativeHome, ".claude") : this.options.configDir ?? join15(homedir6(), ".claude");
|
|
8257
8309
|
if (nativeHome) ownDir(configDir);
|
|
8310
|
+
const gateway = nativeHome || externalAuth ? null : readClaudeGateway(configDir);
|
|
8258
8311
|
const ctx = new RunContext({
|
|
8312
|
+
harnessDomains: gateway ? [gateway.domain] : void 0,
|
|
8259
8313
|
github: options.github,
|
|
8260
8314
|
apps: options.apps,
|
|
8261
8315
|
githubRuntime: options.githubRuntime,
|
|
@@ -8274,8 +8328,8 @@ var ClaudeAdapter = class {
|
|
|
8274
8328
|
privateDir: paths.privateDir,
|
|
8275
8329
|
// Its session store, so `resume` works; keyed by the cwd it sees.
|
|
8276
8330
|
extraWrite: [
|
|
8277
|
-
|
|
8278
|
-
|
|
8331
|
+
join15(configDir, "projects", claudeProjectDirName(options.cwd)),
|
|
8332
|
+
join15(
|
|
8279
8333
|
configDir,
|
|
8280
8334
|
"projects",
|
|
8281
8335
|
claudeProjectDirName(realpathSync9(options.cwd))
|
|
@@ -8334,6 +8388,7 @@ var ClaudeAdapter = class {
|
|
|
8334
8388
|
...options.env,
|
|
8335
8389
|
...ctx.tempEnv(),
|
|
8336
8390
|
...CLAUDE_RUN_ENV,
|
|
8391
|
+
...gateway?.env,
|
|
8337
8392
|
CLAUDE_CODE_TMPDIR: ctx.tmpDir,
|
|
8338
8393
|
...nativeHome ? {
|
|
8339
8394
|
HOME: nativeHome,
|
|
@@ -8520,7 +8575,26 @@ var ClaudeAdapter = class {
|
|
|
8520
8575
|
};
|
|
8521
8576
|
|
|
8522
8577
|
// src/adapters/codex.ts
|
|
8523
|
-
import { isAbsolute as isAbsolute4, join as
|
|
8578
|
+
import { isAbsolute as isAbsolute4, join as join16, relative as relative3 } from "node:path";
|
|
8579
|
+
|
|
8580
|
+
// src/adapters/codex-version.ts
|
|
8581
|
+
var VERSION = /(?:^|[ /])(\d+)\.(\d+)\.(\d+)(?:$|[ ();])/;
|
|
8582
|
+
var MINIMUM_APPROVAL_VERSION = [0, 162, 0];
|
|
8583
|
+
var AUDITED_DYNAMIC_TOOLS = "0.163.0";
|
|
8584
|
+
function codexSupportsRunApproval(version) {
|
|
8585
|
+
const match = VERSION.exec(version ?? "");
|
|
8586
|
+
if (!match) return false;
|
|
8587
|
+
for (const [index, minimum] of MINIMUM_APPROVAL_VERSION.entries()) {
|
|
8588
|
+
const part = Number(match[index + 1]);
|
|
8589
|
+
if (part !== minimum) return part > minimum;
|
|
8590
|
+
}
|
|
8591
|
+
return true;
|
|
8592
|
+
}
|
|
8593
|
+
function codexHasAuditedDynamicTools(version) {
|
|
8594
|
+
return VERSION.exec(version ?? "")?.slice(1).join(".") === AUDITED_DYNAMIC_TOOLS;
|
|
8595
|
+
}
|
|
8596
|
+
|
|
8597
|
+
// src/adapters/codex.ts
|
|
8524
8598
|
var SUBSCRIPTION_AUTH_ERROR = "Codex subscription authentication unavailable";
|
|
8525
8599
|
var SUBSCRIPTION_EXECUTION_ERROR2 = "Codex subscription execution failed";
|
|
8526
8600
|
function subscriptionTokens(value, accountId) {
|
|
@@ -8689,8 +8763,8 @@ var CodexAdapter = class {
|
|
|
8689
8763
|
options.continueSession.runId
|
|
8690
8764
|
).runDir;
|
|
8691
8765
|
carryHistory(
|
|
8692
|
-
|
|
8693
|
-
|
|
8766
|
+
join16(earlier2, "codex-home"),
|
|
8767
|
+
join16(runDir, "codex-home"),
|
|
8694
8768
|
CODEX_HISTORY
|
|
8695
8769
|
);
|
|
8696
8770
|
} catch (error) {
|
|
@@ -8702,7 +8776,7 @@ var CodexAdapter = class {
|
|
|
8702
8776
|
}
|
|
8703
8777
|
}
|
|
8704
8778
|
const codexHome = prepareCodexHome(
|
|
8705
|
-
|
|
8779
|
+
join16(runDir, "codex-home"),
|
|
8706
8780
|
log,
|
|
8707
8781
|
this.options.userHome,
|
|
8708
8782
|
!externalAuth
|
|
@@ -9041,7 +9115,8 @@ var CodexAdapter = class {
|
|
|
9041
9115
|
}),
|
|
9042
9116
|
"initialize"
|
|
9043
9117
|
);
|
|
9044
|
-
if (
|
|
9118
|
+
if (options.mailbox && !codexHasAuditedDynamicTools(initialized.userAgent)) throw new Error("Run permissions require the audited Codex0.163.0 tool interface");
|
|
9119
|
+
if (!codexSupportsRunApproval(initialized.userAgent)) throw new Error("This Codex version is too old for Mikka; update Codex");
|
|
9045
9120
|
await rpc.sendNotification("initialized");
|
|
9046
9121
|
if (externalAuth) {
|
|
9047
9122
|
try {
|
|
@@ -9154,7 +9229,7 @@ var CodexAdapter = class {
|
|
|
9154
9229
|
// src/adapters/cursor.ts
|
|
9155
9230
|
import { Readable, Writable } from "node:stream";
|
|
9156
9231
|
import * as acp from "@agentclientprotocol/sdk";
|
|
9157
|
-
import { join as
|
|
9232
|
+
import { join as join17 } from "node:path";
|
|
9158
9233
|
function acpPermissionResponse(params, policy) {
|
|
9159
9234
|
const pick = (kinds) => {
|
|
9160
9235
|
for (const kind of kinds) {
|
|
@@ -9289,15 +9364,15 @@ var CursorAdapter = class {
|
|
|
9289
9364
|
options.continueSession.runId
|
|
9290
9365
|
).runDir;
|
|
9291
9366
|
carryHistory(
|
|
9292
|
-
|
|
9293
|
-
|
|
9367
|
+
join17(earlier2, "cursor-home"),
|
|
9368
|
+
join17(paths.runDir, "cursor-home"),
|
|
9294
9369
|
CURSOR_HISTORY
|
|
9295
9370
|
);
|
|
9296
9371
|
} catch (error) {
|
|
9297
9372
|
log.info({ err: error }, "could not copy the earlier cursor chats");
|
|
9298
9373
|
}
|
|
9299
9374
|
}
|
|
9300
|
-
const configDir = prepareCursorHome(
|
|
9375
|
+
const configDir = prepareCursorHome(join17(paths.runDir, "cursor-home"));
|
|
9301
9376
|
const ctx = new RunContext({
|
|
9302
9377
|
github: options.github,
|
|
9303
9378
|
childPath: options.env.PATH,
|
|
@@ -9529,8 +9604,8 @@ ${firstMessage}` : firstMessage
|
|
|
9529
9604
|
|
|
9530
9605
|
// src/adapters/mock.ts
|
|
9531
9606
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
9532
|
-
import { mkdirSync as mkdirSync11, readFileSync as
|
|
9533
|
-
import { dirname as dirname9, join as
|
|
9607
|
+
import { mkdirSync as mkdirSync11, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "node:fs";
|
|
9608
|
+
import { dirname as dirname9, join as join18, resolve as resolve8 } from "node:path";
|
|
9534
9609
|
import { setTimeout as sleep2 } from "node:timers/promises";
|
|
9535
9610
|
import { execa as execa5 } from "execa";
|
|
9536
9611
|
|
|
@@ -9586,7 +9661,7 @@ var MockAdapter = class {
|
|
|
9586
9661
|
fixturesDir;
|
|
9587
9662
|
speed;
|
|
9588
9663
|
stateFile(sessionId) {
|
|
9589
|
-
return
|
|
9664
|
+
return join18(
|
|
9590
9665
|
this.options.stateDir,
|
|
9591
9666
|
`mock-${assertSafeId("session id", sessionId)}.json`
|
|
9592
9667
|
);
|
|
@@ -9630,7 +9705,7 @@ var MockAdapter = class {
|
|
|
9630
9705
|
open(sessionId, state, options) {
|
|
9631
9706
|
const name = assertSafeId("fixture", state.fixture.replace(/\.jsonl$/, ""));
|
|
9632
9707
|
const lines = parseFixture(
|
|
9633
|
-
|
|
9708
|
+
readFileSync10(join18(this.fixturesDir, `${name}.jsonl`), "utf8"),
|
|
9634
9709
|
name
|
|
9635
9710
|
);
|
|
9636
9711
|
const abort = new AbortController();
|
|
@@ -9744,18 +9819,18 @@ var MockAdapter = class {
|
|
|
9744
9819
|
|
|
9745
9820
|
// src/agents/verify.ts
|
|
9746
9821
|
import { mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync5, realpathSync as realpathSync10, rmSync as rmSync11 } from "node:fs";
|
|
9747
|
-
import { join as
|
|
9822
|
+
import { join as join19 } from "node:path";
|
|
9748
9823
|
var OUTPUT_TAIL = 4e3;
|
|
9749
9824
|
async function runVerify(sandbox, options) {
|
|
9750
9825
|
mkdirSync12(options.tmpRoot, { recursive: true, mode: 448 });
|
|
9751
|
-
const tmpDir = mkdtempSync5(
|
|
9826
|
+
const tmpDir = mkdtempSync5(join19(realpathSync10(options.tmpRoot), "verify-"));
|
|
9752
9827
|
const child = await spawnCli(sandbox, ["/bin/sh", "-c", options.command], {
|
|
9753
9828
|
cwd: options.worktree,
|
|
9754
9829
|
env: { ...options.env, TMPDIR: tmpDir },
|
|
9755
9830
|
policy: {
|
|
9756
9831
|
allowWrite: options.readOnly ? [tmpDir] : [options.worktree, tmpDir],
|
|
9757
9832
|
denyWrite: [
|
|
9758
|
-
|
|
9833
|
+
join19(options.worktree, ".git"),
|
|
9759
9834
|
...options.readOnly ? [options.worktree] : []
|
|
9760
9835
|
],
|
|
9761
9836
|
denyRead: [
|
|
@@ -9926,7 +10001,7 @@ import { SandboxManager as SandboxManager2 } from "@anthropic-ai/sandbox-runtime
|
|
|
9926
10001
|
import { execFile as execFile3 } from "node:child_process";
|
|
9927
10002
|
import { readdir as readdir2, realpath, stat } from "node:fs/promises";
|
|
9928
10003
|
import { homedir as homedir7, platform } from "node:os";
|
|
9929
|
-
import { basename as basename2, dirname as dirname10, isAbsolute as isAbsolute5, join as
|
|
10004
|
+
import { basename as basename2, dirname as dirname10, isAbsolute as isAbsolute5, join as join20, resolve as resolve9 } from "node:path";
|
|
9930
10005
|
import { promisify as promisify3 } from "node:util";
|
|
9931
10006
|
var run = promisify3(execFile3);
|
|
9932
10007
|
async function git(cwd, args) {
|
|
@@ -9996,7 +10071,7 @@ async function browseFolder(request) {
|
|
|
9996
10071
|
let truncated = false;
|
|
9997
10072
|
const dirs = names.filter((e) => e.isDirectory() || e.isSymbolicLink()).filter((e) => request.showHidden || !e.name.startsWith(".")).sort((a, b) => a.name.localeCompare(b.name));
|
|
9998
10073
|
for (const entry of dirs) {
|
|
9999
|
-
const full =
|
|
10074
|
+
const full = join20(path, entry.name);
|
|
10000
10075
|
if (entry.isSymbolicLink() && !await isDir(full)) continue;
|
|
10001
10076
|
if (folders.length >= FS_MAX_ENTRIES) {
|
|
10002
10077
|
truncated = true;
|
|
@@ -10005,7 +10080,7 @@ async function browseFolder(request) {
|
|
|
10005
10080
|
folders.push({
|
|
10006
10081
|
name: entry.name,
|
|
10007
10082
|
path: full,
|
|
10008
|
-
isRepo: await exists(
|
|
10083
|
+
isRepo: await exists(join20(full, ".git"))
|
|
10009
10084
|
});
|
|
10010
10085
|
}
|
|
10011
10086
|
const parent = dirname10(path);
|
|
@@ -10062,6 +10137,9 @@ async function detectDeviceType() {
|
|
|
10062
10137
|
}
|
|
10063
10138
|
|
|
10064
10139
|
// src/harnesses.ts
|
|
10140
|
+
import { readdirSync as readdirSync4, statSync as statSync2 } from "node:fs";
|
|
10141
|
+
import { homedir as homedir8, userInfo } from "node:os";
|
|
10142
|
+
import { delimiter as delimiter3, isAbsolute as isAbsolute7, join as join22 } from "node:path";
|
|
10065
10143
|
import { execa as execa9 } from "execa";
|
|
10066
10144
|
|
|
10067
10145
|
// src/harness-models.ts
|
|
@@ -10207,12 +10285,99 @@ async function discover(harness, binary) {
|
|
|
10207
10285
|
return {};
|
|
10208
10286
|
}
|
|
10209
10287
|
|
|
10288
|
+
// src/path-search.ts
|
|
10289
|
+
import { accessSync, constants as constants2, statSync } from "node:fs";
|
|
10290
|
+
import { delimiter as delimiter2, isAbsolute as isAbsolute6, join as join21 } from "node:path";
|
|
10291
|
+
function findOnPath(command, path = process.env.PATH ?? "") {
|
|
10292
|
+
for (const directory of path.split(delimiter2)) {
|
|
10293
|
+
if (!directory) continue;
|
|
10294
|
+
const candidate = join21(directory, command);
|
|
10295
|
+
try {
|
|
10296
|
+
accessSync(candidate, constants2.X_OK);
|
|
10297
|
+
if (statSync(candidate).isFile()) return candidate;
|
|
10298
|
+
} catch {
|
|
10299
|
+
}
|
|
10300
|
+
}
|
|
10301
|
+
return null;
|
|
10302
|
+
}
|
|
10303
|
+
function appendToPath(directories) {
|
|
10304
|
+
const entries = (process.env.PATH ?? "").split(delimiter2).filter(Boolean);
|
|
10305
|
+
for (const directory of directories) {
|
|
10306
|
+
if (isAbsolute6(directory) && !entries.includes(directory)) entries.push(directory);
|
|
10307
|
+
}
|
|
10308
|
+
process.env.PATH = entries.join(delimiter2);
|
|
10309
|
+
}
|
|
10310
|
+
|
|
10210
10311
|
// src/harnesses.ts
|
|
10211
10312
|
var HARNESS_BINARIES = {
|
|
10212
10313
|
claude_code: ["claude"],
|
|
10213
10314
|
codex: ["codex"],
|
|
10214
10315
|
cursor: ["cursor-agent", "agent"]
|
|
10215
10316
|
};
|
|
10317
|
+
var LOGIN_SHELL_TIMEOUT_MS = 5e3;
|
|
10318
|
+
var PATH_MARKER = "__MIKKA_PATH__";
|
|
10319
|
+
function subdirectories(directory) {
|
|
10320
|
+
try {
|
|
10321
|
+
return readdirSync4(directory).map((name) => join22(directory, name));
|
|
10322
|
+
} catch {
|
|
10323
|
+
return [];
|
|
10324
|
+
}
|
|
10325
|
+
}
|
|
10326
|
+
function knownAgentDirectories(home = homedir8()) {
|
|
10327
|
+
return [
|
|
10328
|
+
join22(home, ".local/bin"),
|
|
10329
|
+
join22(home, "bin"),
|
|
10330
|
+
join22(home, ".claude/local"),
|
|
10331
|
+
join22(home, ".npm-global/bin"),
|
|
10332
|
+
join22(home, ".bun/bin"),
|
|
10333
|
+
join22(home, ".volta/bin"),
|
|
10334
|
+
join22(home, ".local/share/pnpm"),
|
|
10335
|
+
join22(home, "Library/pnpm"),
|
|
10336
|
+
join22(home, ".asdf/shims"),
|
|
10337
|
+
join22(home, ".local/share/mise/shims"),
|
|
10338
|
+
...subdirectories(join22(home, ".nvm/versions/node")).map((version) => join22(version, "bin")),
|
|
10339
|
+
...subdirectories(join22(home, ".local/share/fnm/node-versions")).map((version) => join22(version, "installation/bin")),
|
|
10340
|
+
"/opt/homebrew/bin",
|
|
10341
|
+
"/usr/local/bin",
|
|
10342
|
+
"/snap/bin"
|
|
10343
|
+
];
|
|
10344
|
+
}
|
|
10345
|
+
async function loginShellPath(shell = process.env.SHELL || userInfo().shell) {
|
|
10346
|
+
if (!shell || !isAbsolute7(shell)) return [];
|
|
10347
|
+
let timer;
|
|
10348
|
+
try {
|
|
10349
|
+
const shellProcess = execa9(shell, ["-ilc", `printf '${PATH_MARKER}%s${PATH_MARKER}' "$PATH"`], {
|
|
10350
|
+
stdin: "ignore",
|
|
10351
|
+
detached: true,
|
|
10352
|
+
reject: false
|
|
10353
|
+
});
|
|
10354
|
+
const timedOut = new Promise((resolve12) => {
|
|
10355
|
+
timer = setTimeout(() => {
|
|
10356
|
+
try {
|
|
10357
|
+
process.kill(-shellProcess.pid, "SIGKILL");
|
|
10358
|
+
} catch {
|
|
10359
|
+
}
|
|
10360
|
+
resolve12(null);
|
|
10361
|
+
}, LOGIN_SHELL_TIMEOUT_MS);
|
|
10362
|
+
});
|
|
10363
|
+
const result = await Promise.race([shellProcess, timedOut]);
|
|
10364
|
+
return String(result?.stdout ?? "").split(PATH_MARKER)[1]?.split(delimiter3).filter(isAbsolute7) ?? [];
|
|
10365
|
+
} catch {
|
|
10366
|
+
return [];
|
|
10367
|
+
} finally {
|
|
10368
|
+
clearTimeout(timer);
|
|
10369
|
+
}
|
|
10370
|
+
}
|
|
10371
|
+
function harnessFingerprint() {
|
|
10372
|
+
appendToPath(knownAgentDirectories());
|
|
10373
|
+
return Object.values(HARNESS_BINARIES).map((binaries) => {
|
|
10374
|
+
for (const binary of binaries) {
|
|
10375
|
+
const found = findOnPath(binary);
|
|
10376
|
+
if (found) return `${found}:${statSync2(found).mtimeMs}`;
|
|
10377
|
+
}
|
|
10378
|
+
return "";
|
|
10379
|
+
}).join("|");
|
|
10380
|
+
}
|
|
10216
10381
|
async function versionOf(binary) {
|
|
10217
10382
|
try {
|
|
10218
10383
|
const { stdout } = await execa9(binary, ["--version"], {
|
|
@@ -10228,6 +10393,7 @@ async function versionOf(binary) {
|
|
|
10228
10393
|
}
|
|
10229
10394
|
}
|
|
10230
10395
|
async function detectHarnesses() {
|
|
10396
|
+
if (!daemonTestMode(process.env)) appendToPath([...await loginShellPath(), ...knownAgentDirectories()]);
|
|
10231
10397
|
const detected = await Promise.all(
|
|
10232
10398
|
Object.keys(HARNESS_BINARIES).map(
|
|
10233
10399
|
async (harness) => {
|
|
@@ -10248,16 +10414,136 @@ async function detectHarnesses() {
|
|
|
10248
10414
|
];
|
|
10249
10415
|
}
|
|
10250
10416
|
|
|
10417
|
+
// src/sandbox-tools.ts
|
|
10418
|
+
import { chmodSync as chmodSync2, existsSync as existsSync5, lstatSync as lstatSync8, mkdirSync as mkdirSync13, mkdtempSync as mkdtempSync6, readdirSync as readdirSync5, renameSync as renameSync2, rmSync as rmSync12, writeFileSync as writeFileSync7 } from "node:fs";
|
|
10419
|
+
import { join as join23 } from "node:path";
|
|
10420
|
+
import { execa as execa10 } from "execa";
|
|
10421
|
+
var TOOLS = [
|
|
10422
|
+
{ command: "bwrap", package: "bubblewrap", versionFlag: "--version" },
|
|
10423
|
+
{ command: "socat", package: "socat", versionFlag: "-V" },
|
|
10424
|
+
{ command: "rg", package: "ripgrep", versionFlag: "--version" }
|
|
10425
|
+
];
|
|
10426
|
+
var APT_TIMEOUT_MS = 12e4;
|
|
10427
|
+
var TOOL_CHECK_TIMEOUT_MS = 5e3;
|
|
10428
|
+
var runTool = async (file, args, cwd, env) => {
|
|
10429
|
+
const { stdout } = await execa10(file, args, { cwd, env, stdin: "ignore", timeout: file === "apt-get" ? APT_TIMEOUT_MS : TOOL_CHECK_TIMEOUT_MS });
|
|
10430
|
+
return { stdout: String(stdout) };
|
|
10431
|
+
};
|
|
10432
|
+
function sandboxToolsDir(dataDir) {
|
|
10433
|
+
return join23(dataDir, "sandbox-tools", "bin");
|
|
10434
|
+
}
|
|
10435
|
+
function missingSandboxTools() {
|
|
10436
|
+
return TOOLS.filter((tool2) => !findOnPath(tool2.command)).map((tool2) => tool2.package);
|
|
10437
|
+
}
|
|
10438
|
+
async function ensureSandboxTools(options) {
|
|
10439
|
+
if ((options.platform ?? process.platform) !== "linux") return [];
|
|
10440
|
+
const { dataDir, log, run: run2 = runTool } = options;
|
|
10441
|
+
const binDir = sandboxToolsDir(dataDir);
|
|
10442
|
+
appendToPath([binDir]);
|
|
10443
|
+
const needed = TOOLS.filter((tool2) => !findOnPath(tool2.command));
|
|
10444
|
+
if (needed.length === 0) return [];
|
|
10445
|
+
const packages = needed.map((tool2) => tool2.package);
|
|
10446
|
+
if (!findOnPath("apt-get") || !findOnPath("dpkg-deb")) {
|
|
10447
|
+
log.warn({ missing: packages }, "sandbox tools missing and apt is unavailable");
|
|
10448
|
+
return packages;
|
|
10449
|
+
}
|
|
10450
|
+
mkdirSync13(binDir, { recursive: true, mode: 448 });
|
|
10451
|
+
const work = mkdtempSync6(join23(dataDir, "sandbox-tools", ".install-"));
|
|
10452
|
+
try {
|
|
10453
|
+
const apt = await downloadPackages(work, packages, run2);
|
|
10454
|
+
for (const tool2 of needed) {
|
|
10455
|
+
try {
|
|
10456
|
+
await installTool(tool2, { work, dataDir, apt, run: run2 });
|
|
10457
|
+
} catch (err) {
|
|
10458
|
+
log.warn({ package: tool2.package, err: errorMessage2(err) }, "sandbox tool unusable on this machine");
|
|
10459
|
+
}
|
|
10460
|
+
}
|
|
10461
|
+
} catch (err) {
|
|
10462
|
+
log.warn({ missing: packages, err: errorMessage2(err) }, "could not download sandbox tools");
|
|
10463
|
+
} finally {
|
|
10464
|
+
rmSync12(work, { recursive: true, force: true });
|
|
10465
|
+
}
|
|
10466
|
+
const missing = missingSandboxTools();
|
|
10467
|
+
if (missing.length < packages.length) log.info({ installed: packages.filter((name) => !missing.includes(name)) }, "sandbox tools installed");
|
|
10468
|
+
return missing;
|
|
10469
|
+
}
|
|
10470
|
+
async function installTool(tool2, context) {
|
|
10471
|
+
const { work, dataDir, apt, run: run2 } = context;
|
|
10472
|
+
const root = join23(work, "root");
|
|
10473
|
+
await run2("dpkg-deb", ["-x", join23(work, debFile(work, tool2.package)), root], work);
|
|
10474
|
+
const unpacked = join23(root, "usr", "bin", tool2.command);
|
|
10475
|
+
chmodSync2(unpacked, 493);
|
|
10476
|
+
const binDir = sandboxToolsDir(dataDir);
|
|
10477
|
+
try {
|
|
10478
|
+
await run2(unpacked, [tool2.versionFlag], work);
|
|
10479
|
+
renameSync2(unpacked, join23(binDir, tool2.command));
|
|
10480
|
+
return;
|
|
10481
|
+
} catch {
|
|
10482
|
+
}
|
|
10483
|
+
const plan = await run2("apt-get", ["-s", "-qq", ...apt, "install", tool2.package], work);
|
|
10484
|
+
const dependencies = [...String(plan?.stdout ?? "").matchAll(/^Inst (\S+)/gm)].map((match) => match[1]).filter((name) => name !== tool2.package);
|
|
10485
|
+
if (dependencies.length === 0) throw new Error("the tool does not run and has no missing dependencies");
|
|
10486
|
+
await run2("apt-get", ["-qq", ...apt, "download", ...dependencies], work);
|
|
10487
|
+
for (const dependency of dependencies) await run2("dpkg-deb", ["-x", join23(work, debFile(work, dependency)), root], work);
|
|
10488
|
+
const libDir = join23(dataDir, "sandbox-tools", "lib");
|
|
10489
|
+
mkdirSync13(libDir, { recursive: true, mode: 448 });
|
|
10490
|
+
for (const directory of [join23(root, "lib"), join23(root, "usr", "lib")]) moveSharedLibraries(directory, libDir);
|
|
10491
|
+
await run2(unpacked, [tool2.versionFlag], work, { LD_LIBRARY_PATH: libDir });
|
|
10492
|
+
const realDir = join23(dataDir, "sandbox-tools", "libexec");
|
|
10493
|
+
mkdirSync13(realDir, { recursive: true, mode: 448 });
|
|
10494
|
+
renameSync2(unpacked, join23(realDir, tool2.command));
|
|
10495
|
+
const launcher = join23(work, `${tool2.command}.launcher`);
|
|
10496
|
+
writeFileSync7(launcher, `#!/bin/sh
|
|
10497
|
+
LD_LIBRARY_PATH=${shellQuote2(libDir)} exec ${shellQuote2(join23(realDir, tool2.command))} "$@"
|
|
10498
|
+
`, { mode: 493 });
|
|
10499
|
+
renameSync2(launcher, join23(binDir, tool2.command));
|
|
10500
|
+
}
|
|
10501
|
+
function moveSharedLibraries(directory, libDir) {
|
|
10502
|
+
if (!existsSync5(directory)) return;
|
|
10503
|
+
for (const entry of readdirSync5(directory)) {
|
|
10504
|
+
const path = join23(directory, entry);
|
|
10505
|
+
if (lstatSync8(path).isDirectory()) moveSharedLibraries(path, libDir);
|
|
10506
|
+
else if (entry.includes(".so") && !existsSync5(join23(libDir, entry))) renameSync2(path, join23(libDir, entry));
|
|
10507
|
+
}
|
|
10508
|
+
}
|
|
10509
|
+
function shellQuote2(value) {
|
|
10510
|
+
return `'${value.replaceAll("'", `'\\''`)}'`;
|
|
10511
|
+
}
|
|
10512
|
+
async function downloadPackages(work, packages, run2) {
|
|
10513
|
+
const cache = join23(work, "cache");
|
|
10514
|
+
mkdirSync13(join23(cache, "archives", "partial"), { recursive: true });
|
|
10515
|
+
const unprivileged = ["-o", `Dir::Cache=${cache}`, "-o", "Debug::NoLocking=1", "-o", "APT::Sandbox::User="];
|
|
10516
|
+
try {
|
|
10517
|
+
await run2("apt-get", ["-qq", ...unprivileged, "download", ...packages], work);
|
|
10518
|
+
return unprivileged;
|
|
10519
|
+
} catch {
|
|
10520
|
+
const lists = join23(work, "lists");
|
|
10521
|
+
mkdirSync13(join23(lists, "partial"), { recursive: true });
|
|
10522
|
+
const privateLists = [...unprivileged, "-o", `Dir::State::lists=${lists}`];
|
|
10523
|
+
await run2("apt-get", ["-qq", ...privateLists, "update"], work);
|
|
10524
|
+
await run2("apt-get", ["-qq", ...privateLists, "download", ...packages], work);
|
|
10525
|
+
return privateLists;
|
|
10526
|
+
}
|
|
10527
|
+
}
|
|
10528
|
+
function debFile(work, name) {
|
|
10529
|
+
const file = readdirSync5(work).find((entry) => entry === `${name}.deb` || entry.startsWith(`${name}_`));
|
|
10530
|
+
if (!file) throw new Error(`${name} package was not downloaded`);
|
|
10531
|
+
return file;
|
|
10532
|
+
}
|
|
10533
|
+
function errorMessage2(err) {
|
|
10534
|
+
return err instanceof Error ? err.message.slice(0, 300) : "unknown error";
|
|
10535
|
+
}
|
|
10536
|
+
|
|
10251
10537
|
// src/outbox.ts
|
|
10252
10538
|
import {
|
|
10253
10539
|
appendFileSync,
|
|
10254
|
-
mkdirSync as
|
|
10255
|
-
readFileSync as
|
|
10256
|
-
readdirSync as
|
|
10257
|
-
rmSync as
|
|
10540
|
+
mkdirSync as mkdirSync14,
|
|
10541
|
+
readFileSync as readFileSync11,
|
|
10542
|
+
readdirSync as readdirSync6,
|
|
10543
|
+
rmSync as rmSync13,
|
|
10258
10544
|
truncateSync
|
|
10259
10545
|
} from "node:fs";
|
|
10260
|
-
import { join as
|
|
10546
|
+
import { join as join24 } from "node:path";
|
|
10261
10547
|
var Outbox = class {
|
|
10262
10548
|
constructor(dir, link, log, retryMs = 1e3, onUndeliverable = () => void 0, retainResources = false) {
|
|
10263
10549
|
this.dir = dir;
|
|
@@ -10266,7 +10552,7 @@ var Outbox = class {
|
|
|
10266
10552
|
this.retryMs = retryMs;
|
|
10267
10553
|
this.onUndeliverable = onUndeliverable;
|
|
10268
10554
|
this.retainResources = retainResources;
|
|
10269
|
-
|
|
10555
|
+
mkdirSync14(dir, { recursive: true, mode: 448 });
|
|
10270
10556
|
}
|
|
10271
10557
|
dir;
|
|
10272
10558
|
link;
|
|
@@ -10280,15 +10566,15 @@ var Outbox = class {
|
|
|
10280
10566
|
/** Runs whose file was checked for a torn tail since this process started. */
|
|
10281
10567
|
repaired = /* @__PURE__ */ new Set();
|
|
10282
10568
|
file(runId) {
|
|
10283
|
-
return
|
|
10569
|
+
return join24(this.dir, `${assertSafeId("run id", runId)}.jsonl`);
|
|
10284
10570
|
}
|
|
10285
10571
|
ackFile(runId) {
|
|
10286
|
-
return
|
|
10572
|
+
return join24(this.dir, `${assertSafeId("run id", runId)}.ack.json`);
|
|
10287
10573
|
}
|
|
10288
10574
|
parse(runId) {
|
|
10289
10575
|
let data;
|
|
10290
10576
|
try {
|
|
10291
|
-
data =
|
|
10577
|
+
data = readFileSync11(this.file(runId));
|
|
10292
10578
|
} catch {
|
|
10293
10579
|
return { items: [], validBytes: 0, torn: false, tornTail: false };
|
|
10294
10580
|
}
|
|
@@ -10373,7 +10659,7 @@ var Outbox = class {
|
|
|
10373
10659
|
}
|
|
10374
10660
|
runIds() {
|
|
10375
10661
|
try {
|
|
10376
|
-
return
|
|
10662
|
+
return readdirSync6(this.dir).filter((name) => name.endsWith(".jsonl")).map((name) => name.slice(0, -".jsonl".length)).filter((runId) => isSafeId(runId));
|
|
10377
10663
|
} catch {
|
|
10378
10664
|
return [];
|
|
10379
10665
|
}
|
|
@@ -10441,8 +10727,8 @@ var Outbox = class {
|
|
|
10441
10727
|
}
|
|
10442
10728
|
remove(runId) {
|
|
10443
10729
|
if (this.retainResources) return;
|
|
10444
|
-
|
|
10445
|
-
|
|
10730
|
+
rmSync13(this.file(runId), { force: true });
|
|
10731
|
+
rmSync13(this.ackFile(runId), { force: true });
|
|
10446
10732
|
}
|
|
10447
10733
|
scheduleRetry() {
|
|
10448
10734
|
if (this.retryTimer || this.closed) return;
|
|
@@ -10467,15 +10753,15 @@ var Outbox = class {
|
|
|
10467
10753
|
};
|
|
10468
10754
|
|
|
10469
10755
|
// src/quota/local-credentials.ts
|
|
10470
|
-
import { homedir as
|
|
10471
|
-
import { join as
|
|
10756
|
+
import { homedir as homedir9 } from "node:os";
|
|
10757
|
+
import { join as join26 } from "node:path";
|
|
10472
10758
|
|
|
10473
10759
|
// src/quota/files.ts
|
|
10474
10760
|
import { execFile as execFile4 } from "node:child_process";
|
|
10475
|
-
import { constants as
|
|
10761
|
+
import { constants as constants3 } from "node:fs";
|
|
10476
10762
|
import { lstat as lstat2, open } from "node:fs/promises";
|
|
10477
10763
|
import { promisify as promisify4 } from "node:util";
|
|
10478
|
-
var NOFOLLOW =
|
|
10764
|
+
var NOFOLLOW = constants3.O_NOFOLLOW ?? 0;
|
|
10479
10765
|
var execFileAsync = promisify4(execFile4);
|
|
10480
10766
|
var KEYCHAIN_TIMEOUT_MS = 3e4;
|
|
10481
10767
|
var MAX_CREDENTIAL_BYTES = 64 * 1024;
|
|
@@ -10551,7 +10837,7 @@ async function readSecureFile(filePath, maxBytes = MAX_CREDENTIAL_BYTES) {
|
|
|
10551
10837
|
if (before.size > maxBytes) {
|
|
10552
10838
|
throw new Error(`Credential file exceeds ${maxBytes} bytes: ${filePath}`);
|
|
10553
10839
|
}
|
|
10554
|
-
const handle = await open(filePath,
|
|
10840
|
+
const handle = await open(filePath, constants3.O_RDONLY | NOFOLLOW);
|
|
10555
10841
|
try {
|
|
10556
10842
|
const after = await handle.stat();
|
|
10557
10843
|
assertRegularFile(after, filePath);
|
|
@@ -10966,12 +11252,12 @@ async function readCodexQuota(options) {
|
|
|
10966
11252
|
|
|
10967
11253
|
// src/quota/cursor.ts
|
|
10968
11254
|
import { lstat as lstat3 } from "node:fs/promises";
|
|
10969
|
-
import { join as
|
|
11255
|
+
import { join as join25 } from "node:path";
|
|
10970
11256
|
var ENDPOINT3 = "https://cursor.com/api/usage-summary";
|
|
10971
11257
|
var ACCESS_TOKEN_KEY = "cursorAuth/accessToken";
|
|
10972
11258
|
function cursorDatabasePath(platform3, home) {
|
|
10973
11259
|
if (platform3 === "darwin") {
|
|
10974
|
-
return
|
|
11260
|
+
return join25(
|
|
10975
11261
|
home,
|
|
10976
11262
|
"Library",
|
|
10977
11263
|
"Application Support",
|
|
@@ -10982,7 +11268,7 @@ function cursorDatabasePath(platform3, home) {
|
|
|
10982
11268
|
);
|
|
10983
11269
|
}
|
|
10984
11270
|
if (platform3 === "win32") {
|
|
10985
|
-
return
|
|
11271
|
+
return join25(
|
|
10986
11272
|
home,
|
|
10987
11273
|
"AppData",
|
|
10988
11274
|
"Roaming",
|
|
@@ -10992,7 +11278,7 @@ function cursorDatabasePath(platform3, home) {
|
|
|
10992
11278
|
"state.vscdb"
|
|
10993
11279
|
);
|
|
10994
11280
|
}
|
|
10995
|
-
return
|
|
11281
|
+
return join25(home, ".config", "Cursor", "User", "globalStorage", "state.vscdb");
|
|
10996
11282
|
}
|
|
10997
11283
|
var CURSOR_PLANS = {
|
|
10998
11284
|
pro: "Pro",
|
|
@@ -11164,10 +11450,10 @@ async function readCursorQuota(options) {
|
|
|
11164
11450
|
// src/quota/local-credentials.ts
|
|
11165
11451
|
var KEYCHAIN_SERVICE = "Claude Code-credentials";
|
|
11166
11452
|
function claudeCredentialPath(home) {
|
|
11167
|
-
return
|
|
11453
|
+
return join26(home, ".claude", ".credentials.json");
|
|
11168
11454
|
}
|
|
11169
11455
|
function codexAuthPath(home) {
|
|
11170
|
-
return
|
|
11456
|
+
return join26(home, ".codex", "auth.json");
|
|
11171
11457
|
}
|
|
11172
11458
|
function unknown2(vendor, observedAt) {
|
|
11173
11459
|
return {
|
|
@@ -11186,7 +11472,7 @@ var LocalCredentialsSource = class {
|
|
|
11186
11472
|
options;
|
|
11187
11473
|
id = "local_credentials";
|
|
11188
11474
|
async read(signal) {
|
|
11189
|
-
const home = this.options.home ??
|
|
11475
|
+
const home = this.options.home ?? homedir9();
|
|
11190
11476
|
const platform3 = this.options.platform ?? process.platform;
|
|
11191
11477
|
const fetchImpl = this.options.fetch ?? globalThis.fetch;
|
|
11192
11478
|
const now = this.options.now ?? Date.now;
|
|
@@ -11319,7 +11605,7 @@ var QuotaPoller = class {
|
|
|
11319
11605
|
|
|
11320
11606
|
// src/rpc/server.ts
|
|
11321
11607
|
import { timingSafeEqual } from "node:crypto";
|
|
11322
|
-
import { chmodSync as
|
|
11608
|
+
import { chmodSync as chmodSync3, rmSync as rmSync14 } from "node:fs";
|
|
11323
11609
|
import { createServer as createServer2 } from "node:net";
|
|
11324
11610
|
import {
|
|
11325
11611
|
createMessageConnection as createMessageConnection2,
|
|
@@ -11360,13 +11646,13 @@ var RpcServer = class {
|
|
|
11360
11646
|
sockets = /* @__PURE__ */ new Set();
|
|
11361
11647
|
async listen() {
|
|
11362
11648
|
const { socketPath } = this.options;
|
|
11363
|
-
|
|
11649
|
+
rmSync14(socketPath, { force: true });
|
|
11364
11650
|
const server = createServer2((socket) => this.accept(socket));
|
|
11365
11651
|
await new Promise((resolve12, reject) => {
|
|
11366
11652
|
server.once("error", reject);
|
|
11367
11653
|
server.listen(socketPath, () => resolve12());
|
|
11368
11654
|
});
|
|
11369
|
-
|
|
11655
|
+
chmodSync3(socketPath, 384);
|
|
11370
11656
|
this.server = server;
|
|
11371
11657
|
}
|
|
11372
11658
|
accept(socket) {
|
|
@@ -11433,7 +11719,7 @@ var RpcServer = class {
|
|
|
11433
11719
|
this.server.close(() => resolve12());
|
|
11434
11720
|
});
|
|
11435
11721
|
this.server = null;
|
|
11436
|
-
|
|
11722
|
+
rmSync14(this.options.socketPath, { force: true });
|
|
11437
11723
|
}
|
|
11438
11724
|
};
|
|
11439
11725
|
|
|
@@ -11496,12 +11782,12 @@ var RunJournal = class {
|
|
|
11496
11782
|
};
|
|
11497
11783
|
|
|
11498
11784
|
// src/runs/check.ts
|
|
11499
|
-
import { execa as
|
|
11785
|
+
import { execa as execa11 } from "execa";
|
|
11500
11786
|
async function fixedCheckSnapshot(repoPath, worktree, sha) {
|
|
11501
11787
|
if (!/^[a-f0-9]{40}$/.test(sha))
|
|
11502
11788
|
throw new Error("Check requires an exact candidate SHA");
|
|
11503
11789
|
const gitDir = await worktreeGitDir(repoPath, worktree);
|
|
11504
|
-
const git2 = async (...args) => (await
|
|
11790
|
+
const git2 = async (...args) => (await execa11(
|
|
11505
11791
|
"git",
|
|
11506
11792
|
[
|
|
11507
11793
|
"-c",
|
|
@@ -11656,15 +11942,15 @@ function createRunMasker(secrets) {
|
|
|
11656
11942
|
|
|
11657
11943
|
// src/runs/supervisor.ts
|
|
11658
11944
|
import { createHash as createHash4, randomUUID as randomUUID6 } from "node:crypto";
|
|
11659
|
-
import { join as
|
|
11660
|
-
import { execa as
|
|
11945
|
+
import { join as join28, resolve as resolve10 } from "node:path";
|
|
11946
|
+
import { execa as execa13 } from "execa";
|
|
11661
11947
|
|
|
11662
11948
|
// src/agents/checkpoint.ts
|
|
11663
|
-
import { mkdtempSync as
|
|
11949
|
+
import { mkdtempSync as mkdtempSync7, rmSync as rmSync15, writeFileSync as writeFileSync8 } from "node:fs";
|
|
11664
11950
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
11665
|
-
import { join as
|
|
11951
|
+
import { join as join27 } from "node:path";
|
|
11666
11952
|
import { gunzipSync as gunzipSync2, gzipSync as gzipSync2 } from "node:zlib";
|
|
11667
|
-
import { execa as
|
|
11953
|
+
import { execa as execa12 } from "execa";
|
|
11668
11954
|
var CheckpointRecoveryError = class extends Error {
|
|
11669
11955
|
constructor(message) {
|
|
11670
11956
|
super(message);
|
|
@@ -11709,12 +11995,12 @@ async function takeCheckpoint(options) {
|
|
|
11709
11995
|
}
|
|
11710
11996
|
async function applyCheckpoint(options) {
|
|
11711
11997
|
const git2 = await pinnedGit(options.repoPath, options.worktree);
|
|
11712
|
-
const dir =
|
|
11713
|
-
const file =
|
|
11998
|
+
const dir = mkdtempSync7(join27(tmpdir2(), "mikka-checkpoint-"));
|
|
11999
|
+
const file = join27(dir, "checkpoint.patch");
|
|
11714
12000
|
try {
|
|
11715
12001
|
const patch = gunzipSync2(Buffer.from(options.checkpoint.patch, "base64"));
|
|
11716
12002
|
if (!patch.length && options.checkpoint.files === 0) return true;
|
|
11717
|
-
|
|
12003
|
+
writeFileSync8(file, patch);
|
|
11718
12004
|
for (const args of [
|
|
11719
12005
|
["apply", "--binary", "--whitespace=nowarn", file],
|
|
11720
12006
|
["apply", "--binary", "--3way", "--whitespace=nowarn", file]
|
|
@@ -11727,11 +12013,11 @@ async function applyCheckpoint(options) {
|
|
|
11727
12013
|
}
|
|
11728
12014
|
return false;
|
|
11729
12015
|
} finally {
|
|
11730
|
-
|
|
12016
|
+
rmSync15(dir, { recursive: true, force: true });
|
|
11731
12017
|
}
|
|
11732
12018
|
}
|
|
11733
12019
|
async function hasCommit(repoPath, commit) {
|
|
11734
|
-
return
|
|
12020
|
+
return execa12(
|
|
11735
12021
|
"git",
|
|
11736
12022
|
["-c", "core.hooksPath=/dev/null", "cat-file", "-e", `${commit}^{commit}`],
|
|
11737
12023
|
{ cwd: repoPath, stdin: "ignore" }
|
|
@@ -12948,7 +13234,7 @@ var RunSupervisor = class {
|
|
|
12948
13234
|
if (!this.deps.adapterStateDir || assignment.harness === "mock" || !session.sessionId || resuming && session.sessionId !== entry.sessionId || assignment.requireSessionResume && session.sessionId !== assignment.resumeSessionId)
|
|
12949
13235
|
throw new Error("Skill mount requires the actual original harness session");
|
|
12950
13236
|
verifySkillAssignment(assignment);
|
|
12951
|
-
const file =
|
|
13237
|
+
const file = join28(
|
|
12952
13238
|
runPaths(this.deps.adapterStateDir, runId).runDir,
|
|
12953
13239
|
SKILLS_DIR,
|
|
12954
13240
|
skillSlug(assignment.skills[0].name),
|
|
@@ -13181,7 +13467,7 @@ function stopReasonOf(event, run2) {
|
|
|
13181
13467
|
return event.outcome === "failed" ? "error" : "turn_ended";
|
|
13182
13468
|
}
|
|
13183
13469
|
async function unsandboxedVerify(run2) {
|
|
13184
|
-
const result = await
|
|
13470
|
+
const result = await execa13(run2.command, {
|
|
13185
13471
|
shell: true,
|
|
13186
13472
|
cwd: run2.worktree,
|
|
13187
13473
|
env: buildChildEnv(),
|
|
@@ -13212,10 +13498,10 @@ function fixedCandidateCheck(assignment) {
|
|
|
13212
13498
|
|
|
13213
13499
|
// src/repositories.ts
|
|
13214
13500
|
import { createHash as createHash5, randomUUID as randomUUID7 } from "node:crypto";
|
|
13215
|
-
import { existsSync as
|
|
13216
|
-
import { dirname as dirname11, join as
|
|
13501
|
+
import { existsSync as existsSync6, lstatSync as lstatSync9, mkdirSync as mkdirSync15, readdirSync as readdirSync7, realpathSync as realpathSync11, renameSync as renameSync3, rmSync as rmSync16 } from "node:fs";
|
|
13502
|
+
import { dirname as dirname11, join as join29, resolve as resolve11 } from "node:path";
|
|
13217
13503
|
import { setTimeout as delay2 } from "node:timers/promises";
|
|
13218
|
-
import { execa as
|
|
13504
|
+
import { execa as execa14 } from "execa";
|
|
13219
13505
|
import lockfile2 from "proper-lockfile";
|
|
13220
13506
|
var RepositoryCache = class {
|
|
13221
13507
|
constructor(root, allowFile = daemonTestMode(process.env), retainResources = false) {
|
|
@@ -13241,19 +13527,19 @@ var RepositoryCache = class {
|
|
|
13241
13527
|
const release = await this.lock(path, signal);
|
|
13242
13528
|
try {
|
|
13243
13529
|
signal?.throwIfAborted();
|
|
13244
|
-
const git2 = (args, cwd) =>
|
|
13530
|
+
const git2 = (args, cwd) => execa14("git", [
|
|
13245
13531
|
...FETCH_GIT,
|
|
13246
13532
|
"-c",
|
|
13247
13533
|
`protocol.file.allow=${this.allowFile ? "always" : "never"}`,
|
|
13248
13534
|
...args
|
|
13249
13535
|
], { cwd, env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }, stdin: "ignore", timeout: FETCH_TIMEOUT_MS, cancelSignal: signal, killDescendants: true });
|
|
13250
|
-
if (!
|
|
13536
|
+
if (!existsSync6(path)) {
|
|
13251
13537
|
const temporary = `${path}.clone-${randomUUID7()}`;
|
|
13252
13538
|
try {
|
|
13253
13539
|
await git2(["clone", "--no-checkout", "--no-hardlinks", "--no-recurse-submodules", "--", remote, temporary]);
|
|
13254
|
-
|
|
13540
|
+
renameSync3(temporary, path);
|
|
13255
13541
|
} finally {
|
|
13256
|
-
if (!this.retainResources)
|
|
13542
|
+
if (!this.retainResources) rmSync16(temporary, { recursive: true, force: true });
|
|
13257
13543
|
}
|
|
13258
13544
|
} else {
|
|
13259
13545
|
this.assertClone(path);
|
|
@@ -13273,36 +13559,36 @@ var RepositoryCache = class {
|
|
|
13273
13559
|
await assertBranchName(baseBranch);
|
|
13274
13560
|
return `origin/${baseBranch}`;
|
|
13275
13561
|
}
|
|
13276
|
-
const { stdout } = await
|
|
13562
|
+
const { stdout } = await execa14("git", [...FETCH_GIT, "symbolic-ref", "--short", "refs/remotes/origin/HEAD"], { cwd: path, stdin: "ignore" });
|
|
13277
13563
|
if (!stdout.startsWith("origin/")) throw new Error("Repository default branch unavailable");
|
|
13278
13564
|
return stdout.trim();
|
|
13279
13565
|
}
|
|
13280
13566
|
/** Cache paths for retention/orphan cleanup; never consult user checkouts. */
|
|
13281
13567
|
paths() {
|
|
13282
13568
|
const visit = (path) => {
|
|
13283
|
-
if (!
|
|
13284
|
-
if (
|
|
13569
|
+
if (!existsSync6(path) || lstatSync9(path).isSymbolicLink()) return [];
|
|
13570
|
+
if (existsSync6(join29(path, ".git"))) {
|
|
13285
13571
|
this.assertClone(path);
|
|
13286
13572
|
return [path];
|
|
13287
13573
|
}
|
|
13288
|
-
return
|
|
13574
|
+
return readdirSync7(path, { withFileTypes: true }).flatMap((entry) => entry.isDirectory() && !entry.name.endsWith(".lock") && !entry.name.includes(".clone-") ? visit(join29(path, entry.name)) : []);
|
|
13289
13575
|
};
|
|
13290
13576
|
return visit(resolve11(this.root));
|
|
13291
13577
|
}
|
|
13292
13578
|
ensureParents(path) {
|
|
13293
|
-
|
|
13294
|
-
if (
|
|
13579
|
+
mkdirSync15(this.root, { recursive: true, mode: 448 });
|
|
13580
|
+
if (lstatSync9(this.root).isSymbolicLink()) throw new Error("Repository cache contains a symlink");
|
|
13295
13581
|
const root = realpathSync11(this.root);
|
|
13296
13582
|
let current = resolve11(this.root);
|
|
13297
13583
|
for (const part of path.slice(current.length + 1).split("/").filter(Boolean)) {
|
|
13298
|
-
current =
|
|
13299
|
-
if (
|
|
13300
|
-
|
|
13584
|
+
current = join29(current, part);
|
|
13585
|
+
if (existsSync6(current) && lstatSync9(current).isSymbolicLink()) throw new Error("Repository cache contains a symlink");
|
|
13586
|
+
mkdirSync15(current, { recursive: true, mode: 448 });
|
|
13301
13587
|
if (!isInside(root, realpathSync11(current))) throw new Error("Repository cache escapes its directory");
|
|
13302
13588
|
}
|
|
13303
13589
|
}
|
|
13304
13590
|
assertClone(path) {
|
|
13305
|
-
if (
|
|
13591
|
+
if (lstatSync9(path).isSymbolicLink() || !lstatSync9(join29(path, ".git")).isDirectory() || lstatSync9(join29(path, ".git")).isSymbolicLink()) throw new Error("Repository cache is not a standard clone");
|
|
13306
13592
|
if (!isInside(realpathSync11(this.root), realpathSync11(path))) throw new Error("Repository cache escapes its directory");
|
|
13307
13593
|
}
|
|
13308
13594
|
async lock(path, signal) {
|
|
@@ -13323,16 +13609,16 @@ var RepositoryCache = class {
|
|
|
13323
13609
|
import { execFile as execFile5, spawn as spawn4 } from "node:child_process";
|
|
13324
13610
|
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
13325
13611
|
import {
|
|
13326
|
-
existsSync as
|
|
13327
|
-
lstatSync as
|
|
13328
|
-
mkdirSync as
|
|
13329
|
-
mkdtempSync as
|
|
13330
|
-
readdirSync as
|
|
13612
|
+
existsSync as existsSync7,
|
|
13613
|
+
lstatSync as lstatSync10,
|
|
13614
|
+
mkdirSync as mkdirSync16,
|
|
13615
|
+
mkdtempSync as mkdtempSync8,
|
|
13616
|
+
readdirSync as readdirSync8,
|
|
13331
13617
|
realpathSync as realpathSync12,
|
|
13332
|
-
rmSync as
|
|
13618
|
+
rmSync as rmSync17
|
|
13333
13619
|
} from "node:fs";
|
|
13334
13620
|
import { createRequire } from "node:module";
|
|
13335
|
-
import { delimiter as
|
|
13621
|
+
import { delimiter as delimiter4, dirname as dirname12, join as join31 } from "node:path";
|
|
13336
13622
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
13337
13623
|
import { promisify as promisify5 } from "node:util";
|
|
13338
13624
|
|
|
@@ -13342,7 +13628,7 @@ import { chmod, mkdtemp, rm as rm2 } from "node:fs/promises";
|
|
|
13342
13628
|
import { createServer as createServer3, request as httpRequest } from "node:http";
|
|
13343
13629
|
import { connect, isIP as isIP3 } from "node:net";
|
|
13344
13630
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
13345
|
-
import { join as
|
|
13631
|
+
import { join as join30 } from "node:path";
|
|
13346
13632
|
|
|
13347
13633
|
// ../../lib/search/url-policy.ts
|
|
13348
13634
|
import { BlockList, isIP as isIP2 } from "node:net";
|
|
@@ -13411,9 +13697,9 @@ function endToEndHeaders(input) {
|
|
|
13411
13697
|
}
|
|
13412
13698
|
async function startPublicEgress(options) {
|
|
13413
13699
|
options.signal.throwIfAborted();
|
|
13414
|
-
const directory = await mkdtemp(
|
|
13700
|
+
const directory = await mkdtemp(join30(tmpdir3(), "mikka-egress-"));
|
|
13415
13701
|
await chmod(directory, 448);
|
|
13416
|
-
const socketPath =
|
|
13702
|
+
const socketPath = join30(directory, "egress.sock");
|
|
13417
13703
|
const lifetime = new AbortController();
|
|
13418
13704
|
const signal = AbortSignal.any([options.signal, lifetime.signal]);
|
|
13419
13705
|
const sockets = /* @__PURE__ */ new Set();
|
|
@@ -13570,8 +13856,8 @@ async function createHostedBotRunner(host) {
|
|
|
13570
13856
|
}).catch(() => {
|
|
13571
13857
|
throw unavailable2();
|
|
13572
13858
|
});
|
|
13573
|
-
const resources =
|
|
13574
|
-
|
|
13859
|
+
const resources = join31(host.stateDir, "native-resources");
|
|
13860
|
+
mkdirSync16(resources, { recursive: true, mode: 448 });
|
|
13575
13861
|
const removeResource = async (file, record) => {
|
|
13576
13862
|
if (!/^mikka-native-(?:verify-)?[a-f0-9-]{36}$/.test(record.name) || !/^[a-f0-9-]{36}$/.test(record.nonce))
|
|
13577
13863
|
throw unavailable2();
|
|
@@ -13591,9 +13877,9 @@ async function createHostedBotRunner(host) {
|
|
|
13591
13877
|
if (record.state === "created" && /No such (?:container|object)/i.test(
|
|
13592
13878
|
String(error.stderr)
|
|
13593
13879
|
)) {
|
|
13594
|
-
if (record.assets?.startsWith(
|
|
13595
|
-
|
|
13596
|
-
|
|
13880
|
+
if (record.assets?.startsWith(join31(host.stateDir, "native-verify-git-")))
|
|
13881
|
+
rmSync17(record.assets, { recursive: true, force: true });
|
|
13882
|
+
rmSync17(file, { force: true });
|
|
13597
13883
|
return;
|
|
13598
13884
|
}
|
|
13599
13885
|
throw new Error("native_runtime_cleanup_unconfirmed");
|
|
@@ -13602,13 +13888,13 @@ async function createHostedBotRunner(host) {
|
|
|
13602
13888
|
if (labels?.["com.mikka.native.resource"] !== record.nonce || record.id && record.id !== id4)
|
|
13603
13889
|
throw unavailable2();
|
|
13604
13890
|
await exec3("docker", ["rm", "-f", id4], { env: bareEnv, timeout: 3e4 });
|
|
13605
|
-
if (record.assets?.startsWith(
|
|
13606
|
-
|
|
13607
|
-
|
|
13891
|
+
if (record.assets?.startsWith(join31(host.stateDir, "native-verify-git-")))
|
|
13892
|
+
rmSync17(record.assets, { recursive: true, force: true });
|
|
13893
|
+
rmSync17(file, { force: true });
|
|
13608
13894
|
};
|
|
13609
|
-
for (const name of
|
|
13895
|
+
for (const name of readdirSync8(resources))
|
|
13610
13896
|
if (name.endsWith(".json")) {
|
|
13611
|
-
const file =
|
|
13897
|
+
const file = join31(resources, name);
|
|
13612
13898
|
const record = readJson(file);
|
|
13613
13899
|
if (!record) throw unavailable2();
|
|
13614
13900
|
await removeResource(file, record);
|
|
@@ -13619,7 +13905,7 @@ async function createHostedBotRunner(host) {
|
|
|
13619
13905
|
const bundled = createRequire(
|
|
13620
13906
|
require2.resolve("@anthropic-ai/claude-agent-sdk")
|
|
13621
13907
|
);
|
|
13622
|
-
claude ??=
|
|
13908
|
+
claude ??= join31(
|
|
13623
13909
|
dirname12(
|
|
13624
13910
|
bundled.resolve(
|
|
13625
13911
|
"@anthropic-ai/claude-agent-sdk-linux-x64/package.json"
|
|
@@ -13629,13 +13915,13 @@ async function createHostedBotRunner(host) {
|
|
|
13629
13915
|
);
|
|
13630
13916
|
} catch {
|
|
13631
13917
|
}
|
|
13632
|
-
const codex = host.binaries?.codex ?? (process.env.PATH ?? "").split(
|
|
13918
|
+
const codex = host.binaries?.codex ?? (process.env.PATH ?? "").split(delimiter4).map((dir) => join31(dir, "codex")).find((path) => existsSync7(path));
|
|
13633
13919
|
const binaries = { codex, claude_code: claude };
|
|
13634
13920
|
for (const kind of ["codex", "claude_code"])
|
|
13635
13921
|
if (binaries[kind]) {
|
|
13636
13922
|
try {
|
|
13637
13923
|
binaries[kind] = realpathSync12(binaries[kind]);
|
|
13638
|
-
if (!
|
|
13924
|
+
if (!lstatSync10(binaries[kind]).isFile()) delete binaries[kind];
|
|
13639
13925
|
} catch {
|
|
13640
13926
|
delete binaries[kind];
|
|
13641
13927
|
}
|
|
@@ -13643,12 +13929,12 @@ async function createHostedBotRunner(host) {
|
|
|
13643
13929
|
if (!binaries.codex && !binaries.claude_code) throw unavailable2();
|
|
13644
13930
|
const command = async (worktree, script, readOnly, timeoutMs, signal) => {
|
|
13645
13931
|
const name = `mikka-native-verify-${randomUUID8()}`;
|
|
13646
|
-
const file =
|
|
13932
|
+
const file = join31(resources, name + ".json");
|
|
13647
13933
|
const resource = { name, nonce: randomUUID8(), state: "creating" };
|
|
13648
13934
|
const timing = { createMs: 0, runMs: 0 };
|
|
13649
13935
|
let phase = "create";
|
|
13650
13936
|
let began = performance.now();
|
|
13651
|
-
const gitCopy =
|
|
13937
|
+
const gitCopy = mkdtempSync8(join31(host.stateDir, "native-verify-git-"));
|
|
13652
13938
|
resource.assets = gitCopy;
|
|
13653
13939
|
try {
|
|
13654
13940
|
const cwd = realpathSync12(worktree);
|
|
@@ -13664,7 +13950,7 @@ async function createHostedBotRunner(host) {
|
|
|
13664
13950
|
"--no-checkout",
|
|
13665
13951
|
"--",
|
|
13666
13952
|
cwd,
|
|
13667
|
-
|
|
13953
|
+
join31(gitCopy, "repo")
|
|
13668
13954
|
],
|
|
13669
13955
|
{
|
|
13670
13956
|
env: {
|
|
@@ -13679,8 +13965,8 @@ async function createHostedBotRunner(host) {
|
|
|
13679
13965
|
maxBuffer: 1024 * 1024
|
|
13680
13966
|
}
|
|
13681
13967
|
);
|
|
13682
|
-
const safeGit =
|
|
13683
|
-
const protectedGit =
|
|
13968
|
+
const safeGit = join31(gitCopy, "repo", ".git");
|
|
13969
|
+
const protectedGit = lstatSync10(join31(cwd, ".git")).isFile() ? join31(cwd, ".git") : safeGit;
|
|
13684
13970
|
writeJsonAtomic(file, resource);
|
|
13685
13971
|
const created = await exec3(
|
|
13686
13972
|
"docker",
|
|
@@ -13767,8 +14053,8 @@ async function createHostedBotRunner(host) {
|
|
|
13767
14053
|
timing
|
|
13768
14054
|
};
|
|
13769
14055
|
} finally {
|
|
13770
|
-
if (
|
|
13771
|
-
else
|
|
14056
|
+
if (existsSync7(file)) await removeResource(file, resource);
|
|
14057
|
+
else rmSync17(gitCopy, { recursive: true, force: true });
|
|
13772
14058
|
}
|
|
13773
14059
|
};
|
|
13774
14060
|
return {
|
|
@@ -13784,7 +14070,7 @@ async function createHostedBotRunner(host) {
|
|
|
13784
14070
|
throw unavailable2();
|
|
13785
14071
|
const name = `mikka-native-${randomUUID8()}`;
|
|
13786
14072
|
const nonce = randomUUID8();
|
|
13787
|
-
const resourceFile =
|
|
14073
|
+
const resourceFile = join31(resources, name + ".json");
|
|
13788
14074
|
const resource = { name, nonce, state: "creating" };
|
|
13789
14075
|
const lifetime = new AbortController();
|
|
13790
14076
|
let closed = false;
|
|
@@ -13823,7 +14109,7 @@ async function createHostedBotRunner(host) {
|
|
|
13823
14109
|
void brokerClosed.catch(() => void 0);
|
|
13824
14110
|
try {
|
|
13825
14111
|
await creating?.catch(() => void 0);
|
|
13826
|
-
if (
|
|
14112
|
+
if (existsSync7(resourceFile)) await removeResource(resourceFile, resource);
|
|
13827
14113
|
} finally {
|
|
13828
14114
|
try {
|
|
13829
14115
|
await brokerClosed;
|
|
@@ -13856,11 +14142,11 @@ async function createHostedBotRunner(host) {
|
|
|
13856
14142
|
return current;
|
|
13857
14143
|
};
|
|
13858
14144
|
const paths = runPaths(host.stateDir, assignment.runId);
|
|
13859
|
-
|
|
13860
|
-
const shadow =
|
|
13861
|
-
const emptyHome =
|
|
13862
|
-
|
|
13863
|
-
if (!
|
|
14145
|
+
mkdirSync16(paths.runDir, { recursive: true, mode: 448 });
|
|
14146
|
+
const shadow = join31(paths.runDir, "runtime-git");
|
|
14147
|
+
const emptyHome = join31(paths.runDir, "git-bootstrap-home");
|
|
14148
|
+
mkdirSync16(emptyHome, { recursive: true, mode: 448 });
|
|
14149
|
+
if (!existsSync7(shadow))
|
|
13864
14150
|
await exec3(
|
|
13865
14151
|
"git",
|
|
13866
14152
|
[
|
|
@@ -13889,9 +14175,9 @@ async function createHostedBotRunner(host) {
|
|
|
13889
14175
|
}
|
|
13890
14176
|
);
|
|
13891
14177
|
await live();
|
|
13892
|
-
if (!
|
|
14178
|
+
if (!lstatSync10(shadow).isDirectory() || !lstatSync10(join31(shadow, ".git")).isDirectory() || !realpathSync12(shadow).startsWith(realpathSync12(paths.runDir) + "/"))
|
|
13893
14179
|
throw unavailable2();
|
|
13894
|
-
const ledger =
|
|
14180
|
+
const ledger = join31(
|
|
13895
14181
|
host.stateDir,
|
|
13896
14182
|
"native-ledgers",
|
|
13897
14183
|
assignment.runId + ".json"
|
|
@@ -13908,15 +14194,15 @@ async function createHostedBotRunner(host) {
|
|
|
13908
14194
|
modelId: first.modelId
|
|
13909
14195
|
};
|
|
13910
14196
|
const previous = readJson(ledger);
|
|
13911
|
-
if (
|
|
14197
|
+
if (existsSync7(ledger) && (!previous || JSON.stringify(previous.scope) !== JSON.stringify(scope) || typeof previous.sessionId !== "string"))
|
|
13912
14198
|
throw unavailable2();
|
|
13913
|
-
|
|
14199
|
+
mkdirSync16(dirname12(ledger), { recursive: true, mode: 448 });
|
|
13914
14200
|
const record = async (sessionId) => {
|
|
13915
14201
|
assertOpen();
|
|
13916
14202
|
writeJsonAtomic(ledger, { scope, sessionId });
|
|
13917
14203
|
};
|
|
13918
14204
|
brokerStarting = createNativeSubscriptionBroker({
|
|
13919
|
-
root:
|
|
14205
|
+
root: join31(host.stateDir, "native-brokers"),
|
|
13920
14206
|
revision,
|
|
13921
14207
|
check,
|
|
13922
14208
|
worker: {
|
|
@@ -13943,7 +14229,7 @@ async function createHostedBotRunner(host) {
|
|
|
13943
14229
|
});
|
|
13944
14230
|
const readyBroker = await brokerStarting;
|
|
13945
14231
|
await live();
|
|
13946
|
-
const githubCli = options.github ? (process.env.PATH ?? "").split(
|
|
14232
|
+
const githubCli = options.github ? (process.env.PATH ?? "").split(delimiter4).map((dir) => join31(dir, "gh")).find((file) => existsSync7(file)) : void 0;
|
|
13947
14233
|
if (options.github && !githubCli) throw new Error("Install GitHub CLI (gh) in the cloud worker image");
|
|
13948
14234
|
const githubDomains = options.github ? ["github.com", "api.github.com", new URL(options.github.endpoint).host] : [];
|
|
13949
14235
|
const egressMaximum = runDomains(runPolicy(options.policy), [...options.networkAllow ?? [], ...githubDomains]);
|
|
@@ -13960,8 +14246,8 @@ async function createHostedBotRunner(host) {
|
|
|
13960
14246
|
}
|
|
13961
14247
|
const cwd = realpathSync12(options.cwd);
|
|
13962
14248
|
const runDir = realpathSync12(paths.runDir);
|
|
13963
|
-
const protectedGit =
|
|
13964
|
-
if (!
|
|
14249
|
+
const protectedGit = lstatSync10(join31(cwd, ".git")).isFile() ? join31(cwd, ".git") : join31(shadow, ".git");
|
|
14250
|
+
if (!lstatSync10(runDir).isDirectory() || !runDir.startsWith(realpathSync12(host.stateDir) + "/runs/")) {
|
|
13965
14251
|
await close();
|
|
13966
14252
|
throw unavailable2();
|
|
13967
14253
|
}
|
|
@@ -14014,7 +14300,7 @@ async function createHostedBotRunner(host) {
|
|
|
14014
14300
|
`${MCP_SERVER_SCRIPT}:${MCP_SERVER_SCRIPT}:ro`,
|
|
14015
14301
|
...githubCli ? ["-v", `${githubCli}:/usr/local/bin/mikka-gh:ro`, "-v", `${GITHUB_CREDENTIAL_SCRIPT}:${GITHUB_CREDENTIAL_SCRIPT}:ro`] : [],
|
|
14016
14302
|
"-v",
|
|
14017
|
-
`${
|
|
14303
|
+
`${join31(dirname12(MCP_SERVER_SCRIPT), "capture-copy.mjs")}:${join31(dirname12(MCP_SERVER_SCRIPT), "capture-copy.mjs")}:ro`,
|
|
14018
14304
|
"-v",
|
|
14019
14305
|
`${readyBroker.socket}:/run/mikka-native.sock:ro`,
|
|
14020
14306
|
...computerGrant ? [
|
|
@@ -14057,13 +14343,13 @@ async function createHostedBotRunner(host) {
|
|
|
14057
14343
|
}
|
|
14058
14344
|
const spawnHosted = (config) => {
|
|
14059
14345
|
assertOpen();
|
|
14060
|
-
const home =
|
|
14061
|
-
|
|
14346
|
+
const home = join31(runDir, "runtime-home");
|
|
14347
|
+
mkdirSync16(home, { recursive: true, mode: 448 });
|
|
14062
14348
|
const env = {
|
|
14063
14349
|
...config.env,
|
|
14064
14350
|
HOME: kind === "claude_code" ? config.env.HOME ?? home : home,
|
|
14065
|
-
PATH: `${options.github ?
|
|
14066
|
-
GIT_DIR:
|
|
14351
|
+
PATH: `${options.github ? join31(runDir, "github", "bin") + ":" : ""}/usr/local/bin:/usr/bin:/bin`,
|
|
14352
|
+
GIT_DIR: join31(shadow, ".git"),
|
|
14067
14353
|
GIT_WORK_TREE: cwd,
|
|
14068
14354
|
GIT_CONFIG_GLOBAL: "/dev/null",
|
|
14069
14355
|
GIT_CONFIG_SYSTEM: "/dev/null",
|
|
@@ -14082,7 +14368,7 @@ async function createHostedBotRunner(host) {
|
|
|
14082
14368
|
signal: AbortSignal.any([lifetime.signal, ...config.signal ? [config.signal] : []])
|
|
14083
14369
|
});
|
|
14084
14370
|
child.stdin.write(
|
|
14085
|
-
JSON.stringify({ kind, args: config.args, cwd, env: task.env, publicEgress: Boolean(egress), ...options.github ? { githubBin:
|
|
14371
|
+
JSON.stringify({ kind, args: config.args, cwd, env: task.env, publicEgress: Boolean(egress), ...options.github ? { githubBin: join31(runDir, "github", "bin") } : {} }) + "\n"
|
|
14086
14372
|
);
|
|
14087
14373
|
return child;
|
|
14088
14374
|
};
|
|
@@ -14217,7 +14503,7 @@ import {
|
|
|
14217
14503
|
createHash as createHash7,
|
|
14218
14504
|
timingSafeEqual as timingSafeEqual2
|
|
14219
14505
|
} from "node:crypto";
|
|
14220
|
-
import { chmodSync as
|
|
14506
|
+
import { chmodSync as chmodSync4 } from "node:fs";
|
|
14221
14507
|
import { createServer as createServer4 } from "node:net";
|
|
14222
14508
|
|
|
14223
14509
|
// src/computer/driver.mjs
|
|
@@ -14467,7 +14753,7 @@ var ComputerBroker = class {
|
|
|
14467
14753
|
else this.server.listen(this.socketPath, resolve12);
|
|
14468
14754
|
});
|
|
14469
14755
|
if (this.transport === "tcp") this.socketPath = `tcp://127.0.0.1:${this.server.address().port}`;
|
|
14470
|
-
else
|
|
14756
|
+
else chmodSync4(this.socketPath, 384);
|
|
14471
14757
|
}
|
|
14472
14758
|
request(token, value, signal) {
|
|
14473
14759
|
const grant = this.grants.get(token);
|
|
@@ -14691,6 +14977,11 @@ function loadDeviceFile(raw) {
|
|
|
14691
14977
|
}
|
|
14692
14978
|
return file;
|
|
14693
14979
|
}
|
|
14980
|
+
var HARNESS_RESCAN_MS = 5 * 6e4;
|
|
14981
|
+
var SANDBOX_REPAIR_RETRY_MS = 60 * 6e4;
|
|
14982
|
+
function missingToolsUnchanged(issue) {
|
|
14983
|
+
return !issue?.missing.length || missingSandboxTools().length === issue.missing.length;
|
|
14984
|
+
}
|
|
14694
14985
|
var Daemon = class {
|
|
14695
14986
|
constructor(options) {
|
|
14696
14987
|
this.options = options;
|
|
@@ -14762,8 +15053,8 @@ var Daemon = class {
|
|
|
14762
15053
|
}
|
|
14763
15054
|
async startInternal() {
|
|
14764
15055
|
const { paths } = this;
|
|
14765
|
-
|
|
14766
|
-
if (process.platform !== "win32")
|
|
15056
|
+
mkdirSync17(paths.dataDir, { recursive: true, mode: 448 });
|
|
15057
|
+
if (process.platform !== "win32") chmodSync5(paths.dataDir, 448);
|
|
14767
15058
|
this.releaseLock = await acquireLock(
|
|
14768
15059
|
paths.dataDir,
|
|
14769
15060
|
paths.lock,
|
|
@@ -14776,7 +15067,7 @@ var Daemon = class {
|
|
|
14776
15067
|
if (this.options.credential)
|
|
14777
15068
|
this.saveDevice({ credential: this.options.credential });
|
|
14778
15069
|
this.journal = new RunJournal(paths.journal);
|
|
14779
|
-
this.captureUploader = new CaptureUploader((runId) =>
|
|
15070
|
+
this.captureUploader = new CaptureUploader((runId) => join32(runPaths(paths.adapterState, runId).runDir, CAPTURES_DIR), this.options.link, this.log, join32(paths.dataDir, "capture-pending"));
|
|
14780
15071
|
this.outbox = new Outbox(
|
|
14781
15072
|
paths.outbox,
|
|
14782
15073
|
this.options.link,
|
|
@@ -14793,7 +15084,7 @@ var Daemon = class {
|
|
|
14793
15084
|
if (this.localComputerDriver && this.options.link.syncComputerReviews && this.options.link.localComputerAuthority) {
|
|
14794
15085
|
this.localComputerBroker = new ComputerBroker({
|
|
14795
15086
|
driver: this.localComputerDriver,
|
|
14796
|
-
socketPath:
|
|
15087
|
+
socketPath: join32(paths.dataDir, "local-computer.sock"),
|
|
14797
15088
|
transport: "tcp",
|
|
14798
15089
|
permitted: (runId) => {
|
|
14799
15090
|
const assignment = this.journal.get(runId)?.assignment;
|
|
@@ -14835,7 +15126,7 @@ var Daemon = class {
|
|
|
14835
15126
|
};
|
|
14836
15127
|
this.cloudComputerBroker = new ComputerBroker({
|
|
14837
15128
|
driver,
|
|
14838
|
-
socketPath:
|
|
15129
|
+
socketPath: join32(paths.dataDir, "computer.sock"),
|
|
14839
15130
|
permitted: (runId) => {
|
|
14840
15131
|
const entry = this.journal.get(runId);
|
|
14841
15132
|
return Boolean(!this.stopped && this.registered && entry?.assignment.computer && this.supervisor?.computerRunAllowed(runId));
|
|
@@ -14958,7 +15249,7 @@ var Daemon = class {
|
|
|
14958
15249
|
worktree,
|
|
14959
15250
|
tree,
|
|
14960
15251
|
github: { ...assignment.github, runToken: assignment.mcp.token, issueId: assignment.issueId },
|
|
14961
|
-
privateDir:
|
|
15252
|
+
privateDir: join32(paths.adapterState, "pids"),
|
|
14962
15253
|
...hosted ? { hosted: true } : {},
|
|
14963
15254
|
env: githubReceiptEnvironment()
|
|
14964
15255
|
}) : publishRun({
|
|
@@ -14999,17 +15290,16 @@ var Daemon = class {
|
|
|
14999
15290
|
if (this.stopped) throw new Error("daemon stopped during startup");
|
|
15000
15291
|
const detected = hosted ? hosted.harnesses.map((harness) => ({ harness, installed: true, version: null, subscriptionBroker: true, ...this.cloudComputerBroker ? { computerBroker: true } : {} })) : this.options.harnesses ?? await detectHarnesses();
|
|
15001
15292
|
if (this.stopped) throw new Error("daemon stopped during startup");
|
|
15002
|
-
|
|
15003
|
-
|
|
15004
|
-
this.harnesses = detected.filter((info) => this.adapters.has(info.harness)).map((info) => ({
|
|
15293
|
+
if (!hosted && !this.options.harnesses) this.harnessPrint = harnessFingerprint();
|
|
15294
|
+
this.harnesses = [...detected.filter((info) => this.adapters.has(info.harness)).map((info) => ({
|
|
15005
15295
|
...info,
|
|
15006
15296
|
// Local enforcement requires the successful owned SRT probe. Hosted
|
|
15007
15297
|
// enforcement uses its existing network-none/read-only Docker boundary
|
|
15008
15298
|
// and gate-bound broker/container teardown; general egress stays outside
|
|
15009
15299
|
// that ceiling. Codex also verifies its pinned interface at initialize.
|
|
15010
|
-
toolApproval:
|
|
15300
|
+
toolApproval: this.supportsToolApproval(info),
|
|
15011
15301
|
coordinator: hosted ? false : coordinatorCapable(info)
|
|
15012
|
-
}));
|
|
15302
|
+
})), ...this.sandboxBlockedHarnesses(detected)];
|
|
15013
15303
|
await this.supervisor.resumeAll();
|
|
15014
15304
|
if (!hosted && this.options.quotaSource !== null) {
|
|
15015
15305
|
this.quota = new QuotaPoller(
|
|
@@ -15193,6 +15483,58 @@ var Daemon = class {
|
|
|
15193
15483
|
}
|
|
15194
15484
|
return acted;
|
|
15195
15485
|
}
|
|
15486
|
+
supportsToolApproval(info) {
|
|
15487
|
+
if (typeof this.options.link.prepareRunToolApproval !== "function") return void 0;
|
|
15488
|
+
if (this.options.hostedSubscriptions) return true;
|
|
15489
|
+
if (this.ownedSandbox === null || this.sandbox !== this.ownedSandbox) return void 0;
|
|
15490
|
+
return info.harness === "claude_code" || info.harness === "codex" && codexSupportsRunApproval(info.version) ? true : void 0;
|
|
15491
|
+
}
|
|
15492
|
+
/** Report a CLI the daemon cannot run as present but not installed, so no run is pinned here. */
|
|
15493
|
+
sandboxBlockedHarnesses(detected) {
|
|
15494
|
+
const issue = this.sandboxIssue;
|
|
15495
|
+
if (!issue) return [];
|
|
15496
|
+
return detected.filter((info) => info.installed && !this.adapters.has(info.harness)).map((info) => ({
|
|
15497
|
+
harness: info.harness,
|
|
15498
|
+
installed: false,
|
|
15499
|
+
version: info.version,
|
|
15500
|
+
sandboxBlocked: { missing: issue.missing }
|
|
15501
|
+
}));
|
|
15502
|
+
}
|
|
15503
|
+
async redetectHarnesses() {
|
|
15504
|
+
const repairing = this.sandboxIssue?.missing.length;
|
|
15505
|
+
if (this.sandboxIssue && repairing) {
|
|
15506
|
+
this.lastSandboxRepair = Date.now();
|
|
15507
|
+
this.sandboxIssue = { missing: await ensureSandboxTools({ dataDir: this.paths.dataDir, log: this.log }) };
|
|
15508
|
+
}
|
|
15509
|
+
const detected = await detectHarnesses();
|
|
15510
|
+
this.harnessPrint = harnessFingerprint();
|
|
15511
|
+
this.harnesses = [...detected.filter((info) => this.adapters.has(info.harness)).map((info) => {
|
|
15512
|
+
return { ...info, toolApproval: this.supportsToolApproval(info), coordinator: coordinatorCapable(info) };
|
|
15513
|
+
}), ...this.sandboxBlockedHarnesses(detected)];
|
|
15514
|
+
if (repairing && this.sandboxIssue?.missing.length === 0) {
|
|
15515
|
+
this.startMaintenance(() => restartService(false, () => {
|
|
15516
|
+
}, void 0, () => !this.stopped));
|
|
15517
|
+
}
|
|
15518
|
+
}
|
|
15519
|
+
/** Notice an agent installed after startup, or retry a failed tool download, without spawning anything per tick. */
|
|
15520
|
+
rescanHarnesses() {
|
|
15521
|
+
const now = Date.now();
|
|
15522
|
+
if (this.options.hostedSubscriptions || this.options.harnesses || this.rescanning || now - this.lastHarnessScan < HARNESS_RESCAN_MS) return;
|
|
15523
|
+
this.lastHarnessScan = now;
|
|
15524
|
+
const retryRepair = Boolean(this.sandboxIssue?.missing.length) && now - this.lastSandboxRepair >= SANDBOX_REPAIR_RETRY_MS;
|
|
15525
|
+
if (harnessFingerprint() === this.harnessPrint && !retryRepair && missingToolsUnchanged(this.sandboxIssue)) return;
|
|
15526
|
+
this.rescanning = true;
|
|
15527
|
+
void this.redetectHarnesses().then(() => this.syncWithServer()).catch((err) => {
|
|
15528
|
+
this.log.warn({ err }, "harness rescan failed");
|
|
15529
|
+
}).finally(() => {
|
|
15530
|
+
this.rescanning = false;
|
|
15531
|
+
});
|
|
15532
|
+
}
|
|
15533
|
+
harnessPrint = "";
|
|
15534
|
+
lastHarnessScan = Date.now();
|
|
15535
|
+
lastSandboxRepair = Date.now();
|
|
15536
|
+
rescanning = false;
|
|
15537
|
+
sandboxIssue = null;
|
|
15196
15538
|
sandbox = null;
|
|
15197
15539
|
ownedSandbox = null;
|
|
15198
15540
|
/** The agent sandbox (one per daemon), or null where there is none. */
|
|
@@ -15201,8 +15543,10 @@ var Daemon = class {
|
|
|
15201
15543
|
}
|
|
15202
15544
|
async createAgentSandbox() {
|
|
15203
15545
|
if (this.options.agentSandbox !== void 0) return this.options.agentSandbox;
|
|
15546
|
+
const missing = await ensureSandboxTools({ dataDir: this.paths.dataDir, log: this.log });
|
|
15204
15547
|
if (!SandboxRuntime.supported()) {
|
|
15205
|
-
this.log.warn("agent sandbox unavailable: platform or dependencies unsupported");
|
|
15548
|
+
this.log.warn({ missing }, "agent sandbox unavailable: platform or dependencies unsupported");
|
|
15549
|
+
this.sandboxIssue = { missing };
|
|
15206
15550
|
return null;
|
|
15207
15551
|
}
|
|
15208
15552
|
const sandbox = new SandboxRuntime(async ({ host }) => {
|
|
@@ -15219,6 +15563,7 @@ var Daemon = class {
|
|
|
15219
15563
|
return sandbox;
|
|
15220
15564
|
} catch (err) {
|
|
15221
15565
|
this.log.warn({ err }, "agent sandbox unavailable");
|
|
15566
|
+
this.sandboxIssue = { missing: [] };
|
|
15222
15567
|
if (!this.options.retainResources) await sandbox.reset().catch((resetError) => {
|
|
15223
15568
|
this.log.warn({ err: resetError }, "agent sandbox cleanup failed");
|
|
15224
15569
|
});
|
|
@@ -15242,11 +15587,11 @@ var Daemon = class {
|
|
|
15242
15587
|
return runVerify(sandbox, {
|
|
15243
15588
|
command,
|
|
15244
15589
|
worktree: realpathSync13(worktree),
|
|
15245
|
-
tmpRoot:
|
|
15590
|
+
tmpRoot: join32(this.paths.adapterState, "verify", runId),
|
|
15246
15591
|
privateDir: paths.privateDir,
|
|
15247
15592
|
pidFile: paths.pidFile.replace(/\.pgid$/, ".verify.pgid"),
|
|
15248
15593
|
networkAllow: repo.networkAllow,
|
|
15249
|
-
env: { ...buildChildEnv(), MIKKA_HANDOFF_FILE:
|
|
15594
|
+
env: { ...buildChildEnv(), MIKKA_HANDOFF_FILE: join32(paths.runDir, "handoff.json") },
|
|
15250
15595
|
timeoutMs,
|
|
15251
15596
|
signal,
|
|
15252
15597
|
readOnly
|
|
@@ -15291,8 +15636,8 @@ var Daemon = class {
|
|
|
15291
15636
|
void this.stop().finally(() => this.options.onLockLost?.(error));
|
|
15292
15637
|
}
|
|
15293
15638
|
ensureSecret() {
|
|
15294
|
-
if (
|
|
15295
|
-
return
|
|
15639
|
+
if (existsSync8(this.paths.secret)) {
|
|
15640
|
+
return readFileSync12(this.paths.secret, "utf8").trim();
|
|
15296
15641
|
}
|
|
15297
15642
|
const secret = randomBytes3(32).toString("hex");
|
|
15298
15643
|
writeFileAtomic(this.paths.secret, `${secret}
|
|
@@ -15389,6 +15734,7 @@ var Daemon = class {
|
|
|
15389
15734
|
this.revokeLocalComputerGrants();
|
|
15390
15735
|
this.registered = false;
|
|
15391
15736
|
}
|
|
15737
|
+
this.rescanHarnesses();
|
|
15392
15738
|
const command = deviceCommands?.[0];
|
|
15393
15739
|
if (command?.kind === "uninstall") {
|
|
15394
15740
|
this.draining = true;
|
|
@@ -15402,7 +15748,7 @@ var Daemon = class {
|
|
|
15402
15748
|
setImmediate(() => {
|
|
15403
15749
|
void this.stop().then(() => uninstallService(() => {
|
|
15404
15750
|
this.saveDevice({ credential: void 0 });
|
|
15405
|
-
|
|
15751
|
+
rmSync18(this.paths.secret, { force: true });
|
|
15406
15752
|
})).catch(() => {
|
|
15407
15753
|
this.options.onDrained?.();
|
|
15408
15754
|
});
|
|
@@ -15414,11 +15760,7 @@ var Daemon = class {
|
|
|
15414
15760
|
if (command.kind === "redetect" || this.maintenanceIdle()) {
|
|
15415
15761
|
try {
|
|
15416
15762
|
if (command.kind === "redetect") {
|
|
15417
|
-
|
|
15418
|
-
this.harnesses = detected.filter((info) => this.adapters.has(info.harness)).map((info) => {
|
|
15419
|
-
const previous = this.harnesses.find((old) => old.harness === info.harness && old.version === info.version);
|
|
15420
|
-
return { ...info, toolApproval: previous?.toolApproval, coordinator: coordinatorCapable(info) };
|
|
15421
|
-
});
|
|
15763
|
+
await this.redetectHarnesses();
|
|
15422
15764
|
this.saveDevice({ completedDeviceCommands: [command.id], failedDeviceCommands: [] });
|
|
15423
15765
|
void this.syncWithServer().catch(() => void 0);
|
|
15424
15766
|
} else {
|
|
@@ -15731,7 +16073,7 @@ var Daemon = class {
|
|
|
15731
16073
|
if (!job || controller.signal.aborted) return;
|
|
15732
16074
|
await runNativeCoordinatorJob(job, {
|
|
15733
16075
|
deviceId,
|
|
15734
|
-
stateDir:
|
|
16076
|
+
stateDir: join32(this.paths.dataDir, "coordinator"),
|
|
15735
16077
|
link,
|
|
15736
16078
|
signal: controller.signal,
|
|
15737
16079
|
sandbox,
|
|
@@ -15774,7 +16116,7 @@ var Daemon = class {
|
|
|
15774
16116
|
}, void 0, () => !this.stopped);
|
|
15775
16117
|
});
|
|
15776
16118
|
} else if (!this.updateCheck && !this.updateVersion) {
|
|
15777
|
-
this.updateCheck = checkLatestVersion(
|
|
16119
|
+
this.updateCheck = checkLatestVersion(join32(this.paths.dataDir, "auto-update.json"), DAEMON_VERSION, runtime).then((version) => {
|
|
15778
16120
|
this.updateVersion = version;
|
|
15779
16121
|
}).catch(() => {
|
|
15780
16122
|
this.log.warn("Daemon automatic update check failed");
|
|
@@ -15832,7 +16174,7 @@ async function startDaemon(options) {
|
|
|
15832
16174
|
}
|
|
15833
16175
|
|
|
15834
16176
|
// src/rpc/client.ts
|
|
15835
|
-
import { readFileSync as
|
|
16177
|
+
import { readFileSync as readFileSync13 } from "node:fs";
|
|
15836
16178
|
import { connect as connect2 } from "node:net";
|
|
15837
16179
|
import {
|
|
15838
16180
|
createMessageConnection as createMessageConnection3,
|
|
@@ -15912,7 +16254,7 @@ function connectDaemonInDataDir(dataDir, client, extra = {}) {
|
|
|
15912
16254
|
const paths = daemonPaths(dataDir);
|
|
15913
16255
|
let secret;
|
|
15914
16256
|
try {
|
|
15915
|
-
secret =
|
|
16257
|
+
secret = readFileSync13(paths.secret, "utf8").trim();
|
|
15916
16258
|
} catch (error) {
|
|
15917
16259
|
return Promise.reject(error);
|
|
15918
16260
|
}
|