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