local-commander-agent-linux-arm64 0.3.45 → 0.3.46
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/package.json +1 -1
- package/runtime/agent.mjs +418 -236
- package/runtime/lifecycle.mjs +14 -1
- package/runtime/manifest.json +5 -5
package/runtime/agent.mjs
CHANGED
|
@@ -4554,10 +4554,10 @@ function mergeDefs(...defs) {
|
|
|
4554
4554
|
function cloneDef(schema) {
|
|
4555
4555
|
return mergeDefs(schema._zod.def);
|
|
4556
4556
|
}
|
|
4557
|
-
function getElementAtPath(obj,
|
|
4558
|
-
if (!
|
|
4557
|
+
function getElementAtPath(obj, path30) {
|
|
4558
|
+
if (!path30)
|
|
4559
4559
|
return obj;
|
|
4560
|
-
return
|
|
4560
|
+
return path30.reduce((acc, key) => acc?.[key], obj);
|
|
4561
4561
|
}
|
|
4562
4562
|
function promiseAllObject(promisesObj) {
|
|
4563
4563
|
const keys = Object.keys(promisesObj);
|
|
@@ -4897,11 +4897,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
4897
4897
|
}
|
|
4898
4898
|
return false;
|
|
4899
4899
|
}
|
|
4900
|
-
function prefixIssues(
|
|
4900
|
+
function prefixIssues(path30, issues) {
|
|
4901
4901
|
return issues.map((iss) => {
|
|
4902
4902
|
var _a3;
|
|
4903
4903
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
4904
|
-
iss.path.unshift(
|
|
4904
|
+
iss.path.unshift(path30);
|
|
4905
4905
|
return iss;
|
|
4906
4906
|
});
|
|
4907
4907
|
}
|
|
@@ -5351,16 +5351,16 @@ function flattenError(error62, mapper = (issue2) => issue2.message) {
|
|
|
5351
5351
|
}
|
|
5352
5352
|
function formatError(error62, mapper = (issue2) => issue2.message) {
|
|
5353
5353
|
const fieldErrors = { _errors: [] };
|
|
5354
|
-
const processError = (error63,
|
|
5354
|
+
const processError = (error63, path30 = []) => {
|
|
5355
5355
|
for (const issue2 of error63.issues) {
|
|
5356
5356
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
5357
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
5357
|
+
issue2.errors.map((issues) => processError({ issues }, [...path30, ...issue2.path]));
|
|
5358
5358
|
} else if (issue2.code === "invalid_key") {
|
|
5359
|
-
processError({ issues: issue2.issues }, [...
|
|
5359
|
+
processError({ issues: issue2.issues }, [...path30, ...issue2.path]);
|
|
5360
5360
|
} else if (issue2.code === "invalid_element") {
|
|
5361
|
-
processError({ issues: issue2.issues }, [...
|
|
5361
|
+
processError({ issues: issue2.issues }, [...path30, ...issue2.path]);
|
|
5362
5362
|
} else {
|
|
5363
|
-
const fullpath = [...
|
|
5363
|
+
const fullpath = [...path30, ...issue2.path];
|
|
5364
5364
|
if (fullpath.length === 0) {
|
|
5365
5365
|
fieldErrors._errors.push(mapper(issue2));
|
|
5366
5366
|
} else {
|
|
@@ -5399,17 +5399,17 @@ function formatError(error62, mapper = (issue2) => issue2.message) {
|
|
|
5399
5399
|
}
|
|
5400
5400
|
function treeifyError(error62, mapper = (issue2) => issue2.message) {
|
|
5401
5401
|
const result2 = { errors: [] };
|
|
5402
|
-
const processError = (error63,
|
|
5402
|
+
const processError = (error63, path30 = []) => {
|
|
5403
5403
|
var _a3;
|
|
5404
5404
|
for (const issue2 of error63.issues) {
|
|
5405
5405
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
5406
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
5406
|
+
issue2.errors.map((issues) => processError({ issues }, [...path30, ...issue2.path]));
|
|
5407
5407
|
} else if (issue2.code === "invalid_key") {
|
|
5408
|
-
processError({ issues: issue2.issues }, [...
|
|
5408
|
+
processError({ issues: issue2.issues }, [...path30, ...issue2.path]);
|
|
5409
5409
|
} else if (issue2.code === "invalid_element") {
|
|
5410
|
-
processError({ issues: issue2.issues }, [...
|
|
5410
|
+
processError({ issues: issue2.issues }, [...path30, ...issue2.path]);
|
|
5411
5411
|
} else {
|
|
5412
|
-
const fullpath = [...
|
|
5412
|
+
const fullpath = [...path30, ...issue2.path];
|
|
5413
5413
|
if (fullpath.length === 0) {
|
|
5414
5414
|
result2.errors.push(mapper(issue2));
|
|
5415
5415
|
continue;
|
|
@@ -5448,8 +5448,8 @@ function treeifyError(error62, mapper = (issue2) => issue2.message) {
|
|
|
5448
5448
|
}
|
|
5449
5449
|
function toDotPath(_path) {
|
|
5450
5450
|
const segs = [];
|
|
5451
|
-
const
|
|
5452
|
-
for (const seg of
|
|
5451
|
+
const path30 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
5452
|
+
for (const seg of path30) {
|
|
5453
5453
|
if (typeof seg === "number")
|
|
5454
5454
|
segs.push(`[${seg}]`);
|
|
5455
5455
|
else if (typeof seg === "symbol")
|
|
@@ -22551,13 +22551,13 @@ function resolveRef(ref, ctx) {
|
|
|
22551
22551
|
if (!ref.startsWith("#")) {
|
|
22552
22552
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
22553
22553
|
}
|
|
22554
|
-
const
|
|
22555
|
-
if (
|
|
22554
|
+
const path30 = ref.slice(1).split("/").filter(Boolean);
|
|
22555
|
+
if (path30.length === 0) {
|
|
22556
22556
|
return ctx.rootSchema;
|
|
22557
22557
|
}
|
|
22558
22558
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
22559
|
-
if (
|
|
22560
|
-
const key =
|
|
22559
|
+
if (path30[0] === defsKey) {
|
|
22560
|
+
const key = path30[1] === void 0 ? void 0 : decodeJSONPointerSegment(path30[1]);
|
|
22561
22561
|
if (!key || !ctx.defs[key]) {
|
|
22562
22562
|
throw new Error(`Reference not found: ${ref}`);
|
|
22563
22563
|
}
|
|
@@ -23192,7 +23192,7 @@ function visit(schema, fnOrHandlers) {
|
|
|
23192
23192
|
return h ? h(node2, rewritten) : node2;
|
|
23193
23193
|
};
|
|
23194
23194
|
const cache2 = /* @__PURE__ */ new Map();
|
|
23195
|
-
function
|
|
23195
|
+
function run2(s) {
|
|
23196
23196
|
const cached2 = cache2.get(s);
|
|
23197
23197
|
if (cached2 === RESOLVING) {
|
|
23198
23198
|
return new $ZodLazy({
|
|
@@ -23218,21 +23218,21 @@ function visit(schema, fnOrHandlers) {
|
|
|
23218
23218
|
let changed = false;
|
|
23219
23219
|
const newShape = {};
|
|
23220
23220
|
for (const k of keys) {
|
|
23221
|
-
const mapped =
|
|
23221
|
+
const mapped = run2(oldShape[k]);
|
|
23222
23222
|
if (mapped !== oldShape[k])
|
|
23223
23223
|
changed = true;
|
|
23224
23224
|
newShape[k] = mapped;
|
|
23225
23225
|
}
|
|
23226
23226
|
let newCatchall = def.catchall;
|
|
23227
23227
|
if (def.catchall) {
|
|
23228
|
-
newCatchall =
|
|
23228
|
+
newCatchall = run2(def.catchall);
|
|
23229
23229
|
if (newCatchall !== def.catchall)
|
|
23230
23230
|
changed = true;
|
|
23231
23231
|
}
|
|
23232
23232
|
return changed ? clone(s, { ...def, shape: newShape, catchall: newCatchall }) : s;
|
|
23233
23233
|
}
|
|
23234
23234
|
case "array": {
|
|
23235
|
-
const mapped =
|
|
23235
|
+
const mapped = run2(def.element);
|
|
23236
23236
|
return mapped === def.element ? s : clone(s, { ...def, element: mapped });
|
|
23237
23237
|
}
|
|
23238
23238
|
case "tuple": {
|
|
@@ -23240,14 +23240,14 @@ function visit(schema, fnOrHandlers) {
|
|
|
23240
23240
|
let changed = false;
|
|
23241
23241
|
const newItems = [];
|
|
23242
23242
|
for (const item of oldItems) {
|
|
23243
|
-
const mapped =
|
|
23243
|
+
const mapped = run2(item);
|
|
23244
23244
|
if (mapped !== item)
|
|
23245
23245
|
changed = true;
|
|
23246
23246
|
newItems.push(mapped);
|
|
23247
23247
|
}
|
|
23248
23248
|
let newRest = def.rest;
|
|
23249
23249
|
if (def.rest) {
|
|
23250
|
-
newRest =
|
|
23250
|
+
newRest = run2(def.rest);
|
|
23251
23251
|
if (newRest !== def.rest)
|
|
23252
23252
|
changed = true;
|
|
23253
23253
|
}
|
|
@@ -23255,12 +23255,12 @@ function visit(schema, fnOrHandlers) {
|
|
|
23255
23255
|
}
|
|
23256
23256
|
case "record":
|
|
23257
23257
|
case "map": {
|
|
23258
|
-
const newKey =
|
|
23259
|
-
const newVal =
|
|
23258
|
+
const newKey = run2(def.keyType);
|
|
23259
|
+
const newVal = run2(def.valueType);
|
|
23260
23260
|
return newKey === def.keyType && newVal === def.valueType ? s : clone(s, { ...def, keyType: newKey, valueType: newVal });
|
|
23261
23261
|
}
|
|
23262
23262
|
case "set": {
|
|
23263
|
-
const newVal =
|
|
23263
|
+
const newVal = run2(def.valueType);
|
|
23264
23264
|
return newVal === def.valueType ? s : clone(s, { ...def, valueType: newVal });
|
|
23265
23265
|
}
|
|
23266
23266
|
case "union": {
|
|
@@ -23268,7 +23268,7 @@ function visit(schema, fnOrHandlers) {
|
|
|
23268
23268
|
let changed = false;
|
|
23269
23269
|
const newOptions = [];
|
|
23270
23270
|
for (const opt of oldOptions) {
|
|
23271
|
-
const mapped =
|
|
23271
|
+
const mapped = run2(opt);
|
|
23272
23272
|
if (mapped !== opt)
|
|
23273
23273
|
changed = true;
|
|
23274
23274
|
newOptions.push(mapped);
|
|
@@ -23276,8 +23276,8 @@ function visit(schema, fnOrHandlers) {
|
|
|
23276
23276
|
return changed ? clone(s, { ...def, options: newOptions }) : s;
|
|
23277
23277
|
}
|
|
23278
23278
|
case "intersection": {
|
|
23279
|
-
const newLeft =
|
|
23280
|
-
const newRight =
|
|
23279
|
+
const newLeft = run2(def.left);
|
|
23280
|
+
const newRight = run2(def.right);
|
|
23281
23281
|
return newLeft === def.left && newRight === def.right ? s : clone(s, { ...def, left: newLeft, right: newRight });
|
|
23282
23282
|
}
|
|
23283
23283
|
case "optional":
|
|
@@ -23289,23 +23289,23 @@ function visit(schema, fnOrHandlers) {
|
|
|
23289
23289
|
case "nonoptional":
|
|
23290
23290
|
case "promise":
|
|
23291
23291
|
case "success": {
|
|
23292
|
-
const newInner =
|
|
23292
|
+
const newInner = run2(def.innerType);
|
|
23293
23293
|
return newInner === def.innerType ? s : clone(s, { ...def, innerType: newInner });
|
|
23294
23294
|
}
|
|
23295
23295
|
case "pipe": {
|
|
23296
|
-
const newIn =
|
|
23297
|
-
const newOut =
|
|
23296
|
+
const newIn = run2(def.in);
|
|
23297
|
+
const newOut = run2(def.out);
|
|
23298
23298
|
return newIn === def.in && newOut === def.out ? s : clone(s, { ...def, in: newIn, out: newOut });
|
|
23299
23299
|
}
|
|
23300
23300
|
case "function": {
|
|
23301
|
-
const newInput =
|
|
23302
|
-
const newOutput =
|
|
23301
|
+
const newInput = run2(def.input);
|
|
23302
|
+
const newOutput = run2(def.output);
|
|
23303
23303
|
return newInput === def.input && newOutput === def.output ? s : clone(s, { ...def, input: newInput, output: newOutput });
|
|
23304
23304
|
}
|
|
23305
23305
|
case "lazy": {
|
|
23306
23306
|
const original = def.getter;
|
|
23307
23307
|
const { _cachedInner, ...rest } = def;
|
|
23308
|
-
return clone(s, { ...rest, getter: () =>
|
|
23308
|
+
return clone(s, { ...rest, getter: () => run2(original()) });
|
|
23309
23309
|
}
|
|
23310
23310
|
// A leaf by choice: `parts` are regex fragments, not data positions.
|
|
23311
23311
|
case "template_literal":
|
|
@@ -23336,7 +23336,7 @@ function visit(schema, fnOrHandlers) {
|
|
|
23336
23336
|
}
|
|
23337
23337
|
}
|
|
23338
23338
|
}
|
|
23339
|
-
return
|
|
23339
|
+
return run2(schema);
|
|
23340
23340
|
}
|
|
23341
23341
|
|
|
23342
23342
|
// node_modules/zod/v4/classic/deep-partial.js
|
|
@@ -25177,8 +25177,8 @@ async function openNetworkPanel(binaryDirectory, identity) {
|
|
|
25177
25177
|
}
|
|
25178
25178
|
|
|
25179
25179
|
// agent/src/main.ts
|
|
25180
|
-
import
|
|
25181
|
-
import
|
|
25180
|
+
import path29 from "node:path";
|
|
25181
|
+
import os8 from "node:os";
|
|
25182
25182
|
|
|
25183
25183
|
// agent/src/posix-store.ts
|
|
25184
25184
|
import { constants } from "node:fs";
|
|
@@ -25597,7 +25597,7 @@ async function acquirePosixJournalGuard(directory, helper) {
|
|
|
25597
25597
|
}
|
|
25598
25598
|
|
|
25599
25599
|
// agent/src/main.ts
|
|
25600
|
-
import { mkdir as mkdir14, open as open13, readFile as
|
|
25600
|
+
import { mkdir as mkdir14, open as open13, readFile as readFile12, realpath as realpath10, rm as rm10 } from "node:fs/promises";
|
|
25601
25601
|
import { fileURLToPath } from "node:url";
|
|
25602
25602
|
|
|
25603
25603
|
// packages/operations/src/crypto.ts
|
|
@@ -25734,13 +25734,13 @@ var exec2 = promisify2(execFile2);
|
|
|
25734
25734
|
async function darwinSupervisorLiveness(helper, pids, records = []) {
|
|
25735
25735
|
if (process.platform !== "darwin" || !process.getuid?.() || process.getuid() !== process.geteuid?.()) return null;
|
|
25736
25736
|
const remaining = new Set(pids), uid = process.getuid(), deadline = Date.now() + 1e4, env = buildChildEnvironment(process.env);
|
|
25737
|
-
const
|
|
25737
|
+
const run2 = (file2, args) => exec2(
|
|
25738
25738
|
file2,
|
|
25739
25739
|
args,
|
|
25740
25740
|
{ env, timeout: Math.max(1, Math.min(7e3, deadline - Date.now())), maxBuffer: 8192, encoding: "utf8", windowsHide: true }
|
|
25741
25741
|
);
|
|
25742
25742
|
try {
|
|
25743
|
-
const boot = (await
|
|
25743
|
+
const boot = (await run2("/usr/sbin/sysctl", ["-n", "kern.bootsessionuuid"])).stdout.trim();
|
|
25744
25744
|
if (!bootSession.test(boot)) return null;
|
|
25745
25745
|
for (const pid of remaining) {
|
|
25746
25746
|
if (Date.now() >= deadline) break;
|
|
@@ -25749,9 +25749,9 @@ async function darwinSupervisorLiveness(helper, pids, records = []) {
|
|
|
25749
25749
|
const proof2 = matches2[0].containment;
|
|
25750
25750
|
if (!validDarwinContainment(proof2) || proof2.uid !== uid || proof2.bootSession !== boot) continue;
|
|
25751
25751
|
try {
|
|
25752
|
-
await
|
|
25753
|
-
if ((await
|
|
25754
|
-
await
|
|
25752
|
+
await run2(helper, ["--reap", proof2.coalition]);
|
|
25753
|
+
if ((await run2(helper, ["--count", proof2.coalition])).stdout.trim() !== "0") continue;
|
|
25754
|
+
await run2("/bin/launchctl", ["bootout", "gui/" + uid + "/" + proof2.label]).catch(() => {
|
|
25755
25755
|
});
|
|
25756
25756
|
remaining.delete(pid);
|
|
25757
25757
|
} catch {
|
|
@@ -26458,10 +26458,12 @@ var ToolCallSchema = external_exports.discriminatedUnion("name", [
|
|
|
26458
26458
|
external_exports.object({ name: external_exports.literal("git_log"), args: external_exports.object({ path: path5.optional(), limit: external_exports.number().int().min(1).max(50).default(15) }).strict() }).strict(),
|
|
26459
26459
|
external_exports.object({ name: external_exports.literal("project_snapshot"), args: external_exports.object({ path: path5.optional(), startup: external_exports.boolean().optional(), taskId: external_exports.string().regex(/^[A-Za-z0-9_-]{1,100}$/).optional() }).strict() }).strict(),
|
|
26460
26460
|
external_exports.object({ name: external_exports.literal("command_run"), args: external_exports.object({ command: external_exports.string().min(1).max(260).refine((v) => !/[\r\n\0]/.test(v)), args: external_exports.array(external_exports.string().max(8192).refine((v) => !v.includes("\0"))).max(128).default([]), cwd: path5.optional(), timeoutMs: external_exports.number().int().min(100).max(864e5).default(6e4) }).strict() }).strict(),
|
|
26461
|
+
// Still image of the device's primary display; the agent requires an owner Full Access workspace.
|
|
26462
|
+
external_exports.object({ name: external_exports.literal("take_screenshot"), args: external_exports.object({}).strict() }).strict(),
|
|
26461
26463
|
external_exports.object({ name: external_exports.literal("localhost_request"), args: external_exports.object({ url: external_exports.string().url().max(2048), method: external_exports.enum(["GET", "HEAD", "POST", "PUT", "PATCH", "DELETE"]).default("GET"), headers: external_exports.record(external_exports.string().max(128), external_exports.string().max(2048)).optional(), body: external_exports.string().max(6e4).optional() }).strict() }).strict()
|
|
26462
26464
|
]);
|
|
26463
26465
|
function scopeForTool(call) {
|
|
26464
|
-
if (call.name === "command_run") return "commands:execute";
|
|
26466
|
+
if (call.name === "command_run" || call.name === "take_screenshot") return "commands:execute";
|
|
26465
26467
|
if (call.name === "localhost_request") return "localhost:access";
|
|
26466
26468
|
return call.name === "fs_write" || call.name === "fs_replace" ? "files:write" : "files:read";
|
|
26467
26469
|
}
|
|
@@ -26565,6 +26567,7 @@ function guardAction(binding2, tool, config2, observedAt) {
|
|
|
26565
26567
|
throw Error("GUARD_IDENTITY_REQUIRED");
|
|
26566
26568
|
}
|
|
26567
26569
|
const name2 = tool.call.name;
|
|
26570
|
+
if (name2 === "take_screenshot") throw Error("GUARD_ACTION_UNSUPPORTED");
|
|
26568
26571
|
const kind = name2 === "command_run" ? "execute" : name2 === "localhost_request" ? "localhost-access" : name2 === "fs_write" || name2 === "fs_replace" ? "write" : name2.startsWith("git_") ? "git-read" : "read";
|
|
26569
26572
|
const resourceKind = kind === "execute" ? "workspace" : kind === "localhost-access" ? "localhost-service" : kind === "git-read" ? "git-repository" : name2 === "fs_read" || kind === "write" ? "file" : "workspace";
|
|
26570
26573
|
return { payloadHash: guardHash(tool.effective), request: BoundActionRequestSchema.parse({
|
|
@@ -27246,6 +27249,7 @@ import { constants as constants4 } from "node:fs";
|
|
|
27246
27249
|
|
|
27247
27250
|
// agent/src/posix-consent.ts
|
|
27248
27251
|
import { openSync, closeSync } from "node:fs";
|
|
27252
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
27249
27253
|
import { isatty, ReadStream, WriteStream } from "node:tty";
|
|
27250
27254
|
import { createInterface } from "node:readline/promises";
|
|
27251
27255
|
import path8 from "node:path";
|
|
@@ -27348,7 +27352,7 @@ async function planPermissionChange(current2, programs, input2) {
|
|
|
27348
27352
|
}
|
|
27349
27353
|
|
|
27350
27354
|
// agent/src/posix-consent.ts
|
|
27351
|
-
async function terminal2(
|
|
27355
|
+
async function terminal2(run2, timeoutMs2, signal) {
|
|
27352
27356
|
if (!process.getuid || process.getuid() === 0 || process.geteuid?.() !== process.getuid() || signal?.aborted) throw Error("OWNER_REVIEW_UNAVAILABLE");
|
|
27353
27357
|
let readFd;
|
|
27354
27358
|
try {
|
|
@@ -27384,7 +27388,7 @@ async function terminal2(run, timeoutMs2, signal) {
|
|
|
27384
27388
|
};
|
|
27385
27389
|
input2.on("data", bound);
|
|
27386
27390
|
try {
|
|
27387
|
-
return await
|
|
27391
|
+
return await run2(async (prompt) => {
|
|
27388
27392
|
if (stop.signal.aborted) throw Error("OWNER_REVIEW_CANCELLED");
|
|
27389
27393
|
return review.question(prompt, { signal: stop.signal });
|
|
27390
27394
|
});
|
|
@@ -27413,16 +27417,41 @@ async function choosePosixFolder() {
|
|
|
27413
27417
|
return await ask("Read/write folder: " + permissionLabel(folder) + "\nType APPROVE to accept: ") === "APPROVE" ? folder : null;
|
|
27414
27418
|
}, 12e4);
|
|
27415
27419
|
}
|
|
27420
|
+
var ACCESS_TEXT = "Local Commander lets your AI work on this computer.\n\nFull Access: files, commands and localhost with your account's rights (not an OS sandbox).\nChoose Folder: read and write one folder only.\n\nThis replaces the previous selection and lasts until you change or revoke it.";
|
|
27421
|
+
function selection(folder, full) {
|
|
27422
|
+
if (!path8.isAbsolute(folder) || folder.length > 4096 || /[\u0000-\u001f]/.test(folder)) throw Error("WORKSPACE_INVALID");
|
|
27423
|
+
return { mode: full ? "all-drives" : "folders", paths: [full ? "/" : folder] };
|
|
27424
|
+
}
|
|
27425
|
+
function macDialog() {
|
|
27426
|
+
const script = [
|
|
27427
|
+
"on run argv",
|
|
27428
|
+
'set answer to button returned of (display dialog (item 1 of argv) with title "Local Commander" buttons {"Cancel", "Choose Folder\uFFFD", "Full Access"} default button "Full Access" cancel button "Cancel" with icon note)',
|
|
27429
|
+
'if answer is "Full Access" then return "full"',
|
|
27430
|
+
'return "folder:" & POSIX path of (choose folder with prompt "Choose the folder Local Commander may read and write")',
|
|
27431
|
+
"end run"
|
|
27432
|
+
];
|
|
27433
|
+
const result2 = spawnSync2(
|
|
27434
|
+
"/usr/bin/osascript",
|
|
27435
|
+
[...script.flatMap((line) => ["-e", line]), ACCESS_TEXT],
|
|
27436
|
+
{ encoding: "utf8", timeout: 24e4, maxBuffer: 16384, shell: false }
|
|
27437
|
+
);
|
|
27438
|
+
if (result2.error) return void 0;
|
|
27439
|
+
if (result2.status !== 0) return /\(-128\)/.test(result2.stderr) ? null : void 0;
|
|
27440
|
+
const out = result2.stdout.replace(/\n$/, "");
|
|
27441
|
+
if (out === "full") return selection("/", true);
|
|
27442
|
+
if (out.startsWith("folder:")) return selection(out.slice(7).replace(/(.)\/$/, "$1"), false);
|
|
27443
|
+
return void 0;
|
|
27444
|
+
}
|
|
27416
27445
|
async function choosePosixAccess() {
|
|
27446
|
+
if (process.platform === "darwin") {
|
|
27447
|
+
const chosen = macDialog();
|
|
27448
|
+
if (chosen !== void 0) return chosen;
|
|
27449
|
+
}
|
|
27417
27450
|
return terminal2(async (ask) => {
|
|
27418
|
-
|
|
27419
|
-
|
|
27420
|
-
if (
|
|
27421
|
-
|
|
27422
|
-
if (!path8.isAbsolute(folder) || folder.length > 4096 || /[\u0000-\u001f]/.test(folder)) throw Error("WORKSPACE_INVALID");
|
|
27423
|
-
const summary = choice === "2" ? "Full Access allows programs to use your account's capabilities across this computer. This is not an OS sandbox." : "Allow reading and writing files in " + permissionLabel(folder) + ".";
|
|
27424
|
-
if (await ask(summary + "\nThis replaces the previous folder/command/localhost selection and persists until revoked.\nType APPROVE to accept: ") !== "APPROVE") return null;
|
|
27425
|
-
return { mode: choice === "2" ? "all-drives" : "folders", paths: [folder] };
|
|
27451
|
+
const answer = await ask("\n" + ACCESS_TEXT + "\n\nPress Enter for Full Access, type a folder path for one folder, or n to cancel: ");
|
|
27452
|
+
if (answer === "") return selection("/", true);
|
|
27453
|
+
if (/^(n|no|cancel)$/i.test(answer)) return null;
|
|
27454
|
+
return selection(answer, false);
|
|
27426
27455
|
}, 24e4);
|
|
27427
27456
|
}
|
|
27428
27457
|
|
|
@@ -28890,8 +28919,8 @@ var HostMemory = class {
|
|
|
28890
28919
|
|
|
28891
28920
|
// agent/src/tools.ts
|
|
28892
28921
|
import { constants as constants7 } from "node:fs";
|
|
28893
|
-
import { lstat as lstat7, open as open6, readdir as readdir4, realpath as realpath7, rename as rename4, rm as
|
|
28894
|
-
import
|
|
28922
|
+
import { lstat as lstat7, open as open6, readdir as readdir4, realpath as realpath7, rename as rename4, rm as rm6 } from "node:fs/promises";
|
|
28923
|
+
import path18 from "node:path";
|
|
28895
28924
|
import { createHash as createHash14, randomUUID as randomUUID7 } from "node:crypto";
|
|
28896
28925
|
|
|
28897
28926
|
// src/guard.ts
|
|
@@ -29335,6 +29364,116 @@ async function runSupervised(helper, request, options = {}) {
|
|
|
29335
29364
|
});
|
|
29336
29365
|
}
|
|
29337
29366
|
|
|
29367
|
+
// agent/src/screen-capture.ts
|
|
29368
|
+
import { execFile as execFile4 } from "node:child_process";
|
|
29369
|
+
import { mkdtemp, readFile as readFile6, rm as rm5 } from "node:fs/promises";
|
|
29370
|
+
import os4 from "node:os";
|
|
29371
|
+
import path17 from "node:path";
|
|
29372
|
+
var SCREENSHOT_MAX_JPEG_BYTES = 131072;
|
|
29373
|
+
var SCREENSHOT_MAX_EDGE = 1568;
|
|
29374
|
+
function screenshotEnabled(env = process.env) {
|
|
29375
|
+
return env.LC_SCREENSHOT_ENABLED === "true";
|
|
29376
|
+
}
|
|
29377
|
+
var SCREENSHOT_ACCEPTANCE_FILE = "screenshot-acceptance-enabled";
|
|
29378
|
+
var ScreenCaptureError = class extends Error {
|
|
29379
|
+
constructor(code) {
|
|
29380
|
+
super(code);
|
|
29381
|
+
this.code = code;
|
|
29382
|
+
this.name = "ScreenCaptureError";
|
|
29383
|
+
}
|
|
29384
|
+
code;
|
|
29385
|
+
};
|
|
29386
|
+
var KNOWN = /^(SCREEN_UNAVAILABLE|SCREEN_LOCKED|SCREEN_ENCODER_UNAVAILABLE|SCREENSHOT_TOO_LARGE|ARGUMENT_INVALID)$/;
|
|
29387
|
+
function jpegSize(data) {
|
|
29388
|
+
if (data.length < 4 || data[0] !== 255 || data[1] !== 216 || data[data.length - 2] !== 255 || data[data.length - 1] !== 217) return null;
|
|
29389
|
+
for (let at = 2; at + 9 < data.length; ) {
|
|
29390
|
+
if (data[at] !== 255) return null;
|
|
29391
|
+
const marker = data[at + 1], length = data.readUInt16BE(at + 2);
|
|
29392
|
+
if (marker >= 192 && marker <= 207 && ![196, 200, 204].includes(marker)) {
|
|
29393
|
+
const height = data.readUInt16BE(at + 5), width = data.readUInt16BE(at + 7);
|
|
29394
|
+
return width > 0 && height > 0 ? { width, height } : null;
|
|
29395
|
+
}
|
|
29396
|
+
at += 2 + length;
|
|
29397
|
+
}
|
|
29398
|
+
return null;
|
|
29399
|
+
}
|
|
29400
|
+
function run(file2, args, signal, maxBuffer = 65536) {
|
|
29401
|
+
return new Promise((resolve, reject) => {
|
|
29402
|
+
execFile4(
|
|
29403
|
+
file2,
|
|
29404
|
+
args,
|
|
29405
|
+
{ encoding: "buffer", timeout: 15e3, maxBuffer, windowsHide: true, shell: false, env: buildChildEnvironment(process.env, process.platform), signal },
|
|
29406
|
+
(error62, stdout, stderr) => error62 ? reject(Object.assign(error62, { stdout, stderr })) : resolve({ stdout, stderr })
|
|
29407
|
+
);
|
|
29408
|
+
});
|
|
29409
|
+
}
|
|
29410
|
+
async function windows(bridge, signal) {
|
|
29411
|
+
if (!path17.isAbsolute(bridge)) throw new ScreenCaptureError("SCREEN_UNAVAILABLE");
|
|
29412
|
+
let stdout;
|
|
29413
|
+
try {
|
|
29414
|
+
({ stdout } = await run(bridge, ["screenshot", String(SCREENSHOT_MAX_EDGE), String(SCREENSHOT_MAX_JPEG_BYTES)], signal, 262144));
|
|
29415
|
+
} catch (error62) {
|
|
29416
|
+
if (signal.aborted) throw new ScreenCaptureError("CANCELLED");
|
|
29417
|
+
const code = /^\{"error":"([A-Z_]+)"\}$/.exec(String(error62.stderr ?? ""))?.[1];
|
|
29418
|
+
throw new ScreenCaptureError(code && KNOWN.test(code) ? code : "SCREEN_UNAVAILABLE");
|
|
29419
|
+
}
|
|
29420
|
+
try {
|
|
29421
|
+
const value = JSON.parse(stdout.toString("utf8"));
|
|
29422
|
+
const data = Buffer.from(value.data, "base64"), size = jpegSize(data);
|
|
29423
|
+
if (!size || size.width !== value.width || size.height !== value.height || !Number.isSafeInteger(value.sourceWidth) || !Number.isSafeInteger(value.sourceHeight)) throw Error();
|
|
29424
|
+
return { data, width: size.width, height: size.height, sourceWidth: value.sourceWidth, sourceHeight: value.sourceHeight };
|
|
29425
|
+
} catch {
|
|
29426
|
+
throw new ScreenCaptureError("SCREEN_UNAVAILABLE");
|
|
29427
|
+
}
|
|
29428
|
+
}
|
|
29429
|
+
async function mac3(signal) {
|
|
29430
|
+
try {
|
|
29431
|
+
const preflight = await run("/usr/bin/osascript", ["-l", "JavaScript", "-e", "ObjC.import('CoreGraphics'); $.CGPreflightScreenCaptureAccess()"], signal);
|
|
29432
|
+
if (preflight.stdout.toString("utf8").trim() !== "true") {
|
|
29433
|
+
await run("/usr/bin/osascript", ["-l", "JavaScript", "-e", "ObjC.import('CoreGraphics'); $.CGRequestScreenCaptureAccess()"], signal).catch(() => {
|
|
29434
|
+
});
|
|
29435
|
+
throw new ScreenCaptureError("SCREEN_RECORDING_PERMISSION_REQUIRED");
|
|
29436
|
+
}
|
|
29437
|
+
} catch (error62) {
|
|
29438
|
+
if (error62 instanceof ScreenCaptureError) throw error62;
|
|
29439
|
+
throw new ScreenCaptureError(signal.aborted ? "CANCELLED" : "SCREEN_UNAVAILABLE");
|
|
29440
|
+
}
|
|
29441
|
+
const folder = await mkdtemp(path17.join(os4.tmpdir(), "lc-screen-"));
|
|
29442
|
+
try {
|
|
29443
|
+
const full = path17.join(folder, "full.png"), small = path17.join(folder, "small.jpg");
|
|
29444
|
+
try {
|
|
29445
|
+
await run("/usr/sbin/screencapture", ["-x", "-m", "-t", "png", full], signal);
|
|
29446
|
+
} catch {
|
|
29447
|
+
throw new ScreenCaptureError(signal.aborted ? "CANCELLED" : "SCREEN_UNAVAILABLE");
|
|
29448
|
+
}
|
|
29449
|
+
const source = (await run("/usr/bin/sips", ["-g", "pixelWidth", "-g", "pixelHeight", full], signal)).stdout.toString("utf8");
|
|
29450
|
+
const sourceWidth = Number(/pixelWidth: (\d+)/.exec(source)?.[1]), sourceHeight = Number(/pixelHeight: (\d+)/.exec(source)?.[1]);
|
|
29451
|
+
if (!sourceWidth || !sourceHeight) throw new ScreenCaptureError("SCREEN_UNAVAILABLE");
|
|
29452
|
+
for (const edge of [SCREENSHOT_MAX_EDGE, 1280, 1024, 800, 640]) {
|
|
29453
|
+
const target = Math.min(edge, Math.max(sourceWidth, sourceHeight));
|
|
29454
|
+
for (const quality of [75, 60, 45, 35]) {
|
|
29455
|
+
await run("/usr/bin/sips", ["-Z", String(target), "-s", "format", "jpeg", "-s", "formatOptions", String(quality), full, "--out", small], signal);
|
|
29456
|
+
const data = await readFile6(small), size = jpegSize(data);
|
|
29457
|
+
if (!size) throw new ScreenCaptureError("SCREEN_UNAVAILABLE");
|
|
29458
|
+
if (data.length <= SCREENSHOT_MAX_JPEG_BYTES) return { data, ...size, sourceWidth, sourceHeight };
|
|
29459
|
+
}
|
|
29460
|
+
}
|
|
29461
|
+
throw new ScreenCaptureError("SCREENSHOT_TOO_LARGE");
|
|
29462
|
+
} catch (error62) {
|
|
29463
|
+
if (error62 instanceof ScreenCaptureError) throw error62;
|
|
29464
|
+
throw new ScreenCaptureError(signal.aborted ? "CANCELLED" : "SCREEN_UNAVAILABLE");
|
|
29465
|
+
} finally {
|
|
29466
|
+
await rm5(folder, { recursive: true, force: true }).catch(() => {
|
|
29467
|
+
});
|
|
29468
|
+
}
|
|
29469
|
+
}
|
|
29470
|
+
async function captureScreen(options) {
|
|
29471
|
+
if (options.signal.aborted) throw new ScreenCaptureError("CANCELLED");
|
|
29472
|
+
if (process.platform === "win32") return windows(options.ownerBridgePath, options.signal);
|
|
29473
|
+
if (process.platform === "darwin") return mac3(options.signal);
|
|
29474
|
+
throw new ScreenCaptureError("SCREENSHOT_UNSUPPORTED");
|
|
29475
|
+
}
|
|
29476
|
+
|
|
29338
29477
|
// agent/src/tools.ts
|
|
29339
29478
|
var NativeToolError = class extends Error {
|
|
29340
29479
|
constructor(code) {
|
|
@@ -29425,13 +29564,13 @@ var NativeTools = class {
|
|
|
29425
29564
|
constructor(options) {
|
|
29426
29565
|
this.options = options;
|
|
29427
29566
|
this.options = structuredClone(options);
|
|
29428
|
-
this.memory = new HostMemory(
|
|
29567
|
+
this.memory = new HostMemory(path18.join(options.stateDirectory, "host-memory.json"), Object.keys(options.programs), Object.fromEntries(Object.entries(options.programs).map(([name2, program]) => [name2, program.executable])));
|
|
29429
29568
|
}
|
|
29430
29569
|
options;
|
|
29431
29570
|
memory;
|
|
29432
29571
|
async readFile(file2, maxBytes, signal) {
|
|
29433
29572
|
try {
|
|
29434
|
-
return await readBoundedFile(file2, maxBytes, this.options.ownerBridgePath ??
|
|
29573
|
+
return await readBoundedFile(file2, maxBytes, this.options.ownerBridgePath ?? path18.join(path18.dirname(this.options.helperPath), "OwnerBridge.exe"), signal);
|
|
29435
29574
|
} catch (error62) {
|
|
29436
29575
|
if (error62.code === "ENOENT") throw error62;
|
|
29437
29576
|
if (error62 instanceof Error && /^[A-Z_]{1,40}$/.test(error62.message)) fail3(error62.message);
|
|
@@ -29441,31 +29580,31 @@ var NativeTools = class {
|
|
|
29441
29580
|
/** Windows only: up to 64 files of at most 1 MiB in one bridge process, each with its own result. */
|
|
29442
29581
|
async readFiles(files, maxTotalBytes, signal) {
|
|
29443
29582
|
try {
|
|
29444
|
-
return await readWindowsFiles(this.options.ownerBridgePath ??
|
|
29583
|
+
return await readWindowsFiles(this.options.ownerBridgePath ?? path18.join(path18.dirname(this.options.helperPath), "OwnerBridge.exe"), files, 1048576, maxTotalBytes, signal);
|
|
29445
29584
|
} catch (error62) {
|
|
29446
29585
|
if (error62 instanceof Error && /^[A-Z_]{1,40}$/.test(error62.message)) fail3(error62.message);
|
|
29447
29586
|
throw error62;
|
|
29448
29587
|
}
|
|
29449
29588
|
}
|
|
29450
|
-
async prepare(workspace2, candidate,
|
|
29589
|
+
async prepare(workspace2, candidate, selection2) {
|
|
29451
29590
|
let prepared;
|
|
29452
29591
|
try {
|
|
29453
29592
|
let projectRoot;
|
|
29454
|
-
if (
|
|
29455
|
-
const target = ProjectTargetBindingSchema.parse(
|
|
29593
|
+
if (selection2) {
|
|
29594
|
+
const target = ProjectTargetBindingSchema.parse(selection2);
|
|
29456
29595
|
if (workspace2.rootHash !== target.workspaceRootHash) fail3("PROJECT_IDENTITY_MISMATCH");
|
|
29457
29596
|
const identity = await this.prepareTool(workspace2, { name: "project_identity", args: { path: target.relativePath } });
|
|
29458
29597
|
const proof2 = JSON.parse((await identity.run(AbortSignal.timeout(15e3))).stdout);
|
|
29459
29598
|
if (!proof2.repositoryFingerprint) fail3("PROJECT_IDENTITY_UNKNOWN");
|
|
29460
29599
|
if (proof2.repositoryFingerprint !== target.repositoryFingerprint) fail3("PROJECT_IDENTITY_MISMATCH");
|
|
29461
|
-
projectRoot =
|
|
29600
|
+
projectRoot = path18.resolve(workspace2.root, target.relativePath);
|
|
29462
29601
|
const common = identity.claims.find((claim2) => claim2.namespace === "git")?.path;
|
|
29463
29602
|
if (common) workspace2 = { ...workspace2, gitCommonDir: common };
|
|
29464
29603
|
}
|
|
29465
29604
|
prepared = await this.prepareTool(workspace2, candidate, projectRoot);
|
|
29466
29605
|
} catch (error62) {
|
|
29467
29606
|
const parsed = ToolCallSchema.safeParse(candidate);
|
|
29468
|
-
if (parsed.success && parsed.data.name === "command_run") await this.memory.record({ ...parsed.data.args, cwd:
|
|
29607
|
+
if (parsed.success && parsed.data.name === "command_run") await this.memory.record({ ...parsed.data.args, cwd: path18.resolve(workspace2.root, parsed.data.args.cwd ?? ".") }, void 0, error62).catch(() => {
|
|
29469
29608
|
});
|
|
29470
29609
|
throw error62;
|
|
29471
29610
|
}
|
|
@@ -29485,17 +29624,17 @@ var NativeTools = class {
|
|
|
29485
29624
|
try {
|
|
29486
29625
|
const canonical2 = await realpath7(workspace2.root);
|
|
29487
29626
|
if (!equalPath3(canonical2, workspace2.root) || hash6(process.platform === "win32" ? canonical2.toLowerCase() : canonical2) !== workspace2.rootHash) fail3("WORKSPACE_CHANGED");
|
|
29488
|
-
const runtimeDirectory =
|
|
29627
|
+
const runtimeDirectory = path18.dirname(this.options.helperPath);
|
|
29489
29628
|
const protectedPaths = [
|
|
29490
29629
|
this.options.stateDirectory,
|
|
29491
29630
|
this.options.helperPath,
|
|
29492
|
-
...["agent.mjs", "node.exe", "OwnerBridge.exe", "LocalCommanderAgent.exe", "node", "owner-store", "posix-host", "job-host.mjs", "lifecycle.mjs", "manifest.json"].map((name2) =>
|
|
29631
|
+
...["agent.mjs", "node.exe", "OwnerBridge.exe", "LocalCommanderAgent.exe", "node", "owner-store", "posix-host", "job-host.mjs", "lifecycle.mjs", "manifest.json"].map((name2) => path18.join(runtimeDirectory, name2))
|
|
29493
29632
|
];
|
|
29494
29633
|
if (this.options.ownerBridgePath) protectedPaths.push(this.options.ownerBridgePath);
|
|
29495
|
-
if (process.platform === "win32" && process.env.LOCALAPPDATA &&
|
|
29496
|
-
protectedPaths.push(
|
|
29634
|
+
if (process.platform === "win32" && process.env.LOCALAPPDATA && path18.isAbsolute(process.env.LOCALAPPDATA)) {
|
|
29635
|
+
protectedPaths.push(path18.join(process.env.LOCALAPPDATA, "LocalCommander"));
|
|
29497
29636
|
}
|
|
29498
|
-
if (process.platform !== "win32") protectedPaths.push(
|
|
29637
|
+
if (process.platform !== "win32") protectedPaths.push(path18.join(process.env.LC_AGENT_DATA_DIR || posixDataHome(), "LocalCommander"));
|
|
29499
29638
|
guard = await PathGuard.create([canonical2], false, { protectedPaths });
|
|
29500
29639
|
if (projectRoot) {
|
|
29501
29640
|
const selected = await guard.resolveDirectory(projectRoot);
|
|
@@ -29584,7 +29723,7 @@ var NativeTools = class {
|
|
|
29584
29723
|
}
|
|
29585
29724
|
if (taken === first - 1 && first <= end) fail3("OUTPUT_LIMIT_EXCEEDED");
|
|
29586
29725
|
const remaining = lines.length - (lines.length > 1 && lines.at(-1) === "" ? 1 : 0);
|
|
29587
|
-
return result({ path:
|
|
29726
|
+
return result({ path: path18.relative(workspace2.root, filename), sha256: hash6(bytes3), startLine: first, endLine: Math.min(taken === first - 1 ? last : taken, lines.length), totalLines: lines.length, content: lines.slice(first - 1, taken).join("\n"), truncated: taken < remaining });
|
|
29588
29727
|
} };
|
|
29589
29728
|
}
|
|
29590
29729
|
if (call.name === "fs_write" || call.name === "fs_replace") {
|
|
@@ -29627,7 +29766,7 @@ var NativeTools = class {
|
|
|
29627
29766
|
bytes3 = encodeText(pieces.join(newText), original.encoding);
|
|
29628
29767
|
}
|
|
29629
29768
|
if (bytes3.length > MAX_FILE_WRITE_BYTES) fail3("FILE_WRITE_LIMIT");
|
|
29630
|
-
const temp =
|
|
29769
|
+
const temp = path18.join(path18.dirname(target), ".lc-write-" + randomUUID7() + ".tmp");
|
|
29631
29770
|
const handle = await open6(temp, constants7.O_CREAT | constants7.O_EXCL | constants7.O_WRONLY, 384);
|
|
29632
29771
|
try {
|
|
29633
29772
|
await handle.writeFile(bytes3);
|
|
@@ -29659,18 +29798,18 @@ var NativeTools = class {
|
|
|
29659
29798
|
}
|
|
29660
29799
|
for (let attempt = 0; attempt < 3; attempt++) {
|
|
29661
29800
|
try {
|
|
29662
|
-
await
|
|
29801
|
+
await rm6(temp);
|
|
29663
29802
|
break;
|
|
29664
29803
|
} catch {
|
|
29665
29804
|
await delay2(100);
|
|
29666
29805
|
}
|
|
29667
29806
|
}
|
|
29668
29807
|
}
|
|
29669
|
-
return result({ path:
|
|
29808
|
+
return result({ path: path18.relative(workspace2.root, target), bytes: bytes3.length, sha256: hash6(bytes3), ...call.name === "fs_replace" ? { replacements } : {} });
|
|
29670
29809
|
} catch (e) {
|
|
29671
29810
|
await handle.close().catch(() => {
|
|
29672
29811
|
});
|
|
29673
|
-
await
|
|
29812
|
+
await rm6(temp, { force: true }).catch(() => {
|
|
29674
29813
|
});
|
|
29675
29814
|
throw e;
|
|
29676
29815
|
}
|
|
@@ -29692,7 +29831,7 @@ var NativeTools = class {
|
|
|
29692
29831
|
const lines = decodeText(bytes3).text.split(/\r?\n/);
|
|
29693
29832
|
scanned++;
|
|
29694
29833
|
for (let i = 0; i < lines.length && matches2.length < call.args.maxResults; i++) if ((call.args.caseSensitive ? lines[i] : lines[i].toLowerCase()).includes(query)) {
|
|
29695
|
-
const match = { path:
|
|
29834
|
+
const match = { path: path18.relative(workspace2.root, filename), line: i + 1, text: lines[i].slice(0, 500) };
|
|
29696
29835
|
if ((room -= Buffer.byteLength(JSON.stringify(match)) + 1) < 0) {
|
|
29697
29836
|
incomplete = true;
|
|
29698
29837
|
break;
|
|
@@ -29735,7 +29874,7 @@ var NativeTools = class {
|
|
|
29735
29874
|
continue;
|
|
29736
29875
|
}
|
|
29737
29876
|
try {
|
|
29738
|
-
const filename = await guard.resolveExisting(
|
|
29877
|
+
const filename = await guard.resolveExisting(path18.join(base, entry.path));
|
|
29739
29878
|
guard.assertSafeFile(filename);
|
|
29740
29879
|
if (!batched) {
|
|
29741
29880
|
searchFile(filename, await this.readFile(filename, 1048576, signal));
|
|
@@ -29759,6 +29898,30 @@ var NativeTools = class {
|
|
|
29759
29898
|
return result({ matches: matches2, scannedFiles: scanned, truncated: listing.truncated || incomplete || matches2.length >= call.args.maxResults || scanned >= 300 });
|
|
29760
29899
|
} };
|
|
29761
29900
|
}
|
|
29901
|
+
if (call.name === "take_screenshot") {
|
|
29902
|
+
if (!screenshotEnabled() && !await lstat7(path18.join(this.options.stateDirectory, SCREENSHOT_ACCEPTANCE_FILE)).then((s) => s.isFile(), () => false)) fail3("SCREENSHOT_DISABLED");
|
|
29903
|
+
if (!workspace2.fullAccess) fail3("FULL_ACCESS_REQUIRED");
|
|
29904
|
+
const bridge = this.options.ownerBridgePath ?? path18.join(path18.dirname(this.options.helperPath), "OwnerBridge.exe");
|
|
29905
|
+
return { call, claims: [{ path: path18.join(this.options.stateDirectory, "screen-capture"), mode: "read" }], run: async (signal) => {
|
|
29906
|
+
let shot;
|
|
29907
|
+
try {
|
|
29908
|
+
shot = await captureScreen({ ownerBridgePath: bridge, signal });
|
|
29909
|
+
} catch (error62) {
|
|
29910
|
+
fail3(error62 instanceof Error && /^[A-Z_]{1,40}$/.test(error62.message) ? error62.message : "SCREEN_UNAVAILABLE");
|
|
29911
|
+
}
|
|
29912
|
+
return result({
|
|
29913
|
+
type: "screenshot",
|
|
29914
|
+
mimeType: "image/jpeg",
|
|
29915
|
+
width: shot.width,
|
|
29916
|
+
height: shot.height,
|
|
29917
|
+
sourceWidth: shot.sourceWidth,
|
|
29918
|
+
sourceHeight: shot.sourceHeight,
|
|
29919
|
+
bytes: shot.data.length,
|
|
29920
|
+
capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
29921
|
+
data: shot.data.toString("base64")
|
|
29922
|
+
});
|
|
29923
|
+
} };
|
|
29924
|
+
}
|
|
29762
29925
|
if (call.name === "localhost_request") {
|
|
29763
29926
|
const url2 = new URL(call.args.url), port = Number(url2.port || (url2.protocol === "https:" ? 443 : 80));
|
|
29764
29927
|
if (!["http:", "https:"].includes(url2.protocol) || !["localhost", "127.0.0.1", "[::1]"].includes(url2.hostname) || url2.username || url2.password || url2.hash || (workspace2.fullAccess ? workspace2.deniedLocalhostPorts?.includes(port) : !workspace2.localhostPorts.includes(port)) || this.options.protectedPorts?.includes(port)) fail3("LOCALHOST_NOT_ALLOWED");
|
|
@@ -29829,9 +29992,9 @@ var NativeTools = class {
|
|
|
29829
29992
|
else if (call.name === "git_diff") {
|
|
29830
29993
|
argv = ["diff", "--no-ext-diff", "--no-textconv", ...call.args.staged ? ["--cached"] : []];
|
|
29831
29994
|
if (call.args.file) {
|
|
29832
|
-
const file2 = await resolve(
|
|
29833
|
-
const relative =
|
|
29834
|
-
if (relative.startsWith(".." +
|
|
29995
|
+
const file2 = await resolve(path18.resolve(cwd, call.args.file));
|
|
29996
|
+
const relative = path18.relative(cwd, file2);
|
|
29997
|
+
if (relative.startsWith(".." + path18.sep) || relative === ".." || path18.isAbsolute(relative)) fail3("PATH_NOT_ALLOWED");
|
|
29835
29998
|
argv.push("--", relative);
|
|
29836
29999
|
} else argv.push("--stat");
|
|
29837
30000
|
} else fail3("TOOL_MISSING");
|
|
@@ -29842,7 +30005,7 @@ var NativeTools = class {
|
|
|
29842
30005
|
const listing = await this.list(guard, cwd, 1, call.args.startup ? 20 : 150, signal);
|
|
29843
30006
|
let packageInfo = null;
|
|
29844
30007
|
try {
|
|
29845
|
-
const name2 = await guard.resolveExisting(
|
|
30008
|
+
const name2 = await guard.resolveExisting(path18.join(cwd, "package.json"));
|
|
29846
30009
|
guard.assertSafeFile(name2);
|
|
29847
30010
|
const value = JSON.parse(utf8(await this.readFile(name2, 64e3, signal)));
|
|
29848
30011
|
packageInfo = { name: typeof value.name === "string" ? value.name : null, version: typeof value.version === "string" ? value.version : null, scripts: value.scripts && typeof value.scripts === "object" ? Object.keys(value.scripts).slice(0, 100) : [] };
|
|
@@ -29862,7 +30025,7 @@ var NativeTools = class {
|
|
|
29862
30025
|
}
|
|
29863
30026
|
const contextFile = async (relative, limit, optional2 = false) => {
|
|
29864
30027
|
try {
|
|
29865
|
-
const file2 = await guard.resolveExisting(
|
|
30028
|
+
const file2 = await guard.resolveExisting(path18.join(primary, relative));
|
|
29866
30029
|
guard.assertSafeFile(file2);
|
|
29867
30030
|
return utf8(await this.readFile(file2, limit, signal));
|
|
29868
30031
|
} catch (error62) {
|
|
@@ -29895,17 +30058,17 @@ var NativeTools = class {
|
|
|
29895
30058
|
} };
|
|
29896
30059
|
}
|
|
29897
30060
|
async resolveProgram(name2, workspace2, args) {
|
|
29898
|
-
const entry = Object.entries(this.options.programs).find(([key, value]) => equalPath3(key, name2) ||
|
|
30061
|
+
const entry = Object.entries(this.options.programs).find(([key, value]) => equalPath3(key, name2) || path18.isAbsolute(name2) && equalPath3(value.executable, path18.resolve(name2)));
|
|
29899
30062
|
if (workspace2.fullAccess) {
|
|
29900
|
-
const commandKey = (value) => process.platform === "win32" ?
|
|
30063
|
+
const commandKey = (value) => process.platform === "win32" ? path18.basename(value).toLowerCase().replace(/\.(exe|com|cmd|bat)$/i, "") : path18.basename(value);
|
|
29901
30064
|
const denied = new Set((workspace2.deniedCommands ?? []).map(commandKey));
|
|
29902
30065
|
if (denied.has(commandKey(name2)) || entry && denied.has(commandKey(entry[0]))) fail3("COMMAND_NOT_ALLOWED");
|
|
29903
|
-
const extension2 =
|
|
29904
|
-
const candidate = entry?.[1].executable ?? (process.platform !== "win32" ? await resolvePosixExecutable(name2) :
|
|
30066
|
+
const extension2 = path18.extname(name2).toLowerCase();
|
|
30067
|
+
const candidate = entry?.[1].executable ?? (process.platform !== "win32" ? await resolvePosixExecutable(name2) : path18.isAbsolute(name2) ? name2 : /^[\w.-]+$/.test(name2) ? resolveWindowsLauncher(
|
|
29905
30068
|
commandKey(name2),
|
|
29906
30069
|
[".exe", ".com", ".cmd", ".bat"].includes(extension2) ? { ...process.env, PATHEXT: extension2 } : process.env
|
|
29907
30070
|
)?.file : void 0);
|
|
29908
|
-
if (!candidate || !
|
|
30071
|
+
if (!candidate || !path18.isAbsolute(candidate)) fail3("COMMAND_NOT_FOUND");
|
|
29909
30072
|
const executable = await realpath7(candidate).catch(() => fail3("COMMAND_NOT_FOUND"));
|
|
29910
30073
|
if (!(await lstat7(executable)).isFile()) fail3("COMMAND_NOT_FOUND");
|
|
29911
30074
|
if (denied.has(commandKey(executable))) fail3("COMMAND_NOT_ALLOWED");
|
|
@@ -29920,7 +30083,7 @@ var NativeTools = class {
|
|
|
29920
30083
|
if (/\.(cmd|bat)$/i.test(executable)) {
|
|
29921
30084
|
if ([executable, ...args].some((value) => /[&|<>^%!"\r\n]/.test(value))) fail3("INVALID_SCRIPT_ARGUMENTS");
|
|
29922
30085
|
const literal2 = (value) => "'" + value.replaceAll("'", "''") + "'";
|
|
29923
|
-
const shell =
|
|
30086
|
+
const shell = path18.join(process.env.SystemRoot ?? "C:\\Windows", "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
|
|
29924
30087
|
if (denied.has("powershell") || denied.has("cmd")) fail3("COMMAND_NOT_ALLOWED");
|
|
29925
30088
|
const script = "& " + literal2(executable) + " @(" + args.map(literal2).join(",") + "); exit $LASTEXITCODE";
|
|
29926
30089
|
return { executable: shell, args: ["-NoProfile", "-NonInteractive", "-EncodedCommand", Buffer.from(script, "utf16le").toString("base64")] };
|
|
@@ -29928,7 +30091,7 @@ var NativeTools = class {
|
|
|
29928
30091
|
if (!/\.(exe|com)$/i.test(executable)) fail3("COMMAND_NOT_ALLOWED");
|
|
29929
30092
|
return { executable, args: [...entry?.[1].prefixArgs ?? [], ...args] };
|
|
29930
30093
|
}
|
|
29931
|
-
if (!entry || !workspace2.allowedCommands.some((v) => equalPath3(v, entry[0])) || !
|
|
30094
|
+
if (!entry || !workspace2.allowedCommands.some((v) => equalPath3(v, entry[0])) || !path18.isAbsolute(entry[1].executable)) fail3("COMMAND_NOT_ALLOWED");
|
|
29932
30095
|
return { executable: entry[1].executable, args: [...entry[1].prefixArgs ?? [], ...args] };
|
|
29933
30096
|
}
|
|
29934
30097
|
async memoryContext(workspace2) {
|
|
@@ -29943,9 +30106,9 @@ var NativeTools = class {
|
|
|
29943
30106
|
async gitExecution(cwd, args) {
|
|
29944
30107
|
if (!["win32", "linux", "darwin"].includes(process.platform)) fail3("COMMAND_NOT_ALLOWED");
|
|
29945
30108
|
const configured = this.options.programs.git;
|
|
29946
|
-
const candidates = configured ? [configured.executable] : process.platform === "win32" ? [[process.env.ProgramFiles, "Git"], [process.env["ProgramFiles(x86)"], "Git"], [process.env.LOCALAPPDATA, "Programs/Git"]].filter(([root]) => root &&
|
|
30109
|
+
const candidates = configured ? [configured.executable] : process.platform === "win32" ? [[process.env.ProgramFiles, "Git"], [process.env["ProgramFiles(x86)"], "Git"], [process.env.LOCALAPPDATA, "Programs/Git"]].filter(([root]) => root && path18.isAbsolute(root)).map(([root, suffix]) => path18.join(root, suffix, "cmd", "git.exe")) : ["/usr/bin/git", "/usr/local/bin/git", "/opt/homebrew/bin/git"];
|
|
29947
30110
|
for (const source of candidates) {
|
|
29948
|
-
if (!
|
|
30111
|
+
if (!path18.isAbsolute(source)) continue;
|
|
29949
30112
|
const candidate = process.platform === "win32" ? source : await resolvePosixExecutable(source);
|
|
29950
30113
|
if (!candidate) continue;
|
|
29951
30114
|
try {
|
|
@@ -29979,7 +30142,7 @@ var NativeTools = class {
|
|
|
29979
30142
|
break;
|
|
29980
30143
|
}
|
|
29981
30144
|
if (item.isSymbolicLink() || excluded.has(item.name.toLowerCase())) continue;
|
|
29982
|
-
const candidate =
|
|
30145
|
+
const candidate = path18.join(current2.path, item.name);
|
|
29983
30146
|
let resolved;
|
|
29984
30147
|
try {
|
|
29985
30148
|
resolved = await guard.resolveExisting(candidate);
|
|
@@ -29989,11 +30152,11 @@ var NativeTools = class {
|
|
|
29989
30152
|
}
|
|
29990
30153
|
if (!equalPath3(candidate, resolved)) continue;
|
|
29991
30154
|
if (item.isDirectory()) {
|
|
29992
|
-
entries.push({ path:
|
|
30155
|
+
entries.push({ path: path18.relative(root, resolved), type: "directory" });
|
|
29993
30156
|
if (current2.level < depth) queue.push({ path: resolved, level: current2.level + 1 });
|
|
29994
30157
|
} else if (item.isFile()) {
|
|
29995
30158
|
const stat2 = await lstat7(resolved).catch(() => null);
|
|
29996
|
-
if (stat2) entries.push({ path:
|
|
30159
|
+
if (stat2) entries.push({ path: path18.relative(root, resolved), type: "file", size: stat2.size });
|
|
29997
30160
|
}
|
|
29998
30161
|
}
|
|
29999
30162
|
if (truncated) break;
|
|
@@ -30003,7 +30166,7 @@ var NativeTools = class {
|
|
|
30003
30166
|
async gitCommonDir(cwd, workspace2, guard) {
|
|
30004
30167
|
let directory = cwd;
|
|
30005
30168
|
while (guard.isWithin(directory, workspace2.root)) {
|
|
30006
|
-
const dotGit =
|
|
30169
|
+
const dotGit = path18.join(directory, ".git");
|
|
30007
30170
|
try {
|
|
30008
30171
|
const stat2 = await lstat7(dotGit);
|
|
30009
30172
|
if (stat2.isSymbolicLink()) fail3("GIT_METADATA_CHANGED");
|
|
@@ -30012,14 +30175,14 @@ var NativeTools = class {
|
|
|
30012
30175
|
else {
|
|
30013
30176
|
const content = utf8(await this.readFile(dotGit, 4096)).trim();
|
|
30014
30177
|
if (!content.startsWith("gitdir: ")) fail3("GIT_METADATA_CHANGED");
|
|
30015
|
-
gitDir = await realpath7(
|
|
30178
|
+
gitDir = await realpath7(path18.resolve(directory, content.slice(8)));
|
|
30016
30179
|
}
|
|
30017
30180
|
if (guard.isWithin(gitDir, this.options.stateDirectory) || !guard.isWithin(gitDir, workspace2.root) && (!workspace2.gitCommonDir || !guard.isWithin(gitDir, workspace2.gitCommonDir))) fail3("GIT_COMMON_DIRECTORY_NOT_APPROVED");
|
|
30018
30181
|
let common = gitDir;
|
|
30019
30182
|
try {
|
|
30020
|
-
const content = utf8(await this.readFile(
|
|
30183
|
+
const content = utf8(await this.readFile(path18.join(gitDir, "commondir"), 4096)).trim();
|
|
30021
30184
|
if (!content) fail3("GIT_METADATA_CHANGED");
|
|
30022
|
-
common = await realpath7(
|
|
30185
|
+
common = await realpath7(path18.resolve(gitDir, content));
|
|
30023
30186
|
} catch (e) {
|
|
30024
30187
|
if (e.code !== "ENOENT") throw e;
|
|
30025
30188
|
}
|
|
@@ -30030,22 +30193,22 @@ var NativeTools = class {
|
|
|
30030
30193
|
if (e.code !== "ENOENT") throw e;
|
|
30031
30194
|
}
|
|
30032
30195
|
if (equalPath3(directory, workspace2.root)) break;
|
|
30033
|
-
directory =
|
|
30196
|
+
directory = path18.dirname(directory);
|
|
30034
30197
|
}
|
|
30035
30198
|
return null;
|
|
30036
30199
|
}
|
|
30037
30200
|
};
|
|
30038
30201
|
|
|
30039
30202
|
// agent/src/scheduler.ts
|
|
30040
|
-
import
|
|
30041
|
-
import
|
|
30203
|
+
import path19 from "node:path";
|
|
30204
|
+
import os5 from "node:os";
|
|
30042
30205
|
function canonical(value) {
|
|
30043
|
-
const p =
|
|
30206
|
+
const p = path19.resolve(value);
|
|
30044
30207
|
return process.platform === "win32" ? p.toLowerCase() : p;
|
|
30045
30208
|
}
|
|
30046
30209
|
function ancestor(a, b) {
|
|
30047
|
-
const relative =
|
|
30048
|
-
return relative === "" || !
|
|
30210
|
+
const relative = path19.relative(a, b);
|
|
30211
|
+
return relative === "" || !path19.isAbsolute(relative) && relative !== ".." && !relative.startsWith(".." + path19.sep);
|
|
30049
30212
|
}
|
|
30050
30213
|
function claimsConflict(a, b) {
|
|
30051
30214
|
return a.some((x) => b.some((y) => (x.namespace ?? "filesystem") === (y.namespace ?? "filesystem") && (x.mode === "write" || y.mode === "write") && (ancestor(x.path, y.path) || ancestor(y.path, x.path))));
|
|
@@ -30053,7 +30216,7 @@ function claimsConflict(a, b) {
|
|
|
30053
30216
|
var NativeScheduler = class {
|
|
30054
30217
|
constructor(options = {}) {
|
|
30055
30218
|
this.options = options;
|
|
30056
|
-
const capacity = Math.max(1, Math.min(16, Math.floor(Math.max(2,
|
|
30219
|
+
const capacity = Math.max(1, Math.min(16, Math.floor(Math.max(2, os5.availableParallelism?.() ?? os5.cpus().length) / 2)));
|
|
30057
30220
|
this.safeSlots = options.safeSlots ?? capacity;
|
|
30058
30221
|
this.maxQueued = options.maxQueued ?? 32;
|
|
30059
30222
|
if (!Number.isInteger(this.safeSlots) || this.safeSlots < 1 || this.safeSlots > 32 || !Number.isInteger(this.maxQueued) || this.maxQueued < 1 || this.maxQueued > 256) throw Error("INVALID_SCHEDULER_LIMIT");
|
|
@@ -30071,16 +30234,16 @@ var NativeScheduler = class {
|
|
|
30071
30234
|
} catch {
|
|
30072
30235
|
}
|
|
30073
30236
|
}
|
|
30074
|
-
schedule(id2, claims, deadlineAt,
|
|
30237
|
+
schedule(id2, claims, deadlineAt, run2, signal) {
|
|
30075
30238
|
if (!this.accepting) return Promise.reject(Error("AGENT_PAUSED"));
|
|
30076
30239
|
if (!id2 || id2.length > 100 || this.active.has(id2) || this.waiting.some((j) => j.id === id2)) return Promise.reject(Error("DUPLICATE_SCHEDULED_EXECUTION"));
|
|
30077
|
-
if (!Array.isArray(claims) || !claims.length || claims.length > 32 || claims.some((c) => !c || !
|
|
30240
|
+
if (!Array.isArray(claims) || !claims.length || claims.length > 32 || claims.some((c) => !c || !path19.isAbsolute(c.path) || !["read", "write"].includes(c.mode))) return Promise.reject(Error("INVALID_RESOURCE_CLAIM"));
|
|
30078
30241
|
const deadline = deadlineAt.getTime();
|
|
30079
30242
|
if (!Number.isFinite(deadline) || deadline <= Date.now()) return Promise.reject(Error("ADMISSION_DEADLINE_EXPIRED"));
|
|
30080
30243
|
if (signal?.aborted) return Promise.reject(Error("CANCELLED_BEFORE_ACCEPTANCE"));
|
|
30081
30244
|
if (this.waiting.length >= this.maxQueued) return Promise.reject(Error("RESOURCE_BUSY"));
|
|
30082
30245
|
return new Promise((resolve, reject) => {
|
|
30083
|
-
const job = { id: id2, claims: claims.map((c) => ({ ...c, path: canonical(c.path) })), deadline, run, signal, resolve, reject };
|
|
30246
|
+
const job = { id: id2, claims: claims.map((c) => ({ ...c, path: canonical(c.path) })), deadline, run: run2, signal, resolve, reject };
|
|
30084
30247
|
const remove = (reason) => {
|
|
30085
30248
|
const index = this.waiting.indexOf(job);
|
|
30086
30249
|
if (index < 0) return;
|
|
@@ -30790,6 +30953,14 @@ function resultOutcome(result2) {
|
|
|
30790
30953
|
if (!result2.treeTerminated || result2.exitCode === null) return "unknown";
|
|
30791
30954
|
return result2.exitCode === 0 ? "success" : "failed";
|
|
30792
30955
|
}
|
|
30956
|
+
function screenshotMetadata(stdout) {
|
|
30957
|
+
try {
|
|
30958
|
+
const { data: _data, ...metadata } = JSON.parse(stdout);
|
|
30959
|
+
return JSON.stringify(metadata);
|
|
30960
|
+
} catch {
|
|
30961
|
+
return "";
|
|
30962
|
+
}
|
|
30963
|
+
}
|
|
30793
30964
|
async function outboundResult(call, result2, binding2, optional2, ledger) {
|
|
30794
30965
|
const shaped = call.name === "command_run" ? shapeCommandResultForAgentDetailed({ command: call.args.command, args: call.args.args, cwd: call.args.cwd ?? "." }, result2) : { result: result2, telemetry: unshapedResultTelemetry(result2) };
|
|
30795
30966
|
if (ledger) {
|
|
@@ -30842,7 +31013,7 @@ var NativeRuntime = class {
|
|
|
30842
31013
|
}
|
|
30843
31014
|
if (frame.type === "result" && this.options.contentAudit) {
|
|
30844
31015
|
const call = this.contexts.get(frame.binding.executionId)?.tool.call;
|
|
30845
|
-
if (call) try {
|
|
31016
|
+
if (call && call.name !== "take_screenshot") try {
|
|
30846
31017
|
this.options.contentAudit.record(frame.binding, call, frame.result);
|
|
30847
31018
|
} catch {
|
|
30848
31019
|
}
|
|
@@ -30979,8 +31150,10 @@ var NativeRuntime = class {
|
|
|
30979
31150
|
const checked = ResultSchema.parse(output2);
|
|
30980
31151
|
const { resultCode, ...journalOutput } = checked;
|
|
30981
31152
|
if (context.guardPermit) await this.options.guard.result(context.guardPermit, checked);
|
|
30982
|
-
const
|
|
30983
|
-
this.
|
|
31153
|
+
const image = runnable.call.name === "take_screenshot" ? journalOutput.stdout : void 0;
|
|
31154
|
+
const final = await this.options.journal.finish(binding2.executionId, image === void 0 ? journalOutput : { ...journalOutput, stdout: screenshotMetadata(image) }, resultCode);
|
|
31155
|
+
const outbound = await outboundResult(runnable.call, journalResult(final.result, resultCode), binding2, this.optionalTelemetry, this.options.efficiencyLedger);
|
|
31156
|
+
this.send({ type: "result", version: 1, binding: binding2, result: image === void 0 ? outbound : { ...outbound, stdout: image } });
|
|
30984
31157
|
}, abort.signal);
|
|
30985
31158
|
context.task = work.catch(async (error62) => {
|
|
30986
31159
|
if (!context.accepted) {
|
|
@@ -31203,9 +31376,9 @@ var NativeRelayBridge = class {
|
|
|
31203
31376
|
|
|
31204
31377
|
// agent/src/local-direct.ts
|
|
31205
31378
|
import net from "node:net";
|
|
31206
|
-
import
|
|
31379
|
+
import path20 from "node:path";
|
|
31207
31380
|
import { createHmac as createHmac2, hkdfSync, randomBytes as randomBytes6, randomUUID as randomUUID8, timingSafeEqual as timingSafeEqual3 } from "node:crypto";
|
|
31208
|
-
import { mkdir as mkdir7, readFile as
|
|
31381
|
+
import { mkdir as mkdir7, readFile as readFile8, rename as rename5, rm as rm7, writeFile as writeFile3 } from "node:fs/promises";
|
|
31209
31382
|
var LocalDirectError = class extends Error {
|
|
31210
31383
|
constructor(code) {
|
|
31211
31384
|
super(code);
|
|
@@ -31223,11 +31396,11 @@ var ADMISSION_MS = 6e4;
|
|
|
31223
31396
|
var MAX_IN_FLIGHT = 16;
|
|
31224
31397
|
var MAX_CONNECTIONS = 32;
|
|
31225
31398
|
function localDirectDirectory(appData) {
|
|
31226
|
-
return
|
|
31399
|
+
return path20.join(appData, "LocalCommander", "LocalMcp");
|
|
31227
31400
|
}
|
|
31228
31401
|
async function localDirectEnabled(directory) {
|
|
31229
31402
|
try {
|
|
31230
|
-
return JSON.parse(await
|
|
31403
|
+
return JSON.parse(await readFile8(path20.join(directory, "settings.json"), "utf8"))?.enabled === true;
|
|
31231
31404
|
} catch {
|
|
31232
31405
|
return false;
|
|
31233
31406
|
}
|
|
@@ -31300,7 +31473,7 @@ var Lines = class {
|
|
|
31300
31473
|
async function readEndpoint(directory) {
|
|
31301
31474
|
let value;
|
|
31302
31475
|
try {
|
|
31303
|
-
value = JSON.parse(await
|
|
31476
|
+
value = JSON.parse(await readFile8(path20.join(directory, "endpoint.json"), "utf8"));
|
|
31304
31477
|
} catch {
|
|
31305
31478
|
fail4("LOCAL_AGENT_NOT_RUNNING");
|
|
31306
31479
|
}
|
|
@@ -31317,9 +31490,9 @@ var LocalDirectServer = class _LocalDirectServer {
|
|
|
31317
31490
|
sockets = /* @__PURE__ */ new Set();
|
|
31318
31491
|
/** Listens only while the owner has enabled direct local access; null otherwise. */
|
|
31319
31492
|
static async start(options) {
|
|
31320
|
-
const endpointFile =
|
|
31493
|
+
const endpointFile = path20.join(options.directory, "endpoint.json");
|
|
31321
31494
|
if (!await localDirectEnabled(options.directory)) {
|
|
31322
|
-
await
|
|
31495
|
+
await rm7(endpointFile, { force: true }).catch(() => {
|
|
31323
31496
|
});
|
|
31324
31497
|
return null;
|
|
31325
31498
|
}
|
|
@@ -31345,7 +31518,7 @@ var LocalDirectServer = class _LocalDirectServer {
|
|
|
31345
31518
|
for (const socket of this.sockets) socket.destroy();
|
|
31346
31519
|
await new Promise((resolve) => this.server.close(() => resolve()));
|
|
31347
31520
|
try {
|
|
31348
|
-
if ((await readEndpoint(this.options.directory)).pid === process.pid) await
|
|
31521
|
+
if ((await readEndpoint(this.options.directory)).pid === process.pid) await rm7(path20.join(this.options.directory, "endpoint.json"), { force: true });
|
|
31349
31522
|
} catch {
|
|
31350
31523
|
}
|
|
31351
31524
|
}
|
|
@@ -35200,9 +35373,9 @@ var rev2026Codec = {
|
|
|
35200
35373
|
});
|
|
35201
35374
|
const parsed = buildSchemas2026().RequestMetaEnvelopeSchema.safeParse(meta3);
|
|
35202
35375
|
if (!parsed.success) for (const issue2 of parsed.error.issues) {
|
|
35203
|
-
const
|
|
35204
|
-
const key =
|
|
35205
|
-
if (
|
|
35376
|
+
const path30 = issue2.path.map(String);
|
|
35377
|
+
const key = path30.length > 0 ? path30.join(".") : "_meta";
|
|
35378
|
+
if (path30.length === 1 && issues.some((existing) => existing.key === key && existing.problem === "missing")) continue;
|
|
35206
35379
|
issues.push({
|
|
35207
35380
|
key,
|
|
35208
35381
|
problem: issue2.message
|
|
@@ -35504,29 +35677,29 @@ var PERMITTED_X_MCP_HEADER_TYPES = /* @__PURE__ */ new Set([
|
|
|
35504
35677
|
function scanXMcpHeaderDeclarations(inputSchema) {
|
|
35505
35678
|
const declarations = [];
|
|
35506
35679
|
const seenLower = /* @__PURE__ */ new Map();
|
|
35507
|
-
const visit2 = (node2,
|
|
35680
|
+
const visit2 = (node2, path30, reachable) => {
|
|
35508
35681
|
if (node2 === null || typeof node2 !== "object") return void 0;
|
|
35509
35682
|
const schema = node2;
|
|
35510
35683
|
if (X_MCP_HEADER_KEY in schema) {
|
|
35511
|
-
if (!reachable ||
|
|
35684
|
+
if (!reachable || path30.length === 0) return `${pathName(path30)}: x-mcp-header is only permitted on properties statically reachable via a chain of 'properties' keys (not under items, additionalProperties, oneOf/anyOf/allOf/not, if/then/else, or $ref)`;
|
|
35512
35685
|
const raw = schema[X_MCP_HEADER_KEY];
|
|
35513
|
-
if (typeof raw !== "string" || raw.length === 0) return `${pathName(
|
|
35514
|
-
if (!RFC9110_TOKEN.test(raw)) return `${pathName(
|
|
35686
|
+
if (typeof raw !== "string" || raw.length === 0) return `${pathName(path30)}: x-mcp-header MUST be a non-empty string`;
|
|
35687
|
+
if (!RFC9110_TOKEN.test(raw)) return `${pathName(path30)}: x-mcp-header '${raw}' is not a valid RFC 9110 token (no spaces, control characters or HTTP delimiters)`;
|
|
35515
35688
|
const type = typeof schema.type === "string" ? schema.type : void 0;
|
|
35516
|
-
if (type === void 0 || !PERMITTED_X_MCP_HEADER_TYPES.has(type)) return `${pathName(
|
|
35689
|
+
if (type === void 0 || !PERMITTED_X_MCP_HEADER_TYPES.has(type)) return `${pathName(path30)}: x-mcp-header is only permitted on primitive-typed properties (string, integer, boolean); got ${type ?? "<none>"}`;
|
|
35517
35690
|
const lower = raw.toLowerCase();
|
|
35518
35691
|
const prior = seenLower.get(lower);
|
|
35519
35692
|
if (prior !== void 0) return `x-mcp-header '${raw}' is not case-insensitively unique (also declared as '${prior}')`;
|
|
35520
35693
|
seenLower.set(lower, raw);
|
|
35521
35694
|
declarations.push({
|
|
35522
|
-
path:
|
|
35695
|
+
path: path30,
|
|
35523
35696
|
headerName: raw,
|
|
35524
35697
|
type
|
|
35525
35698
|
});
|
|
35526
35699
|
}
|
|
35527
35700
|
const properties = schema.properties;
|
|
35528
35701
|
if (properties !== null && typeof properties === "object") for (const [key, child] of Object.entries(properties)) {
|
|
35529
|
-
const fault$1 = visit2(child, [...
|
|
35702
|
+
const fault$1 = visit2(child, [...path30, key], reachable);
|
|
35530
35703
|
if (fault$1 !== void 0) return fault$1;
|
|
35531
35704
|
}
|
|
35532
35705
|
for (const k of NON_REACHABLE_SUBSCHEMA_KEYWORDS) {
|
|
@@ -35534,7 +35707,7 @@ function scanXMcpHeaderDeclarations(inputSchema) {
|
|
|
35534
35707
|
if (sub === void 0) continue;
|
|
35535
35708
|
const branches = Array.isArray(sub) ? sub : sub !== null && typeof sub === "object" && OBJECT_VALUED_SUBSCHEMA_KEYWORDS.has(k) ? Object.values(sub) : [sub];
|
|
35536
35709
|
for (const branch of branches) {
|
|
35537
|
-
const fault$1 = visit2(branch, [...
|
|
35710
|
+
const fault$1 = visit2(branch, [...path30, `<${k}>`], false);
|
|
35538
35711
|
if (fault$1 !== void 0) return fault$1;
|
|
35539
35712
|
}
|
|
35540
35713
|
}
|
|
@@ -35574,8 +35747,8 @@ var OBJECT_VALUED_SUBSCHEMA_KEYWORDS = /* @__PURE__ */ new Set([
|
|
|
35574
35747
|
"$defs",
|
|
35575
35748
|
"definitions"
|
|
35576
35749
|
]);
|
|
35577
|
-
function pathName(
|
|
35578
|
-
return
|
|
35750
|
+
function pathName(path30) {
|
|
35751
|
+
return path30.length === 0 ? "<root>" : path30.join(".");
|
|
35579
35752
|
}
|
|
35580
35753
|
var HEADER_MISMATCH_ERROR_CODE = -32020;
|
|
35581
35754
|
var INBOUND_VALIDATION_LADDER = [
|
|
@@ -35825,7 +35998,7 @@ var PROPERTY_KEYS_BY_TYPE = {
|
|
|
35825
35998
|
array: shapeKeys([UntitledMultiSelectEnumSchemaSchema, TitledMultiSelectEnumSchemaSchema])
|
|
35826
35999
|
};
|
|
35827
36000
|
var SUPPORTED_STRING_FORMATS = new Set(StringSchemaSchema.shape.format.unwrap().options);
|
|
35828
|
-
function walkProperty(node2,
|
|
36001
|
+
function walkProperty(node2, path30, vendor, unsupported) {
|
|
35829
36002
|
if (!isJsonObject(node2)) return node2;
|
|
35830
36003
|
const allowedKeys = typeof node2.type === "string" && Object.hasOwn(PROPERTY_KEYS_BY_TYPE, node2.type) ? PROPERTY_KEYS_BY_TYPE[node2.type] : void 0;
|
|
35831
36004
|
if (allowedKeys === void 0) return node2;
|
|
@@ -35833,8 +36006,8 @@ function walkProperty(node2, path29, vendor, unsupported) {
|
|
|
35833
36006
|
for (const [key, value] of Object.entries(node2)) if (allowedKeys.has(key) || isAnnotationOnlyJsonSchemaKeyword(key)) pruned[key] = value;
|
|
35834
36007
|
else if (key === "pattern" && node2.type === "string" && typeof node2.format === "string") {
|
|
35835
36008
|
if (!SUPPORTED_STRING_FORMATS.has(node2.format)) pruned[key] = value;
|
|
35836
|
-
else if (typeof value !== "string" || !isLibraryFormatPattern(node2.format, value, vendor)) unsupported.push(`${
|
|
35837
|
-
} else unsupported.push(`${
|
|
36009
|
+
else if (typeof value !== "string" || !isLibraryFormatPattern(node2.format, value, vendor)) unsupported.push(`${path30}.${key}`);
|
|
36010
|
+
} else unsupported.push(`${path30}.${key}`);
|
|
35838
36011
|
return pruned;
|
|
35839
36012
|
}
|
|
35840
36013
|
function walkRequestedSchema(converted, vendor) {
|
|
@@ -35851,11 +36024,11 @@ function describeUnsupportedProperties(pruned, fallback) {
|
|
|
35851
36024
|
const offenders = Object.entries(pruned.properties).filter(([, node2]) => !parseSchema(PrimitiveSchemaDefinitionSchema, node2).success).map(([name2]) => `properties.${name2}`);
|
|
35852
36025
|
return offenders.length > 0 ? offenders.join(", ") : fallback;
|
|
35853
36026
|
}
|
|
35854
|
-
function findDroppedConstraintPaths(original, parsed,
|
|
35855
|
-
if (Array.isArray(original) && Array.isArray(parsed)) return original.flatMap((item, index) => findDroppedConstraintPaths(item, parsed[index], `${
|
|
36027
|
+
function findDroppedConstraintPaths(original, parsed, path30 = "") {
|
|
36028
|
+
if (Array.isArray(original) && Array.isArray(parsed)) return original.flatMap((item, index) => findDroppedConstraintPaths(item, parsed[index], `${path30}[${index}]`));
|
|
35856
36029
|
if (!isJsonObject(original) || !isJsonObject(parsed)) return [];
|
|
35857
36030
|
return Object.entries(original).flatMap(([key, value]) => {
|
|
35858
|
-
const childPath =
|
|
36031
|
+
const childPath = path30 ? `${path30}.${key}` : key;
|
|
35859
36032
|
if (!Object.prototype.hasOwnProperty.call(parsed, key)) return isAnnotationOnlyJsonSchemaKeyword(key) ? [] : [childPath];
|
|
35860
36033
|
return findDroppedConstraintPaths(value, parsed[key], childPath);
|
|
35861
36034
|
});
|
|
@@ -39931,8 +40104,8 @@ var require_utils = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
39931
40104
|
for (let i = 0; i < str.length; i++) if (str[i] === token) ind++;
|
|
39932
40105
|
return ind;
|
|
39933
40106
|
}
|
|
39934
|
-
function removeDotSegments(
|
|
39935
|
-
let input2 =
|
|
40107
|
+
function removeDotSegments(path30) {
|
|
40108
|
+
let input2 = path30;
|
|
39936
40109
|
const output2 = [];
|
|
39937
40110
|
let nextSlash = -1;
|
|
39938
40111
|
let len = 0;
|
|
@@ -40085,8 +40258,8 @@ var require_schemes = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
40085
40258
|
wsComponent.secure = void 0;
|
|
40086
40259
|
}
|
|
40087
40260
|
if (wsComponent.resourceName) {
|
|
40088
|
-
const [
|
|
40089
|
-
wsComponent.path =
|
|
40261
|
+
const [path30, query] = wsComponent.resourceName.split("?");
|
|
40262
|
+
wsComponent.path = path30 && path30 !== "/" ? path30 : void 0;
|
|
40090
40263
|
wsComponent.query = query;
|
|
40091
40264
|
wsComponent.resourceName = void 0;
|
|
40092
40265
|
}
|
|
@@ -45653,7 +45826,8 @@ var DESCRIPTIONS = {
|
|
|
45653
45826
|
git_diff: ["Git diff of the repository at a workspace-relative path.", { readOnlyHint: true, openWorldHint: false }],
|
|
45654
45827
|
git_log: ["Recent Git commits of the repository at a workspace-relative path.", { readOnlyHint: true, openWorldHint: false }],
|
|
45655
45828
|
project_snapshot: ["Compact project overview: Git state and, with startup, AGENTS.md policy and task continuation.", { readOnlyHint: true, openWorldHint: false }],
|
|
45656
|
-
command_run: ["Run one executable with an argument array (no shell parsing), hidden, with captured output. Uses this
|
|
45829
|
+
command_run: ["Run one executable with an argument array (no shell parsing), hidden, with captured output. Uses this user account's rights within the owner's grant.", { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true }],
|
|
45830
|
+
take_screenshot: ["Take a still image of this computer's primary screen, returned as a JPEG image. Needs a Full Access workspace; the lock screen is never captured.", { readOnlyHint: true, openWorldHint: false }],
|
|
45657
45831
|
localhost_request: ["HTTP request to a service on this computer (localhost only).", { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false }]
|
|
45658
45832
|
};
|
|
45659
45833
|
var workspace = external_exports.string().min(1).max(4096).optional().describe("Workspace grant id, root path (for example D:\\) or display name from workspace_list. Optional when only one workspace is approved.");
|
|
@@ -45666,6 +45840,14 @@ function failure4(error62) {
|
|
|
45666
45840
|
return text2(code + hint, true);
|
|
45667
45841
|
}
|
|
45668
45842
|
function render(name2, result2) {
|
|
45843
|
+
if (name2 === "take_screenshot" && result2.resultCode === "SUCCESS") {
|
|
45844
|
+
try {
|
|
45845
|
+
const { data, mimeType, ...metadata } = JSON.parse(result2.stdout);
|
|
45846
|
+
if (typeof data === "string" && data && mimeType === "image/jpeg") return { content: [{ type: "image", data, mimeType }, { type: "text", text: JSON.stringify(metadata) }] };
|
|
45847
|
+
} catch {
|
|
45848
|
+
}
|
|
45849
|
+
return text2(JSON.stringify({ resultCode: "SCREEN_UNAVAILABLE" }), true);
|
|
45850
|
+
}
|
|
45669
45851
|
if (name2 !== "command_run" && result2.resultCode === "SUCCESS") return text2(result2.stdout);
|
|
45670
45852
|
const { exitCode, resultCode, timedOut, cancelled, stdout, stderr, stdoutTruncated, stderrTruncated } = result2;
|
|
45671
45853
|
return text2(
|
|
@@ -45686,7 +45868,7 @@ async function serveLocalMcp(options) {
|
|
|
45686
45868
|
return connecting;
|
|
45687
45869
|
};
|
|
45688
45870
|
const server = new McpServer({ name: "local-commander-local", version: options.agentVersion }, {
|
|
45689
|
-
instructions: "Local Commander direct access to this computer, through the owner's approved workspaces. Paths are relative to the selected workspace root; call workspace_list to see roots. Commands run hidden with this
|
|
45871
|
+
instructions: "Local Commander direct access to this computer, through the owner's approved workspaces. Paths are relative to the selected workspace root; call workspace_list to see roots. Commands run hidden with this user account's rights; owner denials still apply."
|
|
45690
45872
|
});
|
|
45691
45873
|
server.registerTool(
|
|
45692
45874
|
"workspace_list",
|
|
@@ -45701,7 +45883,7 @@ async function serveLocalMcp(options) {
|
|
|
45701
45883
|
);
|
|
45702
45884
|
for (const option of ToolCallSchema.options) {
|
|
45703
45885
|
const name2 = option.shape.name.value, entry = DESCRIPTIONS[name2];
|
|
45704
|
-
if (!entry) continue;
|
|
45886
|
+
if (!entry || name2 === "take_screenshot" && !screenshotEnabled()) continue;
|
|
45705
45887
|
const inputSchema = option.shape.args.extend({ workspace });
|
|
45706
45888
|
const callback = async (input2, ctx) => {
|
|
45707
45889
|
const { workspace: selected, ...args } = input2;
|
|
@@ -46440,10 +46622,10 @@ async function connectOnce(options) {
|
|
|
46440
46622
|
// agent/src/machine-identity.ts
|
|
46441
46623
|
import { spawn as spawn5 } from "node:child_process";
|
|
46442
46624
|
import { createHash as createHash16 } from "node:crypto";
|
|
46443
|
-
import
|
|
46625
|
+
import os6 from "node:os";
|
|
46444
46626
|
import { open as open7 } from "node:fs/promises";
|
|
46445
46627
|
import { constants as constants8 } from "node:fs";
|
|
46446
|
-
import
|
|
46628
|
+
import path21 from "node:path";
|
|
46447
46629
|
var MACHINE_GUID = /^\s*MachineGuid\s+REG_SZ\s+([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})\s*$/m;
|
|
46448
46630
|
async function readMachineGuid(timeoutMs2 = 5e3) {
|
|
46449
46631
|
if (process.platform === "linux") {
|
|
@@ -46464,7 +46646,7 @@ async function readMachineGuid(timeoutMs2 = 5e3) {
|
|
|
46464
46646
|
}
|
|
46465
46647
|
}
|
|
46466
46648
|
if (!["win32", "darwin"].includes(process.platform)) return null;
|
|
46467
|
-
const reg = process.platform === "darwin" ? "/usr/sbin/ioreg" :
|
|
46649
|
+
const reg = process.platform === "darwin" ? "/usr/sbin/ioreg" : path21.join(process.env.SystemRoot || "C:\\Windows", "System32", "reg.exe");
|
|
46468
46650
|
const args = process.platform === "darwin" ? ["-rd1", "-c", "IOPlatformExpertDevice"] : ["query", "HKLM\\SOFTWARE\\Microsoft\\Cryptography", "/v", "MachineGuid", "/reg:64"];
|
|
46469
46651
|
const pattern = process.platform === "darwin" ? /"IOPlatformUUID"\s*=\s*"([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})"/ : MACHINE_GUID;
|
|
46470
46652
|
return new Promise((resolve) => {
|
|
@@ -46536,9 +46718,9 @@ async function readComputerName(timeoutMs2 = 5e3) {
|
|
|
46536
46718
|
});
|
|
46537
46719
|
if (valid(name2)) return name2;
|
|
46538
46720
|
}
|
|
46539
|
-
return
|
|
46721
|
+
return os6.hostname();
|
|
46540
46722
|
}
|
|
46541
|
-
function machineProof(deviceId, machineGuid, computerName =
|
|
46723
|
+
function machineProof(deviceId, machineGuid, computerName = os6.hostname()) {
|
|
46542
46724
|
const name2 = computerName.slice(0, 120);
|
|
46543
46725
|
if (!name2 || name2.trim() !== name2 || /[\u0000-\u001f\u007f]/.test(name2)) return null;
|
|
46544
46726
|
const fingerprint3 = createHash16("sha256").update("lcmcp-machine-v1\0" + deviceId.toLowerCase() + "\0" + machineGuid.toLowerCase() + "\0" + name2.toUpperCase(), "utf8").digest("hex");
|
|
@@ -46579,8 +46761,8 @@ function canonicalOrigin2(value) {
|
|
|
46579
46761
|
fail6("ORIGIN_INVALID");
|
|
46580
46762
|
}
|
|
46581
46763
|
}
|
|
46582
|
-
function endpoint(origin,
|
|
46583
|
-
return origin +
|
|
46764
|
+
function endpoint(origin, path30) {
|
|
46765
|
+
return origin + path30;
|
|
46584
46766
|
}
|
|
46585
46767
|
function uuid21(value, code) {
|
|
46586
46768
|
if (typeof value !== "string" || !UUID3.test(value)) fail6(code);
|
|
@@ -47082,15 +47264,15 @@ async function deliverGuardEvidence(target, packet, options = {}) {
|
|
|
47082
47264
|
|
|
47083
47265
|
// agent/src/optimization-ledger.ts
|
|
47084
47266
|
import { constants as constants9 } from "node:fs";
|
|
47085
|
-
import { lstat as lstat8, mkdir as mkdir8, open as open8, readFile as
|
|
47086
|
-
import
|
|
47267
|
+
import { lstat as lstat8, mkdir as mkdir8, open as open8, readFile as readFile9, realpath as realpath8 } from "node:fs/promises";
|
|
47268
|
+
import path22 from "node:path";
|
|
47087
47269
|
var MAX_LEDGER_BYTES = 64 * 1024 * 1024;
|
|
47088
47270
|
var MAX_NOTICE_LEDGER_BYTES = 8 * 1024 * 1024;
|
|
47089
47271
|
function failure5(code) {
|
|
47090
47272
|
return Object.assign(new Error(code), { code });
|
|
47091
47273
|
}
|
|
47092
47274
|
async function safeDirectory2(directory) {
|
|
47093
|
-
const absolute2 =
|
|
47275
|
+
const absolute2 = path22.resolve(directory);
|
|
47094
47276
|
let current2 = absolute2;
|
|
47095
47277
|
for (; ; ) {
|
|
47096
47278
|
try {
|
|
@@ -47098,7 +47280,7 @@ async function safeDirectory2(directory) {
|
|
|
47098
47280
|
} catch (error62) {
|
|
47099
47281
|
if (error62.code !== "ENOENT") throw error62;
|
|
47100
47282
|
}
|
|
47101
|
-
const parent =
|
|
47283
|
+
const parent = path22.dirname(current2);
|
|
47102
47284
|
if (parent === current2) break;
|
|
47103
47285
|
current2 = parent;
|
|
47104
47286
|
}
|
|
@@ -47133,15 +47315,15 @@ var OptimizationLedger = class _OptimizationLedger {
|
|
|
47133
47315
|
closed = false;
|
|
47134
47316
|
static async open(directory) {
|
|
47135
47317
|
const dir = await safeDirectory2(directory);
|
|
47136
|
-
const filename =
|
|
47137
|
-
const noticesFilename =
|
|
47318
|
+
const filename = path22.join(dir, "live-efficiency.v1.jsonl");
|
|
47319
|
+
const noticesFilename = path22.join(dir, "live-efficiency-notices.v1.jsonl");
|
|
47138
47320
|
let existing = "";
|
|
47139
47321
|
try {
|
|
47140
47322
|
const stat2 = await lstat8(filename);
|
|
47141
47323
|
if (!stat2.isFile() || stat2.isSymbolicLink() || stat2.size > MAX_LEDGER_BYTES) {
|
|
47142
47324
|
throw failure5("OPTIMIZATION_LEDGER_INVALID");
|
|
47143
47325
|
}
|
|
47144
|
-
existing = await
|
|
47326
|
+
existing = await readFile9(filename, "utf8");
|
|
47145
47327
|
} catch (error62) {
|
|
47146
47328
|
if (error62.code !== "ENOENT") throw error62;
|
|
47147
47329
|
}
|
|
@@ -47155,7 +47337,7 @@ var OptimizationLedger = class _OptimizationLedger {
|
|
|
47155
47337
|
try {
|
|
47156
47338
|
const noticeStat = await lstat8(noticesFilename);
|
|
47157
47339
|
if (!noticeStat.isFile() || noticeStat.isSymbolicLink() || noticeStat.size > MAX_NOTICE_LEDGER_BYTES) throw failure5("OPTIMIZATION_NOTICE_LEDGER_INVALID");
|
|
47158
|
-
const notices = await
|
|
47340
|
+
const notices = await readFile9(noticesFilename, "utf8");
|
|
47159
47341
|
for (const line of notices.split("\n")) {
|
|
47160
47342
|
if (!line) continue;
|
|
47161
47343
|
const parsed = JSON.parse(line);
|
|
@@ -47283,9 +47465,9 @@ var OptimizationLedger = class _OptimizationLedger {
|
|
|
47283
47465
|
|
|
47284
47466
|
// agent/src/monitor.ts
|
|
47285
47467
|
import { createHash as createHash17, randomUUID as randomUUID12 } from "node:crypto";
|
|
47286
|
-
import { lstat as lstat9, mkdir as mkdir9, open as open9, rename as rename6, rm as
|
|
47287
|
-
import
|
|
47288
|
-
import
|
|
47468
|
+
import { lstat as lstat9, mkdir as mkdir9, open as open9, rename as rename6, rm as rm8 } from "node:fs/promises";
|
|
47469
|
+
import path23 from "node:path";
|
|
47470
|
+
import os7 from "node:os";
|
|
47289
47471
|
|
|
47290
47472
|
// packages/agent-cli/bin/monitor-savings.mjs
|
|
47291
47473
|
var count = (value) => Number.isSafeInteger(value) && value >= 0 && value <= 1e15;
|
|
@@ -47307,7 +47489,7 @@ function lifetimeSavingsView(raw) {
|
|
|
47307
47489
|
// agent/src/monitor.ts
|
|
47308
47490
|
function commandSummary2(tool) {
|
|
47309
47491
|
if (tool.name !== "command_run") return { name: tool.name, command: tool.name };
|
|
47310
|
-
const candidate =
|
|
47492
|
+
const candidate = path23.win32.basename(tool.args.command).replace(/\.(exe|cmd|bat|com)$/i, "").toLowerCase();
|
|
47311
47493
|
const name2 = ["node", "npm", "npx", "git", "rg", "powershell", "pwsh", "cmd", "tsc", "python", "dotnet"].includes(candidate) ? candidate : "command";
|
|
47312
47494
|
let command = name2;
|
|
47313
47495
|
if (name2 === "node" && tool.args.args.includes("--test") && !tool.args.args.some((arg) => ["-e", "--eval", "-p", "--print"].includes(arg))) command += " --test";
|
|
@@ -47320,9 +47502,9 @@ function commandSummary2(tool) {
|
|
|
47320
47502
|
var ProductionMonitor = class {
|
|
47321
47503
|
constructor(directory, stateDirectory, agentVersion3) {
|
|
47322
47504
|
this.agentVersion = agentVersion3;
|
|
47323
|
-
const key = createHash17("sha256").update(
|
|
47324
|
-
this.file =
|
|
47325
|
-
this.transportFile =
|
|
47505
|
+
const key = createHash17("sha256").update(path23.resolve(stateDirectory).toLowerCase()).digest("hex");
|
|
47506
|
+
this.file = path23.join(directory, key + ".json");
|
|
47507
|
+
this.transportFile = path23.join(directory, key + ".transport");
|
|
47326
47508
|
}
|
|
47327
47509
|
agentVersion;
|
|
47328
47510
|
instanceId = randomUUID12();
|
|
@@ -47333,7 +47515,7 @@ var ProductionMonitor = class {
|
|
|
47333
47515
|
measured = /* @__PURE__ */ new Set();
|
|
47334
47516
|
polls = { status: 0, output: 0 };
|
|
47335
47517
|
efficiencyCalls = 0;
|
|
47336
|
-
computer =
|
|
47518
|
+
computer = os7.hostname().replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 64) || "PC";
|
|
47337
47519
|
sequence = 0;
|
|
47338
47520
|
connection = {
|
|
47339
47521
|
state: "starting",
|
|
@@ -47514,7 +47696,7 @@ var ProductionMonitor = class {
|
|
|
47514
47696
|
schemaVersion: 1,
|
|
47515
47697
|
instanceId: this.instanceId,
|
|
47516
47698
|
pid: process.pid,
|
|
47517
|
-
savingsSourceId:
|
|
47699
|
+
savingsSourceId: path23.basename(this.file, ".json"),
|
|
47518
47700
|
lifetimeSavings: this.lifetimeSavings && { ...this.lifetimeSavings },
|
|
47519
47701
|
computer: this.computer,
|
|
47520
47702
|
processName: "lc-agent",
|
|
@@ -47548,7 +47730,7 @@ var ProductionMonitor = class {
|
|
|
47548
47730
|
return this.writing;
|
|
47549
47731
|
}
|
|
47550
47732
|
async write(file2, contents) {
|
|
47551
|
-
const directory =
|
|
47733
|
+
const directory = path23.dirname(file2);
|
|
47552
47734
|
await mkdir9(directory, { recursive: true, mode: 448 });
|
|
47553
47735
|
const stat2 = await lstat9(directory);
|
|
47554
47736
|
if (!stat2.isDirectory() || stat2.isSymbolicLink()) throw Error("MONITOR_DIRECTORY_INVALID");
|
|
@@ -47562,7 +47744,7 @@ var ProductionMonitor = class {
|
|
|
47562
47744
|
}
|
|
47563
47745
|
await rename6(temporary, file2);
|
|
47564
47746
|
} finally {
|
|
47565
|
-
await
|
|
47747
|
+
await rm8(temporary, { force: true });
|
|
47566
47748
|
}
|
|
47567
47749
|
}
|
|
47568
47750
|
async close() {
|
|
@@ -47973,13 +48155,13 @@ var NativeFabricObserver = class {
|
|
|
47973
48155
|
};
|
|
47974
48156
|
|
|
47975
48157
|
// agent/src/native-fabric-startup.ts
|
|
47976
|
-
import { lstat as lstat11, mkdir as mkdir12, open as open11, readFile as
|
|
47977
|
-
import
|
|
48158
|
+
import { lstat as lstat11, mkdir as mkdir12, open as open11, readFile as readFile10 } from "node:fs/promises";
|
|
48159
|
+
import path26 from "node:path";
|
|
47978
48160
|
|
|
47979
48161
|
// src/agent-fabric-service.ts
|
|
47980
48162
|
import { lstat as lstat10, mkdir as mkdir11, realpath as realpath9 } from "node:fs/promises";
|
|
47981
48163
|
import { watch } from "node:fs";
|
|
47982
|
-
import
|
|
48164
|
+
import path25 from "node:path";
|
|
47983
48165
|
|
|
47984
48166
|
// src/agent-runtime-identity.ts
|
|
47985
48167
|
import { createHash as createHash19, randomBytes as randomBytes7, randomUUID as randomUUID14, timingSafeEqual as timingSafeEqual4 } from "node:crypto";
|
|
@@ -47987,13 +48169,13 @@ import { createHash as createHash19, randomBytes as randomBytes7, randomUUID as
|
|
|
47987
48169
|
// src/agent-fabric-state.ts
|
|
47988
48170
|
import { randomUUID as randomUUID13 } from "node:crypto";
|
|
47989
48171
|
import { mkdir as mkdir10, open as open10, rename as rename7, unlink as unlink2 } from "node:fs/promises";
|
|
47990
|
-
import
|
|
48172
|
+
import path24 from "node:path";
|
|
47991
48173
|
var queues = /* @__PURE__ */ new Map();
|
|
47992
48174
|
var FabricStateFile = class {
|
|
47993
48175
|
constructor(file2, maxBytes, parse3) {
|
|
47994
48176
|
this.maxBytes = maxBytes;
|
|
47995
48177
|
this.parse = parse3;
|
|
47996
|
-
this.file =
|
|
48178
|
+
this.file = path24.resolve(file2);
|
|
47997
48179
|
}
|
|
47998
48180
|
maxBytes;
|
|
47999
48181
|
parse;
|
|
@@ -48037,7 +48219,7 @@ var FabricStateFile = class {
|
|
|
48037
48219
|
}
|
|
48038
48220
|
update(fn, create) {
|
|
48039
48221
|
return this.serial(async () => {
|
|
48040
|
-
if (create) await mkdir10(
|
|
48222
|
+
if (create) await mkdir10(path24.dirname(this.file), { recursive: true });
|
|
48041
48223
|
const lockPath = this.file + ".lock";
|
|
48042
48224
|
const token = randomUUID13();
|
|
48043
48225
|
const lock = await open10(lockPath, "wx", 384).catch((error62) => {
|
|
@@ -48681,9 +48863,9 @@ var WorkerRequest = external_exports.discriminatedUnion("operation", [
|
|
|
48681
48863
|
var AgentFabricService = class _AgentFabricService {
|
|
48682
48864
|
constructor(directory, controllerId) {
|
|
48683
48865
|
this.directory = directory;
|
|
48684
|
-
this.identities = new AgentRuntimeIdentityStore(
|
|
48866
|
+
this.identities = new AgentRuntimeIdentityStore(path25.join(directory, "identities.json"));
|
|
48685
48867
|
this.mailbox = new AgentWorkerMailbox(
|
|
48686
|
-
|
|
48868
|
+
path25.join(directory, "mailbox.json"),
|
|
48687
48869
|
controllerId,
|
|
48688
48870
|
this.identities,
|
|
48689
48871
|
void 0,
|
|
@@ -48698,21 +48880,21 @@ var AgentFabricService = class _AgentFabricService {
|
|
|
48698
48880
|
closed = false;
|
|
48699
48881
|
static async open(directory, controllerId, device = null, initialize = true) {
|
|
48700
48882
|
const expected = Binding.parse({ version: 1, controllerId, device, initialized: false });
|
|
48701
|
-
const absolute2 =
|
|
48702
|
-
for (let current2 = absolute2; ; current2 =
|
|
48883
|
+
const absolute2 = path25.resolve(directory);
|
|
48884
|
+
for (let current2 = absolute2; ; current2 = path25.dirname(current2)) {
|
|
48703
48885
|
try {
|
|
48704
48886
|
if ((await lstat10(current2)).isSymbolicLink()) throw Error("FABRIC_DIRECTORY_INVALID");
|
|
48705
48887
|
} catch (error62) {
|
|
48706
48888
|
if (error62.code !== "ENOENT") throw error62;
|
|
48707
48889
|
}
|
|
48708
|
-
if (
|
|
48890
|
+
if (path25.dirname(current2) === current2) break;
|
|
48709
48891
|
}
|
|
48710
48892
|
if (initialize) await mkdir11(absolute2, { recursive: true, mode: 448 });
|
|
48711
48893
|
if (!(await lstat10(absolute2)).isDirectory() || (await realpath9(absolute2)).toLowerCase() !== absolute2.toLowerCase())
|
|
48712
48894
|
throw Error("FABRIC_DIRECTORY_INVALID");
|
|
48713
48895
|
const present = /* @__PURE__ */ new Set();
|
|
48714
48896
|
for (const name2 of ["binding.json", "mailbox.json", "identities.json"]) {
|
|
48715
|
-
const file2 = await lstat10(
|
|
48897
|
+
const file2 = await lstat10(path25.join(absolute2, name2)).catch((error62) => {
|
|
48716
48898
|
if (error62.code === "ENOENT") return null;
|
|
48717
48899
|
throw error62;
|
|
48718
48900
|
});
|
|
@@ -48720,7 +48902,7 @@ var AgentFabricService = class _AgentFabricService {
|
|
|
48720
48902
|
if (file2) present.add(name2);
|
|
48721
48903
|
}
|
|
48722
48904
|
if (!present.has("binding.json") && present.size) throw Error("FABRIC_BINDING_MISSING");
|
|
48723
|
-
const binding2 = new FabricStateFile(
|
|
48905
|
+
const binding2 = new FabricStateFile(path25.join(absolute2, "binding.json"), 2048, (value) => Binding.parse(value));
|
|
48724
48906
|
const service2 = new _AgentFabricService(absolute2, controllerId);
|
|
48725
48907
|
await binding2.update(async (state) => {
|
|
48726
48908
|
if (state.controllerId !== expected.controllerId || JSON.stringify(state.device) !== JSON.stringify(expected.device))
|
|
@@ -48735,7 +48917,7 @@ var AgentFabricService = class _AgentFabricService {
|
|
|
48735
48917
|
state.initialized = true;
|
|
48736
48918
|
}
|
|
48737
48919
|
const snapshot2 = await service2.mailbox.snapshot();
|
|
48738
|
-
if (snapshot2.workers.some((worker) => worker.runtimeId !== null)) await lstat10(
|
|
48920
|
+
if (snapshot2.workers.some((worker) => worker.runtimeId !== null)) await lstat10(path25.join(absolute2, "identities.json"));
|
|
48739
48921
|
}, initialize ? () => expected : void 0);
|
|
48740
48922
|
return service2;
|
|
48741
48923
|
}
|
|
@@ -48822,7 +49004,7 @@ var Delivery = external_exports.strictObject({ capability: external_exports.stri
|
|
|
48822
49004
|
async function openNativeFabric(stateDirectory, enrollment, box, initialize = true) {
|
|
48823
49005
|
const controllerId = "device-" + external_exports.string().uuid().parse(enrollment.deviceId).toLowerCase();
|
|
48824
49006
|
const tenantId = external_exports.string().uuid().parse(enrollment.tenantId).toLowerCase();
|
|
48825
|
-
const parent =
|
|
49007
|
+
const parent = path26.join(stateDirectory, ".local-commander"), marker = path26.join(parent, "fabric-established.json");
|
|
48826
49008
|
try {
|
|
48827
49009
|
await mkdir12(parent, { mode: 448 });
|
|
48828
49010
|
} catch (error62) {
|
|
@@ -48834,7 +49016,7 @@ async function openNativeFabric(stateDirectory, enrollment, box, initialize = tr
|
|
|
48834
49016
|
let fresh = false;
|
|
48835
49017
|
try {
|
|
48836
49018
|
const info = await lstat11(marker);
|
|
48837
|
-
if (!info.isFile() || info.isSymbolicLink() || info.size > 2048 || await
|
|
49019
|
+
if (!info.isFile() || info.isSymbolicLink() || info.size > 2048 || await readFile10(marker, "utf8") !== expected)
|
|
48838
49020
|
throw Error("FABRIC_BINDING_CHANGED");
|
|
48839
49021
|
} catch (error62) {
|
|
48840
49022
|
if (error62.code !== "ENOENT" || !initialize) throw error62;
|
|
@@ -48848,13 +49030,13 @@ async function openNativeFabric(stateDirectory, enrollment, box, initialize = tr
|
|
|
48848
49030
|
fresh = true;
|
|
48849
49031
|
}
|
|
48850
49032
|
const service2 = await AgentFabricService.open(
|
|
48851
|
-
|
|
49033
|
+
path26.join(stateDirectory, ".local-commander", "fabric"),
|
|
48852
49034
|
controllerId,
|
|
48853
49035
|
{ deviceId: enrollment.deviceId.toLowerCase(), enrollmentEvidenceRef: "enrollment-" + tenantId },
|
|
48854
49036
|
fresh
|
|
48855
49037
|
);
|
|
48856
49038
|
const purpose = "native-fabric:" + tenantId + ":" + controllerId;
|
|
48857
|
-
const credentialFile = (workerId) =>
|
|
49039
|
+
const credentialFile = (workerId) => path26.join(service2.directory, external_exports.string().uuid().parse(workerId) + ".capability");
|
|
48858
49040
|
const decode4 = (value) => {
|
|
48859
49041
|
const credential = Credential.parse(JSON.parse(box.open(Buffer.from(value, "base64"), purpose).toString("utf8")));
|
|
48860
49042
|
if (credential.controllerId !== controllerId) throw Error("FABRIC_WORKER_DENIED");
|
|
@@ -48863,7 +49045,7 @@ async function openNativeFabric(stateDirectory, enrollment, box, initialize = tr
|
|
|
48863
49045
|
async function capability(workerId) {
|
|
48864
49046
|
const file2 = credentialFile(workerId), info = await lstat11(file2);
|
|
48865
49047
|
if (!info.isFile() || info.isSymbolicLink() || info.size > 4096) throw Error("FABRIC_CREDENTIAL_UNKNOWN");
|
|
48866
|
-
const encoded = await
|
|
49048
|
+
const encoded = await readFile10(file2, "utf8");
|
|
48867
49049
|
if (decode4(encoded).workerId !== workerId) throw Error("FABRIC_WORKER_DENIED");
|
|
48868
49050
|
return encoded;
|
|
48869
49051
|
}
|
|
@@ -48955,7 +49137,7 @@ async function readFabricRequest(input2 = process.stdin) {
|
|
|
48955
49137
|
|
|
48956
49138
|
// agent/src/supervisor-liveness.ts
|
|
48957
49139
|
import { spawn as spawn6 } from "node:child_process";
|
|
48958
|
-
import
|
|
49140
|
+
import path27 from "node:path";
|
|
48959
49141
|
import { setTimeout as delay3 } from "node:timers/promises";
|
|
48960
49142
|
var ROW = /^"([^"]+)","(\d{1,10})"/;
|
|
48961
49143
|
function parseTasklist(output2, image) {
|
|
@@ -48970,7 +49152,7 @@ function parseTasklist(output2, image) {
|
|
|
48970
49152
|
}
|
|
48971
49153
|
function listProcesses(image, timeoutMs2 = 5e3) {
|
|
48972
49154
|
if (process.platform !== "win32" || !/^[A-Za-z0-9._-]{1,64}\.exe$/i.test(image)) return Promise.resolve(null);
|
|
48973
|
-
const tasklist =
|
|
49155
|
+
const tasklist = path27.join(process.env.SystemRoot || "C:\\Windows", "System32", "tasklist.exe");
|
|
48974
49156
|
return new Promise((resolve) => {
|
|
48975
49157
|
let output2 = "", settled = false;
|
|
48976
49158
|
const finish = (value) => {
|
|
@@ -48999,8 +49181,8 @@ function listProcesses(image, timeoutMs2 = 5e3) {
|
|
|
48999
49181
|
}
|
|
49000
49182
|
function supervisorLiveness(helperPath, options = {}) {
|
|
49001
49183
|
if (process.platform === "linux" && !options.list) return linuxSupervisorLiveness;
|
|
49002
|
-
if (process.platform === "darwin" && !options.list) return (pids, _linux, darwin) => darwinSupervisorLiveness(
|
|
49003
|
-
const image =
|
|
49184
|
+
if (process.platform === "darwin" && !options.list) return (pids, _linux, darwin) => darwinSupervisorLiveness(path27.join(path27.dirname(helperPath), "posix-host"), pids, darwin);
|
|
49185
|
+
const image = path27.basename(helperPath), waitMs = options.waitMs ?? 1e4, pollMs = options.pollMs ?? 500, list = options.list ?? listProcesses;
|
|
49004
49186
|
return async (pids) => {
|
|
49005
49187
|
const deadline = Date.now() + waitMs;
|
|
49006
49188
|
for (; ; ) {
|
|
@@ -49015,8 +49197,8 @@ function supervisorLiveness(helperPath, options = {}) {
|
|
|
49015
49197
|
|
|
49016
49198
|
// agent/src/content-audit.ts
|
|
49017
49199
|
import { createReadStream } from "node:fs";
|
|
49018
|
-
import { appendFile, lstat as lstat12, mkdir as mkdir13, open as open12, readdir as readdir5, readFile as
|
|
49019
|
-
import
|
|
49200
|
+
import { appendFile, lstat as lstat12, mkdir as mkdir13, open as open12, readdir as readdir5, readFile as readFile11, rename as rename8, rm as rm9, writeFile as writeFile4 } from "node:fs/promises";
|
|
49201
|
+
import path28 from "node:path";
|
|
49020
49202
|
import { performance as performance3 } from "node:perf_hooks";
|
|
49021
49203
|
import { createInterface as createInterface2 } from "node:readline";
|
|
49022
49204
|
import { randomBytes as randomBytes9 } from "node:crypto";
|
|
@@ -49185,7 +49367,7 @@ var FILE = /^(full|metrics)-(\d{4}-\d{2}-\d{2})\.jsonl$/;
|
|
|
49185
49367
|
var PAUSED_FILE = "paused.json";
|
|
49186
49368
|
var DAY_MS = 864e5;
|
|
49187
49369
|
function contentAuditDirectory(stateDir) {
|
|
49188
|
-
return
|
|
49370
|
+
return path28.join(path28.dirname(path28.resolve(stateDir)), "Audit");
|
|
49189
49371
|
}
|
|
49190
49372
|
async function plainDirectory(dir) {
|
|
49191
49373
|
await mkdir13(dir, { recursive: true, mode: 448 });
|
|
@@ -49204,7 +49386,7 @@ async function auditFiles(dir) {
|
|
|
49204
49386
|
for (const name2 of names) {
|
|
49205
49387
|
const match = FILE.exec(name2);
|
|
49206
49388
|
if (!match) continue;
|
|
49207
|
-
const info = await lstat12(
|
|
49389
|
+
const info = await lstat12(path28.join(dir, name2));
|
|
49208
49390
|
if (info.isFile()) files.push({ name: name2, kind: match[1], day: match[2], bytes: info.size });
|
|
49209
49391
|
}
|
|
49210
49392
|
return files.sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -49215,7 +49397,7 @@ async function writeJsonAtomic(file2, value) {
|
|
|
49215
49397
|
await writeFile4(temp, JSON.stringify(value) + "\n", { flag: "wx", mode: 384 });
|
|
49216
49398
|
await rename8(temp, file2);
|
|
49217
49399
|
} finally {
|
|
49218
|
-
await
|
|
49400
|
+
await rm9(temp, { force: true }).catch(() => {
|
|
49219
49401
|
});
|
|
49220
49402
|
}
|
|
49221
49403
|
}
|
|
@@ -49242,7 +49424,7 @@ var ContentAudit = class _ContentAudit {
|
|
|
49242
49424
|
skipped = 0;
|
|
49243
49425
|
closed = false;
|
|
49244
49426
|
static async open(options) {
|
|
49245
|
-
const dir =
|
|
49427
|
+
const dir = path28.resolve(options.directory);
|
|
49246
49428
|
await plainDirectory(dir);
|
|
49247
49429
|
const audit = new _ContentAudit(
|
|
49248
49430
|
dir,
|
|
@@ -49251,7 +49433,7 @@ var ContentAudit = class _ContentAudit {
|
|
|
49251
49433
|
{ retentionDays: options.retentionDays ?? AUDIT_RETENTION_DAYS, maxBytes: options.maxBytes ?? AUDIT_MAX_BYTES },
|
|
49252
49434
|
options.now ?? (() => /* @__PURE__ */ new Date())
|
|
49253
49435
|
);
|
|
49254
|
-
await
|
|
49436
|
+
await rm9(path28.join(dir, PAUSED_FILE), { force: true });
|
|
49255
49437
|
await audit.rollover(audit.now());
|
|
49256
49438
|
if (audit.usedBytes >= audit.limits.maxBytes) await audit.pause("QUOTA_EXCEEDED");
|
|
49257
49439
|
return audit;
|
|
@@ -49321,8 +49503,8 @@ var ContentAudit = class _ContentAudit {
|
|
|
49321
49503
|
await this.pause("QUOTA_EXCEEDED");
|
|
49322
49504
|
return;
|
|
49323
49505
|
}
|
|
49324
|
-
await appendFile(
|
|
49325
|
-
await appendFile(
|
|
49506
|
+
await appendFile(path28.join(this.dir, `full-${day}.jsonl`), line, { mode: 384 });
|
|
49507
|
+
await appendFile(path28.join(this.dir, `metrics-${day}.jsonl`), metrics, { mode: 384 });
|
|
49326
49508
|
this.usedBytes += bytes3;
|
|
49327
49509
|
}
|
|
49328
49510
|
/** Daily retention runs on the first write of a new day; no timer or background scan. */
|
|
@@ -49331,7 +49513,7 @@ var ContentAudit = class _ContentAudit {
|
|
|
49331
49513
|
const cutoff = new Date(at.getTime() - this.limits.retentionDays * DAY_MS).toISOString().slice(0, 10);
|
|
49332
49514
|
let used = 0;
|
|
49333
49515
|
for (const file2 of await auditFiles(this.dir)) {
|
|
49334
|
-
if (file2.day <= cutoff) await
|
|
49516
|
+
if (file2.day <= cutoff) await rm9(path28.join(this.dir, file2.name), { force: true });
|
|
49335
49517
|
else used += file2.bytes;
|
|
49336
49518
|
}
|
|
49337
49519
|
this.usedBytes = used;
|
|
@@ -49339,7 +49521,7 @@ var ContentAudit = class _ContentAudit {
|
|
|
49339
49521
|
async pause(reason) {
|
|
49340
49522
|
if (this.paused) return;
|
|
49341
49523
|
this.paused = reason;
|
|
49342
|
-
await writeJsonAtomic(
|
|
49524
|
+
await writeJsonAtomic(path28.join(this.dir, PAUSED_FILE), { reason, at: this.now().toISOString() });
|
|
49343
49525
|
}
|
|
49344
49526
|
};
|
|
49345
49527
|
function percentiles(values) {
|
|
@@ -49361,13 +49543,13 @@ async function* jsonLines(file2) {
|
|
|
49361
49543
|
}
|
|
49362
49544
|
var count2 = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : 0;
|
|
49363
49545
|
async function summarizeContentAudit(directory, key) {
|
|
49364
|
-
const dir =
|
|
49546
|
+
const dir = path28.resolve(directory);
|
|
49365
49547
|
const files = await auditFiles(dir);
|
|
49366
49548
|
const days = /* @__PURE__ */ new Map();
|
|
49367
49549
|
const sizes = [];
|
|
49368
49550
|
const timings = [];
|
|
49369
49551
|
for (const file2 of files.filter((f) => f.kind === "metrics")) {
|
|
49370
|
-
for await (const line of jsonLines(
|
|
49552
|
+
for await (const line of jsonLines(path28.join(dir, file2.name))) {
|
|
49371
49553
|
let day = days.get(file2.day);
|
|
49372
49554
|
if (!day) {
|
|
49373
49555
|
day = { day: file2.day, records: 0, failed: 0, rawBytes: 0, sanitizedBytes: 0, compressedBytes: 0, envelopeBytes: 0 };
|
|
@@ -49387,7 +49569,7 @@ async function summarizeContentAudit(directory, key) {
|
|
|
49387
49569
|
}
|
|
49388
49570
|
let paused = null;
|
|
49389
49571
|
try {
|
|
49390
|
-
const value = JSON.parse(await
|
|
49572
|
+
const value = JSON.parse(await readFile11(path28.join(dir, PAUSED_FILE), "utf8"));
|
|
49391
49573
|
if (typeof value.reason === "string" && typeof value.at === "string") paused = { reason: value.reason.slice(0, 40), at: value.at.slice(0, 40) };
|
|
49392
49574
|
} catch {
|
|
49393
49575
|
}
|
|
@@ -49395,7 +49577,7 @@ async function summarizeContentAudit(directory, key) {
|
|
|
49395
49577
|
const newest = files.filter((f) => f.kind === "full").at(-1);
|
|
49396
49578
|
if (key && newest) {
|
|
49397
49579
|
const tail = [];
|
|
49398
|
-
for await (const line of jsonLines(
|
|
49580
|
+
for await (const line of jsonLines(path28.join(dir, newest.name))) {
|
|
49399
49581
|
tail.push(line);
|
|
49400
49582
|
if (tail.length > 5) tail.shift();
|
|
49401
49583
|
}
|
|
@@ -49429,10 +49611,10 @@ async function summarizeContentAudit(directory, key) {
|
|
|
49429
49611
|
};
|
|
49430
49612
|
}
|
|
49431
49613
|
async function restoreContentAudit(input2, output2, key) {
|
|
49432
|
-
const handle = await open12(
|
|
49614
|
+
const handle = await open12(path28.resolve(output2), "wx", 384);
|
|
49433
49615
|
let records = 0, failed = 0;
|
|
49434
49616
|
try {
|
|
49435
|
-
for await (const line of jsonLines(
|
|
49617
|
+
for await (const line of jsonLines(path28.resolve(input2))) {
|
|
49436
49618
|
try {
|
|
49437
49619
|
await handle.appendFile(JSON.stringify(decryptAuditRecord(line, key)) + "\n");
|
|
49438
49620
|
records += 1;
|
|
@@ -49447,7 +49629,7 @@ async function restoreContentAudit(input2, output2, key) {
|
|
|
49447
49629
|
}
|
|
49448
49630
|
|
|
49449
49631
|
// agent/src/main.ts
|
|
49450
|
-
var AGENT_VERSION2 = true ? "0.3.
|
|
49632
|
+
var AGENT_VERSION2 = true ? "0.3.46" : "0.3.2";
|
|
49451
49633
|
var NETWORK_PUBLIC_KEY = true ? "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAvmu+81vWtJBQDZNHcAIW\nzCSxpG+R9RBsum2df5mP2cOW+wyUDTpnYquFge1qgI5YYTF96j0xCyXL8B9FeNWs\n939opWNmv53j+CQlS4cEIQhBbZSCu0eC4icsVEzBhvf68MB+E668SOtZBcVTEnyh\n96PTcupxS10rQJBWDinbKBXRC2gvGYeu01rWa/nsrndy4vAYP5t3yQtdOC8e8mr0\n+2Mg2Qhiq+KiTCtDd+L9oXvoLqqJYbzUIveNGha25AWxF1Weblp0gOM87hell5gV\nK7q4ZLUq/wBRGYNmQRdLyV7/WRE1FFPSW21/SBZQ/5aU4UqJU/MjMcrJUrnRKngz\nYKmo0czkxS3N7Q2KVxomgR1AQSuQFKMrboZYKjShADp9RIYUxzs7cYg51Of5PnHh\n6Ax+VevDGfzjMD+yHuyxYZqCtX4OwgolJxz63UQbzKlris+8xb5lLYTbIuz90Pss\nn6HK/F5May25c6oMmS3nh/NsiZopL1OvdtWKTt1L4WlRAgMBAAE=\n-----END PUBLIC KEY-----\n" : "";
|
|
49452
49634
|
var AI_CONNECTION_SHIPPED = false;
|
|
49453
49635
|
function processAlive(pid) {
|
|
@@ -49461,7 +49643,7 @@ function processAlive(pid) {
|
|
|
49461
49643
|
}
|
|
49462
49644
|
async function claimAgentProcess(stateDir, runtimeDir, version2) {
|
|
49463
49645
|
await mkdir14(stateDir, { recursive: true });
|
|
49464
|
-
const file2 =
|
|
49646
|
+
const file2 = path29.join(stateDir, "agent-process.json");
|
|
49465
49647
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
49466
49648
|
try {
|
|
49467
49649
|
const handle = await open13(file2, "wx", 384);
|
|
@@ -49472,8 +49654,8 @@ async function claimAgentProcess(stateDir, runtimeDir, version2) {
|
|
|
49472
49654
|
}
|
|
49473
49655
|
return async () => {
|
|
49474
49656
|
try {
|
|
49475
|
-
const current2 = JSON.parse(await
|
|
49476
|
-
if (current2.pid === process.pid) await
|
|
49657
|
+
const current2 = JSON.parse(await readFile12(file2, "utf8"));
|
|
49658
|
+
if (current2.pid === process.pid) await rm10(file2, { force: true });
|
|
49477
49659
|
} catch {
|
|
49478
49660
|
}
|
|
49479
49661
|
};
|
|
@@ -49481,12 +49663,12 @@ async function claimAgentProcess(stateDir, runtimeDir, version2) {
|
|
|
49481
49663
|
if (!error62 || typeof error62 !== "object" || !("code" in error62) || error62.code !== "EEXIST") throw error62;
|
|
49482
49664
|
let stale = true;
|
|
49483
49665
|
try {
|
|
49484
|
-
const current2 = JSON.parse(await
|
|
49666
|
+
const current2 = JSON.parse(await readFile12(file2, "utf8"));
|
|
49485
49667
|
stale = typeof current2.pid !== "number" || !processAlive(current2.pid);
|
|
49486
49668
|
} catch {
|
|
49487
49669
|
}
|
|
49488
49670
|
if (!stale) throw Error("AGENT_ALREADY_RUNNING");
|
|
49489
|
-
await
|
|
49671
|
+
await rm10(file2, { force: true });
|
|
49490
49672
|
}
|
|
49491
49673
|
}
|
|
49492
49674
|
throw Error("AGENT_ALREADY_RUNNING");
|
|
@@ -49737,10 +49919,10 @@ async function openContentAudit(store, stateDir) {
|
|
|
49737
49919
|
async function main() {
|
|
49738
49920
|
if (!["win32", "linux", "darwin"].includes(process.platform)) throw Error("PLATFORM_UNSUPPORTED");
|
|
49739
49921
|
const appData = process.env.LC_AGENT_DATA_DIR ?? (process.platform === "win32" ? process.env.LOCALAPPDATA : posixDataHome());
|
|
49740
|
-
if (!appData || !
|
|
49741
|
-
const stateDir = process.env.LC_AGENT_STATE_DIR ??
|
|
49742
|
-
const binaryDir =
|
|
49743
|
-
const ownerBridgePath = process.env.LC_OWNER_BRIDGE ??
|
|
49922
|
+
if (!appData || !path29.isAbsolute(appData)) throw Error("APP_DATA_MISSING");
|
|
49923
|
+
const stateDir = process.env.LC_AGENT_STATE_DIR ?? path29.join(appData, "LocalCommander", "Agent");
|
|
49924
|
+
const binaryDir = path29.dirname(process.platform === "win32" ? process.execPath : await realpath10(process.execPath));
|
|
49925
|
+
const ownerBridgePath = process.env.LC_OWNER_BRIDGE ?? path29.join(binaryDir, process.platform === "win32" ? "OwnerBridge.exe" : "owner-store");
|
|
49744
49926
|
const store = await WindowsPrivateStore.open(stateDir, ownerBridgePath);
|
|
49745
49927
|
const command = process.argv[2] ?? "run";
|
|
49746
49928
|
if (process.platform !== "win32" && (command.startsWith("guard-") || command.startsWith("network-"))) throw Error("FEATURE_PLATFORM_UNSUPPORTED");
|
|
@@ -49750,7 +49932,7 @@ async function main() {
|
|
|
49750
49932
|
const pairing = new PairingClient(store, { controlPlaneOrigin: origin, agentVersion: AGENT_VERSION2 });
|
|
49751
49933
|
const begun = await pairing.begin();
|
|
49752
49934
|
process.stdout.write(JSON.stringify({ approvalUrl: begun.approvalUrl, confirmationCode: begun.confirmationCode, expiresAt: begun.expiresAt.toISOString() }) + "\n");
|
|
49753
|
-
await pairing.waitAndComplete(begun,
|
|
49935
|
+
await pairing.waitAndComplete(begun, os8.hostname().slice(0, 120));
|
|
49754
49936
|
process.stdout.write("DEVICE_PAIRED\n");
|
|
49755
49937
|
return;
|
|
49756
49938
|
}
|
|
@@ -49835,7 +50017,7 @@ async function main() {
|
|
|
49835
50017
|
}
|
|
49836
50018
|
if (command === "efficiency-report") {
|
|
49837
50019
|
if (args.length) throw Error("AGENT_COMMAND_INVALID");
|
|
49838
|
-
const ledger = await OptimizationLedger.open(
|
|
50020
|
+
const ledger = await OptimizationLedger.open(path29.join(stateDir, "optimization"));
|
|
49839
50021
|
try {
|
|
49840
50022
|
process.stdout.write(JSON.stringify(await ledger.report(), null, 2) + "\n");
|
|
49841
50023
|
} finally {
|
|
@@ -49845,7 +50027,7 @@ async function main() {
|
|
|
49845
50027
|
}
|
|
49846
50028
|
if (command === "guard-configure") {
|
|
49847
50029
|
if (args.length !== 1) throw Error("AGENT_COMMAND_INVALID");
|
|
49848
|
-
const filename = await (await import("node:fs/promises")).realpath(
|
|
50030
|
+
const filename = await (await import("node:fs/promises")).realpath(path29.resolve(args[0]));
|
|
49849
50031
|
const input2 = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await readWindowsFile(ownerBridgePath, filename, 2e5)));
|
|
49850
50032
|
if (!input2 || typeof input2 !== "object" || Object.keys(input2).sort().join(",") !== "compact,settings") throw Error("GUARD_CONFIGURATION_INVALID");
|
|
49851
50033
|
await store.configureGuard(input2.settings, input2.compact);
|
|
@@ -49864,7 +50046,7 @@ async function main() {
|
|
|
49864
50046
|
}
|
|
49865
50047
|
if (command === "guard-evidence") {
|
|
49866
50048
|
if (args.length) throw Error("AGENT_COMMAND_INVALID");
|
|
49867
|
-
const journal = await NativeJournal.open(
|
|
50049
|
+
const journal = await NativeJournal.open(path29.join(stateDir, "journal"), new SecretBox({ "1": await store.loadDataKey() }));
|
|
49868
50050
|
try {
|
|
49869
50051
|
process.stdout.write(JSON.stringify(await journal.guardEvidence()) + "\n");
|
|
49870
50052
|
} finally {
|
|
@@ -49876,7 +50058,7 @@ async function main() {
|
|
|
49876
50058
|
if (args.length !== (command === "guard-export" ? 0 : 1)) throw Error("AGENT_COMMAND_INVALID");
|
|
49877
50059
|
const identity = await store.load();
|
|
49878
50060
|
if (!identity?.enrollment) throw Error("ENROLLMENT_MISSING");
|
|
49879
|
-
const journal = await NativeJournal.open(
|
|
50061
|
+
const journal = await NativeJournal.open(path29.join(stateDir, "journal"), new SecretBox({ "1": await store.loadDataKey() }));
|
|
49880
50062
|
try {
|
|
49881
50063
|
const { tenantId, deviceId } = identity.enrollment;
|
|
49882
50064
|
const records = (await journal.guardEvidence()).filter((record2) => record2.tenantId === tenantId && record2.deviceId === deviceId);
|
|
@@ -49954,27 +50136,27 @@ async function main() {
|
|
|
49954
50136
|
if (args.length) throw Error("AGENT_COMMAND_INVALID");
|
|
49955
50137
|
if (!(await store.load())?.enrollment) throw Error("ENROLLMENT_MISSING");
|
|
49956
50138
|
const releaseProcess = await claimAgentProcess(stateDir, binaryDir, AGENT_VERSION2);
|
|
49957
|
-
const monitor = new ProductionMonitor(
|
|
50139
|
+
const monitor = new ProductionMonitor(path29.join(appData, "LocalCommander", "Monitor"), stateDir, AGENT_VERSION2);
|
|
49958
50140
|
const publishMonitor = () => monitor.flush().catch(() => {
|
|
49959
50141
|
process.stderr.write("MONITOR_WRITE_FAILED\n");
|
|
49960
50142
|
});
|
|
49961
50143
|
await publishMonitor();
|
|
49962
50144
|
try {
|
|
49963
50145
|
const journal = await NativeJournal.open(
|
|
49964
|
-
|
|
50146
|
+
path29.join(stateDir, "journal"),
|
|
49965
50147
|
new SecretBox({ "1": await store.loadDataKey() }),
|
|
49966
|
-
process.platform === "win32" ? {} : { lockHelper:
|
|
50148
|
+
process.platform === "win32" ? {} : { lockHelper: path29.join(binaryDir, "posix-host") }
|
|
49967
50149
|
);
|
|
49968
50150
|
const ledgerLoss = () => {
|
|
49969
50151
|
process.stderr.write("OPTIMIZATION_TELEMETRY_INCOMPLETE\n");
|
|
49970
50152
|
};
|
|
49971
50153
|
const efficiencyLedger = await new OptionalWork(ledgerLoss, 1e3, 1).run(
|
|
49972
|
-
() => OptimizationLedger.open(
|
|
50154
|
+
() => OptimizationLedger.open(path29.join(stateDir, "optimization")),
|
|
49973
50155
|
void 0,
|
|
49974
50156
|
(ledger) => ledger.close()
|
|
49975
50157
|
);
|
|
49976
50158
|
try {
|
|
49977
|
-
const helperPath = process.env.LC_JOB_HOST ??
|
|
50159
|
+
const helperPath = process.env.LC_JOB_HOST ?? path29.join(binaryDir, process.platform === "win32" ? "JobHost.exe" : "job-host.mjs");
|
|
49978
50160
|
const tools = new NativeTools({ stateDirectory: stateDir, helperPath, ownerBridgePath, programs: await store.loadPrograms() });
|
|
49979
50161
|
const stop = new AbortController();
|
|
49980
50162
|
process.once("SIGINT", () => stop.abort());
|
|
@@ -50045,7 +50227,7 @@ async function main() {
|
|
|
50045
50227
|
await releaseProcess();
|
|
50046
50228
|
}
|
|
50047
50229
|
}
|
|
50048
|
-
var entrypoint = process.argv[1] && (process.platform === "win32" ?
|
|
50230
|
+
var entrypoint = process.argv[1] && (process.platform === "win32" ? path29.resolve(process.argv[1]) : await realpath10(process.argv[1]).catch(() => null));
|
|
50049
50231
|
if (entrypoint === fileURLToPath(import.meta.url)) {
|
|
50050
50232
|
void main().catch((error62) => {
|
|
50051
50233
|
const code = error62 instanceof Error && /^[A-Z0-9_]{1,64}$/.test(error62.message) ? error62.message : "AGENT_START_FAILED";
|